pax_global_header00006660000000000000000000000064150017505110014505gustar00rootroot0000000000000052 comment=1462b3e28feda52a210d8eb5c6eb69686a5ecb9b kupfer-328/000077500000000000000000000000001500175051100126575ustar00rootroot00000000000000kupfer-328/COPYING000066400000000000000000001043741500175051100137230ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. 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. Copyright (C) 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 . 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: Copyright (C) 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 . 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 . kupfer-328/Documentation/000077500000000000000000000000001500175051100154705ustar00rootroot00000000000000kupfer-328/Documentation/Contributing.rst000066400000000000000000000065601500175051100207000ustar00rootroot00000000000000 Guidelines and Policy ===================== Contributing ------------ You can structure your changes into a series of commits in git. A series of well disposed changes is easy to review. Write a sufficient commit log message for each change. Do not fear writing down details about why the change is implemented as it is, if there are multiple alternatives. Also, if you forsee any future possibilites or problems, please describe them in the commit log. You can find kupfer's `git repository at github`__ and fork it there, for easy publication of your changes. If you suggest your changes for inclusion into Kupfer, make sure you have read the whole *Guidelines and Policy* chapter of this manual. And take care to structure your changes, do not fear asking for advice. Good Luck! __ https://github.com/kupferlauncher/kupfer Icon Guidelines --------------- Consider the following: * A Leaf is an object, a metaphor for a physical thing. It can have as detailed icon as is possible. * An Action is a verb, a command that can be carried out. Choose its name with care. The icon should be simple, maybe assign the action to a category, rather than trying to illustrate the action itself. For example, all text display actions use the "bold style" icon, in some icon themes simply a bold "A". .. important:: Actions should have stylized, simple icons. Leaves and Sources should have detailed, specific icons. Coding style ------------ Kupfer python code is indented with four spaces. If you contribute to kupfer keep in mind that * Python code should be clear * Kupfer is a simple project. Do simple first. Python's general style guideline is called `PEP 8`_, and you should programmers should read it. The advice given there is very useful when coding for Kupfer. .. _`PEP 8`: https://www.python.org/dev/peps/pep-0008/ Specific Points --------------- Using ``rank_adjust`` ..................... A declaration like this can modify the ranking of an object:: class MyAction (Action): rank_adjust = -5 ... 1. Often, this is useless. Don't use it, let Kupfer learn which actions are important. 2. If the action is destructive, the adjust should be negative. Never positive. For example *Move to Trash* has a negative 10 ``rank_adjust``. 3. If the action is very general, and applies to almost everything but still should never be the default for anything, the adjust should be negative. Using ``super(..)`` ................... You should use the Python 3 ``super()`` without arguments. Old code was using the following style which worked best in older Python, but the style is obsolete:: Source.__init__(self, _("Recent items")) Text and Encodings .................. Care must be taken with all input and output text and its encoding! Internally, kupfer must use ``str`` for all internal text. The module ``kupfer.support.kupferstring`` has functions for the most important text conversions. A resource for unicode in Python: | http://farmdev.com/talks/unicode/ **Always** find out what encoding you must expect for externally read text (from files or command output). If you must guess, use the locale encoding. Text received from GTK is always ``str``, which means encoding is not a problem. Note that the gettext function ``_()`` always returns a unicode string (``str``). .. vim: ft=rst tw=72 et sts=4 .. this document best viewed with rst2html kupfer-328/Documentation/Copyright.rst000066400000000000000000000006701500175051100201750ustar00rootroot00000000000000 Copyright ========= The program Kupfer is released under the `GNU General Public Licence v3`:t: (or at your option, any later version). Please see the main program file for more information. This documentation is released under the same terms as the main program. The documentation sources are available inside the Kupfer source distribution. Copyright 2009–2023 Ulrik Sverdrup and all Kupfer authors .. vim: ft=rst tw=72 et sts=4 kupfer-328/Documentation/GTKTheming.rst000066400000000000000000000017431500175051100201700ustar00rootroot00000000000000==================== GTK+ Theming Support ==================== ---------------------------- Changing Kupfer's Appearance ---------------------------- .. contents:: Introduction ============ In Kupfer's the interface elements are marked-up with names and classes so that Gtk 3's css mechanism can style them. The work is not yet complete. Existing widget names: #kupfer main window #kupfer-object-pane, #kupfer-action-pane, #kupfer-indirect-object-pane the three panes .matchview a pane's view #kupfer-list result list window #kupfer-list-view result list tree view Icons ===== The kupfer-specific icon names we use are: + ``kupfer`` (application) + ``kupfer-catalog`` (root catalog) + ``kupfer-execute`` (default action icon) + ``kupfer-launch`` (default launch icon) + ``kupfer-object`` (blue box generic object icon) + ``kupfer-object-multiple`` (multiple generic objects) .. vim: ft=rst tw=72 et sts=4 sw=4 .. this document best viewed with rst2html kupfer-328/Documentation/Localization.rst000066400000000000000000000052401500175051100206530ustar00rootroot00000000000000 Localization ============ kupfer is translated using gettext and it is managed in the build system using ``intltool``. Translation messages are located in the ``po/`` directory. The user’s guide is located in the ``help/`` directory and it can also be translated, see its section. .. contents:: To create a new translation --------------------------- Go into the directory ``po`` 1. Add the language code ``$LANG`` to the file ``LINGUAS`` 2. Run ``intltool-update --pot``, and copy ``untitled.pot`` to ``$LANG.po`` 3. Edit and check the whole file header: + Write in yourself as author + Check ``plurals`` (copy from a language that you know uses the same number of plural forms, or look up in GNOME's translation pages.) + Replace everything written in CAPS Fill in the charset used; Kupfer translations *must* use the UTF-8 encoding. When the header is filled-in, go to `To update or check an existing translation`_ To update or check an existing translation ------------------------------------------ Go to your Kupfer source directory. Here we will call your language ``$LANG``. You should use a two or four-letter code for your language instead of ``$LANG``, for example "de" for German or "pt_BR" for Brazilian Portuguese. Go to the translation directory ``po``:: cd po/ To update and check the translation file, run:: intltool-update $LANG Now check and edit ``$LANG.po``. Search for all messages marked "fuzzy", and remove the word "fuzzy" from them when they are done. Continue running ``intltool-update $LANG`` and check that you have 0 fuzzy and 0 untranslated, then you're finished. This will also check consistency of the file, so that you know that all your syntax is correct. To try the new translation -------------------------- Make sure the translation is listed in ``po/LINGUAS``. To try it, you have to install kupfer with ``./waf install``, then you can run kupfer as normal. .. note:: If you run ``./kupfer-run`` from the source directory it won't find the installed translations unless you make a symlink called ``locale`` to the installed location (for example ``~/.local/share/locale`` if install prefix was ``~/.local``):: $ ln -s ~/.local/share/locale User’s Guide ------------ Go to ``help/``. The english-language original of the user’s guide is defined in the ``C/`` directory. Use ``make $LANG`` inside ``help`` to update a language’s ``.po`` file. Currently, the best way to view the translated help page during development is to run the regular build and install, which puts the help pages under ``$PREFIX/help/$LANG/kupfer``. .. vim: ft=rst tw=72 et sts=4 .. this document best viewed with rst2html kupfer-328/Documentation/Makefile000066400000000000000000000006041500175051100171300ustar00rootroot00000000000000# This makefile can generate html versions that are pleasant to read # needs python-docutils all: Contributing.html Copyright.html Localization.html Manpage.html \ Manual.html PluginAPI.html \ GTKTheming.html VersionHistory.html index.html %.html: %.rst rst2html5 $^ > $@ %.pdf: %.rst rst2pdf -o $@ $^ index.html: Manual.html cp $^ $@ clean: rm -fv *.html .PHONY: clean all kupfer-328/Documentation/Manpage.rst000066400000000000000000000052271500175051100176000ustar00rootroot00000000000000====== kupfer ====== ----------------------------------------------------------------- Convenient command and access tool for applications and documents ----------------------------------------------------------------- :Author: Ulrik Sverdrup :Date: 2017 :Manual section: 1 SYNOPSIS ======== | ``kupfer`` [ *OPTIONS* | *FILE* ... ] | ``kupfer-exec`` *FILE* ... DESCRIPTION =========== Kupfer is an interface for quick and convenient access to applications and their documents. The most typical use is to find a specific application and launch it. We have tried to make Kupfer easy to extend with plugins so that this quick-access paradigm can be extended to many more objects than just applications. ``kupfer-exec`` is a helper script that can execute commands saved to file, but only by connecting to an already running instance of Kupfer. SPAWNING ======== Running kupfer on the command line (without options) will try to show the program it if already running. Kupfer can be invoked with a list of files ``kupfer`` *FILE* ... The file paths will be sent to and selected in an already running instance of the program. You may also pipe text to ``kupfer`` to pass it to a currently running instance. OPTIONS ======= --no-splash Launch without presenting main interface --debug Enable more verbose output that can help understanding the program's operation. --list-plugins List all installed plugins by their identifier, version and description. The following are options for internal use --exec-helper=HELPER Run plugin helper program, which should be the name of a module inside kupfer. The following are generic options --help Display usage information --version Display version information CONFIGURATION ============= Custom plugins are added to kupfer by installing them to the directory *~/.local/share/kupfer/plugins*, or any kupfer/plugins directory in any of ``$XDG_DATA_DIRS``. ENVIRONMENT VARIABLES ===================== If *KUPFER_NO_CUSTOM_PLUGINS* is set, only allow loading built-in plugins (installed in the program's python package). If *KUPFER_NO_CACHE* is set, do not load from or write to any source cache files. If *KUPFER_NO_KEYBINDER* is set do not use ``Keybinder`` even if it is installed. TROUBLESHOTING / KNOWN BUGS =========================== Wayland ------- Set *GDK_BACKEND* environment variable to ``x11`` solve problem with wrong window position. Some plugins (for example *Windows*) not work due to lack support by *Wnck* library. .. vim: ft=rst tw=72 .. this document best viewed with:: rst2pdf Quickstart.rst && xdg-open Quickstart.pdf kupfer-328/Documentation/Manual.rst000066400000000000000000000017621500175051100174450ustar00rootroot00000000000000 ============================== Kupfer Technical Documentation ============================== .. topic:: `Kupfer Plugin API `_ .. .. topic:: `GTK+ Theme Support `_ .. .. topic:: `Contributing `_ .. .. topic:: `Localization `_ .. .. topic:: `Man Page `_ .. .. topic:: `Version History `_ .. .. topic:: `Copyright `_ .. There is also `User Documentation`__ __ https://kupferlauncher.github.io/help/ .. How to Generate HTML or PDF from this documentation. This is a RestructuredText_ document and it can be rendered by installing ``python-docutils`` (``docutils`` module). This package should also provide the utilities ``rst2html`` and ``rst2pdf`` as well as ``rst2man``. .. _RestructuredText: http://docutils.sourceforge.net/rst.html .. vim: ft=rst tw=72 et sts=4 sw=4 .. this document best viewed with rst2html kupfer-328/Documentation/PluginAPI.rst000066400000000000000000001036371500175051100200240ustar00rootroot00000000000000================= Kupfer Plugin API ================= .. contents:: :depth: 2 Introduction ============ Kupfer is a Python program that allows loading extension modules at runtime. A plugin is equivalent to one Python module implemented as one ``.py`` file or as a Python package. The ``kupfer`` package is organized as follows:: kupfer/ obj/ ui/ core/ plugin/ core/__init__.py applications.py ... support/ ... Plugins live in the package ``kupfer.plugin``. Kupfer also includes directories called ``kupfer/plugins`` from ``$XDG_DATA_DIRS``, which typically means ``/usr/share/kupfer/plugins`` and ``$HOME/.local/share/kupfer/plugins``. These directories are transparently included into the kupfer package, so the user has multiple choices of where to install plugins. The Plugin File ::::::::::::::: A kupfer plugin is a ``.py`` file with some special attributes. It starts like this (an imagined example):: __kupfer_name__ = _("Cool X-Documents") __kupfer_sources__ = ("DocumentSource", ) __kupfer_text_sources__ = () __kupfer_actions__ = ("Open", ) __description__ = _("Documents from the X program") __version__ = "1" __author__ = "Tom Author" All these special variables must be defined before any other code in the module (even imports). For a plugin, the following attributes are required:: __kupfer_name__ (Localized name of plugin) __description__ (Localized description of plugin) __version__ __author__ For the plugin to do anything, the following attributes may be defined:: __kupfer_sources__ = () __kupfer_text_sources__ = () __kupfer_actions__ = () __kupfer_action_generators__ = () __kupfer_contents__ = () They should be tuples of *names* of classes in the module: * all sources have to be subclasses of ``kupfer.objects.Source`` * all text sources have to be subclasses of ``kupfer.objects.TextSource`` * all actions have to be subclasses of ``kupfer.objects.Action`` If an example plugin declares:: __kupfer_sources__ = ("DocumentSource", ) it will later in the file define the class ``DocumentSource``:: from kupfer.objects import Source class DocumentSource (Source): def __init__(self): Source.__init__(self, _("Cool X-Documents")) def get_items(self): ... # later we will see what we can do here! Ok, this looks simple. So what are Leaves, Sources and Actions? A **Leaf** is an object, it represents a program or a file, or a text or something else. Every type of Leaf has different possibilities, and you can define new Leaves. Example: a ``FileLeaf`` represents a file on the disk. A **Source** produces a collection of Leaves, so it makes Kupfer know about new objects. For example, it can provide all the FileLeaves for a particular folder. An **Action** is the part where something happens, an action is applied to a Leaf, and something happens. For example, *Open* can be an action that works with all ``FileLeaf``. A Short Working Example ::::::::::::::::::::::: The very simplest thing we can do is to provide an action on objects that already exist in Kupfer. These actions appear in the right-hand actions pane in kupfer, when an object of the right type is selected. The complete python code for the plugin: .. code:: python __kupfer_name__ = _("Image Viewer") __kupfer_actions__ = ("View", ) __description__ = _("View images quickly") __version__ = "" __author__ = "Tom Author" from gi.repository import Gtk from kupfer.obj import Action, FileLeaf class View (Action): def __init__(self): super().__init__(_("View")) def item_types(self): yield FileLeaf def valid_for_item(self, fileobj): return fileobj.object.endswith(".jpg") def activate(self, fileobj): image_widget = Gtk.Image.new_from_file(fileobj.object) image_widget.show() window = Gtk.Window() window.add(image_widget) window.present() That is all. What we did was the following: * Declare a plugin called "Image Viewer" with an action class ``View``. * Every string inside ``_("")`` is translatable * ``View`` declares that it works with ``FileLeaf`` * ``View`` only accepts ``FileLeaf`` that end with '.jpg' * ``View`` defines a method ``activate`` that when called, will use gtk to show the file in a window .. note:: Kupfer uses a simplified programming style of composition and cooperative superclasses. You normally never call a superclass implementation inside a method that you define, with the exception of ``__init__``. On the other hand, there are superclass methods that should not be overridden. For example, ``KupferObject.get_pixbuf`` is never overridden, instead you implement ``KupferObject.get_icon_name``. Reference ========= Below follows a complete summary. To accompany this reference, you can read kupfer's inline module documentation with pydoc, by doing the following in the source directory:: $ pydoc kupfer.obj or equivalently:: $ python >>> help("kupfer.obj") KupferObject :::::::::::: ``class KupferObject`` implements the things that are common to all objects: *name*, *description*, *icon*, *thumbnail* and *name aliases*. ``__init__(self, name)`` This is called when you call ``Leaf.__init__``, or ``Source.__init__``, and so on in your object's ``__init__`` method. The name parameter must be a unicode string. An object can not change name after it has called __init__. ``get_description(self)`` Return a longer user-visible unicode string that describes the object. ``get_icon_name(self)`` Return a string of one icon name for the object. The icon name should preferably be in the `Icon Naming Specification`_ .. _`Icon Naming Specification`: \ http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html ``get_gicon(self)`` Return a GIcon (GIO icon) object. This takes precedence over the icon name, if it is defined. ``get_thumbnail(self, width, height)`` Implement ``get_thumbnail`` to return a GdkPixbuf object of the requested size that is a thumbnail of the object. If applicable. ``get_pixbuf(self, x)`` This should not be redefined. Define ``get_icon_name`` and/or ``get_gicon`` instead. ``get_icon(self)`` This should not be redefined. Define ``get_icon_name`` and/or ``get_gicon`` instead. ``repr_key(self)`` Return an object whose str() will be used in the __repr__, self is returned by default. This value is used to differentiate and recognize objects. Override this if the objects type and name is not enough to differentiate it from other objects. ``__repr__`` This should not be redefined. Define ``repr_key`` instead. ``kupfer_add_alias(self, alias)`` This should not be redefined, but can be called by the object to add an alternate name to the object. KupferObject Attributes ....................... ``KupferObject.rank_adjust`` A number to adjust the ranking of a certain object. Should only be used on Actions. Should be set in the range -10 to -1 for actions that apply to many objects but not default for any. ``KupferObject.fallback_icon_name`` Used as a the class' fallback for icon name. Do not change this. Leaf :::: ``class Leaf`` inherits from KupferObject. A Leaf represents an object that the user will want to act on. Examples are a file, an application or a free-text query (TextLeaf). This defines, in addition to KupferObject: ``__init__(self, obj, name)`` The default implementation of ``__init__`` stores the parameter ``obj`` into ``self.object`` and passes ``name`` up to ``KupferObject.__init__``. ``obj`` can be any data that the Leaf represents. ``name`` must be a unicode string. ``Leaf.object`` ``Leaf.object`` is the represented object, which is the implementation-specific internal data. ``get_actions()`` Return a sequence of Actions that always apply to the Leaf. These are "built-in" actions. ``__hash__`` and ``__eq__`` Leaves are hashable, can be members in a set, and duplicates are recognized (and removed); this is essential so that equivalent Leaves from different sources are recognized. These methods need normally not be overridden. By default leaves are equal if both the name and the ``Leaf.object`` attribute are the same. ``has_content()`` and ``content_source()`` A leaf can contain something, like a folder contains files or a music album songs. If the Leaf should have content, it should override ``has_content`` to return ``True`` and define ``content_source()`` to return an instance of a Source. A Leaf may decide dynamically if it has content or not. Action :::::: ``class Action`` inherits from KupferObject. An Action represents a command using a direct object and an optional indirect object. One example is ``kupfer.obj.fileactions.Open`` that will open its direct object (which must be a file), with its default viewer. Actions are the most versatile parts of Kupfer, since they can define ways to use objects together. They also have to decide, which types of Leaves they apply to, and if they apply to a given Leaf. An action is either a `Subject + Verb`:t: action: It needs one object, this is the direct object. Or it is a `Subject + Verb + Object`:t: action: It needs two objects, one direct object ("obj") and one indirect object ("iobj"). Action defines, in addition to KupferObject: Activate: Carrying Out the Action ................................. ``activate(self, obj)`` Called to perform the action if the action is a normal `Subject + Verb`:t: action. ``activate(self, obj, iobj)`` Called to perform the action if the action is a three-way `Subject + Verb + Object`:t: action. (That is, ``requires_object`` returns ``True``) ``activate_multiple(self, objects)`` .. ``activate_multiple(self, objects, iobjects)`` If implemented, ``activate_multiple`` is called with preference over ``activate(self, obj, iobj)`` or ``activate(self, obj)`` as appropriate. Implement ``activate_multiple`` to handle multiple objects on either side in a smart way. You should implement ``activate_multiple`` if it is possible to do something better than the equivalent of repeating ``activate`` *n* times for *n* objects. ``activate`` and ``activate_multiple`` also receive a keyword argument called ``ctx`` if the action defines ``wants_context(self)`` to return ``True``. See ``wants_context`` below for more information. Determining Eligible Objects ............................ ``item_types(self)`` This method should return a sequence of all Leaf types that the action can apply to (direct object). ``valid_for_item(self, item)`` This method is called for each potential direct object of the correct type. Return True if the object is compatible with the action. By default always returns ``True``. ``requires_object(self)`` Return ``True`` if the action is a `Subject + Verb + Object`:t: action and requires both a direct and an indirect object. If ``requires_object`` returns ``True``, then you must also define (at least) ``object_types``. ``object_types(self)`` Return a sequence of all Leaf types that are valid for the action's indirect object. ``object_source(self, for_item)`` If the action's indirect objects should not be picked from the full catalog, but from a defined source, return an instance of the Source here, else return None. ``for_item`` is the direct object. ``object_source_and_catalog(self, for_item)`` If the action has an object source, by default only that source is used for indirect objects. Return ``True`` here to use both the custom source and the whole catalog. ``valid_object(self, iobj, for_item)`` This method, if defined, will be called for each indirect object (with the direct object as ``for_item``), to decide if it can be used. Return ``True`` if it can be used. Auxiliary Method ``wants_context(self)`` ........................................ ``wants_context(self)`` Return ``True`` if ``activate`` should receive an ``ExecutionToken`` as the keyword argument ``ctx``. This allows posting late (after-the-fact) results and errors, as well as allowing access to the GUI environment. ``wants_context`` defaults to ``False`` which corresponds to the old protocol without ``ctx``. So instead of ``activate(self, obj)``, the method should be implemented as ``activate(self, obj, ctx)``. The object passed as ``ctx`` has the following interface: ``ctx.register_late_result(result_object)`` Register the ``result_object`` as a late result. It must be a ``Leaf`` or a ``Source``. ``ctx.register_late_error(exc_info=None)`` Register an asynchronous error. (For synchronous errors, simply raise an ``OperationError`` inside ``activate``.) For asynchronous errors, call ``register_late_error``. If ``exc_info`` is ``None``, the current exception is used. If ``exc_info`` is an ``OperationError`` instance, then it is used as error. Otherwise, a tuple like ``sys.exc_info()`` can be passed. ``ctx.environment`` The environment object, which has the following methods: ``get_timestamp(self)`` Return the current event timestamp ``get_startup_notification_id(self)`` Make and return a startup notification id ``get_display(self)`` Return the display name (i.e ``:0.0``) ``present_window(self, window)`` Present ``window`` (a ``Gtk.Window``) on the current workspace and monitor using the current event time. Auxiliary Action Methods ........................ Some auxiliary methods tell Kupfer about how to handle the action: ``is_factory(self)`` Return ``True`` if the return value of ``activate`` is a source that should be displayed immediately. ``has_result(self)`` Return ``True`` if the action's return value in ``activate`` should be selected. ``is_async(self)`` Return ``True`` if the action returns a ``Task`` object conforming to ``kupfer.task.Task`` from ``activate``. The task will be executed asynchronously in Kupfer's task queue. ``repr_key(self)`` Override this to define a unique key for the action, if you need to differentiate between different instances of the same Action class. Class Attributes ................ The attribute ``action_accelerator`` is ``None`` by default but can be a single letter string to suggest a default accelerator for this action. Actions that act like the default open should use ``"o"``. Source :::::: ``class Source`` inherits from KupferObject. A Source understands specific data and delivers Leaves for it. A Source subclass must at a minimum implement ``__init__``, ``get_items`` and ``provides``. ``Source`` defines, in addition to ``KupferObject``: ``__init__(self, names)`` You must call this method with a unicode name in the subclass ``__init__(self)``. ``get_items(self)`` Your source should define ``get_items`` to return a sequence of leaves which are its items; the return value is cached and used until ``mark_for_update`` is called. Often, implementing ``get_items`` in the style of a generator (using ``yield``) is the most convenient. The Leaves shall be returned in natural order (most relevant first), or if sorting is required, return in any order and define ``should_sort_lexically``. ``get_leaves(self)`` ``get_leaves`` must not be overridden, define ``get_items`` instead. ``provides(self)`` Return a sequence of all precise Leaf types the Source may contain. Often, the Source contains Leaves of only one type, in that case the implementation is written simply as ``yield ThatLeafType``. ``should_sort_lexically(self)`` Return ``True`` if the Source's leaves should be sorted alphabethically. If not sorted lexically, ``get_items`` should yield leaves in order of the most relevant object first (for example the most recently used). ``initialize(self)`` This method is called when the source should be made ready to use. This is where it should register for external change callbacks, for example. ``finalize(self)`` This method is called before the Source is disabled (shutdown or plugin deactivated). ``get_leaf_repr(self)`` Return a Leaf that represents the Source, if applicable; for example the DirectorySource is represented by a FileLeaf for the directory. ``__hash__`` and ``__eq__`` Sources are hashable, and equivalents are recognized just like Leaves, and the central SourceController manages them so that there are no duplicates in the application. ``get_items_forced(self)`` Like ``get_items``, called when a refresh is forced. By default it just calls ``get_items``. ``mark_for_update(self)`` Should not be overridden. Call ``mark_for_update`` in the source to mark it so that it is refreshed by calling ``get_items``. ``repr_key(self)`` Define to a unique key if you need to differentiate between sources of the same class. Normally only used with Sources from factory actions or from decorator sources. ``toplevel_source(self)`` If applicable, the source can return a different source to represent it and its objects in the top level of the catalog. The default implementation returns ``self`` which is normally what you want. ``is_dynamic(self)`` Return ``True`` if the Source should not be cached. This is almost never used. Saving Source configuration data ................................ These methods are must be implemented if the Source needs to save user-produced configuration data. ``config_save_name(self)`` Return the name key to save the data under. This should almost always be literally ``return __name__`` ``config_save(self)`` Implement this to return a datastructure that succintly but perfectly represents the configuration data. The returned value must be a composition of simple types, that is, nested compositions of ``dict``, ``list``, ``str`` etc. This is called after ``finalize`` is called on the source. ``config_restore(self, state)`` The ``state`` parameter is passed in as the saved return value of ``config_save``. ``config_restore`` is called before ``initialize`` is called on the Source. Content Decorators .................. A content-decorating source provides content to a Leaf, where it does not control the Leaf. An example is the recent documents content decorator, that provides document collections as content to applications. A normal Source listed in ``__kupfer_sources__`` will be eligible for content decoration as well if it implements the needed methods. Otherwise content-only sources are listed in ``__kupfer_contents__``. ``@classmethod decorates_type(cls)`` Return the type of Leaf that can be decorated. You must also implement ``decorate_item``. ``@classmethod decorate_item(cls, leaf)`` Return an instance of a Source (normally of the same type as the content decorator itself) that is the content for the object ``leaf``. Return ``None`` if not applicable. Sources returned from ``decorate_item`` go into the common Source pool. The new source instance will not be used if the returned instance is equivalent (as defined by class and ``reepr_key`` above). Source Attributes ................. ``Source.source_user_reloadable = False`` Set to ``True`` if the source should have a user-visible *Rescan* action. Normally you much prefer to use change notifications so that this is not necessary. ``Source.source_prefer_sublevel = False`` Set to ``True`` to not export its objects to the top level by default. Normally you don't wan't to change this. ``Source.source_use_cache = True`` If ``True``, the source can be pickled to disk to save its cached items until the next time the launcher is started. ``Source.source_scan_interval`` Set inteval in secounds between refresh source by ``PeriodicRescanner``. Background process check and refresh all sounrces every 60 secounds but not often than ``source_scan_interval``. Sources marked to reload are refresh in next refresh run. ``Source.last_scan`` Object attribute keep information about last rescan time. ``Source._version`` Internal number that is ``1`` by default. Update this number in ``__init__`` to invalidate old versions of cache files. TextSource :::::::::: TextSource inherits from KupferObject. A text source returns items for a given text string, it is much like a simplified version of Source. At a minimum, a TextSource subclass must implement ``get_text_items`` and ``provides``. ``__init__(self, name)`` Override as ``__init__(self)`` to provide a unicode name for the source. ``get_text_items(self, text)`` Return a sequence of Leaves for the unicode string ``text``. ``provides(self)`` Return a sequence of the Leaf types it may contain ``get_rank(self)`` Return a static rank score for text output of this source. ActionGenerator ::::::::::::::: ActionGenerator inherits from object. ActionGenerator is a helper object that can be declared in ``__kupfer_action_generators__``. It allows generating action objects dynamically. ``get_actions_for_leaf(self, leaf)`` Return a sequence of Action objects appropriate for this Leaf .. note:: The ``ActionGenerator`` should not perform any expensive computation, and not access any slow media (files, network) when returning actions. Such expensive checks must postponed and be performed in each Action's ``valid_for_item`` method. The Plugin Runtime :::::::::::::::::: .. topic:: How a plugin is activated 1. The plugin module is imported into Kupfer. If an error occurs, the loading fails and the plugin is disabled. If the error raised is an ImportError then Kupfer report it as a dependency problem. 2. Kupfer will initialize a ``kupfer.plugin_support.PluginSettings`` object if it exists (see next section) 3. Kupfer will call the module-level function ``initialize_plugin(name)`` if it exists. 4. Kupfer instantiates the declared sources and actions and insert sources, actions, content decorators, action generators and text sources into the catalog. .. topic:: When a plugin is deactivated When the plugin is disabled, the module-level function ``finalize_plugin(name)`` is called if it exists. [It is not yet final whether this function is called at shutdown or only when hot-unplugging plugins.] kupfer.plugin_support ::::::::::::::::::::: This module provides important API for several plugin features. PluginSettings .............. To use user-settable configuration parameters, use: .. code:: python __kupfer_settings__ = plugin_support.PluginSettings( { "key" : "frobbers", "label": _("Number of frobbers"), "type": int, "value": 9, }, ) Where ``PluginSettings`` takes a variable argument list of config parameter descriptions. The configuration values are accessed with ``__kupfer_settings__[key]`` where ``key`` is from the parameter description. Notice that ``__kupfer_settings__`` is not updated with the user values until the plugin is properly initialized. ``PluginSettings`` is read-only but supports the GObject signal ``plugin-setting-changed (key, value)`` when values change. Supported parameter types: ``str`` Simple string value that used Entry for enter value. When addidtional parameter ``"multiline": True`` is provided, multiline TextView is used in GUI to enter value. Setting can provide ``alternatives`` - list of possible values to choose. Alternatives may by simple list of strings - then value displayed is equal to value used internally, or as list of tuples (, ). In this case GUI use ComboBox widget. Setting can provide ``helper`` that determine how value is entered in preferences dialog. Supported helpers are: ``choose_directory`` and ``choose_file``. ``alternatives``, ``multiline`` and ``helper`` can't be use together. ``int`` Allow user to enter numeric value. Additional parameters: ``min`` and ``max`` can be provided to limit entered value. ``bool`` Use checkbox for parameter. ``list`` Setting value is list of strings. Additional parameter ``helper`` must be provided to determine how values are entered. For now only supported is ``choose_directory`` helper that allow user to select one or more directories. ``plugin_support.UserNamePassword`` Form used to enter user credentials. check_dbus_support and check_keyring_support ............................................ ``plugin_support`` provides the convenience functions ``check_dbus_support()`` and ``check_keyring_support()`` that raise the appropriate error if a dependency is missing. Alternatives ............ Alternatives are mutually exclusive features where the user must select which to use. Each category permits one choice. .. topic:: Categories of Alternatives :``terminal``: the terminal used for running programs that require terminal :``icon_renderer``: method used to look up icon names :``editor``: editor used by *Edit* action Each category has a specific format of required data that is defined in ``kupfer/plugin_support.py``. A plugin should use the function ``kupfer.plugin_support.register_alternative(caller, category_key, id_, **kwargs)`` to register their implementations of new alternatives. The arguments are: .. topic:: ``register_alternative(caller, category_key, id_, ** kwargs)`` :``caller``: the name of the calling plugin, is always ``__name__`` :``category_key``: one of the above categories :``id_``: the plugin's identifier for the alternative :`kwargs`: key-value pairs defining the alternative ``register_alternative`` is normally called in the plugin's ``initialize_plugin(..)`` function. .. topic:: Fields requried for the category ``terminal`` :``name``: unicode visible name :``argv``: argument list: list of strings :``exearg``: the execute-flag as a byte string (``""`` when N/A) :``desktopid``: the likely application id as a string :``startup_notify``: whether to use startup notification as boolean .. topic:: Fields required for the category ``icon_renderer`` :``name``: unicode visible name :``renderer``: an object with an interface just like ``kupfer.icons.IconRenderer`` .. topic:: Fields requried for the category ``editor`` :``name``: unicode visible name :``argv``: argument list: list of trings :``terminal``: whether to launch application in terminal as boolean Plugin Packages, Resources and Distribution ::::::::::::::::::::::::::::::::::::::::::: A plugin is a Python module–either a single python file or a folder with an ``__init__.py`` file (a package module). In the latter case, the whole of the plugin can be defined inside ``__init__.py``, or it can be split into several modules. Kupfer will look for all the description variables (like ``__kupfer_name__``) in ``__init__.py``. .. topic:: Plugin-installed custom icons A package module may include custom icons as .svg files. The icon files must be declared in a file inside the python package called ``icon-list``. * Each line is a tab-separated field list, with the icon name in the first column and the filename (relative to the plugin package) in the second column. * Lines can be commented with a leading ``#`` * If a literal ``!override`` appears in the third column, the icon is installed even if it overrides the currently used GTK icon theme. Plugins may be installed into any of the ``kupfer/plugins`` data directories. Package modules can also be installed and used as ``.zip`` files, so they too can be distributed as single files. Example Plugins =============== I want to specifically highlight certain files in Kupfer that are good to read as examples. + Custom Leaf and Action: the common case of creating a custom ``Leaf`` type and defining its default ``Open`` action, see ``kupfer/plugin/notes.py`` + Content decoration: making content for objects, see ``kupfer/plugin/archiveinside.py`` (*Deep Archives* plugin) + Asynchronous error reporting: see ``kupfer/plugin/volumes.py``, action *Unmount* Reference to the ``kupfer`` Package =================================== There are several modules inside the ``kupfer`` package that a plugin can reuse. .. topic:: ``kupfer.config`` .. .. topic:: ``kupfer.obj.representation`` This module does not need to be imported just to implement the interface it defines. ``TextRepresentation`` ``get_text_representation`` If a Leaf has a text representation (used for copy-to-clipboard), it should implement this method and return a string. ``UriListRepresentation`` ``get_urilist_representation`` If a Leaf has a uri-list representation (used for copy-to-clipboard), it should implement this method and return a list of strings. .. topic:: ``kupfer.obj`` ``kupfer.obj`` includes the basic objects such as ``Leaf``, ``Action``, ``Source`` etc. ``FileLeaf``, ``AppLeaf``, ``TextLeaf`` etc. The basic re-usable types live here ``OperationError`` Exception type for user-visible errors in action execution. Raise ``OperationError`` with a unicode localized error message inside ``Action.activate`` to notify the user of a serious error. Specialized versions exist in ``kupfer.obj.exceptions``: Such as ``NotAvailableError(toolname)``, ``NoMultiError()`` Other, rarely used object should be imported from kupfer.obj sub-packages, ie: ``kupfe.obj.contacts`` Module provide leaves definition for contacts (emails, im etc) that can be used in plugins supporting email clients and similar software where is some kind of "address book". Contact leaves can be grouped. ``kupfe.obj.helplib`` ``PicklingHelperMixin`` helper for save and load object state ``FilesystemWatchMixin`` allow active monitoring file changes and update objects state ``kupfe.obj.fileactions`` Actions operating on files (``Open``). Usually not need to be used in plugins. ``kupfer.obj.hosts`` Define ``HostLeaf`` and ``HostServiceLeaf`` than can be used for define service on given host (ie. ssh, www etc). This leaves can be grouped by host. .. topic:: ``kupfer.runtimehelper`` Module provide support for async results. .. topic:: ``kupfer.support.datatools`` Caching object and decorators. ``LruCache`` Least-recentrly-used cache with defined max size. ``simple_cache`` Function decorator that remember only one last result and call wrapped function when argumets was changed. ``evaluate_once`` Function decorator that call wrapped function once and always return the same result. .. topic:: ``kupfer.support.fileutils`` Support function related to files and directories. .. topic:: ``kupfer.support.kupferstring`` Kupfer and python internall use unicode strings. Files, command results etc may use other text representation (bytes). When you handle byte strings that is text, you must convert it to unicode as soon as possible. You only know the encoding depending on the source of the byte string. ``tounicode`` decode UTF-8 or unicode object into unicode. ``tolocale(ustr)`` coerce unicode ``ustr`` into a locale-encoded bytestring. ``fromlocale(lstr)`` decode locale-encoded bytestring ``lstr`` to a unicode object. ``localesort`` sort collection of string in locale lexical order. .. topic:: ``kupfer.support.pretty`` Methods than can be used for debugging - logging: ``print_info``, ``print_debug``, ``print_exc`` and ``print_error``. Module also define ``OutputMixin`` that may be included in action, source and leaves objects and provide methods like ``output_info``, ``output_exc``, ``output_debug`` and ``output_error``. .. topic:: ``kupfer.support.system`` System related functions like ``get_hostname``, ``get_homedir`` and ``get_application_filename``. .. topic:: ``kupfer.support.task`` Allow run some task in background. .. topic:: ``kupfer.support.textutils`` Methods for text parsing / extracting. .. topic:: ``kupfer.support.validators`` Check if text is valid email, url etc. .. topic:: ``kupfer.support.weaklib`` Define some object and function useful to create callback with weak references, e.g. ``dbus_signal_connect_weakly``, ``gobject_connect_weakly``. .. topic:: ``kupfer.ui.uiutils`` ``show_notification(title, text='', icon_name='', nid=0)`` Show a notification. If a previous return value is passed as ``nid``, try to replace that previous notification. Returns a notification identifier, or None if notifications are not supported. ``show_text_result(title, text, ctx)`` Open window with text result. .. topic:: ``kupfer.launch`` ``spawn_async(argv)`` Spawn a child process, returning True if successfully started. ``spawn_in_terminal(argv)`` Run commands in terminal. ``show_path(path)`` .. ``show_url(url)`` Display with default viewer for ``path`` or ``url``. ``get_display_path_for_bytestring(filepath)`` ``get_display_path_for_bytestring`` returns a user-displayable text representation as a string. .. topic:: ``kupfer.core`` The module ``kupfer.core`` can not be used by plugins. .. vim: ft=rst tw=72 et sts=4 sw=4 .. this document best viewed with rst2html kupfer-328/Documentation/VersionHistory.rst000066400000000000000000002247541500175051100212470ustar00rootroot00000000000000NEWS for kupfer =============== kupfer v328 (2025-04-xx) ------------------------ + Other changes: + Use modern Ayatana Indicators; require gir1.2-ayatanaappindicator3-0.1; by @N0rbert + Gui: add dark border around main window; this improve visibility Kufper window on bright background + Plugins: + Updated: - *Audacious*: start app on action when not running - *Textutils*: ask user for option in "join lines" actions. - *Trash*: ask user for confirmaton when moving files to trash + Fix + Fix toggle appindicator icon (not show after hide) + Fix invalid handle KUPFER_WINDOW_TYPE_HINT setting + Fix recognize urls with % characters + Fix misleading message when starting Kupfer without install. + Do no store content of Directory and Files sources in disc cache; refres on startup. + Prevent confirm dialog to show behind main Kupfer window. + Dev: + Fix pyxdg dependency in pyproject + Prefer os.scandir over listdir + Add finish_callback to launch.spawn_async/spawn_async_raise + Plugin can get some input from user by configurable dialog + Disable typequard protocols checking; add warn about using kupfer.py + Fix some errors reported by linters; format code + Replace depricated pkgutil.find_loader that will gone in Python3.14. + Use argparse for command line arguments. kupfer v327 (2024-04-28) ------------------------ + Fix: + Fix random crashes reported on Arch and Python 3.11.8 probably caused by broken support for multi display/monitor support. Close: #176 + Fix returning to previous leaf in browser (left key action); when leaves come from action result there is not valid parent, so searching for it is waste of time. + Fix browser window placement; especially after text box is show/hide. + Fix random crashes on startup related probably to too fast application start. + Plugins: + New: - *recoll*: query Recoll full text search system + Fixed: - *tmux*, *libvirt* - fix names + Dev: + Minor fixes (types) kupfer v326 (2024-02-24) ------------------------ + Fix: + Do not lowercase entered search term when passing it to sources that create text leaves. Sources like *Shell Commands* and *Text* now get exact text that user entered/select. Close: #175 + Plugins: + Updated: - *clipboard*: handle errors on creating file leaves from text when text is not valid file path. + Dev: + Minor changes related to handling / logging errors. kupfer v325 (2024-01-21) ------------------------ + Fix: + Fix syntax error that sometimes happen on plugin activation. Close: #173 + Fix missing translations in *websearch* and *qrcode* plugins. kupfer v324 (2024-01-07) ------------------------ + New features: + Allow user to choose how trim displayed text - add new options in preferences "Text ellipsization". Close: #98 + "Actions in first panel" - experimental feature that allow user to run actions by selecting it in first panel and then select target object in next panel. Require enabled "Kupfer Actions" plugin. Close: #77 (maybe). + Fix: + Fix validator for URLs: better support for URLs without FQDN and netloc. + Show only first line of multi-line descriptions. Whole description is in tooltip. Close: #116 + Fix refreshing sources cache on start - sources are force refreshed on plugin enabled and on Kupfer start when cache not contains items. This prevent bizarre behavior when Kupfer is restarted and sources depend on some unavailable files. + Fix return to parent leave - try to load all leaves until parent leave is found instead of go to first leave. + Plugins: + New: - *Kupfer Actions*: put actions into first panel. + Updated: - *clipboard*: fix broken description for URL and file path; handle errors when text is recognized as file path but is broken. - *core*: leaves with can text and uri representation can be used in "OpenTextUrl" action. - *ssh_hosts*: add text representation in form of ssh://host... so now can be opened i.e. in external applications. Add new action "Send file to..." - send file/directory to remote host. - *websearch*: new action "Search..." - search with default engine; user do not have to select search engine, default can be configured or is take from "user search engines" with DDG as fallback. + Dev: + Fix loading plugin configuration that base on `ExtendedSetting`. For now no one plugin use it anyway... + Minor code cleanup kupfer v323 (final, 2023-11-26) ------------------------------- (Changes since v322) + New features: + For grouping leaves (like hosts, contacts) add "copy to clipboard" action for each slot (email, adress, etc). Close: #169 + After launch some action for leave next time this action get some bonus that make it higher on the list. Also, this action get (smaller) bonus for each same type of leaves. + URL-s can be opened with selected application ("Open with..." action) + User can configure preferred text editor; list is loaded from application registry. + List of terminals is loaded from application registry (applications with "terminal" tag). Some terminals are still preconfigured. + In plugins settings user can choose files and directories by appropriate dialog instead of type path manually. + Kupfer can more frequent refresh items in background and cache result; this make searching and browsing faster. + If more than one action have the same accelerator pressing key navigate between them; previously first action was activated. + Hosts and services have additional aliases "service:hostname"; this allow user to fast find items by entering e.g. "sshmyserverhostname". + Add text representation to leaves representing songs (*rhythmbox* and *audacious* plugins) and leaves representing services; user can i.e. copy it to clipboard or use whenever text is acceptable. + Fix: + Make Kupfer window rounded again. Close: #83 + After repoen Kupfer window, if current leaf has qf_id (leaf like selected dir, file, etc), update this leaf (research) and show current value. Close: #172 + Fix error on group merge when source was updated in background. + Fix "mark as default" action broken in beta1. Close: #170 + Add some missing icons (stock_person, stock_mail) + Strip whitespaces from url-s when calling "show url" + Do not decorate leaves in third panel as there is no way to "enter" to it. + If actions have the same name, make it unique by adding plugin name; previously module name was added. + Improve detecting URLs, files path, and emails addresses in text. + Fix not working "select clipboard text" accelerator. + Fix presenting first line from Text leaves: now really show first line. + Browser track history of selected leaves and allow return to parent leaf instead of top of list. + Make sure that file opened in plugins are closed after load. + Plugins: + New: - *Aria2*: download files be remote aria2 instance. - *Librewolf*: load bookmarks from Librewolf web browser - *NetworkManager*: manage network connections - *Screenshot*: take desktop screenshot using 'scrot' or 'flamegraph'. - *Show QRCode* plugin: generate qrcodes from text. - *Textutils*: various tools that convert, format and generate text content (i.e. generate random strings, convert case, encode base64, format json and xml). - *Tmux*: support tmux session and tmuxp workplaces. - *Tracker3*: full-text search in Tracker 3 application. - *Vim*: recent files opened in vim and quick access to configured VimWikis. - *Zoxide*: load most used directories from zoxide database. + Updated: - *Application*: + Add additional aliases do application: executable name and original (English) name. + New action "Open With...": open file with one of application that support given file type. + New action "Launch here": start application in selected folder. + User can enable loading additional application aliases. This make possible to select application by application comment, keywords or generic name but may have impact on overall performance. - *Apt*: add new actions: "Search for file in packages..." and "Browse packages.debian.org". - *Archive manager*: user can select 7zip (7z or 7za) to use instead of file-roller. - *Audacious*: use D-Bus for interaction with audacious. - *Chromium*: monitor and load changes in bookmarks. - *Clipboard*: detect URLs and files path in clipboard items and selected text. - *Dictionary*: add support for GoldenDict - *Favorites*: allow user to add to favorite only leaves than can be added. - *File actions*: new action "Edit file content" that open configured text editor - *Image*: detect images files by mime type, not by extension. - *Libvirt*: monitor state of virtual machines; fix icons - *Rhythmbox*: fix errors when no mpris module available. - *Session gnome*, *Session lxqt*, *Session xfce*: user must confirm "logout" and "shutdown" actions - *Session xfce*: load favorite applications defined in Whisker Menu. - *Show Text*: bring back "Large Type" action. Close: 91 - *Ssh_hosts*: + Fix loading `Match` rules from ssh config file. + Fix monitoring for configuration changes. + Load and use host name from ssh .config file + Update icons - *Textfiles*: + New action "Copy content" (with "C" accelerator): copy content of text file to clipboard + "Write To" action allow user to enter destination file name. + Fix selecting destination directory + Fix encoding on write files - *Thunar*: add "Open Trash" action - *URL Actions*: check response status code (accept only 2xx); if there is not exact filename in response or url, try to guess filename with extension by url and content type. - *Web Search*: allow user to define custom search engines by provide appropriate URLs. - *Volumes*: + New "Mount" action + Separate "Eject" and "Unmount" action. - *Wikipedia*: + User can configure more than one language for Wikipedia search; action "Search in Wikipedia" allow user to select Wikipedia language. + Add "S" accelerator for "Search in Wikipedia" action. - *Windows*: better detection of Kupfer windows. - some plugins now report error (import error) when required command or application is missing in system. + Dev: + *BREAKING*: refactor & modernize code; Python 3.9+ is now required. + *BREAKING*: reorganise and rename some modules, functions. Split long files into smaller. + *BREAKING*: there is no backward compatibility with old/external plugins. + Simplify, optimize code; remove legacy and duplicated code; drop unnecessary list creation (use iterators whenever possible); remove redundant caching. This improve performance and memory usage. + Add types to most core objects. + When run in "debug" mode, when available, use `typeguard` for checking types. *This may slowdown Kupfer*. + Add `pyproject.toml` file. + Refactor ui: remove deprecated components, fix layout. + Upgrade WAF v 2.0.25; fix & update wscript files. + Add `icons.get_gicon_from_file`: quick load gicon from file. + Add `kupfer.support.validators` with some useful functions (validate URLs, etc). + Add some debugging tools to debug.py (ic, etc). + `FileLeaf` accept Path object. + `FilesystemWatchMixin` provide function to monitor single files. + Add some caching for icons (esp. `ComposedIcons`) + Add simpler caches in `kupfer.support.datatools` and some statistics to existing. Add `get_or_insert` method to LruCache. + Plugin preferences may use list of string (type list) and helpers (select directory, file). For int-type preferences can be set min and max value. See *zoxide*, *firefox* plugins for example use. + Dialog like preferences are destroyed on close. + Action may reload leaves list in browser as result of execute. See *Volumes* plugin and "Mount" action. + Refresh action do not duplicate sources in browser. + Sources can define minimal interval between background load data (`source_scan_interval`). `mark_as_default` method have new parameter `postpone` (default False); when true, mark source to update in next rescan campaign but not clear cache. + Purge mnemonics remove first oldest entries. + Plugins can register "favorite" items. See *Session XFCE* plugin. + `AsyncFileResult` wait limited time for file result. + Add some tests. + Add new dbus method - FindObject. + Cache `KupferObject` `repr` value + Colors in console output. + Update translation: pl kupfer v323-rc -------------- (not released) + Fix: + After repoen Kupfer window, if current leaf has qf_id (leaf like selected dir, file, etc), update this leaf (research) and show current value. Close: #172 + Fix error on group merge when source was updated in background. + Plugins: + Updated: - *ssh_hosts*: fix loading `Match` rules from ssh config file. + Dev: + Fix types. + Add new dbus method - FindObject. kupfer v323-beta3 ----------------- + Fix: + Fix detecting ssh configuration changes in `ssh_hosts` plugin + Plugins: + Updated: - *applications*: user can enable loading additional application aliases. This make possible to select application by application comment, keywords or generic name but may have impact on overall performance. + Dev: + Simplify URL validators kupfer v323-beta2 ----------------- + New features: + For grouping leaves (like hosts, contacts) add "copy to clipboard" action for each slot (email, adress, etc). Close: #169 + After launch some action for leave next time this action get some bonus that make it higher on the list. Also this action get (smaller) bonus for each same type of leaves. + URL-s can be opened with selected application ("Open with..." action) + Fix: + Fix "mark as default" action broken in beta1. Close: #170 + Add some missing icons (stock_person, stock_mail) + Strip whitespaces from url-s when calling "show url" + Do not decorate leaves in third panel as there is no way to "enter" to it. + Plugins: + New: - *textutils*: various tools that convert, format and generate text content (i.e. generate random strings, convert case, encode base64, format json and xml). - *librewolf*: load bookmarks from Librewolf web browser + Updated: - *ssh_hosts*: load and use host name from ssh .config file; update icons - *libvirt*: fix icons - some plugins now report error (import error) when required command or application is missing in system. + Dev: - Simplify caching icons/gicons - Cache `KupferObject` `repr` value - Fix types - Colors in console output. kupfer v323-beta1 ----------------- `Python upgrade release: something may be broken.` + New features: + User can configure preferred text editor; list is loaded from application registry. + List of terminals is loaded from application registry (applications with "terminal" tag). Some terminal are still preconfigured. + In plugins settings user can choose files and directories by appropriate dialog instead of type path manually. + Kupfer can more frequent refresh items in background and cache result; this make searching and browsing faster. + Make Kupfer window rounded again. + If more than one action have the same accelerator pressing key navigate between them; previously first action was activated. + Hosts and services have additional aliases "service:hostname"; this allow user to fast find items by entering e.g. "sshmyserverhostname". + Leaves representing songs (*rhythmbox* and *audacious* plugins) and leaves representing services have text representation, so user can i.e. copy it to clipboard or use whenever text is acceptable. + Fix: + If actions have the same name, make it unique by adding plugin name; previously module name was added. + Improve detecting URLs, files path, and emails addresses in text. + Fix not working "select clipboard text" accelerator. + Fix presenting first line from Text leaves: now really show first line. + Browser track history of selected leaves and allow return to parent leaf instead of top of list. + Make sure that file opened in plugins are closed after load. + Plugins: + New: - *NetworkManager*: manage network connections - *Tmux*: support tmux session and tmuxp workplaces. - *Zoxide*: load most used directories from zoxide database. - *Vim*: recent files opened in vim and quick access to configured VimWikis. - *Tracker3*: full-text search in Tracker 3 application. - *Show QRCode* plugin: generate qrcodes from text. - *Aria2*: download files be remote aria2 instance. - *Screenshot*: take desktop screenshot using 'scrot' or 'flamegraph'. + Updated: - *Apt*: add new actions: "Search for file in packages..." and "Browse packages.debian.org". - *Application*: + Add additional aliases do application: executable name and original (English) name. + New action "Open With...": open file with one of application that support given file type. + New action "Launch here": start application in selected folder. - *Web Search*: allow user to define custom search engines by provide appropriate URLs. - *Audacious*: use D-Bus for interaction with audacious. - *Wikipedia*: + User can configure more than one language for Wikipedia search; action "Search in Wikipedia" allow user to select Wikipedia language. + Add "S" accelerator for "Search in Wikipedia" action. - *File actions*: new action "Edit file content" that open configured text editor - *Volumes*: + New "Mount" action + Separate "Eject" and "Unmount" action. - *Textfiles*: + new action "Copy content" (with "C" accelerator): copy content of text file to clipboard + "Write To" action allow user to enter destination file name. + Fix selecting destination directory + Fix encoding on write files - *Show Text*: bring back "Large Type" action. - *Chromium*: monitor and load changes in bookmarks. - *Dictionary*: add support for GoldenDict - *libvirt*: monitor state of virtual machines - *Archive manager*: user can select 7zip (7z or 7za) to use instead of file-roller. - *Session gnome*, *Session lxqt*, *Session xfce*: user must confirm "logout" and "shutdown" actions - *Session xfce*: load favorite applications defined in Whisker Menu. - *Image*: detect images files by mime type, not by extension. - *Rhythmbox*: fix errors when no mpris module available. - *SSH hosts*: fix broken monitoring for configuration changes. - *Windows*: better detection of Kupfer windows. - *Clipboard*: detect URLs and files path in clipboard items and selected text. - *Favorites*: allow user to add to favorite only leaves than can be added. - *Thunar*: add "Open Trash" action - *URL Actions*: check response status code (accept only 2xx); if there is not exact filename in response or url, try to guess filename with extension by url and content type. + Dev: + *BREAKING*: refactor & modernize code; Python 3.9+ is now required. + *BREAKING*: reorganise and rename some modules, functions. Split long files into smaller. + *BREAKING*: there is no backward compatibility with old/external plugins. + Simplify, optimize code; remove legacy and duplicated code; drop unnecessary list creation (use iterators whenever possible); remove redundant caching. This improve performance and memory usage. + Add types to most core objects. + Add `pyproject.toml` file. + Refactor ui: remove deprecated components, fix layout. + Upgrade WAF v 2.0.25; fix & update wscript files. + Add `icons.get_gicon_from_file`: quick load gicon from file. + Add `kupfer.support.validators` with some useful functions; use it in various places. + Add some debugging tools to debug.py (ic, etc). + `FileLeaf` accept Path object. + `FilesystemWatchMixin` provide function to monitor single files. + Add some caching for icons (esp. `ComposedIcons`) + Add simpler caches in `kupfer.support.datatools` and some statistics to existing. Add `get_or_insert` method to LruCache. + Plugin preferences may use list of string (type list) and helpers (select directory, file). For int-type preferences can be set min and max value. See *zoxide*, *firefox* plugins for example use. + Dialog like preferences are destroyed on close. + Action may reload leaves list in browser as result of execute. See *Volumes* plugin and "Mount" action. + Refresh action do not duplicate sources in browser. + Sources can define minimal interval between background load data (`source_scan_interval`). `mark_as_default` method have new parameter `postpone` (default False); when true, mark source to update in next rescan campaign but not clear cache. + Purge mnemonics remove first oldest entries. + Plugins can register "favorite" items. See *Session XFCE* plugin. + `AsyncFileResult` wait limited time for file result. + Add some tests. kupfer v322 ----------- + Update translation: pl + Plugins: + Add support mate-dictionary in *dictionary* plugin by Igor Santos + Fix *Firefox* and *Thunderbird* database connection (closes: #153) + Add support for `file:///` URLs + Add *Firefox tags* plugin + Fix *Thunderbird* plugin - support new database schema + Fix *Thunderbird* plugin - support contact without proper name or other fields (closes: #164) + Add *libvirt* plugin - manage libvirt domains + Add *zeal* plugin - quick search in zeal docsets + Fix *window* plugin - don't break on Wayland, fix switching workspace + Fix segfault on Wayland and newer version of libwnck (closes: #165) + Dev: + Don't embed timestamp in gzip header by kpcyrd + remove some redundant list creation + add missing file names in POTFILES.in kupfer v321 ----------- + Update translations: es, it, pl + Plugins: + Add *WhatsApp Web* by leoen25demayo + Add *Instapaper* by Peter Stuifzand + Add *Pinboard* by Peter Stuifzand + Add *Brotab* by Peter Stuifzand + Fix loading data error in *OpenSearchSource* (closes: #142) + Add *chromium* plugin (port old plugin to Py3) by emareg + In *thunderbird* add support for addressbook in sqlite format + In *XFCE Session* allow configure lock screen command (closes: #146) + Dev: + Fix building distributing tar file (closes: #147) kupfer v320 ----------- + Update translations: es, pl + Fix detecting running gui application, selecting active window and crashes when application was closed (closes #124, #130) + Allow serialize UrlLeaf ans save it as actions (closes #126) + Plugins: + In *Firefox Keywords* provide quick search using '?keyword query' + In *Documents* option for disable checking is file exist before add to list that solve problems when files are in slow/inaccesible locations + Restore *Clawsmail* plugin + Update *VirtualBox* plugin to work with last version + Add *deepdirectories* plugin + Restore *websearch* plugin (closes #127) + In *Firefox* fix openning locked database; fix loading profiles, allow user to select non-default profile by name of path (closes #131) + Add LXQT session suport + Dev: + Update WAF version; use itstool instead of xml2po (closes #125) kupfer v319 ----------- + Fix *Get Parent Folder* to always return a ``FileLeaf`` (not a subclass) + Plugins: + In *Rhythmbox*, always use song uris for enqueueing tracks (fixes an issue with legacy encoded file paths). + In *Rhythmbox*, improve error reporting on errors in *Get File*. + Add *Prefer Dark Theme* that allows you to flip this GTK setting just for Kupfer kupfer v318 ----------- + Refactor some of the UI so that it uses composition instead of inheritance for Gtk widgets. No functional changes intended (except given below). + The result list for the third pane now sticks to the right side. + Plugins: + In *Rhythmbox*, keep the cache even if the player is not running (#75). + In *Rhythmbox*, fix a bug where songs would sometimes be skipped in the *Songs* catalog. + In *Media Player Control*, add item *Pause All* kupfer v317 ----------- + When an input method's preedit is active, backspace, return, arrows and other keys are now reserved for the input method (ibus-mozc was tested). + All exceptions from content decorators from plugins are now caught and logged (#73) + Fix remembering “Make (Action) Default for (Object)” when the object is a text or a shell command. + Change so that ``kupfer`` only reads from stdin when called with no arguments and when not started from a desktop file. This should fix issues with starting from autostart or menus in some environments. (#72) + Fix a crash when the *Show Text* window is closed. (#71) + (API) Trying to install a plugin setting key with a reserved name now raises an exception. + Plugins: + In *Recent Documents*, fix an exception with filenames in unknown encoding + In *Tracker*, fix an exception with malformed ``.savedSearch`` files. kupfer v316 ----------- + Bundle an icon used for windows and workspaces. Based on an icon in Adwaita. + Add two more default terminal alternatives, exo-open and x-terminal-emulator. + Add a few more alternatives in the drop down for large icon size + Plugins + In *Rhythmbox*, look for more album art filenames in the same directory + In *Firefox Keywords*, allow copying them to clipboard (Ctrl + C) + In *Text Files*, fix *Write To* and *Append To* + In *Tracker* support a location restriction for ``.savedSearch`` files. kupfer v315 ----------- + Fix an issue with launching X applications in wayland (#65) + Fix an exception on text input “file://” + Plugins + In *Volumes*, show a notification on successful unmounts (#64) + In *Documents* you can now opt out applications of having their recent documents listed inside. + In *Rhythmbox*, use less memory for storing the library cache + In *Rhythmbox*, sort albums of an artist primarily by year, then title. + In *Shell Commands*, fix the icon name of a command kupfer v314 ----------- + Replaced file action *Reveal* (file manager plugins do this better) with *Get Parent Folder* which has the default accelerator *P* and thus is very handy for navigation. + Fix so that right arrow can enter directories even in text mode + Allow **Action Accelerators** to use more than just A-Z keys + Misc fixes to start **wayland compatibility**. All uses of Wnck now gracefully disable when not applicable. + Wnck is now technically optional, still recommended for best experience in X. + Tweak arrangement of items in the first page of the preferences window, and add a few more icon size alternatives. + Tweak the multiple objects icon to look at bit better + Recognize pasted file:// uris as files + Plugins + New plugin for file manager *Nemo* + Fix *Rhythmbox* to not clear the queue when playing a single song + Fix *Rhythmbox* to handle missing files gracefully + Fix *Rhythmbox*, *Audacious* to not clear cached library/playlist when the respective program exits kupfer v313 ----------- + **Action Accelerators**: every action can have a configurable accelerator key that allows activating it directly. + Changed some default shortcuts: + *Select ‘Selected Text’* now uses Ctrl + G + *Switch to 1st Pane* now has no binding by default + Fix monitor placement in Unity (#45) + The preferences window now loads and shows current icon size + The configuration file is now written in sorted order. + Fix a minor visual issue using some themes (padding under match text) + The set keybinding window now has a button to clear the current binding + The result list now has a minimum size depending on the small icon size, so it sizes better for hidpi + Plugins + Handle errors better in *Tracker* and make *Get Tracker Results...* fetch the results asynchronously. + Fix *Dismiss* action in *Getting Things GNOME* plugin. Thanks @khurshid-alam for the patch! + Another *Create Task* action was added to GTG (an action on the app itself). + *Audacious* now refreshes when the program starts + *Attach in Email To* in *Thunderbird* is now not allowed on directories + *Notes* now has *(Note) → Append → (Text)* which is a reversal of an existing action + *Append To Note* now works for kzrnote as well kupfer v312 ----------- *There are some lingering open bugs for desktop environments that are not my main desktop. Kupfer only becomes what everyone puts in, so if you can help fixing bugs related to your environment, please come to our github page.* + Add several new possible accelerator keys in the main kupfer interface: + *Select Pane 1, 2, 3* + *Select Clipboard Text*, *Select Clipboard File* + Configure them in the keyboard tab in preferences + ``Keybinder`` which is optional is now also treated as such by configure + (API) Minor bugfix so that async Tasks don't need to set a name + Plugins: + Handle errors better in the *Trash* plugin + Fix the way *Rhythmbox* starts playback of multiple songs + Add action *Get File* on *Rhythmbox* songs kupfer v311 ----------- + Work even if ``Keybinder`` is not installed. Also added environment var if you need to disable it, even when it is installed. + (API) Actions can now post sources as “late results”. (*Get Notes Search Results...* now uses this.) + (API) Add ``ShowHide``, ``ShowHideOnDisplay`` to D-Bus interface. + Plugins + In *Notes*, retry opening notes for slow activation in Gnote/Tomboy + Fix task sort order in *Getting Things GNOME* + *Rhythmbox* and *Notes* refresh more often (when their programs restart) kupfer v310 ----------- + Speed up ranking objects a bit when the catalog is large + Show a nicer message when no action matches the search + Using AppIndicator is now an option (and optional dependency) + Plugins: + Add *Firefox Keywords* to use configured keywords as search engines + In *Applications* show more apps in *Open With...* + In *Applications* add new action *Reset Associations* + Reintroduce the *Rhythmbox* plugin, which allows searching the library, playing and enqueuing songs. General Play/Pause/Prev/Next is in the *Media Player Control* plugin already. + Reintroduce the *Getting things GNOME* plugin. + Reintroduce the *Devhelp* plugin. + (API) Allow Sources and TextSources to customize their no match and waiting for search text. + (API) Allow Actions to use both the catalog and an extra source for the indirect object kupfer v309 ----------- + Change Kupfer's D-Bus name and interface and object path. The old names are still active, but the migration period will be very short because we are in a rapid change phase. New names use the domain ``io.github.kupferlauncher``. + Change the no match icon to use transparency instead of ugly pixelation + Change the default text to simply be *Type to search*, which is shorter and simpler. + Folding of *ß* has been restored, so that a search for *ss* will match it. + Plugins: + In *Notes*, some actions are now asynchronous and/or have better error reporting. + In *Notes*, update for kzrnote 0.2 + Enable *Quicksilver Icons* by default kupfer v308.2 ------------- + Fix showing the result list in KWin (#47) with a specific workaround + Plugins: + Fix *Shell Commands* so that they inherit the parent environment + Remove *GNOME Session Management* from the set enabled by default kupfer v308.1 ------------- + Fix widget style/space issue that was especially apparent in the GTK theme Adapta. kupfer v308 ----------- Be sure to check out the settings in the *Applications* plugin in this release. The web site now also shows a language selection for the user’s guide, so that the translations are readily available. + Fix a slight wobble in the result list’s position by making sure the description label stays the same size + Fix how the star and arrow at the right side of the result list line up + Plugin API: Add methods ``get_gfile`` and ``is_content_type`` to ``FileLeaf`` + Prerender and install fixed icon sizes + Plugins: + In *Applications* change how it filters applications based on desktop type. The new default desktop type is blank, and this should pick up the right desktop environment automatically. Make the *Use Desktop Filter* toggle actually work. + Speed up recent documents slightly by caching an intermediate result + In *Documents* also recognize more file extensions when sorting libreoffice documents to the right app. + Remove action *Send in Email To* from *Default Email Client*, since it is unlikely to work for the default ``mailto:`` URL handler. + Rename the remaining action *Compose Email* → *Compose Email To* in default mail, for consistency. kupfer v307 ----------- Released Wednesday, 15 feb 2017 + Fix a bug with disambiguation of action names + Stop merging contacts by full name equality + Accept dropped text and files on Kupfer’s window + Fix API to not ask for content-decoration of a leaf with existing content + Plugins + Reintroduce *Pidgin* + Reintroduce *Shorten Links* + In *Thunderbird*, rename compose email actions to differentiate them, *Compose Email To*, *Compose Email With*. + In *Image Tools*, show an error if ``jpegtran`` is not found + In *Audacious* add runnable item *Show Playing* + Fix *Wikipedia* to use https + In *Documents*, match more applications to their own recent documents, notably LibreOffice + Run copy from *File Actions* asynchronously + Add a new help page, for plugin *Thunar* kupfer v306 ----------- Released Monday, 13 feb 2017 + Fix a compatibility issue with waf wscripts for non UTF-8 locales + Fix plugin info loading from .zip files. + Fix exception on filenames that could not be represented in unicode. They are silently skipped in directory listings for now. + Plugins: + Fix *Deep Archives* to skip directories named with archive extensions + Fix ``=help`` in *Calculator* + Revert the hack that replaced ``,`` with ``.`` in numbers in *Calculator* + Add file action *Attach in Email To...* in *Thunderbird* + Add text action *Compose Email* in *Thunderbird* + Fix *Thunderbird* to read unicode correctly from the address book. + Reintroduce places (GTK bookmarks) in *Documents* kupfer v305 ----------- Released Saturday, 11 feb 2017 + Tweak how the selected pane is drawn. We still haven't arrived at a theme and color-independent way to do this; Gtk 3 drawing and styling knowledge is welcome in github. + Fix some drawing bugs in the main kupfer window by removing some old erronous overrides of the widget size calculation. + Add attribute ``source_use_cache`` to the API for sources + Plugins: + Add new plugin *Media Player Control* for basic control of any mpris-capable player. This plugin is experimental. + Fix bugs in *Volumes* so that it works well under Gtk 3 + Fix the Copy button in the *Show Text* result. The text is also now editable. + *Applications* now only proposes apps in *Open With...* that support opening files. (Add ``%U`` or similar to your application’s command line in the .desktop file, if it's missing.) + Stop enabling *File Actions* by default (copy is not async with Gtk 3 so it is now defective). Please use the Thunar file actions instead. kupfer v304.1 ------------- Released Thursday, 9 feb 2017 + Plugins: + *Clipboard:* add back *Clipboard Text* that was removed in v304 by mistake kupfer v304 ----------- Released Wednesday, 8 feb 2017 + Clean up the distributable tarball; extra content like oldplugins is now only in the repository and not in the tarball. + Fix double-clicking on the Kupfer window + Increase default result list length slightly + Plugins: + Reintroduce *Firefox Bookmarks* + *Clipboard:* attempted fix for a reported stack overflow + *Clipboard:* reintroduce *Clipboard File(s)* proxy object + Fix *File Actions* so that it works (for Gtk 3) kupfer v303 ----------- Released Tuesday, 7 feb 2017 GNOME's hosting of the project is now officially at an end; mailing list and repo there are gone, we are on github now. Thank you GNOME and see you next time! + Completed port to pygi by removing ``pygtkcompat`` + Build config will now look for ``python3`` if ``python`` is too old. + Plugins: + Reintroduce *Locate* kupfer v302 ----------- Released Monday, 6 feb 2017 + Fix sending files from the command line + Fix installation of help pages, new standard location ``/usr/share/help`` and including a file that was missing. + Fix --list-plugins and update man page. + Patch the included waf so that it now builds using Python 3 + Plugin *Applications*: Add MATE as alternative + Fix interface to not draw preedit field at all + Fix *Copy to Clipboard* action. kupfer v301 ----------- Released Monday, 6 feb 2017 A new decade of Kupfer + Fix loading plugin list for Python 3.6 + New: ? starts free text input + New: ? text prefix gets live full text search results (plugin Tracker) + Plugins + reintroduce tracker + fix audacious + fix dictionary + drop multihead (updated, but needs testing) + drop gnome-terminal (obsolete) kupfer v300 ----------- Released Sunday, 5 feb 2017 A new decade of Kupfer dawns! + Port Kupfer to Python 3 + Port Kupfer to Gtk 3 and GObject Introspection + Reindent the codebase to 4 spaces + Regard this release as a preview, it may have bugs + We have a github organization, new webpage, and will need maintainers to hold the wheel into the next decade + Breaking changes: + Plugin configs are reset + Old ``kfcom`` can no longer be parsed + Some changes in the Plugin API + Many plugins are obsolete and have been dropped. Some old plugins can be updated, but I in general Kupfer wants to explore new kinds of interaction, and not necessarily collect all possible plugins in-tree + Gtk theming has changed + New features: + Use CSS for Gtk 3 themes + Implemented using 2010s technology + Dependencies: + This release requires ``Keybinder-3.0`` (using G-I), that will be relaxed later .. role:: lp(strong) kupfer v208 ----------- Released Friday, 1 June 2012 * Fix bug with nonexisting catalog directories (Karol) (:lp:`1000980`) * Fix sending to many with Thunderbird (Karol) (:lp:`955100`) * Fix history file for OpenOffice/LibreOffice (Karol) * *Audacious* plugin: Work with Audacious 3 (Ulrik) * Localization updates: + cs, Marek Černocký + es, Daniel Mustieles + fr, Alexandre Franke, Bruno Brouard + ru, Nikolay Barbariyskiy + sl, Matej Urbančič kupfer v207 ----------- Released Sunday, 26 February 2012 * Documentation translated to French by Bruno Brouard * New translation to Brazilian Portuguese by Djavan Fagundes * New translation to Hungarian by SanskritFritz * Handle large text objects a bit better * Introduce proxy objects *Clipboard File* and *Clipboard Text*. These objects are implemented in the *Clipboard* plugin, just like the *Selected Text* object which has changed home to this plugin. Accordingly, deactivating the clipboard plugin will deactivate these proxies. * Support copying and pasting files from/to the clipboard, which allows much easier integration with file managers. * Add an information text detailing which keyring backend is used to store passwords, visible in the user credentials dialog. * *Vim:* Expand the vim plugin to use a helper process to track running server instances of (G)Vim. Each running session is exported as an object, and most importantly, files can be opened in a session using the action *Open With*. * *Multihead Support:* This new plugin will start the "keyboard shortcut relay" service on additional screens, if it is needed. It is active by default, and does not do anything on configurations with a single X screen. * *Send Keys:* Allow sending key sequences using comma trick. * *Thunar:* Add action *Symlink In...* * *Quicksilver Icons:* New plugin with a few icons from Quicksilver * Use themable custom icon names ``kupfer-execute``, ``kupfer-catalog``, ``kupfer-launch``. Also allow plugins to choose to supply icons when the icon theme lacks them, or always override the icon theme. * Fix passing zero-length arguments to programs (Fabián Ezequiel Gallina) (:lp:`863349`) * *Gmail:* Expose more contact info fields (Adi Sieker, Karol Będkowski) * Add plugin *DuckDuckGo* (Isaac Aggrey) * Add quick note action to *Zim* (Karol Będkowski) * Add *Edit Contact in Gmail* to *Gmail* (Karol) * Fix version detection in *Gajim* (Karol) * *Google Translate:* Since Google no longer provides this API (for free), this plugin is no longer included in Kupfer. * Fix compatibility with dbus-python version 1.0 (:lp:`921829`) * Fix loss of window shape when centering (David Schneider) (:lp:`779845`) * We are now using the format .tar.xz for the distribution tarball. * The git repository and tarball now includes a local copy of waf (1.6.11), unmodified but with unused in Tools/ and extras/ removed. * Localization updates: + (cs) Marek Černocký + (de) Mario Blättermann + (fr) Bruno Brouard + (es) Daniel Mustieles + (hu) SanskritFritz + (pl) Piotr Drąg + (pt_BR) Djavan Fagundes + (sl) Andrej Žnidaršič + (sv) Ulrik kupfer v206 ----------- `The longest changelog ever—the best Kupfer ever?`:t: Released Thursday, 14 April 2011 These are changes since the v205 release. Below this I have included, the full changelog for all the features introduced in v205, since it was not published in whole together with the v205 release. I would like to thank all contributors for patches, bug reports, comments and translations. A special thanks to those who have contributed to the `user documentation`__; it is now complete in both Polish and Spanish. If you like my work with Kupfer, you can support me by donating. There are instructions how to do so on the web page. –ulrik. __ http://kaizer.se/wiki/kupfer/help/ * *Thunderbird:* fix double create email windows (:lp:`747198`) * *Thunderbird:* fix problem with loading contacts (Karol Będkowski) (:lp:`747438`) * Use ``rst2man`` as it was configured (:lp:`747500`) * Reduce runtime memory use for substantially by reimplementing the icon cache (expectations vary btw. 10 to 30 percent). * Prefer gnomekeyring over kwallet, and don't load keyring support if it is not requested by a plugin (:lp:`747864`) * Make the "folder" icon take precedence over "inode/directory" * Fix a regression in *Go To* that would not focus minimized windows. * In *Go To* action, cycle application windows (if they are all on the same workspace). * Fix :lp:`671105`: the user's home is aliased as *Home Folder* and the "lookalike" application is hidden. * Use GTK+ as default icon set, the ASCII icon set remains as a plugin * Fix regression :lp:`749824`, kupfer used a GTK+ 2.20 feature. Kupfer should now run under GTK+ 2.18 (2.16?). GTK+ 2.20 is recommended and needed for full input method support. * Remake ``.desktop`` file parsing to be much more lenient, so that we can launch all applications again. Affected were especially launcher files written by wine. * Make sure the ``Home`` key works in text mode (:lp:`750240`) * *Rhythmbox:* Fix omission of ``.jpg`` extension when searching cover art (William Friesen) * Support xfce4-dict in *Dictionary* plugin (David Schneider) * Make sure ``kupfer.svg`` can be mimetype-detected (NAKAMURA Yoshitaka) (:lp:`750488`) * Fix regression that prevented mimetypes and icon cache from being updated properly when installing from source. * Focus the plugin list search box by default in the preferences window. * Fix regression in *XFCE Session Management* that had a broken logout command. * Install kupfer as a Thunar 'sendto' object. * Fix a bug in the autostart file we installed, it was including a '%F' which broke ``--no-splash`` when autostarted on XFCE. * *LibreOffice:* support their newer recent documents file (Karol Będkowski) * *Notes:* Insert newlines after the new note title (:lp:`748991`) * *Commands:* Recognize absolute paths with arguments as shell commands (for example ``/bin/grep --help``. (:lp:`152093`) * *GNU Screen:* check if sessions are still active (:lp:`756449`), don't give up even if ``$SCREENDIR`` is missing when we are started (:lp:`753376`) * *Notes:* support the program kzrnote as well * Renamed the two like-named command actions in spanish (Daniel Mustieles) * Localization updates for v206: + sl Andrej Žnidaršič + es Daniel Mustieles + de Mario Blättermann This is the changelog for the v205 release, which was released previously. * Changes to the interface + Add a small menu button on the window for explicit access to context actions, preferences window, and help. + Increase icon size to 128px + Always show description field + Use an undecorated window with rounded corners + Let the frame be slightly transparent if supported + Themable colors and properties by using GTK+ styling, see ``Documentation/GTKTheming.rst``, and the plugin *Custom Theme* that shows how to use custom styles. * Add context action "Set X as default action for object Y" + For example, you can make *Launch Again* default for Terminal, and our default configuration uses this setting for two common terminals (GNOME and XFCE). * Updated Kupfer's technical documentation (in ``Documentation/``), including the Plugin API reference. * Implement a preedit widget for input methods, also resolving the incompatibility with ibus (David Schneider) (:lp:`696727`) * Re-implement launching of applications * Allow the user to configure which terminal program is used. Applies to all of *Run in Terminal*, *Open Terminal Here*, for .desktop files that specify ``Terminal=true`` etc. * Implement an "alternatives" mechanism so that plugins can register mutually exclusive alternatives. Currently implemented are Terminals (see above) and Icon Renderers. * *Thunar*: Use Thunar 1.2's Copy and Move API. + These allow copying and moving anything through thunar, and it will show progress dialogs for longer transactions. * Add *Ascii & Unicode Icon Set* for fun * Add simple plugin *Quick Image Viewer* to show images in a simple way. * Add *Send Keys* plugin that can send synthetic keyboard events, and prominently can be used for the *Paste to Foreground Window* action on text. Requires ``xautomation`` package. (:lp:`621453`) * *Volumes:* treat mounts as regular folders, so they can be targets for file operations. * *File Actions:* the action *Move to Trash* switches home to the *Trash* plugin, the archive actions go to new *Archive Manager* plugin. *Archive Manager* also updated to recognize more archive file types, including ``.xz``. * Activate current selection on double-click in the interface. (:lp:`700948`) * Update the preferences window and move the folder configuration to the Catalog tab. * Add ``initialize_plugin`` to the plugin interface. * The D-Bus interface has been extended with X screen and timestamp-aware versions of all methods: + ``PresentOnDisplay``, ``PutFilesOnDisplay``, ``PutTextOnDisplay``, ``ExecuteFileOnDisplay`` all act like their similarly-named predecessors, but take ``$DISPLAY`` and ``$DESKTOP_STARTUP_ID`` as their last two arguments. + ``kupfer-exec`` activation sends the event timestamp so that focus can be carried along correctly even when running ``.kfcom`` files (if activated as an application by startup-notification-aware launchers, this works with most standard desktop components). * Internally, change how actions are carried out by allowing the action execution context object to be passed down the execution chain instead of being a global resource. This also allows plugins to cleanly access current environment (event timestamp, current screen etc). + Support running kupfer on multiple X screens (:lp:`614796`), use the command ``kupfer --relay`` on each additional screen for global keyboard shortcut support. This is experimental until further notice! * The *Tracker 0.8* plugin supports version 0.8 and 0.10 alike. Because of that and the expected compatibility with one version after this too, it's now called *Tracker*. * The *Favorites* plugin lists *Kupfer Help* and *Kupfer Preferences* by default (for new users), so that it's not empty and those items are ranked higher. * In free-text mode, show a character count in the text entry. * The action *Go To* on applications has changed implementation. It will first bring to front all the application's windows on the current workspace, and upon the next invocations it will focus the other workspaces, in order, if they have windows from the same application. For single-window applications, nothing is changed. * Localization updates for v205: + (cs) Marek Černocký + (de) Mario Blättermann + (es) Daniel Mustieles + (ko) Kim Boram + (nb) Kjartan Maraas + (pl) Karol Będkowski + (sl) Andrej Žnidaršič + (sv) Ulrik kupfer v205 ----------- Congratulating ourselves Released Friday, 1 April 2011 * Changes to the interface + NOw we have a teh awsum interface * Add context action "Set X as default action for object Y" + You can finally make Kupfer do what you want. * Implement a preedit widget for input methods, also resolving the incompatibility with ibus (David Schneider) (:lp:`696727`) + Ok, so that foreign people can enter text too. * Updated Kupfer's technical documentation (in ``Documentation/``), including the Plugin API reference. + Someone finally bothered * The action *Go To* on applications has changed implementation. It will first bring to front all yada yada, etc... + Whatever, it finally works in a sensible way * And tons of other stuff, enjoy! kupfer v204 ----------- Released Friday, 18 March 2011 * Expand and improve upon `Kupfer's User Documentation`__. * Use and require **Waf 1.6**, which supports building using either Python 3 or Python 2.6+. Kupfer itself still uses Python 2.6+ only. * Add *Gwibber* plugin that allows integration with Twitter, Identi.ca, Buzz etc. (Karol Będkowski) * Add chat client *Empathy* plugin (Jakh Daven) * Remove the plugin *Twitter* since it is incompatible and has no updated implementation. * Add *Show QRCode* plugin by Thomas Renard (:lp:`611162`) * Periodically save data from plugins so it's not lost if Kupfer can't exit cleanly at logout * *Commands*: Add actions *Pass to Command*, *Filter through Command*, *Send to Command* which add a lot of shell script-related power to Kupfer. These actions, and *Run (Get Output)* as well, use a shell so that you can run shell pipelines. * *Search the Web*: Fix bug in OpenSearch parser (:lp:`682476`) * *VirtualBox*: Support vboxapi4 (Karol Będkowski) * *Thunderbird*: Fix problems in the mork parser (Karol Będkowski) (:lp:`694314`) * *OpenOffice*: Support LibreOffice too (Karol Będkowski) * Fix "Y2011 bug" where the time parameter overflowed INT32 in keybinder * *Shorten Links*: Use only services with stable API, added and removed services. * *Google Search*, *Google Translate* and ``bit.ly`` in *Shorten Links* can use SSL for transport if a third-party plugin is installed. * Fix bug if evolution address book is missing (Luca Falavigna) (:lp:`691305`) * Fix *Search the Web* to use localized ``firefox-addons`` subdirectories for search engines (:lp:`735083`) * Fix bug with integer division (Francesco Marella) * *APT:* Workaround bug with ``subprocess`` (:lp:`711136`) * Find cover art files just like Rhythmbox (William Friesen) (:lp:`676433`) * Use ``readlink`` in ``kupfer-exec`` script too since ``realpath`` is not always available. * Allow plugins to use update notifications (William Friesen) * Bug :lp:`494237` is hopefully fixed once and for all. * The *Large Type* action will work with anything that has ``TextRepresentation`` __ http://kaizer.se/wiki/kupfer/help/ * Localization updates: + (cs) Marek Černocký + (da) Joe Hansen + (de) Mario Blättermann + (es) Daniel Mustieles + (gl) Marcos Lans + (pl) Karol Będkowski + (sl) Andrej Žnidaršič + (sv) Ulrik + (zh_CN) Aron Xu, Yinghua Wang kupfer v203 ----------- .. role:: git(emphasis) Released Saturday, 6 November 2010 * Center Kupfer on the monitor were the mouse pointer is (:lp:`642653`, :git:`3d0ba12`) * Ignore the system's configured input manager by default (User can choose by pressing Shift+F10 in Kupfer). Kupfer is still not compatible with ibus 1.3. (:lp:`601816`, :git:`4f029e6`) * Use ``readlink`` instead of ``realpath`` (:git:`656b32d`) * *Opera Mail*: Handle contacts with multiple e-mail addresses (Chris Parsons) (:lp:`661893`, :git:`12924be`) * *Google Translate*: Fix language list (Karol Będkowski) (:lp:`600406`, :git:`7afac2b`) * *TSClient*: Search recursively for session files (Karol, Freddie Brandt) (:git:`ad58c2e`) * *Rhythmbox*: Fix thumbnail lookup (William Friesen) (:lp:`669077`, :git:`b673f98`) * New Slovenian translation of help by Matej Urbančič (:git:`3b7df25`) * New Turkish translation by M. Deran Delice (:git:`bd95d2a`) kupfer v202 ----------- Released Sunday, 5 September 2010 * Add option to hide Kupfer when focus is lost (and enable by default) (Grigory Javadyan) (:lp:`511972`) * Use application indicators when available (Francesco Marella) (:lp:`601861`) * Python module `keyring` is now optional for Kupfer (but required for the same plugins that used them before) * Update *Google Translate* for protocol changes (Karol, Ulrik) (:lp:`600406`) * Disable saving window position until a better solution is found * Use 'mailto:' as URL (:lp:`630489`) * Fix UI glictch with empty Source (William Friesen) (:lp:`630244`) * Small changes (Francesco Marella) * New Czech translation of the help pages (Marek Černocký) * New Italian translation of the help pages (Francesco Marella) * New Polish translation of the help pages (Karol Będkowski) * New Basque translation (Oier Mees, Iñaki Larrañaga Murgoitio) * New Galician translation (Fran Diéguez) * Localization updates: + cs (Marek Černocký) + de (Mario Blättermann) + pl (Karol Będkowski) + sl (Andrej Žnidaršič) + zh_CN (Aron Xu) kupfer v201 ----------- Released Wednesday, 30 June 2010 * New Logo and Icon by Nasser Alshammari! * New plugin *Opera Mail* by Chris Parsons * New plugin *SSH Hosts* by Fabian Carlström * New plugin *Filezilla* by Karol Będkowski * New plugin *Getting Things GNOME!* (Karol) * New plugin *Vim* (recent files) * *Clipboard:* Option *Copy selection to primary clipboard* (Karol) * *Firefox:* Option *Include visited sites* (Karol) (:lp:`584618`) * *Thunar:* Action *Send To...* (Karol) * New preferences tab for Catalog configuration * Allow disabling and "unloading" plugins at runtime * Support new tracker in plugin *Tracker 0.8* * *Shell Commands:* New Action *Run (Get Output)* * New plugin capabilities: ActionGenerator, Plugin setting change notifications (Karol) * Use ``setproctitle`` module if available to set process title to ``kupfer`` (new optional dependency) * Don't use a crypted keyring (partially addresses :lp:`593319`) * Fix :lp:`544908`: Retain window position across sessions * Fix :lp:`583747`: Use real theme colors for highlight * Fix :lp:`593312`: About window has no icon * More minor changes * Localization updates: + cs, Marek Černocký + de, Mario Blättermann + es, Jorge González + it, Francesco Marella + pl, Karol Będkowski + sl, Andrej Žnidaršič + sv, Ulrik kupfer v200 ----------- Released Wednesday, 7 April 2010 * Add Keyboard Shortcut configuration (Karol Będkowski) * Make it easier to copy and move files (William Friesen), while showing user-friendly errors when action is not possible (Ulrik) (:lp:`516530`) * Collect results in a *Command Results* subcatalog, including results from asynchronous commands (Pro tip: Bind a trigger to *Command Results* → *Search Contents*, for quick access to copied files, downloaded files etc) * *Last Result* proxy object implemented * Add *Cliboards* -> *Clear* action (Karol) * Add *Rescan* action for some sources (Karol) * Add an icon in the plugin list search field to enable clearing it (Karol) * Fix spelling (Francesco Marella) * Fix bug `544289`:lp: * Require python module ``keyring`` (since pandoras-box-1.99, but was not mentioned) * Recommend python-keybinder version 0.0.9 or later * Localization updates: + cs Marek Černocký + de Mario Blättermann + es Jorge González + pl Karol Będkowski + sl Andrej Žnidaršič + sv Ulrik + zh_CN Aron Xu kupfer version pandoras-box-1.99 -------------------------------- Released Tuesday, 16 March 2010 * Plugins can be loaded at runtime, although not unloaded can they not * Plugins can bundle icons, and plugins can be packaged in .zip files * New plugins *Google Search*, *Textfiles* and *Thunar* * New plugin *Deep Archives* to browse inside .zip and .tar files * New plugins *Twitter*, *Gmail* and *Google Picasa* by Karol Będkowski * New plugin *Evolution* by Francesco Marella * New action *Get Note Search Results...* in *Notes* by William Friesen (LP#511954) * New plugin capabilities (user credentials, background loader) by Karol * Added *Next Window* proxy object to *Window List* plugin * Allow saving Kupfer commands to .kfcom files, and executing them with the ``kupfer-exec`` helper script. * Display error notifications to the user when some actions can not be carried out. * Allow collecting selections with the *Clipboard* plugin (Karol) * Include Gnome/Yelp documentation written using Mallard (Mario Blättermann) * Make *Zim* plugin compatible with newer Zim (Karol, Ulrik) * Detect multiple volume rar files (William Friesen) (LP#516021) * Detect XFCE logout better (Karol) (LP#517819) * Fix reading VirtualBox config files (Alexey Porotnikov) (LP#520987) * Fixed module name collision in user plugins (LP#518958), favoriting "loose" applications (LP#518908), bookmarked folders description (LP#509385), Locate plugin on OpenSUSE (LP#517819), Encoding problem for application aliases (LP#537730) * New French translation by Christophe Benz * New Norwegian (Bokmål) translation by Kjartan Maraas * Kupfer now requires Python 2.6 * Localization updates: + cs Marek Černocký + de Mario Blättermann + es Jorge González + fr Christophe Benz + it Francesco Marella + nb Kjartan Maraas + pl Karol Będkowski + pt Carlos Pais + sl Andrej Žnidaršič + sv Ulrik kupfer version pandoras-box-1.1 ------------------------------- Released Monday, 8 February 2010 * Fix bug in contact grouping code that could cause unusable Kupfer with Pidgin plugin. Reported by Vadim Peretokin (LP#517548) * Chromium plugin will index Google Chrome bookmarks as fallback, by William Friesen (LP#513602) * Kupfer's nautilus plugin was changed to be easier to reuse for others * Some minor changes * Localization updates: + pt (Carlos Pais) kupfer version pandoras-box-1 ----------------------------- "Pandora's box" Released Monday, 1 February 2010 * Implement the famous "comma trick": Press , (comma) in the first or third pane to make a stack of objects to perform actions on. This allows actions on many objects and even many-to-many actions. * New plugin: *Triggers*: Add global keybindings to any command you can perform in Kupfer. * New plugin *Skype* by Karol Będkowski * New plugin *Thunderbird* (or Icedove) (Karol) * Implement merging of contacts and hosts: All contacts of the same name are merged into one object. (Karol, Ulrik) * New plugin *Higher-order Actions* to work with saved commands as objects * The *Favorites* plugin was reimplemented: you may favorite (almost) any object. Favorites get a star and a rank boost. * *Window List* plugin was improved, most notably a *Frontmost Window* proxy object was added * New proxy object *Last Command* * The *Firefox* plugin now includes most-visited sites from browser history (William Friesen, Karol, Ulrik) * The list of plugins has a field to allow filtering the list (Karol) * New Czech localization by Marek Černocký * Many smaller changes. * Localization updates: + cs (Marek Černocký, Petr Kovar) + de (Mario Blättermann) + nl (Martin Koelewijn) + pl (Karol) + sv + sl (Andrej Žnidaršič) kupfer version c19.1 -------------------- Released 31 December 2009 * New plugin: *Shorten Links* by Karol Będkowski * Implemented *Ctrl+C* (and *Ctrl+X*) to copy (cut) selected object * Fix bug LP #498542: restore window position code to c18 * Partial fix of bug LP #494237, window is sometimes blank * Fix bug LP #500395, column order in *Top* plugin (Karol) * Fix bug LP #500619, handle network errors in *Google Translate* plugin (Karol) * Localization updates: + pl (Karol) + sv kupfer version c19 ------------------ Released 18 December 2009 * New plugins: + *Gnome Terminal Profiles* by Chmouel Boudjnah + *OpenOffice* recent documents in OpenOffice by Karol Będkowski + *Top* show and send signals to running tasks (Karol) + *Truecrypt* show volumes in truecrypt history and allow mounting them (Karol) + *Vinagre* Remote Desktop Viewer (Karol) + *XFCE Session Management* (Karol) + *Audacious* by Horia V. Corcalciuc * New Slovenian translation by Andrej Žnidaršič * Some plugins will now explicitly require a D-Bus connection and fail to load if no connection was found. * Add accelerators *Page Up*, *Page Down* and *Home* in the result list. (Karol) * Use customized or localized desktop directory instead of hardcoding ``~/Desktop`` by default. It will not affect users who already customized which directories Kupfer indexes. * It now is possible to favorite shell commandlines * *Gajim* plugin now works with version 0.13 (Karol) (LP #489484) * Basic support for Right-to-left (RTL) interface * Fix bugs with "loose" Applications (not in system directories), reported by Chmouel. * Add accelerator *Ctrl+Return* for **Compose Command**: You may compose a command object out of an (Object, Action) combination, to be used with the new action *Run After Delay...*. * Added file action *Send by Email* to *Claws Mail* plugin (Karol) * Added file action *Mount as TrueCrypt Volume* to *TrueCrypt* plugin (Karol) * Many small bugfixes Localization updates: * de: Mario Blättermann * es: Jorge González * it: Francesco Marella * pl: Karol Będkowski * sl: new (Andrej) * sv: Ulrik Sverdrup kupfer version c18.1 -------------------- Released 20 November 2009 * Fix bug to toss out malfunctioning plugins properly (Reported by Jan) * Fix bug in showing the shutdown dialog, reported by user sillyfofilly (LP 484664) * Fix bug in plugin *Document Templates*, reported by Francesco Marella (part of LP 471462) kupfer version c18 ------------------ Released 18 November 2009 "Mímisbrunnr" * New plugins: + *Pidgin* by Chmouel Boudjnah + *Google Translate* by Karol Będkowski + *APT* (package manager APT) by Martin Koelewijn and Ulrik + *Document Templates* + *Kupfer Plugins* + *Show Text* * *Gajim* plugin matches contacts by jid as well as name, suggested by Stanislav G-E (LP 462866) * Action *Rescan* on sources is now debug only (should not be needed) * Kupfer installs its Python package into ``$PREFIX/share`` by default, instead of installing as a system-wide Python module. * Kupfer can take input on stdin and pass as text to an already running instance * Fix bug in *Services* for Arch Linux, reported by lh (LP 463071) * Changes for plugin authors: + May use ``uiutils.show_text_result`` to show text + ``kupfer.task.ThreadTask`` is now a reliable way to run actions asynchronously (in a thread) + You can use item *Restart Kupfer* to restart (in debug mode) + Plugins may be implemented as Python packages, as well as modules * Updated the dependencies in the README. pygobject 2.18 is required. Added gvfs as very recommended. * Other bugfixes Localization updates: * de (Mario Blättermann) * es (Jorge González) * nl (Martin Koelewijn) * pl (Karol Będkowski) * sv * zh_CH (lh) kupfer version c17 ------------------ Released, 25 October 2009 "A fire lit by nine kinds of wood" * 8 new plugins by Karol Będkowski: + *Claws Mail*, Contacts and actions + *Gajim*, Access to gajim contacts + *Opera Bookmarks*, for the web browser Opera + *PuTTY Sessions*, access to PuTTY sessions + *System Services*, start, stop or restart system services + *Terminal Server Client*, access to TSClient sessions + *VirtualBox*, control virtual machines, Sun or OSE version + *Zim*, access pages in the desktop wiki * New plugin *Chromium Bookmarks* by Francesco Marella * Plugins missing dependencies will be presented in the GUI with a clear error message. * *Firefox Bookmarks* plugin: Workaround Firefox 3.5 writing invalid JSON (Karol, Ulrik) * *Locate* plugin: Ignore case by default, add option to control this. (Karol) * Kupfer is much more friendly and says "Type to search in *Catalog*" when it is ready to be used. * Localization updates: + New Simplified Chinese localization (lh) + New Dutch localization (Martin Koelewijn) + New Portuguese localization (Carlos Pais) + Updated pl (Karol) + Updated es (Jesús Barbero Rodríguez) kupfer version c16 ------------------ Released 5 October 2009 * Translation to German (Thibaud Roth) * Polish translation updated (Maciej Kwiatkowski) * Add search engine descriptions from ``firefox-addons`` (Francesco Marella) * Speed up directory browsing by using much less system calls * Improve documentation and put it together into a `Manual`. * Generate man page from reStructuredText document `Quickstart`. * Evaluate valid actions (per object) lazily to save work. * Add accelerators *Ctrl+Q* (select quit) and *Alt+A* (activate) * Parse even horribly wrong search engine descriptions (Bug reported by Martin Koelewijn) kupfer version c15 ------------------ * Translation to Polish by Maciej Kwiatkowski * Speed up the string ranker tremendously; 3x faster in common cases. * All objects now have an alias in the basic latin alphabet (if possible) so that, for example, query `wylacz` matches item *Wyłącz*. * Show notification icon by default * Read XML with cElementTree (Faster.) * Read Firefox 3's bookmarks (Python2.5 requires `cjson` module) * New Plugin: Image Tools, with action *Scale...* and JPEG rotation actions (*Scale* requires ImageMagick (`convert`), JPEG actions `jpegtran` and `jhead`) * Basic support for a Magic Keybinding: summon kupfer with current selection kupfer version c14.1 -------------------- * Fix two bugs with new browisng mode (soft reset for text mode, backspace or left to erase a subcatalog search) kupfer version c14 ------------------ * Rewrite and improve browsing mode: * Browsing the catalog or folders is much improved; it is easier to keep the overview and be oriented. * Returning to kupfer after having performed an action, the old object is still available, but without locking the catalog to its location. When spawning kupfer again, the previous context is available if you immediately browse; if you search, you search the whole catalog. * The search times out after 2 seconds if no key is typed. Now the highlight text will fade to show this. * Add accelerators `Ctrl+G` and `Ctrl+T` to get current selection in nautilus and currently selected text (if available). kupfer version c13.1 -------------------- * Fix two bugs with *Rename To...* kupfer version c13 ------------------ * New Plugin: Calculator * New Action: *Rename To...* in File Actions Plugin * Smaller changes (Stop learned mnemonics database from growing indefinitely, Catch SIGINT without python's handler, *Copy To...* requires pygobject 2.18 now) kupfer version c12 ------------------ * Translation to Spanish by Leandro Leites * Preferences. Display plugin settings and options beside the plugin list, and allow configuring included (and watched) directories. * Support the new Gnome session protocol to save state on log out. * Improve embarassingly bad shell command quoting for *Execute* and Tracker tag actions. * Specify user data locations with `X-UserData` * Fix an AttributeError in Notes plugin reported by Francesco Marella * Smaller fixes (Add/remove favorite could cease to work, Track intantiated sources better) kupfer version c11 ------------------ The "this one goes to 11" release * New plugin: Notes (Gnote and Tomboy support) * Access notes, Actions: *Create Note* and *Append to Note...* * New plugin: Selected File * Kupfer ships with a Nautilus python extension that once installed, you can access the currently selected file in Nautilus from Kupfer, as the *Selected File* object This release is localized in: Swedish (100%), Italian (90%) kupfer version c10.1 -------------------- * Spanish Translation by Leandro Leites kupfer version c10 ------------------ * Updated italian localization * New plugins: Url Actions, Web Search (rewritten to use all Firefox' search engines) * New actions: *Set Default Application*, *Create Archive In...*, *Restore* (Restore trashed file) * Add accelerators `Control+R` for reset, `Control+S` for select first (source) pane and `Control+.` for untoggle text mode. * Only the bookmarks plugins can toggle "include in toplevel" now. * Other smaller changes (Refuse invalid Application objects from the cache) This release is localized in: Swedish (100%), Italian (93%) kupfer version c9.1 ------------------- * User interface consistency and behaviour improvements. UI is simpler and better. * Other improvements. This release is localized in: Swedish (100%), Italian (60%) kupfer version c9 ----------------- The "c9" release * Search and browse perform better * The interface is now modal. In command mode we can bind special keys to new functions. Type period `.` to enter free-text mode (just like in QS). * Pressing kupfer's keybinding again will hide the window. * Other smaller improvements This release is localized in: Swedish (100%), Italian (60%) kupfer version c8 ----------------- * Make the use of the indirect object pane much more fluid * Apply interface polish (proper english capitalization of actions and other objects, other changes) * Add `Copy To...` action * Try `xdg-terminal` first in *Open Terminal Here* (non-Gnome users can either install `xdg-terminal` or symlink it to their terminal program) * Allow unbinding the keybinding * Fix a bug with tracker tags [Please file bug reports and feature requests.][lp]. Read the files in `Documentation/` and see how you can add new plugins with object and application knowledge to kupfer. This release is localized in: Swedish (100%), Italian (60%) [lp]: http://launchpad.net/kupfer kupfer version c7 ----------------- The "choice" release This is a followup with some small changes after the c6 release, which introduced lots of major changes, including a preferences window and "application content." * Allow wnck to be optional. Kupfer needs wnck to do application matching and focusing of already running applications, but can now run without it if wnck is not available. Window List plugin also needs wnck * Rhythmbox plugin should not crash even if library is not found, now kupfer can run even if rhythmbox's files are not there. * Applications will match names as well as the executables, so that "gedit" matches Text Editor regardless of what the displayed localized name is. [Please file bug reports and feature requests.][lp]. Read the files in `Documentation/` and see how you can add new plugins with object and application knowledge to kupfer. This release is localized in: Swedish (100%), Italian (60%) [lp]: http://launchpad.net/kupfer kupfer version c6 ----------------- The "Sisyphus incremental improvements" release * Preferences window * Allows setting keybinding on the fly * List and enable/disable plugins and set plugin options * Everything was improved slightly, but steadily * Understands more applications, provides more files and objects, and actions with **new plugins:** *Rhythmbox, Abiword, Clipboards, Dictionary, Favorites, Selected Text, Wikipedia* * Connect applications with their related object sources and make it their content, such as Rhythmbox music for the Rhythmbox application. * Applications contain their recently used documents, if available. * Firefox and Epiphany bookmarks are identified with each application * Miscellaneous improvements: * Kupfer object icon ("blue box") * *Some* default application associations are installed (others are learned by launching applications). * Experimental UI with two-line title+description in browse mode * Thumbnails for files and albums in browse mode * Allow sending files and queries to kupfer from the commandline using `kupfer 'query'` or `kupfer docs/file.pdf`. * Even more plugins listen to change callbacks or filesystem monitors to be up to date to the instant. * Do not display nonexisting files as results * Fine-tune how sources are loaded and refreshed on load This release deserves lots of testing. [File bug reports and feature requests.][bug] Read the files in `Documentation/` and see how you can add new plugins with object and application knowledge to kupfer. This release is localized in: Swedish (100%), Italian (60%) Future: part 2 of beautification is refactoring of the interface, so that the UI can be modularized and exchanged in plugins. [bug]: http://launchpad.net/kupfer kupfer version c5 ----------------- The "Beauty from the inside, part 1" release * Big refactorings of the whole data model * Move all of the data model to kupfer.data * Allow actions with indirect objects "threepane kupfer" (with means to configure which objects to use for an action etc) * Uses unicode internally, instead of UTF-8-encoded strings * Some new actions using new possibilities (Open with any, Move file to new location, Add/Remove tracker tags) but more is possible. * Basic manual page included * Fileactions plugin includes unpack archive/create archive * Ship extra and demonstration plugins in contrib/ and interals documentation in Documentation/ * Change learning algorithm to recognize an item's type as well (so that two objects named "project" can be ranked differently) * Small fixes (alphabethic sorting for applications, sources, check if objects still exist after an action, ``rank_adjust`` default actions slightly) This release deserves lots of testing. File bug reports and feature requests. Read the files in Documentation/ and see how you can add new plugins with object and application knowledge to kupfer. This release is localized in: Swedish (100%), Italian (80%) Future: part 2 of beautification is refactoring of the interface, so that the UI can be exchanged. And preferences will hopefully be implemented .. -*- encoding: UTF-8 -*- .. vim: tw=76 ft=rst kupfer-328/NEWS000077700000000000000000000000001500175051100217232Documentation/VersionHistory.rstustar00rootroot00000000000000kupfer-328/README.rst000066400000000000000000000071331500175051100143520ustar00rootroot00000000000000kupfer is a smart, quick launcher +++++++++++++++++++++++++++++++++ :Homepage: https://kupferlauncher.github.io/ :Credits: Copyright 2007–2023 Ulrik Sverdrup and other Kupfer authors :Licence: GNU General Public License v3 (or any later version) Kupfer is an interface for quick and convenient access to applications and their documents. The most typical use is to find a specific application and launch it. We have tried to make Kupfer easy to extend with plugins so that this quick-access paradigm can be extended to many more objects than just applications. Installing ========== This project is configured for the Waf build system, which is included. Run it using either ``./waf`` or ``python3 waf`` (using your python.) Installation follows the steps:: ./waf configure ./waf If configure does not find the right Python 3 executable, set ``PYTHON`` explicitly first. then:: ./waf install or :: sudo ./waf install You can use ``--prefix=$PREFIX`` when configuring to assign an installation spot. By default, Kupfer is installed for all users. Installing only for your user is possible, but the binary directory must be in your ``$PATH``. About Waf --------- Waf is included in both the distributable tarball and the repository (so that full source code is incuded. See the file `waf` for author and licensing information). Waf was acquired through https://waf.io/, version 2.0.25. The following files extracted:: ./waf-light -> ./waf ./waflib -> ./waflib ./ChangeLog -> ./Waf.ChangeLog ./waflib/Tools/* some files excluded ./waflib/extras/* some files excluded Build Requirements ------------------ * Python 3.9+ * intltool * optionally: rst2man (python-docutils) to install the manpage * optionally: itstool to install mallard help pages Runtime Requirements -------------------- Kupfer requires Python 3.9 or later, and the following important libraries: Because the port to Python 3 and Gtk 3 is new, I don't know what the lower boundaries of dependencies are. I've given the versions where it is known to work. * Gtk-3.0 version 3.22 * libkeybinder-3.0 version 0.3.1 * python gir1.2 * dbus python bindings * python-xdg Opportunistic dependencies * If available, 'setproctitle' is used to set the process name * If available, you can use AyatanaAppIndicator3. On debian the package name needed for the dependency is ``gir1.2-ayatanaappindicator3-0.1`` (g-i bindings). Recommended dependencies * Wnck-3.0 version 3.20 (Without this you can't focus already running applications) * Yelp, the help browser Some plugins will require additional python modules! Spawning ======== The program is installed as ``kupfer`` into ``$PREFIX/bin``. Only one instance can be active for one user at a given time. Normal use of kupfer requires an active dbus session bus. Keybinder Module ---------------- Keybinder is a library for global keyboard shortcuts. You can use kupfer without the keybinder module, for example by assigning a window manager keybinding to the ``kupfer`` binary. If ``Keybinder`` gi bindings are installed, the library is used. If you must disable it without uninstalling them then see the man page. Documentation ============= The user’s guide is installed as Mallard help pages, available under the “Kupfer Help” object in the program itself; it is also on the web page. Kupfer will use the help browser if there is a handler for the ``help:`` URI scheme. The user’s guide’s source is under ``help/``, and it is translatable. Please read ``Documentation/`` and ``Documentation/Manpage.rst`` for technical and contributor documentation. .. vim: ft=rst tw=78 kupfer-328/Waf.ChangeLog000066400000000000000000000251461500175051100151550ustar00rootroot00000000000000NEW IN WAF 2.0.25 ----------------- * Fix invalid characters returned by find_program #2397 * Prepare for distutils removal (Python 3.12 regression) #2402 * Improve cp65001 compat in cpython < 3.3 #2346 * Add Fujitsu Fortran compiler detection on ARM64FX #2348 * Support multiple Sphinx output formats #2344 * Improve PyQt5 detection #2343 * Add asynchronous wafcache uploads NEW IN WAF 2.0.24 ----------------- * Use EXT_SUFFIX config var over the deprecated/removed SO (Python 3.11 regression) #2386 * When detecting Visual Studio compilers, prefer the oldest version regardless of compiler type #2352 * Update the MacOS-specific examples #2337 * Fix Configure.find_program() invalid character handling in default variable names #2397 NEW IN WAF 2.0.23 ----------------- * Fix the Qt3D* libraries detection #2368 * Fix swig processing when \r is preset in the module name #2350 * Add RISC-V generic detection #2322 * Detect gcc first on GNU/kFreeBSD #2336 * Improve waflib/extras/msvcdeps performance #2323 NEW IN WAF 2.0.22 ----------------- * Fix stdin propagation with faulty vcvarsall scripts #2315 * Enable mixing Unix-style paths with destdir on Windows platforms #2337 * Fix shell escaping unit test parameters #2314 * Improve extras/clang_compilation_database and extras/swig compatibility #2336 * Propagate C++ flags to the Cuda compiler in extras/cuda #2311 * Fix detection of Qt 5.0.0 (preparation for Qt6) #2331 * Enable Haxe processing #2308 * Fix regression in MACOSX_DEPLOYMENT_TARGET caused by distutils #2330 * Fix extras/wafcache concurrent trimming issues #2312 * Fix extras/wafcache symlink handling #2327 NEW IN WAF 2.0.21 ----------------- * Set the default --msvc_version from VSCMD_VER if present #2299 * Force unit-test reruns on ut_str, ut_cmd or ut_path changes #2302 * Describe Qt5's library detection #2288 * Introduce conf.env.ASMDEFINES_ST to enable assembly-specific define flags * Update extras/xcode6 to Python3 #2290 * Enable parameter "always" in extras/doxygen #2292 * Fix extras/c_dumbpreproc as it was previously broken * Fix extras/gccdeps and extras/msvcdeps on header renaming #2293 * Improve extras/msvcdeps debug outputs and flags #2287 #2291 * Add add MCST Elbrus CPU detection in c config #2297 * Add minio object copies to extras/wafcache #2304 NEW IN WAF 2.0.20 ----------------- * Detect -flto and -fno-lto in parse_config #2281 * Improve custom option processing #2280 * Enable Clang on cygwin #2279 * Make distclean target 'no_lock_in_top/run' modifiers compatible with env vars #2271 * Update irix compiler detection * Exclude ConfigSet from altering ConfigurationContext.run_build caches #2273 * Add gas support in extras/gccdeps.py #2278 * Improve compatibility with custom commands in extras/clang_compilation_database #2274 NEW IN WAF 2.0.19 ----------------- * Enable race-free pdb file generation waflib/extras/msvc_pdb.py #1731 * Fix negative values for -j #2256 * Fix Swig example compatibility with Python3 #2259 * Fix lto settings for endianness configuration tests #2250 * Tune the application name on --help #2254 * Improve Qt5's fPIC/fPIE detection * Propagate LDFLAGS to Fortran tasks (in addition to LINKFLAGS) * Enable local and remote build object caches waflib/extras/wafcache.py NEW IN WAF 2.0.18 ----------------- * Fix a deadlock with cython and subst tasks #2244 * Fix rpath processing so that it no longer breaks dependency chains * Fix fast_partial.py failures on configuration tests * Fix duplicate -fno-strict-aliasing flags in Python compilation flags detection * Fix annoying PIE errors in demos/asm/ * Improve configuration tests cache accuracy #2251 * Improve extras/fast_partial.py compatibility * Improve extras/doxygen.py outdir parameter settings #2255 * Add a dependency scanner for assembly files (Gas/Yasm) * Add executable arguments for configuration tests / execute=True * Add a QtTest example to demos/qt5/ #2241 * Add a cross-compilation option to extras/objcopy.py #2247 NEW IN WAF 2.0.17 ----------------- * Improve build performance on FreeBSD and Python3 #2241 * Add Python 3.8 flag detection for building embedded interpreters #2239 * Prevent Qt5 uninstallation errors when c++ files are generated * Improve installation/uninstallation colors NEW IN WAF 2.0.16 ----------------- * Fix task semaphore errors on stateful tasks #2232 * Fix encoding errors with UTF-8 paths on Python 2 #2230 * Fix encoding errors in waf_unit_test #2220 * Improve dependency between javac task and use-d generated jars nodes * Install pdb files with /debug:* flags #2224 * Make javadoc detection optional #2225 * Improve md5_tstamp documentation #2221 * Add extras/color_msvc to colorizes MSVC outputs #2221 * Fix symbol regex on mac-o binaries in extras/syms #2222 * Maintain order of lines in doxyfile in extras/doxygen #2223 * Improve extras/msvcdeps path handling * Add extras/clang_cross for cross-compilation using clang NEW IN WAF 2.0.15 ----------------- * Fix Python path detection under Git-Bash #2217 * Provide an option to disable args files #2216 * Improve command line length calculation for args files #2214 * Add libs/stubs to Cuda library path #2213 * Suppress ant_glob java warnings #2212 * Support multiple 'default_cmd' #2211 * Warn when buildcopy is used without any files to copy #2210 * Protobuf examples enhancements #2208 #2209 * Fix all DeprecationWarning: invalid escape sequence #2207 NEW IN WAF 2.0.14 ----------------- * Support Fortran 2008 submodules #2205 * Possible solution for Msys/Python 3.6 path issues #2217 * Support NEC SX-Aurora TSUBASA system's Fortran compiler extras/fc_nfort.py #2206 * Fix ignored configuration flags in gccdeps extras/gccdeps.py #2203 * Fix included protoc search on nested wscripts extras/protoc.py #2202 * Support extra taskgen and out of project include directories extras/protoc.py #2204 NEW IN WAF 2.0.13 ----------------- * Fix "broken revdeps" extra error message on certain build failures * Avoid duplicate flags in Python configuration tests * Find more Swig dependencies #2206 * Avoid spawning threads with -j1 on AIX systems NEW IN WAF 2.0.12 ----------------- * Fix broken inheritance task trees #2194 NEW IN WAF 2.0.11 ----------------- * Do not raise an exception on check_cfg/mandatory=False/-vv #2193 * Post past task generators in lazy sub-folder builds #2191 * Disable warnings on versioned library installation * Fix cpplint concurrent execution problems NEW IN WAF 2.0.10 ----------------- * Add a task semaphore system * Fix --help when no wscript is supplied #2184 * Fix Fortran processing with generated Fortran files NEW IN WAF 2.0.9 ---------------- * Add dependencies on scriptlet outputs * Made options optional for cython waftool * Improve doxygen error handling NEW IN WAF 2.0.8 ---------------- * Improve Windows console encoding outputs on Python 3.6 and Japanese code page #2163 * Improve msvc detection on Python 3.6 and Japanese code page #2155 * Improve moc/rcc flag parsing with msvc #2169 * Improve Eclipse project generation #2166 #2165 #2164 #2149 #2145 * Improve Boost project detection on dpkg-based systems #2146 NEW IN WAF 2.0.7 ---------------- * Apply priorities to dynamically-generated tasks #2137 * Fix upcoming Python 3.7 incompatibilities #2126 * Fix Python3 support in extras/xcode6.py #2121 * Improve priority support in extras/swig.py #2137 * Improve support extras/protoc.py #2135 * Improve argument handling in extras/clang_compilation_database.py #2127 * Add glib DBus bindings in extras/gdbus.py #2134 * Avoid name collisions for precompiled headers and libraries with similar names in extras/pch.py #2122 NEW IN WAF 2.0.6 ---------------- * Add Task.deep_inputs to enable further dependencies on input file tasks * Set unit tests to depend on input file tasks instead of timestamps NEW IN WAF 2.0.5 ---------------- * Force unit tests to depend on the executable creation time besides file contents * Enhance the Eclipse project generator * Update the cuda examples NEW IN WAF 2.0.4 ---------------- * Enable more advanced warnings of ant_glob on build folders in verbose mode * Defer node.ant_glob(..., generator=True) evaluation * Enable 'waf clean' to get the list of files to remove from bld.clean_files * Define the environment variable WAF_NO_PREFORK to skip pre-forking * Fix Can't pickle local object '_createenviron..encode' exceptions (Python 3.6) * Improve the Erlang module #2095 * Add task target to parallel_debug outputs #2091 NEW IN WAF 2.0.3 ---------------- * Enable install_path=None for Python targets #2087 * Skip empty or duplicates in java user classpath #2084 * Change the unit test summary color scheme to use green and red colors * Improve the deadlock error message * Report sys.path values from Context.load_tool to improve error messages * Cache qrc uic->h conversions to enable qrc re-use across targets * Output long-running tasks outputs immediately using bld(rule=..., stdout=None) NEW IN WAF 2.0.2 ---------------- * Improve Intel Fortran compiler detection on Windows #2063 * Ensure that the task count starts at 1 in the build outputs * Add a --pdb option to start pdb on unexpected exceptions #2052 * Fix conflicting qm/qrc re-used output files for multiple targets #2065 * Add java support in protobuf (extras) #2049 * Add a java test example (extras) #2062 * Enable symbol processing for empty targets (extras) #2053 NEW IN WAF 2.0.1 ---------------- * Improve the default preprocessor behaviour for gcc/msvc * Accept task objects in Build.add_to_group for compatibility reasons * Prevent xcode generator from overwriting existing features #2038 * Fix self.includes data scope #2035 * Fix Node.ant_glob case sensitivity regression #2034 * Fix Logs.verbose options regression #2033 NEW IN WAF 2.0.0 ---------------- * Provide a new priority system to improve scalability on complex builds * Provide TaskGroup objects to improve scalability on complex builds * Force new files into the build directory by default (use Node objects to bypass) * Provide built-in support for building over UNC paths * Simplify the Task class hierarchy; TaskBase is removed * Display commands as string with "WAF_CMD_FORMAT=string waf build -v" * Have ant_glob(..., generator=True) return a Python generator * Accept nested lists and generators in bld(source=...) * Sort TaskGen methods in alphabetical order by reversing TaskGen.prec order * Remove 'ut_fun' from waf_unit_test.py * Remove Node.sig and Node.cache_sig * Remove the BuildContext.rule decorator * Remove Task.update_outputs, Task.always_run * Remove atleast-version, exact-version and max-version from conf.check_cfg * Remove c_preproc.trimquotes * Remove field_name, type_name, function_name from conf.check() tests * Remove extras/mem_reducer.py as a better solution has been merged * Remove Utils.ex_stack (use traceback.format_exc()) kupfer-328/auxdata/000077500000000000000000000000001500175051100143065ustar00rootroot00000000000000kupfer-328/auxdata/hicolor/000077500000000000000000000000001500175051100157455ustar00rootroot00000000000000kupfer-328/auxdata/hicolor/128x128/000077500000000000000000000000001500175051100167025ustar00rootroot00000000000000kupfer-328/auxdata/hicolor/128x128/apps/000077500000000000000000000000001500175051100176455ustar00rootroot00000000000000kupfer-328/auxdata/hicolor/128x128/apps/kupfer.png000066400000000000000000000365671500175051100216700ustar00rootroot00000000000000PNG  IHDR>asBIT|d pHYsffSێtEXtSoftwarewww.inkscape.org< IDATxg$u2]Lv(J$(G[#sswV+i$HQ+Q%=iEG a1~zL̈x2\WUW4=ܙJoܸq#^5z^5#W;$ `XAF@^ srRya9k2i&_Rҍ <{܊`7пi f-'`GL7ymFvp!$QEH)h(5k5\>2gϞ(─?-IV ^1Gw^~]&2b}z 2[zK |)Ln$J4nq:VM]e1{(fs/  .jl ba O%\n޳={2~sƥDH ArϧL:wz.(=ELڰ̶[PH+hL3v$< b(l':ÅW1ۯ.ûO, @hߴs+wqd:R!"(E?Z?$t:ݏ+-sK'1NWZv_Úqq :ɝzճn@94 ">Hn/*5 鉫<3\X~/> ~$_ {آ,a};ؿиS Rxjߵy=P s HIr7=.uTtmCv-aTXܑ>XL;ۻHҋ_dWQǟ-ऺI ZG츙M{st?\f+wVEB#ߴ}۷RP8T%TJ }I.o3L>0/f,ZDFpK0VË=݇?fgʴArd7bMZs|}Ll,?Ib)wF>R pNm\ZBPxTh 's`x/oi=S~D4($"l6_~㗐pR)P*< 鄃HRJHB7sE X峌WO}X]wC(O?,Bt+. $zC-ם!Pa0_{z+ˮ%hl50QƁqН1_f'҄</QKJ]7Ϡf6X[!U)R4,#P0hd}otW?u;n} T'xE5}# =]Hpy&cWOOkC ܎+<ػa{ Ds/W04-|{?uVO1RT/"B8)j"8n2rlsL|D@%/فAvÏ?).SX^4e@^@F=[FIVmkU~x/ni;RJ%RXL8>_wɽR$. %^8u} _'aS!D,J3 uAD=o-$*yJv׭Hr݈n(!̏Կ@ ~mYlp/Nvu g}DS^>N6 yř|m<0OOs|y6UZ y .s.(Y[xx>r;rA dW&` ?E [o]ϢB& b ޵fb-̉u~mGa8.nBIPw3X7KOp/paD /\G-T|1 yƾ_&@:Nw/}ڼHnXPs?֘! @1 RkZCuܰy&NXv (fRI`4s i${O{xO1ғ⦍OxcFv`WHP,@ԽsI݀vM@Id"H"Bſ2B&D& QA{qAɺc]{ erN-*>)xLoQ:wTeY8(t(E7 lC;tD DVzU_A-}^OߚCKF$"CyB l~seng]6 Vz<gd34>d4+b=uVP~J#]  {HTP+R"KY|*^8̨e6wc ?7 ~`Tb.֯$͕io7n\CMͱ[.}{[_|D${s^TQӇL]7Z $RUA)TH3Yo 4A-U=x2n߉]u5aGi}e<)$ _5~;B`]\4?nYa^9u])dxVFThJYIbZD_8f4{ =y㊛]̅Z@ fv%h7Fʰ*ܵ~?hNQ=0w׀nlt  pl8O% D~3\<83Gs_Oa]G7Z)u Gܲ#l87#2_Y\k koeXաh 8F]8Ø0 yr[ZR땱:j5!o [ARK'wd oxŶuUau.RqRAu^>&u EuK746;_U#]ݢX&f|JW_.b r㕰}LBh֯YMl% T#KWZ k+ꎔlb7w/'e@_ \ǯk6 MNPPWR ')^ S*b \@ L<+զjaLmwCGPRO&]J2;7fckhVJ|=C&Rm=/brRS,V.О AqsP44xVt@`:k=(i훻0VTn};D'@T}4@· L98t$?n+UI0gnٲ,KSe(P 헵_ v+Z*uT3 U,m;:yoȺ`AEٰ7ԄkGj?22WG{_k%3Smgo"}M[p*xB!x4oQ-~i9#6XQ}` [P#@gGU1:sFqU):jjcgՍ7n\^76l_|Mh 4 v:@W=?F[@m{^nOvkFQug`o$L,gE[.lC],"TxMR-D%%S 0{4ҳqh8|ٵø^L!,S??֪Q*a_ JD ՅGffpTxWǏnV}ZVj N5 SR] `Dڜ@K|S P#=KO|!ʧ^{Oq~ATjZEkj?ڂsAu%SK+y+gg }xY$a2}6jEuĭruItbdDg3]{F{kx{ZߺMaGMTmˢvWCwXZSpdns.]?@ 7:ԺvF3dmἔ6ˑDt lnDռ60) B!}oyzdmSPvS{f wo1<:J3og:W^z~7ӊѺNy:5zPYQ3 4Tn0 /`w_Lr^lɶhD̓9ܶ^3FC._๿Ғ~G_Zr:t%V*¢ai<=X{_ԅdz5kC604"7_!^B[ZP)~=?ƻ?گ۟=J*{RuKM; Xõbs~iP'μgs"U(Ak72{?F2aþ ^;Lr}?79d@ځ.g'{ᾷfGxe SW|y~=uB^0_RenI Z6՟P~a;SQq^[@t]_`=MrݼWy'9^ pUD{&܌ [p۹uwn!<2~*\1fnEõ̫E{k},qIDATU" :+N^ Wh $>w<8~s7H@P,dJ5>J [on55]rOr%&^e~fR1D"A*bhd6m֝itr73L]8[xZ3b7sRdG/N"=YO48 ܖL)Hgor 4px;%ЂIk fpkQt%gTpZ%om k7E)Ro~%'jڒ: ංo(74;횈ǖÏ|+']݄D& k9<wDsB%XaNJ:~ /Г Wԥ"arWǟ],C4iq>hss|Kc ylm>+osN(Ҽ\{OO/ 47;' #CX$Rؕ9 |#O<]oy.cubSXwzK?$MBv%_~QtM6MKve p,O|ʯEvpYMJ4WjfhZ&1IaL0[bph}toX _åکF yOO]OyKWOGJ]{Q C~KIor.q_VleټOM ؄:@Ce\ɧ7P4B(Mj}%hV\?==˯=ܚAQ;:ۛ=.GOIR_anjzGP*4­f+W_~dN\)ғ%Q 0ߜqY퀐JsqZjchɦs٤PxJX.;ґ_S_bb.T՟|iZв>ɷ!+mh9>Pǖ ˳lma #7m-4 XQW8f^g]"|E[s.P4Wfa#gD-B۶ o51ƒLZ;ʶpuRZ5ltw] 犔 X t^+X|(U f뙽6꥾rM# \Fx6Ϛj>mC>㼶N&l髕e >\~.8yrZ@cWb,iJۜIhpa|vr:稞 Xy/  }/ p~0ƒ&nzkR%A1@VU~-QΘL[YՁA=C^V| lF^{KX>+\-0߃p$z)M-,B|&`ѵX(yDD}lԸZ\aVNv .\\[Mu> P5gA! =% 0 ZuÚE sgꚗv7ZmwX:!z 9/OSZX麾Z;٫Bt"ۇ%{Ėoo`BK +txxkRO8>~Xblb.tQ8{ 9,`腉)dG7⨡g4D3m@U wvKzs4YӲ($39zųW+u C/q]˵_:_ǧndo۩;nr[m3V13cm 囻 @,_uekGlZB]˙+SLM_մ ˠH4 3dF6h{iΘsf/:;__hn˼tZMC׳.UD6gYѪࡗ8-Xc-ϝ:5Tp]RTC4F3Č0BZ2-eGH 9||!`~$cM LZ |_> P|^:}aaݸdOSlY֋`6%ϧy0]|_g ; Ypy_5W&9{!\UHpñVB*}b 0WXX~zLN:2?s"c'8_duѪq ہ4~E*IvUhv.]nݹB bGW%kp"`UN)\^tV>œ~ crr ! ?TLlw_㺍OKsM\n?Pw;,Ct0û)x5S'6ɯ^5~LٿO}kTFJd5{ӽfkd3Wy,Kqge"o}c~ m 7`~j,NhhFύ\EQ.yT* noݳ{n@HPFk&Nh~vzf7v~ӳ9uSC Кu*_ 6bd~R(aQ;Zq" ג>\ZsqJL"d^LmFCp`U9bQyy_Y+}WZ_TLO; 5ʎnХܬ:#r?3$7LNM13u4B9tnwfb0_ߚ+ER\_Own`bzGOWYP)4at9Ȧop5fxsB\?8L*)5CY.\2*gR& -N'b'+WyxSvzOIn 쬌l,tZ4|ڡLlhxmfZhڠjtCjYY(d\lVzLUv*+W/8R@A1J7/c]in5w Uh@?~kOU^ݯ*mr2i'kv=e+/aa yg\JRcm8~5:\j]7!K:Q,|>oɤd2LLL CY m:Ta~i61<9)sfeKDʎ\SWQR)%RZ*-R*#B+cP;}BZSYɩ]7̆!Ն+g;1L$Q}qX/oK Azc`.rYWϝfv…A^qzĎJeU*0Vii6hehqnс6qv@N.$M6frxؤlꪡ;tHO'*Qr㔔yʓqG))U GʐRI) p18R^fwylU$Þq>rʉ>f.f9殜/-iƒ7&D߄Tгvv3gLi'rakV |Tr۟/8ɜR+K` H-N`Xhe1v\hct:aLH$t tt[|lYONN M-B̂+0TT8UJP([0_*!#Q(aT|׾/מ]Ѵ.)2??/>$[vfYBHgsk03s)LQ"Klmk&t ?DfhTcQ<%Ο>')5X)״AZa#A+B PB02@J$0GKP:pmM6ZyRJ/Kbcǵ)`#-V4/@k]WƘʱV$M?n akE>44Ao+o]`R#su>Ko0t Ivp kADQ@afX?%ѾGrn&p3YpS]ƟNA[c|( >"(q:;nlY4FJZmbtJ`xxr9q>=R)Ί\:mS*aɤv n*M-#m3k(0ya gr,\;ws陲jk@ZV[i#jXm(cc6Ii.˶69[lfmjb,{H:?vj/ϫt:tZ&Jr)PJ)(TJJe(6Zh%TR֡-`L\1 0Ji`.]/f?0D=t $SZ^@aIM2mkS盯nJ?7 >~]6VjaRjk6j)6Vj}#F+@Wh뺁֎hhv$:nhŢf:H 6豱~}w}& 5V ,IY.DB pv]PR*%:V -R!FYc0‘RJ#V(#Jr׆ cʔ8V)K9!L&Nr ,؁PSe:6/3/]L{Eiji1+m 4Dnj-QViFiUc m}8 [6)ӱOG'I;99lR\o7Jw0vƽr,b@m2yJ'RT8ڑ'%22V)PF%V)T(+J+1Z)J)!}ƌ.`"X+u;hB/yi8r*1F#1FJ#0RZJ&/QV -8 &}&P&(7L"k\lj}q?Ls#}GF.bdւGw ?])ϓ~2)~kSWr+H#DP&1R*cUVXkV#RVX+5V4Rӣ=&!e֤]` %I!KRQB/s2{i72dJi !j)-H-(ct RZ-U`@WquB QDB]׸ I3rtN4 _`$~I/-ZmؔϋY Bl, ?Ɍ~ғIߗ6%H]ZZ h0ZK#Z+1F1JZku"k:BY+plM/E-5\ BXD' !6@oU}e#D:c6dvԂu TIfgm24{>1 DaoPsqӑ* b !("DoC %|ϓ2Fh L [9ND"1XkqMk 5> B e@pGK2S'p d暃{;4Μŵm*D ':?^9Ch=z[33DnEk _1ɟ<9 [q,b"4L AOR8g KK82=Ӽg3lBecxe6vҳԏ\Ӌ E=4fonU)hܣ~!4n%bB {dyr 0P0\DtdU!?rJAu <~6ժB\>RCcGvzdf(]@]9@`HFOy ݴj"B=HF`۸+]RSNnĴ>U@P Fcr-uBVdǫ,ܥCEQِB/;/c~'E5FabbhS!=]2s*@(!PEYLv?,zY5|\}V=D X[R>_=Ø5cqN|R DmO Oq|} UĐT/(VJQC+YL)V]Ix\qOx7\jB¿gF465"%Jx-u5:٢= JTSהE|%I  Cߐ-"Klx0lP|hthf9oC|ca|:""*n֥ߜd\06}uF4bkpMƨi 44 :͙sgϾIŬ*8U(,f"ӱe Vآ"db$0]lnhc\ijKjX,8sX*a4AD;݊sO[G{6ZN_szO(¶ LVv*ERkkvqj_/7VyIENDB`kupfer-328/auxdata/hicolor/32x32/000077500000000000000000000000001500175051100165265ustar00rootroot00000000000000kupfer-328/auxdata/hicolor/32x32/apps/000077500000000000000000000000001500175051100174715ustar00rootroot00000000000000kupfer-328/auxdata/hicolor/32x32/apps/kupfer.png000066400000000000000000000043251500175051100214770ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYsZZhtEXtSoftwarewww.inkscape.org<RIDATX͗klwf]{c&v؎c&-*$@~UU T @V?~@EHD)-HHEBTQ!'?{c_3;s퇵oҴEj=ߜs;?6e&`p2ƚv1o;ByoT'9_ 7'ھq}gs" t( c=NN/dN~}\_qն3]8Zu/ Aӳ}rԅf4JK*¾]ۺ^~oM0ggy81SHaOr[ ӭX~醁I;w5?M*sоO)MruD7ogGdz+@xONegI^e^?@ywӳ2dՅ4?ڐ *0'f׮m?X@6Ȋ_#+6uQRW`< ɦsK29u#Wsfě)Hr<VM\Ƴ`Zh0I0 ] DVVkpg'MK6f_~*1F*L$ Kt]]$" 1)Z\niJXNF]a%4gؼT K?jz\k0 Y0| GjNyD5廊*RU\ gO<-wbI+/Pq/_H~qmPR;>*c=\ ,.8ahWLVXnb&_cyevNMrG9/#}Ї3wGڶ&Ҋ!j˨\)XFm5xKm9126=֡Hoعs8N( Ft([[ޢOmܐN%c K( $Evn~LjuVˣ'dž.Dž떫j%ǎ,|.~]fwh4!M3! HAۛ;doX5иvjvr Ebb ̜G33V S5M)m{8,שK#'!8ais7uȹ}qoJ#xb’S7ϕO!KZ ՅFa obhk2B`+e!i8к ,W**y~SSLR*RĨ޻w_T\ew|HyzIENDB`kupfer-328/auxdata/hicolor/48x48/000077500000000000000000000000001500175051100165445ustar00rootroot00000000000000kupfer-328/auxdata/hicolor/48x48/apps/000077500000000000000000000000001500175051100175075ustar00rootroot00000000000000kupfer-328/auxdata/hicolor/48x48/apps/kupfer.png000066400000000000000000000100171500175051100215100ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs}xtEXtSoftwarewww.inkscape.org<IDAThi\WumhZˌI#ɒ%[%#/" !SP`rBXbB*|TRI a+!@6!HH Ll#K,۲fF2Y׷%zEUV~s]f |fUƢ@hLXf <ϵ%9Ldv<|Js굪- _wϷd?;nNF# כ]({*W."F)tÐX~=mpwykpn3/ ӥGu#|>~j;O%s)9rhza0O 8$v<a.8X<ijO >s?\94qLW mVwݭr8>]mw֔!h.5dgf߾La3ة v" B0ŗw`70zI:BK6.O3SLY@XQOgͺvOprxI6# ?B[2N6b!ƀVh@*JHmO[^\hgWI$ gP-u7_i7n\ĵ%C# ?]0P|;ӂ[ױ=mIq,/W5ajnf`*V.yx2|8jɠMor$X6a%n~Nnv2`j%(T]h46wgq%/Rmq{*NJ׈\3qncn61ˍ~!4Kh۴&yCC;:x߽W1Zz Y* Ƒ :1aQ4Q ي/ #AJXxݐ#āΖگ.Oli/БD!Q*<,LM^GN# jɆ2 ӺzYگҕw6pm+M;|l[s12*ZQPT+#F3>7B)PaBdbFh۲cN)Mרe{/NKR1 zXkXKi/\+Q&kXr%±,a L6J#$kvJ_!t @er04iz7MbiWzaʀ440vi6@IUZN\RR-רT*u~DjNz?Md;BO;Rn[hCzE Y3gI\?D7Z놹>4j)ĥ^sBqϿ  ?yIԠp@lE 3Y`EDj2D}A&I_gtȁ?I*(`'(^{IǬސ X 5#L@dQ@>~wtRNdTݨ)+]{-L\o} BҀ`E sn`HH)Q٧fev'$ n9t':Tb@B]AUtne5~|1s?r< \-Gx LWV%\K 3,W?g B5ٖҙLzLq,l1oY.R# ϭ}$5@F >wrakƱTL:ؠ(_p[ F^̮N"z*OM0)_ŕp0Fk5~%oh@ùgOq3l޶[ҵyy "W^ο :±3VgHX6r(*.C\qwC*{WsˡHڐڠ$Z12o@@d֝4Q#u렻3?\+L1+MV_|@`'22V5_\wy`|K:+Tv&Dńs+ts ! 5 Z280Nd)R=張<_e߿+]*R|8Ozr:·6$%1>Qb\Y6ٮn~R|-KBc?2Zl#7" ,cy# $U4Gq %l1?i*ٴw12U1? _]벷}WFKu4݌Y"f!:aTB1M2lXkxhMY|W7/"JlP5f|=ff@iJUb6}& vJ?˜_ X幗kٍ;H5άg 4bFAJ2knjؗ.a(I'l*9G8݅%,N?7ge-z6n'3gk}qJ` >v^9붯^DAps5m+K3΂̓ȴеʉɓZ'no<'VE_L@g+^gLNM/kfe?c;ev<#,QQ0 ,Jx~Ց1lk,ng[48p\uܤ:ioSݻwv1O @9r:[8˗]JbAWN*n0HxHZ~{ʃYGڶky/|"+ Lhn@gHgiLۆij9^}EY?u'9B6Web1߮V`ÆtZ;vL3MsvhzIlj0۱XҊn$5*!Hnc6ls , T Q3zY|q i NkƘ]5Duu5j cXtĉK+8}ٞ9Z0)bqmǔ qq-D܊t,f;M倫x&krm$3y1 U+䘨W˄74%?|*^AV`kmJvL]*Rme :,+ P9sF5bO8q谲WSSS"'Ĵ'\!"G+pl˲mp|mlpjd#Zdٓ;}eQ*c4JCXI8dKuÇ뾾G6bGCCCV>Ţ}ߒR -*%(T*%Rm`Wu]]mc9E8<ؘǎkZ'ORV3׷lE+OhIENDB`kupfer-328/auxdata/hicolor/64x64/000077500000000000000000000000001500175051100165405ustar00rootroot00000000000000kupfer-328/auxdata/hicolor/64x64/apps/000077500000000000000000000000001500175051100175035ustar00rootroot00000000000000kupfer-328/auxdata/hicolor/64x64/apps/kupfer.png000066400000000000000000000136761500175051100215220ustar00rootroot00000000000000PNG  IHDR@@iqsBIT|d pHYs-OCtEXtSoftwarewww.inkscape.org<;IDATxy\}?c .@[  HS6eK]V%**J*q\*MUJ"U*rlJe;V!;,+$("A$.@X{# uU7ۿOI[YQ$۱ KF @Kʼ\F0a|?i~b<>~I[68RvuvJbqDR)sδI͹֖oJ_՟?VLLM-o]pm`&XzIXbnϜԹ sy ygݖ7"j{ Dyd,Iƽ$n&/&&%=sWxz3l;w!L3k&2 \bk֓覩OPQJ-Ci<%iټkϏӣrQJo>^{DlG{]]䮼A0uau:¦557g_+/1߱-\xz6avfo=*9zs_]鈗Z>K.oO~#Iz6rxkneƛ6=?Cr:/x?? %TCAD3-["D_r5ypdh^ ӷ%71t]X'C>󑞋‘X(L^ΏKr`3[vy8~ʌ&L&͆n筛3]Jf;~hsOk`JogOW=&*D'ljǑ8pQVI 0`H l}h#[NTJ-W[k34uŹ8t©Y^||f -<{xK3Nl4V}O6k c?/B[hD'I$>uATPY@X47_oicpxiʧi'q=ك|Y&1ik;] `8߰ȯo?Ov(&cd3N H uN)V &wĒM>\C{`޾>M.P~a?:ѽOqhck Y|jźY?*hzg̋I6㶴uvⶶ#Z5Bxs!%sN1[l>p~rDYL!ˡ}b0OqE@\"c.Aj0K$ 9 \|}d<ԂցލҶ2x8途Ȋvn|/cBn^">}$Rt B d-X7e&eйx>2ق։%pb]!SXSF=cQǺ*D3oDvy _ҕ AV ٰDk[xul-kkFMk ,6 Jar-VyRc:Lj>EܕlLH)"3ü†M]IKԽ@rDٲ1kTdbCes|S*bàaZcʤR͉8k>LV+t)0MC+v$=nмfQ4VQ p\56(%L tUTuUL޿rRvbN ayT!BK}k0a=.%:0 )pB,3kQp[5 (kBP*kJ0JIP::QV `j3#l |j'C0a{@XXt--Dap4ׂ45*n$X1:D!6a#t0.{ tTJaA;MЕ#h\`{sLFR=PJ/:HMmVl)cA[ "T ˊge4VEVVXoSHS7)&\h/'ݗ^R4}{O!oMxy8 "tUp$HJc3/5v]bh 鰱ٗEOc>0o>_ ]pUյ$^'h-rksiDZO>E2jםs:{LV Z,, f,'@U,<5!fz+$Aoc.(W\Fv)We/-6ԐQk3%n> +$Ic @׿7ɤ3UŅS/,)5T.,8~|Z7am<;2EE2L]B-~sWa]Tk_+@, 2PU|4any WOxe%qyp5]4 8W R(M1;W2[zt9UkX:X֍IlwtW(NUp>YHf/QY<,dV.ܘcg]WV¹O Y⑝륇!{N` }<{+ NW^,ˬ|Mzڿ0Uqdc'Ԇ_jJXo'jslUsEژ17Y5m]8V]RsS0J Ff zpT.'^e+93Y:_j7 8M\=L e?~glK m+^ zB-0_XjVK+}d%&n7/z.)$vt XWj4 + tش^w{/l4J#`DSgG zDʍKOeu '=yXxr|{+d#Big"s?Q> `Yk-z*B׶\ $݇̚1ϋM?< 3)BxWNEH1hjxu٩lo Zn{5 кfu?@˧TPIS4Vio㍌ȑctuu9v=%?|1;$K!=|Ha{!ddszq3HZ ~Iw=L;q ^;mHHj}鶶6m6Op1ɓ5Gıc8y̙3tqX&sC.1kSo͘d}~RzckuHGrz x<wc_~A_t76 O;77LNNW>4&ǏqZ[o8x^^NqoYw~ mٶ]nڽ?D%fkGI*w-=lc`A!sgxaDFL{զo%B dhl)jv`^H Hez'w:22"yYNmɤo7FŬ\c\H*ˎ#nwBkd&'NOR̦4/޿!D7x{M.5n"m)oyyYhaek("ҁn [0S(}޽[͙;wZFF$x pvXkD튱 k@qs6Gŭᵟ~عn~Vgh#[cA~PAÀٛWy\}Nf#ԌC( [w*˺2zͫǎ==2~뺮`b縉5Ǻ>c|pȘOZkGzgMq0]:mҝNK{pq||T"NTjFgRZH1za[3h!B 'e:R("T( 2uP)J7isɪSUɓG޸qIHxhў,܂1# x Cykp] =OX߳X! !ޝF(^ǹPұ Pnd-%,Db)YMQ% M24j``@OOOǎFFKQ1==-緊N":AsLx]$}q#(G9(#1ҳVX]p$+Qp!RJ#Z:ugv(qӤ„(ұ\δX,fꖖܹӎ.UX,prd~z_tZyJ A+%ڔZJ?^7B86q] n:c @{{47n4'N0R!wB_,EI5Ν;?R&ПTS kupfer-328/auxdata/kupfer-exec.desktop.in000066400000000000000000000002371500175051100205260ustar00rootroot00000000000000 [Desktop Entry] Version=1.0 Type=Application Exec=kupfer-exec %F _Name=Execute in Kupfer Icon=kupfer NoDisplay=true StartupNotify=true MimeType=text/x-kfcom; kupfer-328/auxdata/kupfer-mimetypes.xml.in000066400000000000000000000006051500175051100207440ustar00rootroot00000000000000 <_comment>Saved Kupfer Command kupfer-328/auxdata/kupfer.desktop.in000066400000000000000000000004361500175051100176050ustar00rootroot00000000000000[Desktop Entry] Version=1.0 _Name=Kupfer _GenericName=Application Launcher _Comment=Convenient command and access tool for applications and documents Icon=kupfer Exec=kupfer %F Type=Application Categories=Utility; StartupNotify=true X-UserData=$CONFIG/kupfer;$DATA/kupfer;$CACHE/kupfer kupfer-328/auxdata/wscript000066400000000000000000000067771500175051100157450ustar00rootroot00000000000000#! /usr/bin/env python import os from waflib import Options, Utils, Logs def options(opt): opt.add_option( "--no-hooks", action="store_true", default=False, help="Don't run any mime, icon cache or similar update hooks [Default:False]", ) opt.add_option( "--no-update-mime", action="store_true", default=False, help="Do not update mime and desktop databases [Default:Update]", ) opt.add_option( "--no-update-icon-cache", action="store_true", default=False, help="Do not update icon cache [Default:Update]", ) def configure(conf): if not Options.options.no_update_mime and not Options.options.no_hooks: conf.env["AUXDATA_MIME"] = 1 if ( not Options.options.no_update_icon_cache and not Options.options.no_hooks ): conf.env["UPDATE_ICON_CACHE"] = 1 def build(bld): # merge translations into the .desktop file # and set it up to be installed def install_desktop_file(desktop_subst_file): return bld( features="intltool_in", podir="../po", flags=("-d", "-q", "-u"), source=desktop_subst_file + ".in", target=desktop_subst_file, install_path="${DATADIR}/applications", chmod=0o755, ) k_desktop = install_desktop_file("kupfer.desktop") _x_desktop = install_desktop_file("kupfer-exec.desktop") ## install kupfer.desktop as a Thunar sendto object kd_install = os.path.join( Utils.subst_vars(k_desktop.install_path, bld.env), "kupfer.desktop" ) symlink_location = Utils.subst_vars( "${DATADIR}/Thunar/sendto/kupfer.desktop", bld.env ) symlink_target = os.path.relpath( kd_install, os.path.dirname(symlink_location) ) bld.symlink_as(symlink_location, symlink_target) ## install mimetype descriptions mimetypes_file = "kupfer-mimetypes.xml" bld( features="intltool_in", podir="../po", flags=("-x", "-q", "-u"), source=mimetypes_file + ".in", target=mimetypes_file, install_path="${DATADIR}/mime/packages/", ) def update_mime(bld): Logs.pprint("GREEN", "Updating mime database") bld.exec_command( [ "update-mime-database", Utils.subst_vars("${DATADIR}/mime", bld.env), ] ) bld.exec_command( [ "update-desktop-database", Utils.subst_vars("${DATADIR}/applications", bld.env), ] ) if bld.is_install and bld.env["AUXDATA_MIME"]: bld.add_post_fun(update_mime) ## install kupfer icon icons_inst = bld.install_files( "${DATADIR}/icons/hicolor", bld.path.ant_glob("hicolor/**"), cwd=bld.path.find_dir("hicolor"), relative_trick=True, ) def update_icon_cache(bld): icon_dir = Utils.subst_vars("${DATADIR}/icons/hicolor", bld.env) if not Options.options.destdir: Logs.pprint("GREEN", "Updating Gtk icon cache.") command = f"gtk-update-icon-cache -q -f -t {icon_dir}" bld.exec_command(command) else: Logs.pprint( "YELLOW", "Icon cache not updated. After install, run this:" ) Logs.pprint("YELLOW", f"gtk-update-icon-cache -q -f -t {icon_dir}") if icons_inst and bld.is_install and bld.env["UPDATE_ICON_CACHE"]: bld.add_post_fun(update_icon_cache) kupfer-328/bin/000077500000000000000000000000001500175051100134275ustar00rootroot00000000000000kupfer-328/bin/kupfer-exec.in000077500000000000000000000015161500175051100162030ustar00rootroot00000000000000#!/bin/sh # This is a helper program to execute saved command files, # by sending them to a running instance of Kupfer. export TEXTDOMAIN='@PACKAGE@' export TEXTDOMAINDIR='@LOCALEDIR@' PYTHON='@PYTHON@' if test ! -f "$1" then echo "A file argument required" exit 1 fi SERVICE="io.github.kupferlauncher" OBJ="/io/github/kupferlauncher" IFACE="io.github.kupferlauncher.Listener" while test $# != 0 do FILE=$(readlink -f "$1") dbus-send --print-reply --dest=$SERVICE $OBJ \ $IFACE.ExecuteFileOnDisplay string:"$FILE" \ string:"$DISPLAY" string:"$DESKTOP_STARTUP_ID" \ > /dev/null 2>&1 KUPFER_RUNNING=$? if test $KUPFER_RUNNING != 0 then # NOTE: If you change this string, you have to change # it inside kupfer/version.py as well. zenity --info --text "$(gettext 'Could not find running Kupfer')" & exit 1 fi shift done kupfer-328/bin/kupfer.in000077500000000000000000000051161500175051100152610ustar00rootroot00000000000000#!/bin/sh # kupfer A convenient command and access tool # # Copyright 2007--2017 Ulrik Sverdrup # # 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 . # This script invokes kupfer by calling an already running instance, or # starting a new if none is found running. _hasprefix () { test "x${1#$2}" != "x$1" } PYTHON="@PYTHON@" PYTHONDIR="@PYTHONDIR@" _hasprefix "$PYTHON" "@" && PYTHON=python3 _hasprefix "$PYTHONDIR" "@" && PYTHONDIR=$(dirname $(readlink -f -- $0))/.. SERVICE="io.github.kupferlauncher" OBJ="/io/github/kupferlauncher" IFACE="io.github.kupferlauncher.Listener" # If there are any options, like "--help", we run Kupfer directly _hasprefix "$1" "--" KUPFER_HAS_OPTIONS=$? # We allow reading directly from stdin if we pipe text into Kupfer if [ ! -t 0 -a $# = 0 -a -z "$DESKTOP_STARTUP_ID" ] then echo "kupfer: Reading from stdin" >&2 TEXT_INPUT=$(cat) fi test $KUPFER_HAS_OPTIONS != 0 && dbus-send --type=method_call --print-reply \ --dest=$SERVICE $OBJ $IFACE.PresentOnDisplay string:"$DISPLAY" \ "string:$DESKTOP_STARTUP_ID" >/dev/null 2>&1 KUPFER_RUNNING=$? if test \( -n "$TEXT_INPUT" -a $KUPFER_HAS_OPTIONS != 0 \) then dbus-send --type=method_call --dest=$SERVICE $OBJ \ $IFACE.PutTextOnDisplay string:"$TEXT_INPUT" \ string:"$DISPLAY" string:"$DESKTOP_STARTUP_ID" fi _realpaths () { # Emit realpaths for arguments, separated by NUL bytes while test $# != 0 do LINK=$(readlink -e -- "$1") if test $? != 0 ; then echo "Error: $1 does not exist" >&2 shift continue fi printf "%s\0" "$LINK" shift done } if test \( -n "$1" -a $KUPFER_HAS_OPTIONS != 0 \) then # NOTE: We must escape commas here since it is dbus-send's # array item separator. This is then unescaped by kupfer ARRAY=$(_realpaths "$@" | sed -e 's/,/%%kupfercomma%%/g' | tr \\0 ,) dbus-send --type=method_call --dest=$SERVICE $OBJ \ $IFACE.PutFilesOnDisplay array:string:"$ARRAY" \ string:"$DISPLAY" string:"$DESKTOP_STARTUP_ID" fi if test $KUPFER_RUNNING != 0 then exec ${PYTHON} "$PYTHONDIR/kupfer.py" "$@" fi kupfer-328/data/000077500000000000000000000000001500175051100135705ustar00rootroot00000000000000kupfer-328/data/credentials_dialog.ui000066400000000000000000000233061500175051100177470ustar00rootroot00000000000000 True False gtk-cancel True False gtk-save False 6 User credentials False True center dialog Kupfer User credentials True False vertical 12 True False end Cancel True True True icon_cancel False False 0 _Change True True True True True icon_save True False False 1 False False end 0 True False vertical 12 True False 0 gtk-dialog-authentication 6 True True 0 True False 6 12 True True False _User: True 0 0 0 True True True 1 0 True False _Password: True 0 0 1 True True True False 1 1 True True 1 True False True False gtk-dialog-info False True 0 250 True False 10 15 True 0 True True 1 False True 2 False False 1 button_cancel button_ok kupfer-328/data/defaults.cfg000066400000000000000000000043741500175051100160700ustar00rootroot00000000000000# This is the kupfer default configuration file # This file is not intended to be modified; # users should modify their settings in # $XDG_CONFIG_HOME/kupfer/kupfer.cfg # (normally ~/.config/kupfer/kupfer.cfg) # The separator is semicolon (;). Continued lines # have to be indented [Kupfer] Keybinding = space MagicKeybinding = ShowStatusIcon = True UseCommandKeys = True action_accelerator_modifer = ctrl [Keybindings] activate = a comma_trick = comma compose_action = Return erase_affinity_for_first_pane = mark_as_default = reset_all = r select_quit = q select_selected_file = select_selected_text = g show_help = F1 show_preferences = semicolon switch_to_source = toggle_text_mode_quick = period [Tools] terminal = kupfer.plugin.core.gnome-terminal editor = kupfer.plugin.core.sys-editor icon_renderer = kupfer.plugin.core.gtk [Appearance] icon_large_size = 128 icon_small_size = 24 list_height = 250 ellipsize_mode = 0 # Catalog: The sources of the plugin are included # as subcatalogs in the main search catalog, and # its items are not available in the main catalog # Directories to keep in catalog [Directories] Catalog = Direct = ~/; USER_DIRECTORY_DESKTOP; # Deep directories are recursive down to @depth [DeepDirectories] Depth = 2 Catalog = Direct = [plugin_core] kupfer_enabled = True kupfer_hidden = True [plugin_applications] kupfer_enabled = True [plugin_archivemanager] kupfer_enabled = True [plugin_calculator] kupfer_enabled = True [plugin_clipboard] kupfer_enabled = True [plugin_commands] kupfer_enabled = True [plugin_dictionary] kupfer_enabled = True [plugin_documents] kupfer_enabled = True [plugin_favorites] kupfer_enabled = True [plugin_fileactions] kupfer_enabled = False [plugin_qsicons] kupfer_enabled = True [plugin_session_gnome] kupfer_enabled = False [plugin_session_xfce] kupfer_enabled = False [plugin_screen] kupfer_enabled = False [plugin_show_text] kupfer_enabled = True [plugin_tracker1] kupfer_enabled = False [plugin_triggers] kupfer_enabled = True [plugin_trash] kupfer_enabled = True [plugin_urlactions] kupfer_enabled = True [plugin_volumes] kupfer_enabled = True [plugin_wikipedia] kupfer_enabled = True [plugin_windows] kupfer_enabled = False kupfer-328/data/getdata_dialog.ui000066400000000000000000000135071500175051100170650ustar00rootroot00000000000000 False 6 Kupfer False True center 300 dialog center Kupfer Get Data True False vertical 12 True False end gtk-close True True False True False False 0 gtk-ok True True True True True True False False 1 False False end 0 True False vertical 6 True False 0 0 False True 0 True False True 0 0 False True 1 True False 6 12 True True 2 True True 1 buttonclose buttonok kupfer-328/data/getkey_dialog.ui000066400000000000000000000225471500175051100167500ustar00rootroot00000000000000 True False gtk-cancel True False gtk-clear False 6 Set Keyboard Shortcut False True center normal static Kupfer Set Keyboard Shortcut True False vertical 12 True False end Clear True False False icon_clear False False 0 Cancel True False False icon_cancel False False 1 False False end 0 True False 12 True False gtk-preferences 6 True True 0 True False vertical 6 True False Set Keyboard Shortcut 0 0 True True 0 True False Please press desired key combination True 0 0 True True 1 True False 12 True False gtk-dialog-error False False 0 True False Keybinding could not be bound 0 False False 1 False False 2 True False 0 True True 3 True True 1 False True 1 buttoncancel kupfer-328/data/preferences.ui000066400000000000000000001551661500175051100164460ustar00rootroot00000000000000 True False gtk-add True False gtk-close True False help-contents True False gtk-remove True False edit-undo True False edit-undo False 10 Kupfer Preferences Preferences center kupfer Kupfer Preferences True False vertical 12 True True True False 12 12 True False vertical 12 True False vertical 6 True False Desktop Environment 0 True True 0 True False vertical 6 Start automatically on login True True False True True True 0 Show icon in notification area True True False True True True True 1 Show icon in notification area True True False True True True True 2 True False 6 12 True True False 1 0 True False 3 Terminal emulator: 0 0 0 True False 3 Text editor: 0 0 1 True False 1 1 False False 3 False True 1 False True 0 True False vertical 6 True False Appearance 0 False True 0 True False 6 12 True True False 128 112 96 80 64 48 40 32 24 16 1 2 True False 3 Small Icon Size: 0 0 2 True False 3 Large Icon Size: 0 0 1 True False 256 240 224 208 192 176 160 144 128 112 96 80 72 64 56 48 32 1 1 True False 1 0 True False 3 Icon set: 0 0 0 True False What sort of ellipsization should be applied to text. Restart may be required. 3 Text ellipsization: 0 0 3 True False in the middle at the end 1 3 False True 1 False True 1 False True 0 True False General False True False 12 vertical 6 True False vertical 6 True False <b>Global Keyboard Shortcuts</b> True 0 0 False True 0 True False vertical 3 True True in 90 True True 0 True False Reset True True True icon_reset1 False False end 0 False True 1 True True 1 False True 0 True False vertical 6 True False <b>Browser Keyboard Shortcuts</b> True 0 0 False True 0 True False vertical 3 True True True True in 100 True True 0 True False Reset True True True icon_reset2 False True end 0 False True 1 True True 1 True True 1 Use single keystroke commands (Space, /, period, comma etc.) True True False True False True 10 2 True False vertical 6 Action accelerators use Alt True True False True radio_actionaccelctrl False True 0 Action accelerators use Ctrl True True False True radio_actionaccelalt False True 1 False True 3 1 True False Keyboard 1 False True False 12 12 True False vertical 3 True True never in 200 True True 0 True True False gtk-clear False False False False 1 False True 0 320 True True True 1 2 True False Plugins 2 False True False 12 6 12 True False vertical 6 True False start start Inclusion in Top Level Searches True 30 0 False False 0 True False start start Marked sources have their objects included in top level searches. An unmarked source's contents are only available by locating its subcatalog. True 30 0 False False 1 0 0 True True True True external in 400 1 0 True False True True vertical 3 True True in 400 True True 0 True False Add True True True icon_add True False False end 0 Remove True False True True icon_remove False False end 1 False True end 1 1 1 True False vertical 6 True False start start Indexed Folders True 30 0 False False 0 True False start start Folders whose files are always available in the catalog. True 30 0 False False 1 0 1 3 True False Catalog 2 False True True 0 True False Help True True True icon_help False False 0 Close True True True icon_close False False end 1 False False 1 kupfer-328/data/progress_dialog.ui000066400000000000000000000103051500175051100173110ustar00rootroot00000000000000 True False gtk-cancel False 6 center 439 Kupfer Progress Dialog True False vertical 12 True False vertical 6 True False 0 True True 0 True False True middle 0 0 False True 1 True False True True 2 False True 0 True False Cancel True True True icon_cancel False False end 0 False True 1 kupfer-328/data/result.ui000066400000000000000000000077771500175051100154670ustar00rootroot00000000000000 True False gtk-close True False edit-copy False 10 center 800 600 kupfer Kupfer Result True False vertical 10 True True True True False word True True True 0 True False Copy True True True icon_copy False False 0 Close True True True icon_close False False 1 False True 1 kupfer-328/data/wscript_build000066400000000000000000000002411500175051100163620ustar00rootroot00000000000000# configuration defaults and ui files bld.install_files("${DATADIR}/kupfer/", "defaults.cfg") bld.install_files("${DATADIR}/kupfer/", bld.path.ant_glob("*.ui")) kupfer-328/help/000077500000000000000000000000001500175051100136075ustar00rootroot00000000000000kupfer-328/help/C/000077500000000000000000000000001500175051100137715ustar00rootroot00000000000000kupfer-328/help/C/Makefile000066400000000000000000000014231500175051100154310ustar00rootroot00000000000000pages=$(wildcard *.page plugin/*.page) htmls=$(patsubst %.page,%.html,$(pages)) all: $(htmls) index.cache index.cache : $(pages) echo '$@.in echo ' xmlns="http://projectmallard.org/1.0/">' >> $@.in for page in $(pages); do \ echo "" >> $@.in; \ done echo '' >> $@.in xsltproc `pkg-config --variable xsltdir gnome-doc-utils`/mallard/cache/mal-cache.xsl $@.in | xmllint --format - > $@ rm $@.in $(htmls) : index.cache $(htmls) : %.html : %.page xsltproc \ --stringparam mal.cache.file `pwd`/index.cache \ --param mal.chunk.chunk_top 1 \ `pkg-config --variable mal2html gnome-doc-utils` $< .PHONY: clean clean: rm -fv index.cache *.html kupfer-328/help/C/generalusage.page000066400000000000000000000064241500175051100172770ustar00rootroot00000000000000 How to start using Kupfer. Basic Usage
Keyboard Interface

Kupfer is to the largest part a keyboard-managed interface to applications and documents.

Kupfer's default mode is the command mode: If you type a query, kupfer will search for a match in its catalog.

The arrow keys allow you to browse query matches quite naturally, going to the previous or next match, and going up and down in the subcatalogs.

In command mode, some keystrokes have special meanings:

or Space

Go to the next match

or ShiftSpace

Go to the previous match

or /

Descend into an object with content

Backspace

Erase a character from the query. If the query is empty, go up a level

.

Activate free-text mode

,

Put selected object on the stack ("Comma Trick")

Additionally:

Return activates the current selection: the command is executed.

Escape clears the current selection.

Tab switches between the object and the action pane.

By default you show Kupfer using the global keyboard shortcut CtrlSpace.

See for more information.

Learning Habits

Kupfer remembers which objects and actions are used the most and which abbreviations you use to access them. When starting, you have to use the arrow keys at times to make it precise which object you want to find. After a few uses of that object, Kupfer will rank it higher.

The Catalog

The Catalog is the collection of objects you can access in Kupfer, such as documents and programs.

Objects in the catalog that have content, like folders, are marked with an arrow. Pressing will enter these objects. Much of the catalog is composed of subcatalogs; plugin subcatalogs do in general list objects that are also available directly from the top level. Subcatalogs can be used for a narrower view or search scope, when using Kupfer.

Most subcatalogs update their content automatically. For example, the Desktop folder source is always up-to-date.

kupfer-328/help/C/index.page000066400000000000000000000013431500175051100157370ustar00rootroot00000000000000 Ulrik Sverdrup ulrik.sverdrup@gmail.com 2009 Kupfer Development Team Creative Commons Share Alike 3.0 Kupfer Manual
Using Kupfer
About Specific Plugins
kupfer-328/help/C/introduction.page000066400000000000000000000013371500175051100173540ustar00rootroot00000000000000 Introduction to Kupfer. Introduction

Kupfer is an interface for quick and convenient access to applications and their documents.

The most typical use is to find a specific application and launch it. We have tried to make Kupfer easy to extend with plugins so that this quick-access paradigm can be extended to many more objects than just applications.

We hope that using Kupfer feels both very fun and different.

kupfer-328/help/C/keyboard.page000066400000000000000000000204251500175051100164320ustar00rootroot00000000000000 Complete keyboard shortcuts reference. Command Keys and Accelerator Keys
Keyboard Interface

In command mode, the following keystrokes have special meanings:

or Space

Go to the next match

or ShiftSpace

Go to the previous match

or /

Descend into an object with content

Backspace

Erase a character from the query. If the query is empty, go up a level

.

Activate free-text mode

,

Put selected object on the stack ("Comma Trick")

Quick access keys:

=

Activate free-text mode with = prefix (for )

/

Activate free-text mode (when nothing is selected) with / prefix (to input a rooted path)

Additionally:

Return activates the current selection: the command is executed.

Escape clears the current selection.

Tab switches between the object and the action pane.

The meaning of the keys Space, ., ,, / and = can not be changed, but you can deactivate their special meaning with the checkbox Use single keystroke commands in Kupfer Preferences.

Kupfer's Keyboard Shortcuts

These keyboard shortcuts are used in Kupfer's interface. They have the following meanings and default shortcuts (some have no default).

AltA

Alternate activate

Ctrl.

Toggle text mode

Ctrl,

The comma trick

Ctrl;

Show preferences window

CtrlR

Reset all

CtrlReturn

Compose command

Switch to 1st pane

Switch to 2st pane

Switch to 3st pane

CtrlQ

Select 'Quit'

Select 'Clipboard File'

Select 'Clipboard Text'

Select 'Selected File'

CtrlG

Select 'Selected Text'

F1

Show Help

How to configure a keyboard shortcut

Open Kupfer Preferences and go to the Keyboard tab.

Double-click the shorcut's row under Browser Keyboard Shortcuts.

Using the window that appears, press modifier keys and a letter or number key to set a shortcut. An example is pressing and holding Ctrl and then pressing and releasing T to bind CtrlT.

Action Accelerators

Action acclerators are a quick way to select or run a certain action on an object. All action accelerators use the same modifier key, which is Ctrl by default.

An action's accelerator is a key that is pressed together with the modifier to directly run the action on the currently selected object (in the case of actions that need an indirect object, the third pane will be focused instead).

How to configure an action accelerator

Open Kupfer and find an object that allows the action you are configuring. Switch to the action pane with Tab.

Find the action to configure an accelerator for in the action pane.

Click the kupfer context menu in the window and select the option Assign Accelerator to “(Action)”

Press and release a single key (with or without the action accelerator’s modifier) in the window that pops up. Escape cancels the configuration, and Backspace unsets the accelerator key for the action.

Regular keyboard shortcuts in Kupfer take precedence over action accelerator keys. If multiple simultaneously eligible actions have the same accelerator key, the highest ranked one will be activated.

Global Keyboard Shortcuts

Kupfer always listens to global shortcuts, even if it is not currently in the foreground.

They have the following meanings and default shortcuts:

CtrlSpace

Show/hide Kupfer

(not configured by default)

Show Kupfer with 'Selection' object focused

How to configure a global keyboard shortcut

Open Kupfer Preferences and go to the Keyboard tab.

Double-click the shorcut's row under Global Keyboard Shortcuts.

Using the window that appears, press modifier keys and a letter or number key to set a global shortcut. An example is pressing and holding Super and then pressing and releasing Space to bind SuperSpace.

Since these keyboard shortcuts are global, they can be used from any application. Select shortcuts with care so that they do not conflict with other functions.

Triggers

The plugin Triggers allows to activate actions with global keyboard shortcuts. Trigger shortcuts do not appear in Kupfer Preferences.

See for more information.

kupfer-328/help/C/legal.xml000066400000000000000000000001231500175051100155730ustar00rootroot00000000000000

CC-BY-SA 3.0

kupfer-328/help/C/license.page000066400000000000000000000025701500175051100162550ustar00rootroot00000000000000 You can copy, modify and share Kupfer. License

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 gnu.org/licenses.

This documentation is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.

As a special exception, the copyright holders give you permission to copy, modify, and distribute the example code contained in this document under the terms of your choosing, without restriction.

kupfer-328/help/C/managing-plugins.page000066400000000000000000000106451500175051100200750ustar00rootroot00000000000000 Using plugins with Kupfer. How to Configure Plugins

Functionality in Kupfer is organized by extentsion modules called "plugins". Each plugin provides additional functionality, for example integration with an external application.

Configuring Plugins Open <app>Kupfer Preferences</app> to the Plugins tab

Use one of the following methods:

Click the Kupfer icon in the notification area and select the item Preferences

.

Search for the object Kupfer Preferences in Kupfer itself. Press Return to open it.

Use the keyboard shortcut Ctrl;

Select the tab Plugins

Select plugins in the list to read about them, and tick the box next to its name to activate the plugin, or untick to deactivate.

If the plugin has any configurable parameters, they will be visible below the plugin information.

The plugin Kupfer Plugins allows fast access to each plugin's information page as well as the action "Show Source Code" which reveals the implementation.

If a Plugin can not be Activated

If a plugin fails to activate because it requires a software module that is not available, its plugin information will display a message like this:

Plugin could not be read due to an error:

Python module 'gdata' is needed

This means that you need to install a needed python module from your distribution—and possibly the plugin documentation can tell you how.

The plugin may also unexpectedly fail to load, and display a different error message. It may then be a program error in either the plugin or Kupfer.

Installing more Plugins

You can install custom plugins into the folder ~/.local/share/kupfer/plugins. Each plugin is either a single .py file or a python package (a folder directly containing a file called __init__.py). Plugins in the package format can include icon files. Python packages can even be installed as .zip files.

Caution: Treat a plugin as a computer program. Do not install untrusted plugins.

Creating Plugins

Documentation for plugin creators is available in the file Documentation/Manual.rst in the source distribution on the webpage at Kupfer Manual. An easy way to start is to copy an existing plugin and experimenting with it.

The <em>Catalog</em> Tab in Preferences

Each plugin can export a number of sources which contain objects. Normally, all these objects are directly accessible from a top-level search. Some plugins export so specialized or so many objects that their catalogs should better not have their objects exported to the top level. To reach those objects, you have to first find the catalog by name, then enter the catalog using the action Search Contents.

In the tab Catalog in Kupfer Preferences, a ticked box next to each source means that its objects are exported. An unticked box means that its contents are hidden from the top level.

Note: Kupfer may become slow if large enough subcatalogs are exported to the top level.

kupfer-328/help/C/moreusage.page000066400000000000000000000152561500175051100166270ustar00rootroot00000000000000 More advanced usage information. Using <app>Kupfer</app> in Depth
Adding Applications and Scripts

Kupfer will show all applications that are configured visible in your menu editor.

If you want to add an application manually, you can create a new .desktop file and place it in one of the standard directories for applications, for example ~/.local/share/applications, where Kupfer will find it.

If you have a collection of scripts that you want to call from Kupfer, you can add the scripts folder as a catalog directory to Kupfer in the preferences. Scripts that you add to Kupfer's catalog this way can be run directly or in the terminal as long as they are executable.

You can also save command-lines by using the action Add to Favorites.

Opening Files and Folders

Using the action Open, files and folders are opened in their preferred application. The application associations can be changed, see .

Show Hidden Files

Use Alt instead of just when descending into a directory to list hidden files too.

The <em>Comma Trick</em>

The comma trick allows the user to use actions on many objects at the same time.

Simply press comma , when an object is selected. The object is put on a "stack", and you can find yet another file or object, press comma to put it on the stack. When you subsequently invoke an action, the action is carried out on all of the objects at the same time.

Some actions are only "multiplied" when used with many objects, other are smarter than that:

Selecting many files and using the Create Archive action, all files will be packed into the same archive.

If you select multiple contacts and use a Send Email action, it creates one email directed at all the contacts.

If you select multiple subcatalogs (For example Firefox Bookmarks and Epiphany Bookmarks) and use Search Contents.., you get a subcatalog search restricted to the objects of those two catalogs! You can even bind a trigger to this command(!)

The comma trick is directly taken from Quicksilver (the example given in the external article should work identically in Kupfer).

Grab Current Selection

To use the current selected text, from any application, with Kupfer, you can configure a global keyboard shortcut for the action Show with Selection in Kupfer Preferences.

If configured, pressing the global keyboard shortcut will summon Kupfer with the current selection as the focused object.

See

Command-line Connection

The command kupfer on the command-line will focus Kupfer if it's already running, otherwise it will start it.

The command kupfer can be used to send files or text from the command-line to Kupfer. For example, if you are using the shell in a directory where you have a file called "report.pdf", you can focus this file in Kupfer by running kupfer report.pdf.

You can also send text if you pipe the output of a command into kupfer.

Managing Context and Current Selection

If you find the object you want to use, then invoke an action, Kupfer goes away to perform the action (for example start a program or play a song). When you come back to Kupfer, it will still keep the same object and action selected. Some actions make sense to be repeated (like skipping to the next song) and it can be useful to perform different actions on the same object.

However, you always have the top level catalog reachable when you "come back" to Kupfer -- say you went into the subcatalog "Albums" to browse your albums only; you select an album to play, and play it. You come back with the album selected -- but your next search will still go over the top level catalog, not just albums.

How to come back into the subcatalog you were in? You do that by simply browsing, not searching the first thing you do when you focus Kupfer again. A quick way is to press down-arrow or space to open the browse window; think of it as saying "I want to stay in this subfolder". With the browse window open, your next query will search the current subcatalog.

This way you can work both ways -- you can quickly drill down into folders to find a file, and when you come back for the next action with Kupfer you can either summon any normal toplevel object (just start typing), or stay around where you were, deep in that folder (press space, then type a query).

Saving Commands as Files

You can use keyboard shortcut for Compose Command (by default it is CtrlReturn) to create a command object out of the currently focused command in Kupfer. This object can be saved as a runnable file if you use the Save As... action. The resulting file will can be executed when opened from the file manager (it requires that Kupfer is already running).

Ignoring Accents

You can find an object by an unaccented version of its name (this is more or less only implemented for latin-based alphabets). For example an item named Suð í can be matched with sud i because the accent is removed and the ð transliterated to d.

kupfer-328/help/C/plugin-applications.page000066400000000000000000000054261500175051100206200ustar00rootroot00000000000000 Using the applications plugin. <app>Applications</app>
Applications Plugin

Applications provides all installed programs.

Basic Usage Launching an application

Activate Kupfer and type an abbreviation of the application name

Press Return to launch the application.

Opening a file with a specific application

Select a file in Kupfer

Type Tab and select the action Open With...

Type Tab to select the third (indirect object) pane and in it, select the application to open the file with.

The action Open opens files and folders with the registered default application for that specific file type. This can be configured using the action Set Default Application....

The file type associations are provided by the desktop environment, and modifying them here will modify them on the desktop as well. This may not be true when not using GNOME or XFCE.

Selecting default application for a file type or folders

Select a file or folder in Kupfer

Type Tab and select the action Set Default Application...

Type Tab to select the third (indirect object) pane and in it, select the application to always open the file type with.

Configuration

The configuration option Applications for Desktop Environment in the plugin's information pane in Kupfer Preferences determines how Kupfer should act with regard to the desktop environment configuration—certain applications request not to be shown depending on which desktop environment is used.

The default setting is blank which means that it will use the environment variable XDG_CURRENT_DESKTOP to identify the desktop environment automatically.

kupfer-328/help/C/plugin-calculator.page000066400000000000000000000035411500175051100202570ustar00rootroot00000000000000 Using the calculator plugin. <app>Calculator</app>
Calculator Plugin

The calculator plugin lets you calculate expressions quickly. It can evaluate expressions entered as text starting with "=". Entering = from command mode will start text mode directly with = prefixed for quick access.

Basic Usage

Activate Kupfer and type =

Type in a mathematical expression using +,-,/,* (and ** for exponentiation)

Press Return to get the result.

Notes

The Calculator uses python's math and complex math modules, and parses expressions as Python expressions. You may use common mathematical functions, such as sqrt, sin, exp and log; the command =help will show a list of all defined functions and constants.

Notice that the power operator in Python is double stars, for example =3**3 will evaluate to 27.

To calculate trig functions for angles, convert to radians first:

sin(radians(30)) -> 0.5

The last result is stored as the name _ (an underscore, just like in the Python console).

kupfer-328/help/C/plugin-favorites.page000066400000000000000000000034701500175051100201310ustar00rootroot00000000000000 Using the favorites plugin. <app>Favorites</app>
Favorites Plugin

With Favorites you mark objects, for example files, for quicker access. It is a sort of shelf on which you can store objects in Kupfer. Objects marked as favorites will also be ranked higher and are adorned with a star symbol.

Basic Usage

Find an object in Kupfer

Type Tab and select either the action Add to Favorites or Remove from Favorites.

Power User Tips

If you favorite an object, you can access it in more places. Not only in the "Favorites" subcatalog, but also as the indirect (secondary) object for some actions. For example:

Command-lines from favorites are quick to access.

When scaling images with the Scale... action from the Image Tools plugin. This action needs a size description as the third object, like "1024" or "1200x800". If you often scale to the same size, say "1200x800", add this to favorites, and it will always appear as a suggestion for the action.

Actions needing an email address as the indirect object will pick up email addresses from favorites as well as well.

kupfer-328/help/C/plugin-notes.page000066400000000000000000000034241500175051100172560ustar00rootroot00000000000000 Using the notes plugin. <app>Notes</app>
Notes Plugin

With Notes you can access or create new notes in either the program Gnote or Tomboy. Notes will work identically with either application—you can configure which one to use in the plugin's information pane in Kupfer Preferences.

Basic Usage Creating a new note

Activate Kupfer and type . to enter text mode, then type in a note title

Type Tab and select the action Create Note and press Return.

Finding a note by title

Simply search for the note title in Kupfer

Finding a note by content

Activate Kupfer and type . to enter text mode, then type in a search query

Type Tab and select the action Get Note Search Results... and press Return.

Power User Tips

You can use the Selected Text object and create a new note with the content of the selection.

kupfer-328/help/C/plugin-thunar.page000066400000000000000000000022161500175051100174250ustar00rootroot00000000000000 Using the Thunar plugin. <app>Thunar</app>
Thunar Plugin

Thunar is a file manager, and with its plugin in Kupfer you can initiate a number of actions: empty trash, select file in thunar, show file properties, copy file to (...), move file to (...) and make symlink to file in (...).

Power User Tips

In Thunar itself configure a custom action for selecting files in Kupfer: Create a new custom action called Send to Kupfer with the command kupfer %F and enable it for all files.

If you can, temporarily enable editable menu accelerators to assign a shortcut key to the new custom action. If you now select files in Thunar and press the shortcut key, Kupfer will be summoned with the files selected.

kupfer-328/help/C/plugin-triggers.page000066400000000000000000000064651500175051100177640ustar00rootroot00000000000000 Using the triggers plugin. <app>Triggers</app>
Triggers Plugin

With Triggers you can take a command you would normally perform in Kupfer, such as launching an application or opening a document, and bind a global key combination to run this command. As long as Kupfer is running, any application can have the current focus.

Basic Usage Creating a new trigger

Set up a command in Kupfer that you want to run

Press CtrlReturn to create a composed command.

Type Tab and select the action Add Trigger... and press Return

Using the window that appears, press modifier keys and a letter or number key to set a global shortcut. An example is pressing and holding CtrlAlt and then pressing and releasing R to bind CtrlAltR.

Removing a trigger

Find the source Triggers in Kupfer and press to see its contents.

Find the active trigger in the list and use the action Remove Trigger.

Since trigger keyboard shortcuts are global, they can be used from any application. Select shortcuts with care so that they do not conflict with other functions.

Power User Tips

Proxy objects such as Selected Text, Clipboard Text, Clipboard File, Frontmost Window, Last Command et cetera allow very powerful triggers.

The application action Launch is special; if you bind a trigger using Launch, it will start the application if it is not running, but focus the application when it is already running. By contrast, Start Again will start the application if it is running or not.

Example Triggers <em>Text Editor → Launch</em>

Start Text Editor or focus its window if it is already running.

<em>Selected Text → Search in Wikpedia</em>

Search using the currently selected text.

<em>Songs → Search Contents</em>

You may even add a trigger to open a specific subcatalog in Kupfer, for example Rhythmbox's songs.

kupfer-328/help/Makefile000066400000000000000000000007671500175051100152610ustar00rootroot00000000000000# This makefile is for convenience. # # Run 'make' to build HTML documentation in the C directory # Run 'make $LANG' to update the translation file for language $LANG # # To add a new language, edit Makefile.am include Makefile.am C: make -C C $(HELP_LINGUAS): C/*.page msgfmt "$@/$@.po" -o "$@/$@.mo" itstool -m "$@/$@.mo" -o $@/ C/*.page html: for lang in C $(HELP_LINGUAS) ; do \ rm -r $$lang ; \ mkdir $$lang ; \ yelp-build html -o $$lang /usr/share/help/$$lang/kupfer ; \ done kupfer-328/help/Makefile.am000066400000000000000000000013511500175051100156430ustar00rootroot00000000000000# # This file defines variables and files for Kupfer's # mallard documentation. # # This file is needed for GNOME's translation infrastructure, # but it is never used as a real Makefile. # # Define all languages for translation in the variable HELP_LINGUAS # # @YELP_HELP_RULES@ HELP_ID = kupfer HELP_FILES = \ generalusage.page \ index.page \ introduction.page \ keyboard.page \ license.page \ managing-plugins.page \ moreusage.page \ plugin-applications.page \ plugin-calculator.page \ plugin-favorites.page \ plugin-gwibber.page \ plugin-nautilusselection.page \ plugin-notes.page \ plugin-thunar.page \ plugin-triggers.page \ plugin-websearch.page HELP_LINGUAS = cs de el es fr it pl ro sl # dist-hook: doc-dist-hook kupfer-328/help/cs/000077500000000000000000000000001500175051100142145ustar00rootroot00000000000000kupfer-328/help/cs/cs.po000066400000000000000000002114171500175051100151670ustar00rootroot00000000000000# Czech translation for kupfer help. # Copyright (C) 2010 kupfer's COPYRIGHT HOLDER # This file is distributed under the same license as the kupfer help. # # Marek Černocký , 2010, 2011, 2013. # msgid "" msgstr "" "Project-Id-Version: kupfer master\n" "POT-Creation-Date: 2014-03-23 21:59+0000\n" "PO-Revision-Date: 2013-03-24 06:06+0100\n" "Last-Translator: Marek Černocký \n" "Language-Team: čeština \n" "Language: cs\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: Gtranslator 2.91.6\n" #: C/plugin-websearch.page:7(desc) msgid "Using the search the web plugin." msgstr "Používání zásuvného modulu Prohledat web." #: C/plugin-websearch.page:10(app) msgid "Search the Web" msgstr "Prohledat web" #: C/plugin-websearch.page:13(title) C/plugin-triggers.page:23(title) #: C/plugin-notes.page:22(title) C/plugin-nautilusselection.page:13(title) #: C/plugin-gwibber.page:25(title) C/plugin-favorites.page:22(title) #: C/plugin-calculator.page:21(title) C/plugin-applications.page:19(title) #: C/generalusage.page:10(title) msgid "Basic Usage" msgstr "Základy používání" #: C/plugin-websearch.page:15(p) msgid "Activate Kupfer and make sure it is in free-text mode (press period)" msgstr "" "Aktivujte Kupfer a ujistěte se, zda je v režimu volného textu (zmáčkněte " "tečku)" #: C/plugin-websearch.page:17(p) msgid "" "Type in a search query and tap Tab to switch to the action pane." msgstr "" "Napište hledaný dotaz a ťukněte na Tab, čímž se přepnete na panel " "akce." #: C/plugin-websearch.page:19(p) msgid "" "Type \"Search With\" to find Search the Web's action and tap Tab " "again to switch to the third pane (indirect object)." msgstr "" "Napište „Prohledat pomocí“, abyste našli akci z Prohledat web a ťuknutím na " "Tab se přepnete na třetí panel (nepřímý objekt)." #: C/plugin-websearch.page:22(p) msgid "" "Select search engine with the arrow keys and type Return to open " "the search in a web browser." msgstr "" "Šipkou vyberte vyhledávací stroj a zmáčknutím Enter otevřete " "hledání ve webovém prohlížeči." #: C/plugin-websearch.page:29(title) msgid "Search Engines" msgstr "Vyhledávací stroje" #: C/plugin-websearch.page:30(p) msgid "" "The Search the Web plugin uses Firefox' search engines, so you " "can add Search Engines directly in Firefox and Kupfer " "will find them later." msgstr "" "Zásuvný modul Prohledat web používá vyhledávací stroj aplikace Firefox, takže můžete přidávat vyhledávače přímo do aplikace Firefox " "a aplikace Kupfer si je následně najde také." #: C/plugin-websearch.page:35(p) msgid "" "You can also install custom search plugins directly, only for Kupfer, in the folder:" msgstr "" "Můžete si také nainstalovat přímo, pouze pro aplikaci Kupfer, " "vlastní vyhledávací zásuvné moduly a to do složky:" #: C/plugin-websearch.page:39(code) #, no-wrap msgid "~/.local/share/kupfer/searchplugins/" msgstr "~/.local/share/kupfer/searchplugins/" #: C/plugin-websearch.page:40(p) msgid "The search engine descriptions must written in OpenSearch format." msgstr "Popisy vyhledávacích strojů musí být napsané ve formátu OpeanSearch." #: C/plugin-triggers.page:7(desc) msgid "Using the triggers plugin." msgstr "Používání zásuvného modulu Spouštěče." #: C/plugin-triggers.page:10(app) C/keyboard.page:213(title) msgid "Triggers" msgstr "Spouštěče" #: C/plugin-triggers.page:13(title) msgid "Triggers Plugin" msgstr "Zásuvný modul Spouštěče" #: C/plugin-triggers.page:14(p) msgid "" "With Triggers you can take a command you would normally perform " "in Kupfer, such as launching an application or opening a " "document, and bind a global key combination to run this command. As long as " "Kupfer is running, any application can have the current focus." msgstr "" "Pomocí zásuvného modulu Spouštěče můžete vzít příkaz, který " "normálně v aplikaci Kupfer provádíte, jak například spuštění " "aplikace nebo otevření dokumentu, a přiřadit mu globální kombinaci kláves, " "kterou se bude spouštět. Kdykoliv aplikace Kupfer běží, může " "libovolná aplikace získat aktuální zaměření." #: C/plugin-triggers.page:25(title) msgid "Creating a new trigger" msgstr "Vytváření nového spouštěče" #: C/plugin-triggers.page:27(p) msgid "Set up a command in Kupfer that you want to run" msgstr "Nastavte v aplikaci Kupfer příkaz, který chcete spustit" #: C/plugin-triggers.page:32(p) msgid "" "Press CtrlReturn to create a " "composed command." msgstr "" "Zmáčknutím CtrlEnter vytvořte " "složený příkaz." #: C/plugin-triggers.page:38(p) msgid "" "Type Tab and select the action Add Trigger... and press " "Return" msgstr "" "Zmáčkněte Tab, vyberte akci Přidat spouštěč… a zmáčkněte " "Enter" #: C/plugin-triggers.page:44(p) msgid "" "Using the window that appears, press modifier keys and a letter or number " "key to set a global shortcut. An example is pressing and holding " "CtrlAlt and then pressing and " "releasing R to bind CtrlAltR." msgstr "" "V okně, které se objeví, zmáčkněte klávesový modifikátor a klávesu s " "písmenem nebo číslem. Tím klávesovou zkratku nastavíte. Například zmáčknutím " "a držením modifikátorů CtrlAlt a " "následným zmáčknutím a uvolněním R přiřadíte CtrlAltR." #: C/plugin-triggers.page:54(title) msgid "Removing a trigger" msgstr "Odstranění spouštěče" #: C/plugin-triggers.page:56(p) msgid "" "Find the source Triggers in Kupfer and press to see its contents." msgstr "" "Najděte v aplikaci Kupfer zdroj Spouštěče a zmáčknutím " " zobrazte jeho obsah." #: C/plugin-triggers.page:62(p) msgid "" "Find the active trigger in the list and use the action Remove Trigger." msgstr "" "Najděte v seznamu aktivní spouštěč a použijte akci Odstranit spouštěč." #: C/plugin-triggers.page:68(p) msgid "" "Since trigger keyboard shortcuts are global, they can be used from any " "application. Select shortcuts with care so that they do not conflict with " "other functions." msgstr "" "Vzhledem k tomu, že klávesové zkratky jsou globální, můžete je použít z " "kterékoliv aplikace. Z toho důvodu je ale vybírejte s rozmyslem, aby nebyly " "v konfliktu s jinými funkcemi." #: C/plugin-triggers.page:74(title) C/plugin-notes.page:60(title) #: C/plugin-gwibber.page:68(title) C/plugin-favorites.page:38(title) msgid "Power User Tips" msgstr "Rady pro pokročilé uživatele" #: C/plugin-triggers.page:75(p) msgid "" "Proxy objects such as Selected Text, Selected File, Frontmost Window, Last Command et cetera allow very " "powerful triggers." msgstr "" "Objekty proxy, jako je Vybraný text, Vybraný soubor, Okno zcela nahoře, Poslední příkaz atd., dávají " "možnosti pro velmi mocné spouštěče." #: C/plugin-triggers.page:79(p) msgid "" "The application action Launch is special; if you bind a trigger " "using Launch, it will start the application if it is not running, " "but focus the application when it is already running. By contrast, Start " "Again will start the application if it is running or not." msgstr "" "Aplikační akce Spustit je speciální. Když přiřadíte spouštěč akcí " "Spustit, bude spouštět aplikace, pokud již neběží, a pokud běží, " "tak jim bude předávat zaměření. Oproti tomu, Spustit znovu spustí " "aplikaci, ať už běží nebo ne." #: C/plugin-triggers.page:87(title) msgid "Example Triggers" msgstr "Příklady spouštěčů" #: C/plugin-triggers.page:90(em) msgid "Text Editor → Launch" msgstr "Textový editor → Spustit" #: C/plugin-triggers.page:91(p) msgid "" "Start Text Editor or focus its window if it is already running." msgstr "" "Spustí Textový editor, případně zaměří jeho okno, pokud již běží" #: C/plugin-triggers.page:97(em) msgid "Selected Text → Search With → Google" msgstr "Vybraný text → Prohledat pomocí → Google" #: C/plugin-triggers.page:98(p) msgid "Search the web using the currently selected text." msgstr "Vyhledá na webu právě vybraný text." #: C/plugin-triggers.page:100(em) msgid "Selected File → Move To → (Downloads Folder)" msgstr "Vybraný soubor → Přesunout do → (složka Stažené)" #: C/plugin-triggers.page:101(p) msgid "Move the currently selected file to a specific folder" msgstr "Přesune právě vybraný soubor do zadané složky" #: C/plugin-triggers.page:105(em) msgid "Songs → Search Contents" msgstr "Skladby → Prohledat obsah" #: C/plugin-triggers.page:106(p) msgid "" "You may even add a trigger to open a specific subcatalog in Kupfer, for " "example Rhythmbox's songs." msgstr "" "Můžete také přidat spouštěč, který otevře zadaný podkatalog v aplikaci " "Kupfer, například se skladbami přehrávače Rhythmbox." #: C/plugin-notes.page:7(desc) msgid "Using the notes plugin." msgstr "Používání zásuvného modulu Poznámky." #: C/plugin-notes.page:10(app) C/plugin-calculator.page:37(title) msgid "Notes" msgstr "Poznámky" #: C/plugin-notes.page:13(title) msgid "Notes Plugin" msgstr "Zásuvný modul Poznámky" #: C/plugin-notes.page:14(p) msgid "" "With Notes you can access or create new notes in either the " "program Gnote or Tomboy. Notes will work " "identically with either application—you can configure which one to use in " "the plugin's information pane in Kupfer Preferences." msgstr "" "Pomocí zásuvného modulu Poznámky můžete přistupovat k poznámkám " "nebo je i vytvářet buď v aplikaci Gnote nebo Tomboy. " "Poznámky pracují úplně stejně v obou aplikacích – můžete si ji " "vybrat v informačním panelu zásuvného modulu v Předvolbách Kupfer." #: C/plugin-notes.page:24(title) msgid "Creating a new note" msgstr "Vytváření nové poznámky" #: C/plugin-notes.page:26(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "note title" msgstr "" "Aktivujte Kupfer, zmáčkněte . pro přechod do textového režimu a " "pak napište název poznámky" #: C/plugin-notes.page:32(p) msgid "" "Type Tab and select the action Create Note and press " "Return." msgstr "" "Zmáčkněte Tab, vyberte akci Vytvořit poznámku a " "zmáčkněte Enter." #: C/plugin-notes.page:39(title) msgid "Finding a note by title" msgstr "Hledání poznámky podle názvu" #: C/plugin-notes.page:41(p) msgid "Simply search for the note title in Kupfer" msgstr "Prostě nadpis poznámky v aplikaci Kupfer hledejte" #: C/plugin-notes.page:45(title) msgid "Finding a note by content" msgstr "Hledání poznámky podle obsahu" #: C/plugin-notes.page:47(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "search query" msgstr "" "Aktivujte Kupfer, zmáčkněte . pro přechod do textového režimu a " "pak napište vyhledávací dotaz" #: C/plugin-notes.page:53(p) msgid "" "Type Tab and select the action Get Note Search Results... and press Return." msgstr "" "Zmáčkněte Tab, vyberte akci Získat výsledky hledávání " "poznámek… a zmáčkněte Enter." #: C/plugin-notes.page:63(p) msgid "" "You can use the Selected Text object and create a new note with the " "content of the selection." msgstr "" "Můžete použít objekt Vybrat text a vytvořit novou poznámku s " "obsahem té vybrané." #: C/plugin-nautilusselection.page:7(desc) msgid "Using the selected file plugin." msgstr "Používání zásuvného modulu Vybraný soubor." #: C/plugin-nautilusselection.page:10(app) msgid "Selected File" msgstr "Vybraný soubor" #: C/plugin-nautilusselection.page:14(p) msgid "" "Select a file in the file manager. Open Kupfer and search for the " "object Selected File, which represents the file or files that are " "selected." msgstr "" "Vyberte soubor ve správci souborů. Otevřete aplikaci Kupfer a " "vyhledejte objekt Vybraný soubor, který reprezentuje soubor nebo " "soubory, které jsou vybrány." #: C/plugin-nautilusselection.page:19(p) msgid "" "Instead of searching, you can press CtrlG to directly focus the selected file. See " "for more information." msgstr "" "Místo hledání můžete zmáčknout CtrlG " "pro přímé zaměření vybraného souboru. Více informací viz ." #: C/plugin-nautilusselection.page:26(title) msgid "Selected File requires Nautilus" msgstr "" "Zásuvný modul Vybraný soubor vyžaduje aplikaci Nautilus" #: C/plugin-nautilusselection.page:27(p) msgid "" "The selected file plugin works with the Nautilus file browser and " "requires that the extension kupfer_provider.py is installed (it " "is normally installed together with Kupfer). After installing it " "for the first time, Nautilus must start anew before it is active." msgstr "" "Zásuvný modul Vybraný soubor pracuje se správcem souborů Nautilus " "a vyžaduje, aby bylo nainstalováno rozšíření kupfer_provider.py " "(to se normálně nainstaluje spolu s aplikací Kupfer). Po " "nainstalování se na poprvé musí nejdříve spustit Nautilus, aby " "došlo k aktivaci." #: C/plugin-gwibber.page:7(desc) msgid "Using the Gwibber plugin." msgstr "Používání zásuvného modulu Gwiber." #: C/plugin-gwibber.page:10(app) msgid "Gwibber" msgstr "Gwiber" #: C/plugin-gwibber.page:13(title) msgid "Gwibber Plugin" msgstr "Zásuvný modul Gwiber" #: C/plugin-gwibber.page:14(p) msgid "" "With the Gwibber plugin you can send messages to social networks " "such as Twitter or Identi.ca." msgstr "" "Pomocí zásuvného modulu Gwibber můžete posílat zprávy do " "sociálních sítí, jako je Twitter nebo Identi.ca." #: C/plugin-gwibber.page:18(p) msgid "" "The plugin requires that the application Gwibber is installed and " "configured for your user. Kupfer will start and use Gwibber's " "service in the background." msgstr "" "Zásuvný modul vyžaduje, aby byla nainstalována aplikace Gwibber a " "nastavena pro vás, jako uživatele. Aplikace Kupfer spustí a " "použije službu Gwibber na pozadí." #: C/plugin-gwibber.page:27(title) msgid "Sending a message to all services" msgstr "Odesílání zprávy na všechny služby" #: C/plugin-gwibber.page:29(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "message." msgstr "" "Aktivujte Kupfer, zmáčkněte . pro přechod do textového režimu a " "pak napište zprávu." #: C/plugin-gwibber.page:35(p) msgid "" "Type Tab and select the action Send Message and press " "Return." msgstr "" "Zmáčkněte Tab, vyberte akci Odeslat zprávu a zmáčkněte " "Enter." #: C/plugin-gwibber.page:42(title) msgid "Sending a message to a specific service" msgstr "Odesílání zprávy na vybranou službu" #: C/plugin-gwibber.page:44(p) msgid "" "Activate Kupfer and search for the service object, for example Identi." "ca" msgstr "" "Aktivujte Kupfer a vyhledejte objekt služby, například Tweeter" #: C/plugin-gwibber.page:50(p) msgid "Type Tab and select the action Send Message." msgstr "Zmáčkněte Tab a vyberte akci Odeslat zprávu." #: C/plugin-gwibber.page:55(p) msgid "" "Type Tab to select the last pane, and type in a message. Press " "Return to send." msgstr "" "Zmáčkněte Tab pro výběr posledního panelu a napište zprávu. " "Zmáčknutím Enter ji odešlete." #: C/plugin-gwibber.page:61(p) msgid "" "The plugin also provides a source for incoming messages, Gwibber " "Messages and more actions on messages such as Reply, Send " "Private Message etc." msgstr "" "Zásuvný modul poskytuje rovněž zdroje pro příchozí zprávy, Zprávy " "Gwibber a další akce se zprávami, jako Odpovědět, Odeslat " "soukromou zprávu atd." #: C/plugin-gwibber.page:71(p) msgid "" "You can use the comma trick if you want to send a message to more " "than one service, but not all, at the same time." msgstr "" "Jestliže chcete odeslat zprávu naráz na více služeb, ale ne na všechny, " "můžete použít vložení do zásobníku." #: C/plugin-favorites.page:7(desc) msgid "Using the favorites plugin." msgstr "Používání zásuvného modulu Oblíbené." #: C/plugin-favorites.page:10(app) msgid "Favorites" msgstr "Oblíbené" #: C/plugin-favorites.page:13(title) msgid "Favorites Plugin" msgstr "Zásuvný modul Oblíbené" #: C/plugin-favorites.page:14(p) msgid "" "With Favorites you mark objects, for example files, for quicker " "access. It is a sort of shelf on which you can store objects in Kupfer. " "Objects marked as favorites will also be ranked higher and are adorned with " "a star symbol." msgstr "" "Pomocí zásuvného modulu Oblíbené označujete objekty, např. " "soubory, pro rychlý přístup. Je to jakési odkladiště, ve kterém si můžete " "schovávat objekty. Objekty označené jako oblíbené jsou také výše hodnoceny a " "ozdobeny symbolem hvězdičky." #: C/plugin-favorites.page:25(p) msgid "Find an object in Kupfer" msgstr "Najděte v aplikaci Kupfer nějaký objekt" #: C/plugin-favorites.page:30(p) msgid "" "Type Tab and select either the action Add to Favorites " "or Remove from Favorites." msgstr "" "Zmáčkněte Tab a vyberte buď Přidat do oblíbených nebo " "Odebrat z oblíbených." #: C/plugin-favorites.page:39(p) msgid "" "If you favorite an object, you can access it in more places. Not only in the " "\"Favorites\" subcatalog, but also as the indirect (secondary) object for " "some actions. For example:" msgstr "" "Když nějaký objekt přidáte do oblíbených, můžete k němu přistupovat na více " "místech. Ne jen v podkatalogu „Oblíbené“, ale také jako k nepřímému " "(druhému) objektu některých akcí. Například:" #: C/plugin-favorites.page:45(p) msgid "Command-lines from favorites are quick to access." msgstr "Z oblíbených jsou rychle přístupné příkazové řádky." #: C/plugin-favorites.page:46(p) msgid "" "When scaling images with the Scale... action from the Image " "Tools plugin. This action needs a size description as the third " "object, like \"1024\" or \"1200x800\". If you often scale to the same size, " "say \"1200x800\", add this to favorites, and it will always appear as a " "suggestion for the action." msgstr "" "Když měníte rozměry obrázků pomocí akce Změnit velikost… v zásuvném " "modulu Nástroje na obrázky. Tato akce vyžaduje jako třetí objekt " "popis velikosti, např. „1024“ nebo „1200x800“. Pokud často měníte velikost " "na ty stejné rozměry, řekněme „1200x800“, přidejte si je do oblíbených a ony " "se pak vždy objeví jako doporučené pro akci." #: C/plugin-favorites.page:54(p) msgid "" "Actions needing an email address as the indirect object will pick up email " "addresses from favorites as well as well." msgstr "" "Stejně tak akce, které potřebují e-mailovou adresu jako nepřímý objekt, " "získají e-mailové adresy z oblíbených." #: C/plugin-calculator.page:7(desc) msgid "Using the calculator plugin." msgstr "Používání zásuvného modulu Kalkulačka." #: C/plugin-calculator.page:10(app) msgid "Calculator" msgstr "Kalkulačka" #: C/plugin-calculator.page:13(title) msgid "Calculator Plugin" msgstr "Zásuvný modul Kalkulačka" #: C/plugin-calculator.page:14(p) msgid "" "The calculator plugin lets you calculate expressions quickly. It can " "evaluate expressions entered as text starting with \"=\". Entering = from " "command mode will start text mode directly with = prefixed for quick access." msgstr "" "Zásuvný modul Kalkulačka vám umožňuje rychlý výpočet výrazů. Umí vyhodnotit " "výraz zadaný jako text začínající „=“. Zadáním = v příkazovém režimu spustí " "přímo textový režim začínající = pro rychlý přístup." #: C/plugin-calculator.page:23(p) msgid "Activate Kupfer and type =" msgstr "Aktivujte Kupfer a zmáčkněte =" #: C/plugin-calculator.page:26(p) msgid "" "Type in a mathematical expression using +,-,/,* (and ** for exponentiation)" msgstr "" "Napište matematický výraz s použitím +,-,/," "* (a ** pro mocninu)" #: C/plugin-calculator.page:30(p) msgid "Press Return to get the result." msgstr "Zmáčkněte Enter a obdržíte výsledek" #: C/plugin-calculator.page:38(p) msgid "" "The Calculator uses python's math and complex math modules, and parses " "expressions as Python expressions. You may use common mathematical " "functions, such as sqrt, sin, exp and " "log; the command =help will show a list of all defined " "functions and constants." msgstr "" "Kalkulačka používá moduly jazyka Python math a complex math a zpracovává " "výrazy jako výrazy jazyka Python. Můžete používat běžné matematické funkce, " "jako je sqrt (odmocnina), sin, exp a " "log. Příkaz =help vám ukáže seznam všech definovaných " "funkcí a konstant." #: C/plugin-calculator.page:47(p) msgid "" "Notice that the power operator in Python is double stars, for example " "=3**3 will evaluate to 27." msgstr "" "Všimněte si, že operátor mocniny tvoří v jazyce Python dvě hvězdičky, např. " "=3**3 bude vyhodnoceno jako 27." #: C/plugin-calculator.page:53(p) msgid "To calculate trig functions for angles, convert to radians first:" msgstr "" "Při výpočtu trigonometrických funkcí je zapotřebí nejprve převést úhly na " "radiány:" #: C/plugin-calculator.page:56(code) #, no-wrap msgid "sin(radians(30)) -> 0.5" msgstr "sin(radians(30)) -> 0.5" #: C/plugin-calculator.page:59(p) msgid "" "The last result is stored as the name _ (an underscore, just like in the " "Python console)." msgstr "" "Poslední výsledek je uchován pod názvem _ (podtržítko, stejně jako v konzole " "Python)." #: C/plugin-calculator.page:65(p) msgid "" "The Calculator lets you also calculate expression without \"=\" on the " "beginning as long it have inside one of operators: +, -, *, /, ^, |, &, " "~." msgstr "" "Kalkulačka umožňuje vypočítat výraz i bez znaku „=“ na začátku, stačí když " "obsahuje jeden z operátorů: +, -, *, /, ^, |, &, ~." #: C/plugin-applications.page:7(desc) msgid "Using the applications plugin." msgstr "Používání zásuvného modulu Aplikace." #: C/plugin-applications.page:10(app) msgid "Applications" msgstr "Aplikace" #: C/plugin-applications.page:13(title) msgid "Applications Plugin" msgstr "Zásuvný modul Aplikace" #: C/plugin-applications.page:14(p) msgid "Applications provides all installed programs." msgstr "" "Zásuvný modul Aplikace poskytuje všechny nainstalované aplikace." #: C/plugin-applications.page:21(title) msgid "Launching an application" msgstr "Spuštění aplikace" #: C/plugin-applications.page:23(p) msgid "Activate Kupfer and type an abbreviation of the application name" msgstr "Aktivujte Kupfer a napište zkratku pro název aplikace" #: C/plugin-applications.page:28(p) msgid "Press Return to launch the application." msgstr "Zmáčknutím Enter aplikaci spustíte." #: C/plugin-applications.page:34(title) msgid "Opening a file with a specific application" msgstr "Otevření souboru pomocí zadané aplikace" #: C/plugin-applications.page:36(p) msgid "Select a file in Kupfer" msgstr "V aplikaci Kupfer vyberte soubor" #: C/plugin-applications.page:41(p) msgid "Type Tab and select the action Open With..." msgstr "Zmáčkněte Tab a vyberte akci Otevřít s…" #: C/plugin-applications.page:46(p) msgid "" "Type Tab to select the third (indirect object) pane and in it, " "select the application to open the file with." msgstr "" "Zmáčkněte Tab pro výběr třetího panelu (nepřímého objektu) a v " "něm vyberte aplikaci, pomocí níž se má soubor otevřít." #: C/plugin-applications.page:53(p) msgid "" "The action Open opens files and folders with the registered default " "application for that specific file type. This can be configured using the " "action Set Default Application...." msgstr "" "Akce Otevřít otevře soubory a složky pomocí výchozí aplikace " "registrované pro zadaný typ souboru. Tuto aplikaci lze nastavit pomocí akce " "Nastavit výchozí aplikaci…." #: C/plugin-applications.page:58(p) msgid "" "The file type associations are provided by the desktop environment, and " "modifying them here will modify them on the desktop as well. This may not be " "true when not using GNOME or XFCE." msgstr "" "Přidružení souborů jsou poskytována pracovním prostředím a když je změníte " "zde, změní se i pro celé pracovní prostředí. Což ale nemusí být pravda, " "pokud nepoužíváte GNOME nebo XFCE." #: C/plugin-applications.page:64(title) msgid "Selecting default application for a file type or folders" msgstr "Výběr výchozí aplikace pro typ souboru a složky" #: C/plugin-applications.page:66(p) msgid "Select a file or folder in Kupfer" msgstr "V aplikaci Kupfer vyberte soubor nebo složku" #: C/plugin-applications.page:71(p) msgid "" "Type Tab and select the action Set Default Application..." msgstr "" "Zmáčkněte Tab a vyberte akci Nastavit výchozí aplikaci…" #: C/plugin-applications.page:77(p) msgid "" "Type Tab to select the third (indirect object) pane and in it, " "select the application to always open the file type with." msgstr "" "Zmáčkněte Tab pro výběr třetího panelu (nepřímého objektu) a v " "něm vyberte aplikaci, pomocí níž se má soubor vždy otevírat." #: C/plugin-applications.page:85(title) msgid "Configuration" msgstr "Nastavení" #: C/plugin-applications.page:86(p) msgid "" "The configuration option Applications for Desktop Environment in " "the plugin's information pane in Kupfer Preferences determines " "how Kupfer should act with regard to the desktop environment " "configuration—certain applications request not to be shown depending on " "which desktop environment is used. By default, it behaves like GNOME." msgstr "" "Volba nastavení Aplikace pro pracovní prostředí v informačním " "panelu v Předvolbách Kupfer určuje, jak by měla aplikace " "Kupfer chovat vůči nastavení pracovního prostředí – určité " "požadavky aplikací nejsou v závislosti na použitém pracovním prostředí " "zobrazeny. Ve výchozím stavu se chová jako GNOME." #: C/moreusage.page:7(desc) msgid "More advanced usage information." msgstr "Další pokročilé informace o používání." #: C/moreusage.page:10(title) msgid "Using Kupfer in Depth" msgstr "Použití aplikace Kupfer do hloubky" #: C/moreusage.page:13(title) msgid "Adding Applications and Scripts" msgstr "Přidávání aplikací a skriptů" #: C/moreusage.page:14(p) msgid "" "Kupfer will show all applications that are configured visible in " "your menu editor." msgstr "" "Aplikace Kupfer bude zobrazovat všechny aplikace, které jsou " "nastavené jako viditelné ve vašem editoru nabídky." #: C/moreusage.page:18(p) msgid "" "If you want to add an application manually, you can create a new ." "desktop file and place it in one of the standard directories for " "applications, for example ~/.local/share/applications, where " "Kupfer will find it." msgstr "" "Pokud chcete přidat aplikaci ručně, můžete vytvořit nový soubor ." "desktop a umístit jej do jedné ze standardních složek pro aplikace, " "například ~/.local/share/applications, kde jej dokáže aplikace " "Kupfer najít." #: C/moreusage.page:24(p) msgid "" "If you have a collection of scripts that you want to call from Kupfer, you can add the scripts folder as a catalog directory to Kupfer in the preferences. Scripts that you add to Kupfer's catalog " "this way can be run directly or in the terminal as long as they are " "executable." msgstr "" "V případě, že máte sadu skriptů, které chcete z aplikace Kupfer " "volat, můžete přidat složku se skripty jako složku katalogu do předvoleb " "Kupfer. Skripty, které přidáte do katalogu aplikace Kupfer tímto způsobem, lze spouštět přímo nebo v terminálu, pokud jsou " "spustitelné." #: C/moreusage.page:31(p) msgid "" "You can also save command-lines by using the action Add to Favorites." msgstr "" "Můžete také ukládat příkazové řádky pomocí akce Přidat oblíbené." #: C/moreusage.page:38(title) msgid "Opening Files and Folders" msgstr "Otevírání souborů a složek" #: C/moreusage.page:39(p) msgid "" "Using the action Open, files and folders are opened in their " "preferred application. The application associations can be changed, see " "." msgstr "" "Použitím akce Otevřít se soubory a složky otevřou ve své " "upřednostňované aplikaci. Přidruženou aplikaci je možné změnit, viz ." #: C/moreusage.page:47(title) msgid "The Comma Trick" msgstr "Vkládání do zásobníku („trik s čárkou“)" #: C/moreusage.page:48(p) msgid "" "The comma trick allows the user to use actions on many objects at the same " "time." msgstr "" "Pomocí vložení do zásobníku (tzv. „trik s čárkou“, v originále „comma " "trick“) může uživatel použít akce na více objektů naráz." #: C/moreusage.page:52(p) msgid "" "Simply press comma , when an object is selected. The object is " "put on a \"stack\", and you can find yet another file or object, press comma " "to put it on the stack. When you subsequently invoke an action, the action " "is carried out on all of the objects at the same time." msgstr "" "Jednoduše zmáčkněte čárku , ve chvíli, kdy je vybrán nějaký " "objekt. Objekt se vloží do „zásobníku objektů“ a vy můžete hledat další " "soubor nebo objekt, který zase zmáčknutím čárky vložíte do zásobníku. Když " "následně vyvoláte akci, provede se na všech objektech naráz." #: C/moreusage.page:58(p) msgid "" "Some actions are only \"multiplied\" when used with many objects, other are " "smarter than that:" msgstr "" "Některé akce jsou pouze „vícenásobné“, když se spustí s více objekty, jiné " "se chovají elegantněji:" #: C/moreusage.page:61(p) msgid "" "Selecting many files and using the Create Archive action, all files will be " "packed into the same archive." msgstr "" "Vybráním více souborů a použitím akce Vytvořit archiv v… budou všechny " "soubory zabaleny do jediného archívu." #: C/moreusage.page:63(p) msgid "" "If you select multiple contacts and use a Send Email action, it creates one " "email directed at all the contacts." msgstr "" "Když vyberete více kontaktů a použijete akci Napsat e-mail, vytvoří se " "poštovní zpráva přímo se všemi kontakty jako příjemci." #: C/moreusage.page:65(p) msgid "" "If you select multiple subcatalogs (For example Firefox Bookmarks and " "Epiphany Bookmarks) and use Search Contents.., you get a subcatalog search " "restricted to the objects of those two catalogs! You can even bind a trigger " "to this command(!)" msgstr "" "Když vyberete více podkatalogů (například Záložky ve Firefoxu a Záložky v " "Epiphany) a použijete Prohledat obsah…, získáte výsledky hledání omezené na " "objekty těchto podkatalogů! Navíc můžete na tento příkaz navázat spouštěč!" #: C/moreusage.page:71(p) msgid "" "The comma trick is directly taken from Quicksilver (the " "example given in the external article should work identically in Kupfer)." msgstr "" "Trik s čárkou je převzat přímo z aplikace Quicksilver " "(příklad uvedený v externím článku by měl být víceméně totožný i pro " "aplikaci Kupfer; článek je v angličtině)." #: C/moreusage.page:80(title) msgid "Grab Current Selection" msgstr "Zachytávání aktuálního výběru" #: C/moreusage.page:81(p) msgid "" "To use the current selected text, from any application, with Kupfer, you can configure a global keyboard shortcut for the action Show " "with Selection in Kupfer Preferences." msgstr "" "Jestli chcete použít aktuálně vybraný text z libovolné aplikace v aplikaci " "Kupfer, můžete si v Předvolbách Kupfer nastavit " "globální klávesovou zkratku pro akci Zobrazit s výběrem." #: C/moreusage.page:85(p) msgid "" "If configured, pressing the global keyboard shortcut will summon " "Kupfer with the current selection as the focused object." msgstr "" "Když je nastavená a zmáčknete ji, vyvolá se aplikace Kupfer s " "aktuálním výběrem jako zaměřeným objektem." #: C/moreusage.page:90(p) msgid "See " msgstr "Viz " #: C/moreusage.page:94(title) msgid "Command-line Connection" msgstr "Napojení na příkazový řádek" #: C/moreusage.page:95(p) msgid "" "The command kupfer on the command-line will focus Kupfer if it's already running, otherwise it will start it." msgstr "" "Příkaz kupfer v příkazovém řádku zaměří aplikaci Kupfer, pokud již běží, pokud neběží, tak ji spustí." #: C/moreusage.page:99(p) msgid "" "The command kupfer can be used to send files or text from the " "command-line to Kupfer. For example, if you are using the shell " "in a directory where you have a file called \"report.pdf\", you can focus " "this file in Kupfer by running kupfer report.pdf." msgstr "" "Příkaz kupfer lze použít k poslání souborů nebo textu z příkazové " "řádky do aplikace Kupfer. Například, když použijete shell ve " "složce, kde máte soubor nazvaný „zpráva.pdf“, můžete tento soubor v aplikaci " "Kupfer zaměřit spuštěním kupfer zpráva.pdf." #: C/moreusage.page:107(p) msgid "" "You can also send text if you pipe the output of a command into kupfer." msgstr "" "Text můžete předat také tak, že použijete rouru mezi výstupem nějaké příkazu " "a příkazem kupfer." #: C/moreusage.page:114(title) msgid "Managing Context and Current Selection" msgstr "Správa kontextu a aktuálního výběru" #: C/moreusage.page:115(p) msgid "" "If you find the object you want to use, then invoke an action, Kupfer goes away to perform the action (for example start a program or play a " "song). When you come back to Kupfer, it will still keep the same " "object and action selected. Some actions make sense to be repeated (like " "skipping to the next song) and it can be useful to perform different actions " "on the same object." msgstr "" "Když najdete objekt, který chcete použít, vyvolejte akci a aplikace " "Kupfer zmizí akci provést (například spustit program nebo přehrát " "skladbu). Když se vrátíte zpět do aplikace Kupfer, bude stále " "držet ten stejný objekt a vybranou akci. Některé akce reagují na opakování " "(jako například přesun na další skladbu) a mohou být použity k provedení " "jiné akce s tím též objektem." #: C/moreusage.page:123(p) msgid "" "However, you always have the top level catalog reachable when you \"come back" "\" to Kupfer -- say you went into the subcatalog \"Albums\" to " "browse your albums only; you select an album to play, and play it. You come " "back with the album selected -- but your next search will still go over the " "top level catalog, not just albums." msgstr "" "Přesto máte, když se „vrátíte zpět“ do aplikace Kupfer, vždy " "dosažitelný katalog v nejvyšší úrovni. Řekněme, že jste přešli do " "podkatalogu „Alba“, abyste procházeli pouze svá alba. Vyberete si album, " "které chcete přehrát a začnete jej přehrávat. Vrátíte se zpět a máte vybráno " "album, ale následující hledání bude stále probíhat v horní úrovni katalogu, " "ne jen v albech." #: C/moreusage.page:130(p) msgid "" "How to come back into the subcatalog you were in? You do that by simply " "browsing, not searching the first thing you do when you focus Kupfer again. A quick way is to press down-arrow or space to open the browse " "window; think of it as saying \"I want to stay in this subfolder\". With the " "browse window open, your next query will search the current subcatalog." msgstr "" "Jak se vrátit do podkatalogu, ve kterém jste byli? Uděláte to jednoduše " "procházením, místo abyste jako první věc po opětovném zaměření aplikace " "Kupfer provedli vyhledávání. Rychlou cestou je zmáčknout šipku " "dolů nebo mezerník, aby se otevřelo okno prohlížeče. Smyslem toho je říci " "„Chci zůstat v této podsložce“. Při otevřeném okně prohlížeče bude váš " "následující dotaz prohledávat aktuální podkatalog." #: C/moreusage.page:137(p) msgid "" "This way you can work both ways -- you can quickly drill down into folders " "to find a file, and when you come back for the next action with Kupfer you can either summon any normal toplevel object (just start typing), " "or stay around where you were, deep in that folder (press space, then type a " "query)." msgstr "" "Touto cestou můžete pracovat oběma způsoby - můžete se rychle zanořovat do " "složek, abyste našli soubor a když se vrátíte zpět kvůli další akci s " "aplikací Kupfer, můžete buď vyvolat objekt některé normální " "nejvyšší úrovně (prostě tak, že začnete psát) nebo zůstat kde jste, zanořeni " "v této složce (zmáčknutím mezerníku a teprve pak psaním dotazu)." #: C/moreusage.page:146(title) msgid "Saving Commands as Files" msgstr "Ukládání příkazů jako souborů" #: C/moreusage.page:147(p) msgid "" "You can use keyboard shortcut for Compose Command (by default it is " "CtrlReturn) to create a command " "object out of the currently focused command in Kupfer. This object can be " "saved as a runnable file if you use the Save As... action. The " "resulting file will can be executed when opened from the file manager (it " "requires that Kupfer is already running)." msgstr "" "Můžete použít klávesovou zkratku pro Sestavit příkaz (ve výchozím " "stavu to je CtrlEnter), který vytvoří " "příkazový objekt z právě zaměřeného příkazu v aplikaci Kupfer. Tento objekt " "je možné uložit jako spustitelný soubor pomocí akce Uložit jako…. " "Výsledný soubor lze spouštět otevřením ve správci souborů (je potřeba, aby " "již běžela aplikace Kupfer)." #: C/managing-plugins.page:7(desc) msgid "Using plugins with Kupfer." msgstr "Používání zásuvných modulů v aplikaci Kupfer." #: C/managing-plugins.page:10(title) msgid "How to Configure Plugins" msgstr "Jak nastavit zásuvné moduly" #: C/managing-plugins.page:12(p) msgid "" "Functionality in Kupfer is organized by extentsion modules called \"plugins" "\". Each plugin provides additional functionality, for example integration " "with an external application." msgstr "" "Funkcionalita v aplikaci Kupfer je dána rozšiřujícími moduly nazývanými " "„zásuvné moduly“. Každý zásuvný modul funkcionalitu nějakým způsobem " "doplňuje, například integrací externí aplikace." #: C/managing-plugins.page:19(title) msgid "Configuring Plugins" msgstr "Nastavování zásuvných modulů" #: C/managing-plugins.page:21(title) msgid "Open Kupfer Preferences to the Plugins tab" msgstr "Otevřete Předvolby Kupfer na kartě Zásuvné moduly" #: C/managing-plugins.page:23(p) msgid "Use one of the following methods:" msgstr "Použijte jeden z následujících postupů:" #: C/managing-plugins.page:25(p) msgid "" "Click the Kupfer icon in the notification area and select the item " "Preferences" msgstr "" "Klikněte na ikonu Kupfer v oznamovací oblasti a vyberte položku " "Předvolby" #: C/managing-plugins.page:25(item) msgid "." msgstr "." #: C/managing-plugins.page:29(p) msgid "" "Search for the object Kupfer Preferences in Kupfer itself. Press " "Return to open it." msgstr "" "Vyhledejte objekt Předvolby Kupfer přímo v aplikaci Kupfer. " "Zmáčknutím Enter jej pak otevřete." #: C/managing-plugins.page:33(p) msgid "Use the keyboard shortcut Ctrl;" msgstr "" "Použijte klávesovou zkratku Ctrl;" #: C/managing-plugins.page:39(p) msgid "Select the tab Plugins" msgstr "Vyberte kartu Zásuvné moduly" #: C/managing-plugins.page:45(p) msgid "" "Select plugins in the list to read about them, and tick the box next to its " "name to activate the plugin, or untick to deactivate." msgstr "" "Vyberte zásuvný modul v seznamu a můžete si o něm přečíst informace. " "Zaškrtnutím políčka vedle jeho názvu jej můžete aktivovat, zrušením " "zaškrtnutí deaktivovat." #: C/managing-plugins.page:49(p) msgid "" "If the plugin has any configurable parameters, they will be visible below " "the plugin information." msgstr "" "Pokud má zásuvný modul nějaké parametry nastavení, budou zobrazeny pod " "informacemi o něm." #: C/managing-plugins.page:53(p) msgid "" "The plugin Kupfer Plugins allows fast access to each plugin's " "information page as well as the action \"Show Source Code\" which reveals " "the implementation." msgstr "" "Zásuvný modul Zásuvné moduly Kupfer umožňuje rychlý přístup k " "informační stránce jednotlivých zásuvných modulů. Nabízí i akci „Zobrazit " "zdrojový kód“, která prozradí, jak je implementován." #: C/managing-plugins.page:59(title) msgid "If a Plugin can not be Activated" msgstr "Když nejde zásuvný modul aktivovat" #: C/managing-plugins.page:60(p) msgid "" "If a plugin fails to activate because it requires a software module that is " "not available, its plugin information will display a message like this:" msgstr "" "Když aktivace zásuvného modulu selže, protože vyžaduje softwarový modul, " "který není dostupný, zobrazí se informace v podobě takovéto zprávy:" #: C/managing-plugins.page:65(em) msgid "Plugin could not be read due to an error:" msgstr "Zásuvný modul nemohl být načten kvůli výskytu chyby:" #: C/managing-plugins.page:66(em) msgid "Python module 'gdata' is needed" msgstr "Je zapotřebí modul Python „gdata“" #: C/managing-plugins.page:67(p) msgid "" "This means that you need to install a needed python module from your " "distribution—and possibly the plugin documentation can tell you how." msgstr "" "Znamená to, že potřebujete nainstalovat požadovaný modul jazyka Python ve " "své distribuci – a jak na to vám snad poradí dokumentace k zásuvnému modulu." #: C/managing-plugins.page:72(p) msgid "" "The plugin may also unexpectedly fail to load, and display a different error " "message. It may then be a program error in either the plugin or Kupfer." msgstr "" "Zásuvný modul může také neočekávaně selhat při načítání a zobrazit jinou " "chybovou zprávu. Může se jednat o programovou chybu buď v zásuvném modulu " "nebo aplikaci Kupfer." #: C/managing-plugins.page:79(title) msgid "Installing more Plugins" msgstr "Instalace dalších zásuvných modulů" #: C/managing-plugins.page:80(p) msgid "" "You can install custom plugins into the folder ~/.local/share/kupfer/" "plugins. Each plugin is either a single .py file or a " "python package (a folder directly containing a file called __init__." "py). Plugins in the package format can include icon files. Python " "packages can even be installed as .zip files." msgstr "" "Vlastní zásuvné moduly můžete instalovat do složky ~/.local/share/" "kupfer/plugins. Každý zásuvný modul má podobu buď jediného souboru " ".py nebo balíčku python (složka která přímo obsahuje soubor s " "názvem __init__.py). Zásuvné moduly ve formátu balíčku mohou " "zahrnovat soubory ikon. Balíčky python mohou být instalovány také v podobě " "souborů .zip." #: C/managing-plugins.page:88(p) msgid "" "Caution: Treat a plugin as a computer program. Do not install " "untrusted plugins." msgstr "" "Varování: Přistupujte k zásuvným modulům jako k jiným počítačovým " "programům. Neinstalujte neověřené zásuvné moduly." #: C/managing-plugins.page:95(title) msgid "Creating Plugins" msgstr "Vytváření zásuvných modulů" #: C/managing-plugins.page:96(p) msgid "" "Documentation for plugin creators is available in the file " "Documentation/Manual.rst in the source distribution on the " "webpage at Kupfer " "Manual. An easy way to start is to copy an existing plugin and " "experimenting with it." msgstr "" "Dokumentace pro autory zásuvných modulů je dostupná v souboru " "Documentation/Manual.rst ve zdrojových kódech na webové stránce " "Příručka aplikace " "Kupfer. Nejjednodušší způsob, jak začít, je zkopírovat existující " "zásuvný modul a experimentovat s ním." #: C/managing-plugins.page:107(title) msgid "The Catalog Tab in Preferences" msgstr "Karta Katalog v předvolbách" #: C/managing-plugins.page:108(p) msgid "" "Each plugin can export a number of sources which contain objects. Normally, " "all these objects are directly accessible from a top-level search. Some " "plugins export so specialized or so many objects that their catalogs should " "better not have their objects exported to the top level. To reach those " "objects, you have to first find the catalog by name, then enter the catalog " "using the action Search Contents." msgstr "" "Každý zásuvný modul může exportovat řadu zdrojů, které obsahují objekty. " "Normálně jsou všechny tyto objekty přímo přístupné z nejvyšší úrovně " "hledání. Některé zásuvné moduly jsou příliš specializované nebo obsahují " "příliš mnoho objektů na to, aby bylo vhodné exportovat jejich objekty do " "nejvyšší úrovně. Abyste se k jejich objektům dostali, musíte nejprve podle " "názvu vyhledat katalog a pak do něj vstoupit pomocí akce Prohledat " "obsah." #: C/managing-plugins.page:118(p) msgid "" "In the tab Catalog in Kupfer Preferences, a ticked box " "next to each source means that its objects are exported. An unticked box " "means that its contents are hidden from the top level." msgstr "" "Na kartě Katalog v Předvolbách Kupfer najdete u každého " "zdroje zaškrtávací políčko. Zaškrtnuté znamená, že jeho objekty jsou " "exportovány, nezaškrtnuté, že jeho obsah je pro nejvyšší úroveň skryt." #: C/managing-plugins.page:123(p) msgid "" "Note: Kupfer may become slow if large enough subcatalogs are " "exported to the top level." msgstr "" "Poznámka: Když jsou do nejvyšší úrovně exportovány opravdu rozsáhlé " "katalogy, může se Kupfer zpomalit." #: C/license.page:7(desc) msgid "You can copy, modify and share Kupfer." msgstr "Aplikaci Kupfer můžete kopírovat, upravovat a sdílet." #: C/license.page:10(title) msgid "License" msgstr "Licence" #: C/license.page:12(p) msgid "" "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." msgstr "" "Tento program je svobodný software: Můžete jej dále šířit a/nebo upravovat " "za podmínek licence GNU General Public License v podobě, v jaké ji " "vydala Free Software Foundation, a to buď ve verzi 3 této licence nebo (dle " "vaší volby) v libovolné novější verzi." #: C/license.page:18(p) msgid "" "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." msgstr "" "Tento program je šířen ve víře, že bude užitečný, ale BEZ JAKÝCHKOLIV ZÁRUK, " "a to i bez předpokládané záruky na PRODEJNOST nebo VHODNOST PRO KONKRÉTNÍ " "ÚČEL. Více podrobností najdete přímo v licenci GNU General Public " "License." #: C/license.page:24(p) msgid "" "You should have received a copy of the GNU General Public License along with " "this program. If not, see gnu." "org/licenses." msgstr "" "Spolu s tímto programem byste měli obdržet kopii licence GNU General Public " "License. Pokud se tak nestalo, podívejte se na gnu.org/licenses." #: C/license.page:30(p) msgid "" "This documentation is licensed under a Creative Commons Attribution-Share Alike 3.0 " "Unported License." msgstr "" "Tato dokumentace je licencována pod Creative Commons Attribution-Share Alike 3.0 Unported " "License." #: C/license.page:36(p) msgid "" "As a special exception, the copyright holders give you permission to copy, " "modify, and distribute the example code contained in this document under the " "terms of your choosing, without restriction." msgstr "" "Jako speciální výjimku vám držitel autorských práv uděluje svolení " "kopírovat, upravovat a šířit ukázkový kód obsažený v tomto dokumentu za " "podmínek, které si zvolíte, bez dalších omezení." #: C/keyboard.page:7(desc) msgid "Complete keyboard shortcuts reference." msgstr "Úplný přehled klávesových zkratek." #: C/keyboard.page:10(title) msgid "Command Keys and Accelerator Keys" msgstr "Příkazové klávesy a klávesové zkratky" #: C/keyboard.page:13(title) C/generalusage.page:12(title) msgid "Keyboard Interface" msgstr "Obsluha z klávesnice" #: C/keyboard.page:14(p) msgid "In command mode, the following keystrokes have special meanings:" msgstr "V příkazovém režimu mají následující klávesy speciální význam:" #: C/keyboard.page:19(p) C/generalusage.page:34(p) msgid " or Space" msgstr " nebo Mezerník" #: C/keyboard.page:20(p) C/generalusage.page:35(p) msgid "Go to the next match" msgstr "Přejít na následující nalezenou shodu" #: C/keyboard.page:23(p) C/generalusage.page:38(p) msgid " or ShiftSpace" msgstr " nebo ShiftMezerník" #: C/keyboard.page:26(p) C/generalusage.page:41(p) msgid "Go to the previous match" msgstr "Přejít na předchozí nalezenou shodu" #: C/keyboard.page:29(p) C/generalusage.page:44(p) msgid " or /" msgstr " nebo/" #: C/keyboard.page:30(p) C/generalusage.page:45(p) msgid "Descend into an object with content" msgstr "Přejít do objektu s obsahem" #: C/keyboard.page:33(key) C/generalusage.page:48(key) msgid "Backspace" msgstr "Backspace" #: C/keyboard.page:34(p) C/generalusage.page:49(p) msgid "Erase a character from the query. If the query is empty, go up a level" msgstr "Smazat znak z dotazu. Pokud je dotaz prázdný, přejde o úroveň výš." #: C/keyboard.page:39(key) C/keyboard.page:93(key) C/generalusage.page:54(key) msgid "." msgstr "." #: C/keyboard.page:40(p) C/generalusage.page:55(p) msgid "Activate free-text mode" msgstr "Aktivovat volný textový režim" #: C/keyboard.page:43(key) C/keyboard.page:97(key) C/generalusage.page:58(key) msgid "," msgstr "," #: C/keyboard.page:44(p) C/generalusage.page:59(p) msgid "Put selected object on the stack (\"Comma Trick\")" msgstr "" "Vložit objekt do zásobníku (tzv. „trik s čárkou“, v originále „Comma Trick“)" #: C/keyboard.page:47(p) msgid "Quick access keys:" msgstr "Klávesy pro rychlý přístup:" #: C/keyboard.page:53(key) msgid "=" msgstr "=" #: C/keyboard.page:55(p) msgid "" "Activate free-text mode with = prefix (for )" msgstr "" "Aktivuje volný textový režim s předponou = (pro objekt )" #: C/keyboard.page:61(key) msgid "/" msgstr "/" #: C/keyboard.page:63(p) msgid "" "Activate free-text mode (when nothing is selected) with / " "prefix (to input a rooted path)" msgstr "" "Aktivuje volný textový režim (pokud není nic vybráno) s předponou / (pro zadání kořenové cesty)" #: C/keyboard.page:68(p) C/generalusage.page:62(p) msgid "Additionally:" msgstr "Navíc:" #: C/keyboard.page:72(p) C/generalusage.page:66(p) msgid "" "Return activates the current selection: the command is executed." msgstr "Enter aktivuje aktuální výběr: příkaz je proveden." #: C/keyboard.page:74(p) C/generalusage.page:68(p) msgid "Escape clears the current selection." msgstr "Esc vymaže aktuální výběr." #: C/keyboard.page:75(p) C/generalusage.page:69(p) msgid "Tab switches between the object and the action pane." msgstr "Tab přepne mezi panelem objektu a akce." #: C/keyboard.page:77(p) msgid "" "The meaning of the keys Space, ., ,, /" " and = can not be changed, but you can deactivate their " "special meaning with the checkbox Use single keystroke commands " "in Kupfer Preferences." msgstr "" "Význam kláves Mezerník, ., ,, / " "a = nelze změnit, ale můžete jejich speciální funkci deaktivovat " "pomocí zaškrtávacího políčka Použít jednoklávesové příkazy v " "Předvolbách Kupfer." #: C/keyboard.page:86(title) msgid "Kupfer's Keyboard Shortcuts" msgstr "Klávesové zkratky aplikace Kupfer" #: C/keyboard.page:87(p) msgid "" "These keyboard shortcuts are used in Kupfer's interface. They " "have the following meanings and default shortcuts:" msgstr "" "Tyto klávesové zkratky jsou použity v rozhraní aplikace Kupfer. " "Mají následující významy a výchozí klávesy:" #: C/keyboard.page:93(key) C/keyboard.page:97(key) C/keyboard.page:101(key) #: C/keyboard.page:105(key) C/keyboard.page:113(key) C/keyboard.page:117(key) #: C/keyboard.page:121(key) C/keyboard.page:125(key) C/keyboard.page:129(key) #: C/keyboard.page:174(key) msgid "Ctrl" msgstr "Ctrl" #: C/keyboard.page:94(p) msgid "Toggle text mode" msgstr "Přepnout textový režim" #: C/keyboard.page:98(p) msgid "The comma trick" msgstr "Vložit do zásobníku" #: C/keyboard.page:101(key) msgid ";" msgstr ";" #: C/keyboard.page:102(p) msgid "Show preferences window" msgstr "Zobrazit okno předvoleb" #: C/keyboard.page:105(key) msgid "R" msgstr "R" #: C/keyboard.page:106(p) msgid "Reset all" msgstr "Vše vynulovat" #: C/keyboard.page:109(key) msgid "Alt" msgstr "Alt" #: C/keyboard.page:109(key) msgid "A" msgstr "A" #: C/keyboard.page:110(p) msgid "Alternate activate" msgstr "Přepnout aktivaci" #: C/keyboard.page:113(key) msgid "Return" msgstr "Enter" #: C/keyboard.page:114(p) msgid "Compose command" msgstr "Sestavit příkaz" #: C/keyboard.page:117(key) msgid "S" msgstr "S" #: C/keyboard.page:118(p) msgid "Switch to first pane" msgstr "Přepnout na první panel" #: C/keyboard.page:121(key) msgid "Q" msgstr "Q" #: C/keyboard.page:122(p) msgid "Select 'Quit'" msgstr "Vybrat „Ukončit“" #: C/keyboard.page:125(key) msgid "G" msgstr "G" #: C/keyboard.page:126(p) msgid "Select 'Selected File'" msgstr "Vybrat „Vybraný soubor“" #: C/keyboard.page:129(key) msgid "T" msgstr "T" #: C/keyboard.page:130(p) msgid "Select 'Selected Text'" msgstr "Vybrat „Vybraný text“" #: C/keyboard.page:133(key) msgid "F1" msgstr "F1" #: C/keyboard.page:134(p) msgid "Show Help" msgstr "Zobrazit nápovědu" #: C/keyboard.page:139(title) msgid "How to configure a keyboard shortcut" msgstr "Jak nastavit klávesové zkratky" #: C/keyboard.page:141(p) C/keyboard.page:185(p) msgid "Open Kupfer Preferences and go to the Keyboard tab." msgstr "" "Otevřete Předvolby Kupfer a přejděte na kartu Klávesnice." #: C/keyboard.page:147(p) msgid "" "Double-click the shorcut's row under Browser Keyboard Shortcuts." msgstr "" "Dvojitě klikněte na řádek klávesové zkratky pod Klávesové zkratky " "prohlížeče." #: C/keyboard.page:153(p) msgid "" "Using the window that appears, press modifier keys and a letter or number " "key to set a shortcut. An example is pressing and holding Ctrl " "and then pressing and releasing T to bind CtrlT." msgstr "" "V okně, které se objeví, zmáčkněte klávesový modifikátor a klávesu s " "písmenem nebo číslem. Tím klávesovou zkratku nastavíte. Například zmáčknutím " "a držením modifikátoru Ctrl a následným zmáčknutím a uvolněním " "T přiřadíte CtrlT." #: C/keyboard.page:164(title) msgid "Global Keyboard Shortcuts" msgstr "Globální klávesové zkratky" #: C/keyboard.page:165(p) msgid "" "Kupfer always listens to global shortcuts, even if it is not " "currently in the foreground." msgstr "" "Aplikace Kupfer naslouchá, jestli není zmáčknuta nějaká klávesová " "zkratka, vždy, i když zrovna není na popředí." #: C/keyboard.page:169(p) msgid "They have the following meanings and default shortcuts:" msgstr "Mají následující význam a výchozí klávesy:" #: C/keyboard.page:174(key) msgid "Space" msgstr "Mezerník" #: C/keyboard.page:175(p) msgid "Show/hide Kupfer" msgstr "Zobrazit/skrýt aplikaci Kupfer" #: C/keyboard.page:178(p) msgid "(not configured by default)" msgstr "(ve výchozím stavu nenataveno)" #: C/keyboard.page:179(p) msgid "Show Kupfer with 'Selection' object focused" msgstr "Zobrazit aplikaci Kupfer se zaměřeným objektem „Výběr“" #: C/keyboard.page:183(title) msgid "How to configure a global keyboard shortcut" msgstr "Jak nastavit globální klávesové zkratky" #: C/keyboard.page:191(p) msgid "" "Double-click the shorcut's row under Global Keyboard Shortcuts." msgstr "" "Dvojitě klikněte na řádek klávesové zkratky pod Globální klávesové " "zkratky." #: C/keyboard.page:197(p) msgid "" "Using the window that appears, press modifier keys and a letter or number " "key to set a global shortcut. An example is pressing and holding Super and then pressing and releasing Space to bind " "SuperSpace." msgstr "" "V okně, které se objeví, zmáčkněte klávesový modifikátor a klávesu s " "písmenem nebo číslem. Tím klávesovou zkratku nastavíte. Například zmáčknutím " "a držením modifikátoru Super (obvykle klávesa s logem Windows) a " "následným zmáčknutím a uvolněním Mezerníku přiřadíte " "SuperMezerník." #: C/keyboard.page:206(p) msgid "" "Since these keyboard shortcuts are global, they can be used from any " "application. Select shortcuts with care so that they do not conflict with " "other functions." msgstr "" "Díky tomu, že jsou klávesové zkratky globální, můžete je použít v kterékoliv " "aplikaci. Vybírejte je ale obezřetně, aby nebyly v konfliktu s jinými " "funkcemi těchto aplikací." #: C/keyboard.page:214(p) msgid "" "The plugin Triggers allows to activate actions with global keyboard " "shortcuts. Trigger shortcuts do not appear in Kupfer Preferences." msgstr "" "Zásuvný modul Spouštěče umožňuje aktivovat akce pomocí globálních " "klávesových zkratek. Spouštěcí zkratky se neobjeví v Předvoblách " "Kupfer." #: C/keyboard.page:220(p) msgid "See for more information." msgstr "Více informací viz ." #: C/introduction.page:7(desc) msgid "Introduction to Kupfer." msgstr "Úvod do aplikace Kupfer." #: C/introduction.page:10(title) msgid "Introduction" msgstr "Úvod" #: C/introduction.page:12(p) msgid "" "Kupfer is an interface for quick and convenient access to " "applications and their documents." msgstr "" "Aplikace Kupfer je rozhraní pro rychlý a pohodlný přístup k " "aplikacím a jejich dokumentům." #: C/introduction.page:16(p) msgid "" "The most typical use is to find a specific application and launch it. We " "have tried to make Kupfer easy to extend with plugins so that " "this quick-access paradigm can be extended to many more objects than just " "applications." msgstr "" "Typickou ukázkou použití je najít konkrétní aplikaci a spustit ji. Snažili " "jsme se vytvořit Kupfer tak, aby šel snadno rozšiřovat pomocí " "zásuvných modulů, takže základní funkčnost rychlého přístupu lze rozšířit i " "na další objekty, než jsou jen aplikace." #: C/introduction.page:22(p) msgid "" "We hope that using Kupfer feels both very fun and " "different." msgstr "" "Doufáme, že se při používání aplikace Kupfer budete cítit " "jako při zábavě a zároveň odlišně." #: C/introduction.page:26(p) msgid "" "For up-to-date information about Kupfer, visit its homepage." msgstr "" "Aktuální informace o aplikaci Kupfer najdete na domovské stránce." #: C/index.page:9(name) msgid "Ulrik Sverdrup" msgstr "Ulrik Sverdrup" #: C/index.page:10(email) msgid "ulrik.sverdrup@gmail.com" msgstr "ulrik.sverdrup@gmail.com" #: C/index.page:13(year) msgid "2009" msgstr "2009" #: C/index.page:14(name) msgid "Kupfer Development Team" msgstr "Vývojářský tým Kupfer" #: C/index.page:17(license) msgid "Creative Commons Share Alike 3.0" msgstr "Creative Commons Share Alike 3.0" #: C/index.page:21(title) msgid "Kupfer Manual" msgstr "Příručka aplikace Kupfer" #: C/index.page:24(title) msgid "Using Kupfer" msgstr "Používání aplikace Kupfer" #: C/index.page:27(title) msgid "About Specific Plugins" msgstr "O konkrétních zásuvných modulech" #: C/generalusage.page:7(desc) msgid "How to start using Kupfer." msgstr "Jak začít používat aplikaci Kupfer." #: C/generalusage.page:14(p) msgid "" "Kupfer is to the largest part a keyboard-managed interface to " "applications and documents." msgstr "" "Aplikace Kupfer z velké části spravuje přístup k aplikacím a " "dokumentům z klávesnice." #: C/generalusage.page:18(p) msgid "" "Kupfer's default mode is the command mode: If you type a query, kupfer will " "search for a match in its catalog." msgstr "" "Výchozí režim aplikace Kupfer je příkazový: Když píšete dotaz, aplikace " "Kupfer bude ve svých katalozích hledat shodu." #: C/generalusage.page:23(p) msgid "" "The arrow keys allow you to browse query matches quite naturally, going to " "the previous or next match, and going up and down in the subcatalogs." msgstr "" "Klávesové šipky vám dovolují zcela přirozeně procházet výsledky dotazu, " "přecházet na předchozí nebo následující nalezenou položku a přecházet nahoru " "a dolů v podkatalozích." #: C/generalusage.page:29(p) msgid "In command mode, some keystrokes have special meanings:" msgstr "V příkazovém režimu mají některé klávesy speciální význam:" #: C/generalusage.page:71(p) msgid "" "By default you show Kupfer using the global keyboard shortcut " "CtrlSpace." msgstr "" "Standardně aplikaci Kupfer zobrazíte pomocí globální klávesové " "zkratky CtrlMezerník." #: C/generalusage.page:74(p) msgid "See for more information." msgstr "Více informací viz " #: C/generalusage.page:78(title) msgid "Learning Habits" msgstr "Učení návyků" #: C/generalusage.page:79(p) msgid "" "Kupfer remembers which objects and actions are used the most. " "When beginning to use it, you have to use the arrow keys at times to make it " "precise which object you want to find. After a few uses of that object, " "Kupfer will rank it higher. Objects marked as favorites are also ranked higher." msgstr "" "Aplikace Kupfer si pamatuje, které objekty a akce se nejvíce " "používají. Když s ní poprvé začnete pracovat, musíte často používat šipky, " "abyste našli ten správný objekt. Po několika použitích těchto objektů je " "začne Kupfer hodnotit výše. Výše jsou hodnoceny rovněž objekty označené jako " "oblíbené." #: C/generalusage.page:90(title) msgid "The Catalog" msgstr "Katalog" #: C/generalusage.page:91(p) msgid "" "The Catalog is the collection of objects you can access in Kupfer, such as " "documents and programs." msgstr "" "Katalog je kolekce objektů, ke kterým můžete v aplikaci Kupfer přistupovat. " "Jedná se například o dokumenty nebo programy." #: C/generalusage.page:96(p) msgid "" "Objects in the catalog that have content, like folders, are marked with an " "arrow. Pressing will enter these objects. Much of the catalog " "is composed of subcatalogs; plugin subcatalogs do in general list objects " "that are also available directly from the top level. Subcatalogs can be used " "for a narrower view or search scope, when using Kupfer." msgstr "" "Objekt katalogu, který má nějaký obsah, jako třeba složka, je označen " "šipkou. Zmáčknutím šipky doprava do tohoto objektu vstoupíte. " "Řada katalogů je složena z podkatalogů. Zásuvné moduly subkatalogů vytváří " "obecné seznamy objektů, které jsou přímo dostupné i z nejvyšší úrovně. " "Subkatalogy jsou použitelné k užšímu pohledu nebo prohledávaní ve vymezeném " "rozsahu v aplikaci Kupfer." #: C/generalusage.page:105(p) msgid "" "Most subcatalogs update their content automatically. For example, the " "Desktop folder source is always up-to-date." msgstr "" "Většina subkatalogů aktualizuje svůj obsah automaticky. Například obsah " "katalogu složky pracovní plochy je vždy aktuální." #. Put one translator per line, in the form of NAME , YEAR1, YEAR2 #: C/generalusage.page:0(None) msgid "translator-credits" msgstr "Marek Černocký " kupfer-328/help/de/000077500000000000000000000000001500175051100141775ustar00rootroot00000000000000kupfer-328/help/de/de.po000066400000000000000000001652041500175051100151370ustar00rootroot00000000000000# German translation of the kupfer manual. # Mario Blättermann , 2009-2011. # msgid "" msgstr "" "Project-Id-Version: kupfer manual\n" "POT-Creation-Date: 2011-04-09 21:16+0000\n" "PO-Revision-Date: 2011-06-23 12:04+0100\n" "Last-Translator: Mario Blättermann \n" "Language-Team: German \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: German\n" "X-Poedit-Country: GERMANY\n" #: C/plugin-websearch.page:7(desc) msgid "Using the search the web plugin." msgstr "Verwendung des Websuche-Plugins." #: C/plugin-websearch.page:10(app) msgid "Search the Web" msgstr "Websuche" #: C/plugin-websearch.page:13(title) C/plugin-triggers.page:23(title) #: C/plugin-notes.page:22(title) C/plugin-nautilusselection.page:13(title) #: C/plugin-gwibber.page:25(title) C/plugin-favorites.page:22(title) #: C/plugin-calculator.page:21(title) C/plugin-applications.page:19(title) #: C/generalusage.page:10(title) msgid "Basic Usage" msgstr "Grundlagen der Bedienung" #: C/plugin-websearch.page:15(p) msgid "Activate Kupfer and make sure it is in free-text mode (press period)" msgstr "" "Aktivieren Sie Kupfer und stellen Sich sicher, dass es sich im freien " "Textmodus befindet (drücken Sie ».«)" #: C/plugin-websearch.page:17(p) msgid "" "Type in a search query and tap Tab to switch to the action pane." msgstr "" "Geben Sie eine Suchanfrage ein und drücken Sie die Tabulatortaste, " "um zum Aktionsfenster zu wechseln." #: C/plugin-websearch.page:19(p) msgid "" "Type \"Search With\" to find Search the Web's action and tap Tab " "again to switch to the third pane (indirect object)." msgstr "" "Geben Sie »Suchen mit« ein, um zur Websuche-Aktion zu gelangen und drücken " "Sie erneut die Tabulatortatse, um zur dritten Ansicht zu wechseln " "(indirektes Objekt)." #: C/plugin-websearch.page:22(p) msgid "" "Select search engine with the arrow keys and type Return to open " "the search in a web browser." msgstr "" "Wählen Sie die Suchmaschine mit den Pfeiltasten aus und drücken Sie die " "Eingabetaste, um die Suche in einem Webbrowser zu öffnen." #: C/plugin-websearch.page:29(title) msgid "Search Engines" msgstr "Suchmaschinen" #: C/plugin-websearch.page:30(p) msgid "" "The Search the Web plugin uses Firefox' search engines, so you can " "add Search Engines directly in Firefox and Kupfer will " "find them later." msgstr "" "Das Websuche-Plugin nutzt die Suchfunktionen von Firefox. Sie " "können Suchfunktionen direkt in Firefox hinzufügen, so dass sie " "Kupfer später ebenfalls finden und nutzen kann." #: C/plugin-websearch.page:35(p) msgid "" "You can also install custom search plugins directly, only for Kupfer, in the folder:" msgstr "" "Benutzerdefinierte Suchplugins (nur für Kupfer) können sie direkt " "in folgendem Ordner installieren:" #: C/plugin-websearch.page:39(code) #, no-wrap msgid "~/.local/share/kupfer/searchplugins/" msgstr "~/.local/share/kupfer/searchplugins/" #: C/plugin-websearch.page:40(p) msgid "The search engine descriptions must written in OpenSearch format." msgstr "" "Die Beschreibungen für die Suchmaschine müssen im OpenSearch-Format angegeben " "werden." #: C/plugin-triggers.page:7(desc) msgid "Using the triggers plugin." msgstr "Verwendung des Auslöser-Plugins." #: C/plugin-triggers.page:10(app) C/keyboard.page:213(title) msgid "Triggers" msgstr "Auslöser" #: C/plugin-triggers.page:13(title) msgid "Triggers Plugin" msgstr "Auslöser-Plugin" #: C/plugin-triggers.page:14(p) msgid "" "With Triggers you can take a command you would normally perform in " "Kupfer, such as launching an application or opening a document, " "and bind a global key combination to run this command. As long as " "Kupfer is running, any application can have the current focus." msgstr "" "Mit Auslösern können Sie einen Befehl angeben, den Sie " "normalerweise in Kupfer ausführen, und diesen Befehl einer " "globalen Tastenkombination zuordnen. Beispiele dafür sind das Starten einer " "Anwendung oder das Öffnen eines Dokuments. Während Kupfer läuft, " "kann jede Anwendung aktuell fokussiert sein." #: C/plugin-triggers.page:25(title) msgid "Creating a new trigger" msgstr "Anlegen eines neuen Auslösers" #: C/plugin-triggers.page:27(p) msgid "Set up a command in Kupfer that you want to run" msgstr "" "Geben Sie in Kupfer einen Befehl an, den Sie ausführen wollen." #: C/plugin-triggers.page:32(p) msgid "" "Press CtrlReturn to create a " "composed command." msgstr "" "Drücken Sie StrgEingabetaste, um " "einen zusammengesetzten Befehl zu erstellen." #: C/plugin-triggers.page:38(p) msgid "" "Type Tab and select the action Add Trigger... and press " "Return" msgstr "" "Drücken Sie die Tabulatortaste, wählen Sie die Aktion Auslöser " "hinzufügen … und drücken Sie die Eingabetaste." #: C/plugin-triggers.page:44(p) msgid "" "Using the window that appears, press modifier keys and a letter or number key " "to set a global shortcut. An example is pressing and holding " "CtrlAlt and then pressing and " "releasing R to bind CtrlAltR." msgstr "" "Drücken Sie nun Modifikationstasten und eine Buchstaben- oder Zifferntaste, " "um ein globales Tastenkürzel festzulegen. Beispiel: Drücken Sie " "StrgAlt und halten Sie diese Tasten " "gedrückt. Dann drücken Sie R und lassen die Taste wieder los, um " "die Tastenkombination StrgAltR zu verwenden." #: C/plugin-triggers.page:54(title) msgid "Removing a trigger" msgstr "Entfernen eines Auslösers" #: C/plugin-triggers.page:56(p) msgid "" "Find the source Triggers in Kupfer and press " "to see its contents." msgstr "" "Schauen Sie in Kupfer nach den festgelegten Auslösern und " "drücken Sie , um deren Inhalt anzusehen." #: C/plugin-triggers.page:62(p) msgid "" "Find the active trigger in the list and use the action Remove Trigger." msgstr "" "Suchen Sie nach dem aktiven Auslöser in der Liste und wählen Sie Auslöser " "entfernen." #: C/plugin-triggers.page:68(p) msgid "" "Since trigger keyboard shortcuts are global, they can be used from any " "application. Select shortcuts with care so that they do not conflict with " "other functions." msgstr "" "Da die Auslöser-Tastenkombinationen globaler Natur sind, können sie aus jeder " "Anwendung heraus aufgerufen werden. Wählen Sie die Tastenkombinationen mit " "Vorsicht, damit sie nicht mit anderen Funktionen in Konflikt geraten." #: C/plugin-triggers.page:74(title) C/plugin-notes.page:60(title) #: C/plugin-gwibber.page:68(title) C/plugin-favorites.page:38(title) msgid "Power User Tips" msgstr "Profitipps" #: C/plugin-triggers.page:75(p) msgid "" "Proxy objects such as Selected Text, Selected File, Frontmost Window, Last Command et cetera allow very " "powerful triggers." msgstr "" "Proxy-Objekte wie Ausgewählter Text, Ausgewählte Datei, Vorderstes Fenster, Letzter Befehl usw. ermöglichen " "sehr mächtige Auslöser." #: C/plugin-triggers.page:79(p) msgid "" "The application action Launch is special; if you bind a trigger " "using Launch, it will start the application if it is not running, " "but focus the application when it is already running. By contrast, Start " "Again will start the application if it is running or not." msgstr "" "Die Anwendungsaktion Starten ist fallabhängig. Wenn Sie einen " "Auslöser an Starten binden, dann wird die Anwendung gestartet, " "sofern sie noch nicht läuft. Sollte sie jedoch schon laufen, erhält sie den " "Fokus. Im Gegensatz dazu startet die Aktion Erneut starten die " "Anwendung, ganz gleich, ob sie schon läuft oder nicht." #: C/plugin-triggers.page:87(title) msgid "Example Triggers" msgstr "Beispiele für Auslöser" #: C/plugin-triggers.page:90(em) msgid "Text Editor → Launch" msgstr "Texteditor → starten" #: C/plugin-triggers.page:91(p) msgid "Start Text Editor or focus its window if it is already running." msgstr "" "Starten den Texteditor oder fokussiert dessen Fenster, falls er " "schon läuft." #: C/plugin-triggers.page:97(em) msgid "Selected Text → Search With → Google" msgstr "Ausgewählter Text → Suchen mit → Google" #: C/plugin-triggers.page:98(p) msgid "Search the web using the currently selected text." msgstr "Sucht im Web nach dem aktuell ausgewählten Text." #: C/plugin-triggers.page:100(em) msgid "Selected File → Move To → (Downloads Folder)" msgstr "Ausgewählte Datei → Verschieben nach → (Download-Ordner)" #: C/plugin-triggers.page:101(p) msgid "Move the currently selected file to a specific folder" msgstr "Verschiebt die aktuell ausgewählte Datei in einem bestimmten Ordner" #: C/plugin-triggers.page:105(em) msgid "Songs → Search Contents" msgstr "Musiktitel → Inhalte durchsuchen" #: C/plugin-triggers.page:106(p) msgid "" "You may even add a trigger to open a specific subcatalog in Kupfer, for " "example Rhythmbox's songs." msgstr "" "Sie können einen Auslöser festlegen, um in Kupfer einen bestimmten " "unterkatalog zu öffnen, zum Beispiel die Titel in Rhythmbox." #: C/plugin-notes.page:7(desc) msgid "Using the notes plugin." msgstr "Verwendung des Notizen-Plugins." #: C/plugin-notes.page:10(app) C/plugin-calculator.page:37(title) msgid "Notes" msgstr "Notizen" #: C/plugin-notes.page:13(title) msgid "Notes Plugin" msgstr "Notizen-Plugin" #: C/plugin-notes.page:14(p) msgid "" "With Notes you can access or create new notes in either the " "program Gnote or Tomboy. Notes will work " "identically with either application—you can configure which one to use in the " "plugin's information pane in Kupfer Preferences." msgstr "" #: C/plugin-notes.page:24(title) msgid "Creating a new note" msgstr "Erstellen einer neuen Notiz" #: C/plugin-notes.page:26(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a note " "title" msgstr "" "Aktivieren Sie Kupfer und geben Sie . ein, um in den Textmodus zu " "gelangen. Geben Sie dann den Titel der Notiz ein" #: C/plugin-notes.page:32(p) msgid "" "Type Tab and select the action Create Note and press " "Return." msgstr "" #: C/plugin-notes.page:39(title) msgid "Finding a note by title" msgstr "Suchen nach einer Notiz anhand des Titels" #: C/plugin-notes.page:41(p) msgid "Simply search for the note title in Kupfer" msgstr "Suchen Sie einfach nach dem Titel der Notiz in Kupfer." #: C/plugin-notes.page:45(title) msgid "Finding a note by content" msgstr "Nach einer Notiz anhand des Inhalts suchen" #: C/plugin-notes.page:47(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "search query" msgstr "" "Aktivieren Sie Kupfer und geben Sie . ein, um in den Textmodus zu " "gelangen. Geben Sie dann Ihre Suchanfrage ein" #: C/plugin-notes.page:53(p) msgid "" "Type Tab and select the action Get Note Search Results... " "and press Return." msgstr "" #: C/plugin-notes.page:63(p) msgid "" "You can use the Selected Text object and create a new note with the " "content of the selection." msgstr "" #: C/plugin-nautilusselection.page:7(desc) msgid "Using the selected file plugin." msgstr "Verwendung des »Ausgewählte Datei«-Plugins" #: C/plugin-nautilusselection.page:10(app) msgid "Selected File" msgstr "Ausgewählte Datei" #: C/plugin-nautilusselection.page:14(p) msgid "" "Select a file in the file manager. Open Kupfer and search for the " "object Selected File, which represents the file or files that are " "selected." msgstr "" "Wählen Sie eine Datei in der Dateiverwaltung aus. Öffnen Sie Kupfer und suchen Sie nach dem Objekt Ausgewählte Datei, welches die " "ausgewählte(n) Datei(en) repräsentiert." #: C/plugin-nautilusselection.page:19(p) msgid "" "Instead of searching, you can press CtrlG to directly focus the selected file. See " "for more information." msgstr "" "Anstelle der Suche können Sie StrgG " "drücken, um die ausgewählte Datei direkt zu fokussieren. Weitere " "Informationen hierzu finden Sie in ." #: C/plugin-nautilusselection.page:26(title) msgid "Selected File requires Nautilus" msgstr "Ausgewählte Datei benötigt Nautilus." #: C/plugin-nautilusselection.page:27(p) msgid "" "The selected file plugin works with the Nautilus file browser and " "requires that the extension kupfer_provider.py is installed (it is " "normally installed together with Kupfer). After installing it for " "the first time, Nautilus must start anew before it is active." msgstr "" "Dieses Plugin funktioniert mit der Dateiverwaltung Nautilus und " "benötigt die installierte Erweiterung kupfer_provider.py. Diese " "gehört normalerweise zu einer Kupfer-Installation. Nach der " "Erstinstallation müssen Sie Nautilus neu starten, bevor die " "Erweiterung aktiv wird." #: C/plugin-gwibber.page:7(desc) msgid "Using the Gwibber plugin." msgstr "Verwendung des Gwibber-Plugins." #: C/plugin-gwibber.page:10(app) msgid "Gwibber" msgstr "Gwibber" #: C/plugin-gwibber.page:13(title) msgid "Gwibber Plugin" msgstr "Gwibber-Plugin" #: C/plugin-gwibber.page:14(p) msgid "" "With the Gwibber plugin you can send messages to social networks " "such as Twitter or Identi.ca." msgstr "" "Mit dem Gwibber-Plugin können Sie Nachrichten an soziale Netzwerke " "wie Twitter oder Identi.ca senden." #: C/plugin-gwibber.page:18(p) msgid "" "The plugin requires that the application Gwibber is installed and " "configured for your user. Kupfer will start and use Gwibber's " "service in the background." msgstr "" "Dieses Plugin erfordert es, dass die Anwendung Gwibber installiert " "und für Ihr Benutzerkonto konfiguriert ist. Kupfer startet und " "verwendet den Gwibber-Dienst im Hintergrund." #: C/plugin-gwibber.page:27(title) msgid "Sending a message to all services" msgstr "Eine Nachricht an alle Dienste senden" #: C/plugin-gwibber.page:29(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "message." msgstr "" "Aktivieren Sie Kupfer und drücken Sie die Taste ., um in den " "Textmodus zu gelangen und geben Sie anschließend Ihre Nachricht ein." #: C/plugin-gwibber.page:35(p) msgid "" "Type Tab and select the action Send Message and press " "Return." msgstr "" "Drücken Sie die Tab-Taste und wählen Sie die Aktion Nachricht " "senden. Drücken Sie anschließend die Eingabetaste." #: C/plugin-gwibber.page:42(title) msgid "Sending a message to a specific service" msgstr "Eine Nachricht an einen bestimmten Dienst senden" #: C/plugin-gwibber.page:44(p) msgid "" "Activate Kupfer and search for the service object, for example Identi.ca" msgstr "" "Aktivieren Sie Kupfer und suchen Sie nach dem Dienst, beispielsweise " "Identi.ca." #: C/plugin-gwibber.page:50(p) msgid "Type Tab and select the action Send Message." msgstr "" "Drücken Sie die Tab-Taste und wählen Sie die Aktion Nachricht " "senden." #: C/plugin-gwibber.page:55(p) msgid "" "Type Tab to select the last pane, and type in a message. Press " "Return to send." msgstr "" "Drücken Sie die Tabulatortaste, um die letzte Leiste auszuwählen " "und geben Sie Ihre Nachricht ein. Drücken Sie anschließend die " "Eingabetaste, um sie zu versenden.." #: C/plugin-gwibber.page:61(p) msgid "" "The plugin also provides a source for incoming messages, Gwibber " "Messages and more actions on messages such as Reply, Send " "Private Message etc." msgstr "" #: C/plugin-gwibber.page:71(p) msgid "" "You can use the comma trick if you want to send a message to more " "than one service, but not all, at the same time." msgstr "" #: C/plugin-favorites.page:7(desc) msgid "Using the favorites plugin." msgstr "Verwendung des Favoriten-Plugins." #: C/plugin-favorites.page:10(app) msgid "Favorites" msgstr "Favoriten" #: C/plugin-favorites.page:13(title) msgid "Favorites Plugin" msgstr "Favoriten-Plugin" #: C/plugin-favorites.page:14(p) msgid "" "With Favorites you mark objects, for example files, for quicker " "access. It is a sort of shelf on which you can store objects in Kupfer. " "Objects marked as favorites will also be ranked higher and are adorned with a " "star symbol." msgstr "" #: C/plugin-favorites.page:25(p) msgid "Find an object in Kupfer" msgstr "Ein Objekt in Kupfer suchen" #: C/plugin-favorites.page:30(p) msgid "" "Type Tab and select either the action Add to Favorites or " "Remove from Favorites." msgstr "" #: C/plugin-favorites.page:39(p) msgid "" "If you favorite an object, you can access it in more places. Not only in the " "\"Favorites\" subcatalog, but also as the indirect (secondary) object for " "some actions. For example:" msgstr "" #: C/plugin-favorites.page:45(p) msgid "Command-lines from favorites are quick to access." msgstr "" #: C/plugin-favorites.page:46(p) msgid "" "When scaling images with the Scale... action from the Image " "Tools plugin. This action needs a size description as the third object, " "like \"1024\" or \"1200x800\". If you often scale to the same size, say " "\"1200x800\", add this to favorites, and it will always appear as a " "suggestion for the action." msgstr "" #: C/plugin-favorites.page:54(p) msgid "" "Actions needing an email address as the indirect object will pick up email " "addresses from favorites as well as well." msgstr "" #: C/plugin-calculator.page:7(desc) msgid "Using the calculator plugin." msgstr "Verwendung des Taschenrechner-Plugins." #: C/plugin-calculator.page:10(app) msgid "Calculator" msgstr "Taschenrechner" #: C/plugin-calculator.page:13(title) msgid "Calculator Plugin" msgstr "Taschenrechner-Plugin" #: C/plugin-calculator.page:14(p) msgid "" "The calculator plugin lets you calculate expressions quickly. It can evaluate " "expressions entered as text starting with \"=\". Entering = from command mode " "will start text mode directly with = prefixed for quick access." msgstr "" "Mit dem Taschenrechner-Plugin können Sie Ausdrücke schnell und einfach " "berechnen lassen. Die Berechnung von Ausdrücken ist möglich, welche als Text " "eingegeben werden, beginnend mit »=«. Die Eingabe eines = im Befehlsmodus " "startet direkt den Textmodus, wobei für den schnellen Zugriff der Eingabe ein " "= vorangestellt wird." #: C/plugin-calculator.page:23(p) msgid "Activate Kupfer and type =" msgstr "Aktivieren Sie Kupfer und geben Sie = ein." #: C/plugin-calculator.page:26(p) msgid "" "Type in a mathematical expression using +,-,/,* (and ** for exponentiation)" msgstr "" "Geben Sie einen mathematischen Ausdruck mittels +,-," "/,* ein (und ** für Exponenten)." #: C/plugin-calculator.page:30(p) msgid "Press Return to get the result." msgstr "Drücken Sie die Eingabetaste, um das Ergebnis zu erhalten." #: C/plugin-calculator.page:38(p) msgid "" "The Calculator uses python's math and complex math modules, and parses " "expressions as Python expressions. You may use common mathematical functions, " "such as sqrt, sin, exp and log; " "the command =help will show a list of all defined functions and " "constants." msgstr "" "Der Taschenrechner verwendet die Mathematik- und komplexen Mathematikmodule " "aus Python. Ausdrücke werden als Python-Ausdrücke interpretiert. Sie können " "übliche mathematische Funktionen verwenden, wie beispielsweise sqrt, sin, exp und log. Der Befehl " "=help zeigt eine Liste aller definierten Funktionen und Konstanten." #: C/plugin-calculator.page:47(p) msgid "" "Notice that the power operator in Python is double stars, for example " "=3**3 will evaluate to 27." msgstr "" "Beachten Sie, dass Python als Potenzzeichen einen doppelten Asterisk " "verwendet. Beispielsweise wird die Eingabe =3**3 im Ergebnis zu 27." #: C/plugin-calculator.page:53(p) msgid "To calculate trig functions for angles, convert to radians first:" msgstr "" "Um trigonometrische Funktionen für Winkel berechnen zu lassen, wandeln Sie " "diese zunächst in Radiant um:" #: C/plugin-calculator.page:56(code) #, no-wrap msgid "sin(radians(30)) -> 0.5" msgstr "sin(radians(30)) -> 0.5" #: C/plugin-calculator.page:59(p) msgid "" "The last result is stored as the name _ (an underscore, just like in the " "Python console)." msgstr "" "Das letzte Ergebnis wird als Unterstrich gespeichert (wie in der Python-" "Konsole)." #: C/plugin-applications.page:7(desc) msgid "Using the applications plugin." msgstr "Verwendung des Anwendungen-Plugins." #: C/plugin-applications.page:10(app) msgid "Applications" msgstr "Anwendungen" #: C/plugin-applications.page:13(title) msgid "Applications Plugin" msgstr "Anwendungen-Plugin" #: C/plugin-applications.page:14(p) msgid "Applications provides all installed programs." msgstr "Anwendungen stellt alle installierten Programme bereit." #: C/plugin-applications.page:21(title) msgid "Launching an application" msgstr "Starten einer Anwendung" #: C/plugin-applications.page:23(p) msgid "Activate Kupfer and type an abbreviation of the application name" msgstr "" "Aktivieren Sie Kupfer und geben Sie eine Abkürzung des Anwendungsnamens ein." #: C/plugin-applications.page:28(p) msgid "Press Return to launch the application." msgstr "Drücken Sie die Eingabetaste, um die Anwendung zu starten." #: C/plugin-applications.page:34(title) msgid "Opening a file with a specific application" msgstr "Eine Datei mit einer bestimmten Anwendung öffnen" #: C/plugin-applications.page:36(p) msgid "Select a file in Kupfer" msgstr "Eine Datei in Kupfer auswählen" #: C/plugin-applications.page:41(p) msgid "Type Tab and select the action Open With..." msgstr "" #: C/plugin-applications.page:46(p) msgid "" "Type Tab to select the third (indirect object) pane and in it, " "select the application to open the file with." msgstr "" #: C/plugin-applications.page:53(p) msgid "" "The action Open opens files and folders with the registered default " "application for that specific file type. This can be configured using the " "action Set Default Application...." msgstr "" #: C/plugin-applications.page:58(p) msgid "" "The file type associations are provided by the desktop environment, and " "modifying them here will modify them on the desktop as well. This may not be " "true when not using GNOME or XFCE." msgstr "" #: C/plugin-applications.page:64(title) msgid "Selecting default application for a file type or folders" msgstr "Auswahl der Standardanwendung für einen Dateityp und für Ordner" #: C/plugin-applications.page:66(p) msgid "Select a file or folder in Kupfer" msgstr "Dateien oder Ordner in Kupfer auswählen" #: C/plugin-applications.page:71(p) msgid "" "Type Tab and select the action Set Default Application..." msgstr "" #: C/plugin-applications.page:77(p) msgid "" "Type Tab to select the third (indirect object) pane and in it, " "select the application to always open the file type with." msgstr "" #: C/plugin-applications.page:85(title) msgid "Configuration" msgstr "Konfiguration" #: C/plugin-applications.page:86(p) msgid "" "The configuration option Applications for Desktop Environment in the " "plugin's information pane in Kupfer Preferences determines how " "Kupfer should act with regard to the desktop environment " "configuration—certain applications request not to be shown depending on which " "desktop environment is used. By default, it behaves like GNOME." msgstr "" #: C/moreusage.page:7(desc) msgid "More advanced usage information." msgstr "Erweiterte Informationen zur Benutzung." #: C/moreusage.page:10(title) msgid "Using Kupfer in Depth" msgstr "Fortgeschrittene Verwendung von Kupfer" #: C/moreusage.page:13(title) msgid "Adding Applications and Scripts" msgstr "Eigene Anwendungen und Skripte hinzufügen" #: C/moreusage.page:14(p) msgid "" "Kupfer will show all applications that are configured visible in " "your menu editor." msgstr "" #: C/moreusage.page:18(p) msgid "" "If you want to add an application manually, you can create a new ." "desktop file and place it in one of the standard directories for " "applications, for example ~/.local/share/applications, where " "Kupfer will find it." msgstr "" "Wenn Sie eine benutzerdefinierte Anwendung hinzufügen wollen, dann können Sie " "eine neue *.desktop-Datei dafür erstellen und die Datei an einem der " "Standardorte für Anwendungen ablegen, beispielsweise ~/.local/share/" "applications, wo Kupfer ihn finden kann." #: C/moreusage.page:24(p) msgid "" "If you have a collection of scripts that you want to call from Kupfer, you can add the scripts folder as a catalog directory to Kupfer in the preferences. Scripts that you add to Kupfer's catalog " "this way can be run directly or in the terminal as long as they are " "executable." msgstr "" "Falls sie über eine Skriptsammlung verfügen, die Sie aus Kupfer " "heraus aufrufen wollen, dann können Sie den Skriptordner direkt als Katalog " "in den Einstellungen von Kupfer hinzufügen. Auf diese Weise zum " "Katalog von Kupfer hinzugefügte Skripte können direkt oder im " "Terminal aufgerufen werden, sofern Sie ausführbar sind." #: C/moreusage.page:31(p) msgid "" "You can also save command-lines by using the action Add to Favorites." msgstr "" #: C/moreusage.page:38(title) msgid "Opening Files and Folders" msgstr "Dateien und Ordner öffnen" #: C/moreusage.page:39(p) msgid "" "Using the action Open, files and folders are opened in their " "preferred application. The application associations can be changed, see ." msgstr "" #: C/moreusage.page:47(title) msgid "The Comma Trick" msgstr "Der Komma-Trick" #: C/moreusage.page:48(p) msgid "" "The comma trick allows the user to use actions on many objects at the same " "time." msgstr "" #: C/moreusage.page:52(p) msgid "" "Simply press comma , when an object is selected. The object is put " "on a \"stack\", and you can find yet another file or object, press comma to " "put it on the stack. When you subsequently invoke an action, the action is " "carried out on all of the objects at the same time." msgstr "" #: C/moreusage.page:58(p) msgid "" "Some actions are only \"multiplied\" when used with many objects, other are " "smarter than that:" msgstr "" #: C/moreusage.page:61(p) msgid "" "Selecting many files and using the Create Archive action, all files will be " "packed into the same archive." msgstr "" #: C/moreusage.page:63(p) msgid "" "If you select multiple contacts and use a Send Email action, it creates one " "email directed at all the contacts." msgstr "" #: C/moreusage.page:65(p) msgid "" "If you select multiple subcatalogs (For example Firefox Bookmarks and " "Epiphany Bookmarks) and use Search Contents.., you get a subcatalog search " "restricted to the objects of those two catalogs! You can even bind a trigger " "to this command(!)" msgstr "" #: C/moreusage.page:71(p) msgid "" "The comma trick is directly taken from Quicksilver (the " "example given in the external article should work identically in Kupfer)." msgstr "" #: C/moreusage.page:80(title) msgid "Grab Current Selection" msgstr "Aktuelle Auswahl markieren" #: C/moreusage.page:81(p) msgid "" "To use the current selected text, from any application, with Kupfer, you can configure a global keyboard shortcut for the action Show " "with Selection in Kupfer Preferences." msgstr "" #: C/moreusage.page:85(p) msgid "" "If configured, pressing the global keyboard shortcut will summon Kupfer with the current selection as the focused object." msgstr "" #: C/moreusage.page:90(p) msgid "See " msgstr "Siehe " #: C/moreusage.page:94(title) msgid "Command-line Connection" msgstr "Verbindung zur Befehlszeile" #: C/moreusage.page:95(p) msgid "" "The command kupfer on the command-line will focus Kupfer if it's already running, otherwise it will start it." msgstr "" #: C/moreusage.page:99(p) msgid "" "The command kupfer can be used to send files or text from the " "command-line to Kupfer. For example, if you are using the shell in " "a directory where you have a file called \"report.pdf\", you can focus this " "file in Kupfer by running kupfer report.pdf." msgstr "" "Der Befehl kupfer kann dazu verwendet werden, Dateien oder Text " "aus der Befehlszeile an Kupfer zu übergeben. Wenn Sie " "beispielsweise die Shell in einem Ordner verwenden, in dem sich eine Datei " "namens »report.pdf« befindet, können Sie diese Datei mittels Kupfer markieren, indem Sie kupfer report.pdf aufrufen." #: C/moreusage.page:107(p) msgid "" "You can also send text if you pipe the output of a command into kupfer." msgstr "" #: C/moreusage.page:114(title) msgid "Managing Context and Current Selection" msgstr "Verwaltung des Kontexts und der aktuellen Auswahl" #: C/moreusage.page:115(p) msgid "" "If you find the object you want to use, then invoke an action, Kupfer goes away to perform the action (for example start a program or play a " "song). When you come back to Kupfer, it will still keep the same " "object and action selected. Some actions make sense to be repeated (like " "skipping to the next song) and it can be useful to perform different actions " "on the same object." msgstr "" "Wenn Sie das Objekt gefunden haben, das Sie benötigen, dann rufen sie die " "Aktion auf, und Kupfer verschwindet, um die Aktion auszuführen, " "beispielsweise um ein Programm zu starten oder ein Lied abzuspielen. Wenn Sie " "erneut zu Kupfer zurückkehren, dann ist noch immer die gleiche " "Aktion und das gleiche Objekt ausgewählt. Bei einigen Aktionen ergibt es " "durchaus Sinn, sie zu wiederholen, wie beim Springen zum nächsten " "wiederzugebenden Lied. Es kann nützlich sein, verschiedene Aktionen mit dem " "gleichen Objekt auszuführen." #: C/moreusage.page:123(p) msgid "" "However, you always have the top level catalog reachable when you \"come back" "\" to Kupfer -- say you went into the subcatalog \"Albums\" to " "browse your albums only; you select an album to play, and play it. You come " "back with the album selected -- but your next search will still go over the " "top level catalog, not just albums." msgstr "" "Sie befinden sich für die Suche immer im Katalog der obersten Ebene, wenn Sie " "zu Kupfer »zurückkehren«. Wenn Sie in den Unterkatalog »Alben« " "abtauchen, durchsuchen Sie damit nur die Alben, wählen eines zur Wiedergabe " "aus und lassen es abspielen. Doch Ihre nächste Suche springt wieder in den " "Katalog der obersten Ebene und durchsucht nicht nur die Alben." #: C/moreusage.page:130(p) msgid "" "How to come back into the subcatalog you were in? You do that by simply " "browsing, not searching the first thing you do when you focus Kupfer again. A quick way is to press down-arrow or space to open the browse " "window; think of it as saying \"I want to stay in this subfolder\". With the " "browse window open, your next query will search the current subcatalog." msgstr "" "Wie kommen Sie nun wieder in den Unterkatalog zurück, in welchem Sie bereits " "waren? Durch einfaches Navigieren, nicht durch Suchen nach dem ersten Objekt, " "wenn Sie Kupfer wieder fokussieren. Ein einfacher Weg ist das " "Drücken der Pfeiltaste nach unten oder der Leertaste, um das " "Navigationsfenster zu öffnen. Stellen Sie sich das so vor, als ob Sie sagen " "würden: »Ich will in diesem Unterordner bleiben«. Mit geöffnetem " "Navigationsfenster wird für die Suche nur der aktuell markierte Unterkatalog " "abgefragt." #: C/moreusage.page:137(p) msgid "" "This way you can work both ways -- you can quickly drill down into folders to " "find a file, and when you come back for the next action with Kupfer you can either summon any normal toplevel object (just start typing), or " "stay around where you were, deep in that folder (press space, then type a " "query)." msgstr "" "So schlagen Sie zwei Fliegen mit einer Klappe -- Sie tauchen schnell in " "Unterordner ab, um eine Datei zu finden, und wenn Sie das nächste Mal zu " "Kupfer zurückkehren, können sie entweder jedes gewöhnliche Objekt " "der obersten Ebene erfassen (einfach eintippen!) oder Sie bleiben da, wo Sie " "sind, tief in dem jeweiligen Ordner (Leertaste drücken, dann Abfrage " "eingeben)." #: C/moreusage.page:146(title) msgid "Saving Commands as Files" msgstr "Speichern von Befehlen als Datei" #: C/moreusage.page:147(p) msgid "" "You can use keyboard shortcut for Compose Command (by default it is " "CtrlReturn) to create a command object " "out of the currently focused command in Kupfer. This object can be saved as a " "runnable file if you use the Save As... action. The resulting file " "will can be executed when opened from the file manager (it requires that " "Kupfer is already running)." msgstr "" #: C/managing-plugins.page:7(desc) msgid "Using plugins with Kupfer." msgstr "Verwendung von Plugins in Kupfer." #: C/managing-plugins.page:10(title) msgid "How to Configure Plugins" msgstr "Konfigurieren der Plugins" #: C/managing-plugins.page:12(p) msgid "" "Functionality in Kupfer is organized by extentsion modules called \"plugins" "\". Each plugin provides additional functionality, for example integration " "with an external application." msgstr "" #: C/managing-plugins.page:19(title) msgid "Configuring Plugins" msgstr "Einrichten von Plugins" #: C/managing-plugins.page:21(title) msgid "Open Kupfer Preferences to the Plugins tab" msgstr "" "Öffnen Sie die Kupfer-Einstellungen und wechseln Sie zum Plugins-" "Reiter" #: C/managing-plugins.page:23(p) msgid "Use one of the following methods:" msgstr "Verwenden Sie eine der folgenden Methoden:" #: C/managing-plugins.page:25(p) msgid "" "Click the Kupfer icon in the notification area and select the item " "Preferences" msgstr "" "Klicken Sie auf das Kupfer-Symbol im Benachrichtigungsfeld und wählen Sie den " "Eintrag Einstellungen." #: C/managing-plugins.page:25(item) msgid "." msgstr "." #: C/managing-plugins.page:29(p) msgid "" "Search for the object Kupfer Preferences in Kupfer itself. Press " "Return to open it." msgstr "" "Suchen Sie nach dem Objekt Kupfer-Einstellungen in Kupfer selbst. " "Drücken Sie die Eingabetaste zum Öffnen." #: C/managing-plugins.page:33(p) msgid "Use the keyboard shortcut Ctrl;" msgstr "" "Verwenden Sie das Tastenkürzel Strg;" #: C/managing-plugins.page:39(p) msgid "Select the tab Plugins" msgstr "Wählen Sie den Reiter Plugins." #: C/managing-plugins.page:45(p) msgid "" "Select plugins in the list to read about them, and tick the box next to its " "name to activate the plugin, or untick to deactivate." msgstr "" #: C/managing-plugins.page:49(p) msgid "" "If the plugin has any configurable parameters, they will be visible below the " "plugin information." msgstr "" #: C/managing-plugins.page:53(p) msgid "" "The plugin Kupfer Plugins allows fast access to each plugin's " "information page as well as the action \"Show Source Code\" which reveals the " "implementation." msgstr "" #: C/managing-plugins.page:59(title) msgid "If a Plugin can not be Activated" msgstr "Wenn ein Plugin nicht aktiviert werden kann" #: C/managing-plugins.page:60(p) msgid "" "If a plugin fails to activate because it requires a software module that is " "not available, its plugin information will display a message like this:" msgstr "" "Falls das Laden eines Plugins scheitert, weil ein bestimmtes benötigtes " "Softwaremodul nicht verfügbar ist, wird eine Meldung wie die folgende " "angezeigt:" #: C/managing-plugins.page:65(em) msgid "Plugin could not be read due to an error:" msgstr "Plugin kann wegen eines Fehlers nicht gelesen werden" #: C/managing-plugins.page:66(em) msgid "Python module 'gdata' is needed" msgstr "Python-Modul »gdata« wird benötigt" #: C/managing-plugins.page:67(p) msgid "" "This means that you need to install a needed python module from your " "distribution—and possibly the plugin documentation can tell you how." msgstr "" "Dies bedeutet, dass Sie ein Python-Modul aus ihrer Distribution installieren " "müssen. Die Dokumentation des Plugins gibt möglicherweise dazu nähere " "Auskünfte." #: C/managing-plugins.page:72(p) msgid "" "The plugin may also unexpectedly fail to load, and display a different error " "message. It may then be a program error in either the plugin or Kupfer." msgstr "" "Das Laden des Plugins könnte auch aus unerwartetem Grund scheitern und eine " "andere Fehlermeldung anzeigen. Es kann sich dann um einen Programmierfehler " "entweder im Plugin oder in Kupfer handeln." #: C/managing-plugins.page:79(title) msgid "Installing more Plugins" msgstr "Weitere Plugins installieren" #: C/managing-plugins.page:80(p) msgid "" "You can install custom plugins into the folder ~/.local/share/kupfer/" "plugins. Each plugin is either a single .py file or a " "python package (a folder directly containing a file called __init__.py). Plugins in the package format can include icon files. Python packages " "can even be installed as .zip files." msgstr "" "Sie können benutzerdefinierte Plugins in den Ordner ~/.local/share/" "kupfer/plugins installieren. Jedes Plugin ist entweder eine einzelne " ".py-Datei oder ein Python-Package (ein Ordner, der direkt eine " "Datei namens __init__.py enthält). Plugins im Paketformat können " "Symboldateien enthalten. Python-Pakete können auch als .zip-" "Dateien installiert werden." #: C/managing-plugins.page:88(p) msgid "" "Caution: Treat a plugin as a computer program. Do not install " "untrusted plugins." msgstr "" "Achtung: Betrachten Sie Plugins als Computerprogramme. Installieren " "Sie keine Plugins aus Quellen, die nicht vertrauenswürdig sind." #: C/managing-plugins.page:95(title) msgid "Creating Plugins" msgstr "Plugins erstellen" #: C/managing-plugins.page:96(p) msgid "" "Documentation for plugin creators is available in the file " "Documentation/Manual.rst in the source distribution on the " "webpage at Kupfer Manual. An easy way to start is to copy an existing plugin and experimenting " "with it." msgstr "" #: C/managing-plugins.page:107(title) msgid "The Catalog Tab in Preferences" msgstr "Der Katalog-Reiter in den Einstellungen" #: C/managing-plugins.page:108(p) msgid "" "Each plugin can export a number of sources which contain objects. Normally, " "all these objects are directly accessible from a top-level search. Some " "plugins export so specialized or so many objects that their catalogs should " "better not have their objects exported to the top level. To reach those " "objects, you have to first find the catalog by name, then enter the catalog " "using the action Search Contents." msgstr "" #: C/managing-plugins.page:118(p) msgid "" "In the tab Catalog in Kupfer Preferences, a ticked box " "next to each source means that its objects are exported. An unticked box " "means that its contents are hidden from the top level." msgstr "" #: C/managing-plugins.page:123(p) msgid "" "Note: Kupfer may become slow if large enough subcatalogs are " "exported to the top level." msgstr "" "Hinweis: Kupfer kann sehr langsam werden, falls größere " "Unterkataloge in die oberste Ebene exportiert werden." #: C/license.page:7(desc) msgid "You can copy, modify and share Kupfer." msgstr "Sie können Kupfer kopieren, Änderungen vornehmen und weitergeben." #: C/license.page:10(title) msgid "License" msgstr "Lizenz" #: C/license.page:12(p) msgid "" "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." msgstr "" "Dieses Programm ist freie Software. Sie können es unter den Bedingungen der " "GNU General Public License, wie von der Free Software " "Foundation veröffentlicht, weitergeben und/oder modifizieren, entweder gemäß " "Version 3 der Lizenz oder (nach Ihrer Option) jeder späteren Version." #: C/license.page:18(p) msgid "" "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." msgstr "" "Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, dass es Ihnen " "von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, sogar ohne die implizite " "Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. " "Details finden Sie in der GNU General Public License." #: C/license.page:24(p) msgid "" "You should have received a copy of the GNU General Public License along with " "this program. If not, see gnu.org/" "licenses." msgstr "" "Sie sollten eine Kopie der Allgemeinen Öffentlichen GNU-Lizenz zusammen mit " "diesem Programm erhalten haben. Falls nicht finden Sie sie hier." #: C/license.page:30(p) msgid "" "This documentation is licensed under a Creative Commons Attribution-Share Alike 3.0 " "Unported License." msgstr "" "Diese Dokumentation ist lizenziert unter einer Creative Commons Attribution-Share " "Alike 3.0 Unported License." #: C/license.page:36(p) msgid "" "As a special exception, the copyright holders give you permission to copy, " "modify, and distribute the example code contained in this document under the " "terms of your choosing, without restriction." msgstr "" "Als besondere Ausnahme erteilen Ihnen die Urheberrechtsinhaber die " "Genehmigung, den in diesem Dokument enthaltenen Beispielcode ohne " "Einschränkung unter den Bedingungen Ihrer Wahl zu verbreiten." #: C/keyboard.page:7(desc) msgid "Complete keyboard shortcuts reference." msgstr "Vollständige Referenz der Tastenkombinationen." #: C/keyboard.page:10(title) msgid "Command Keys and Accelerator Keys" msgstr "Befehlstasten und Zugriffstasten" #: C/keyboard.page:13(title) C/generalusage.page:12(title) msgid "Keyboard Interface" msgstr "Tastaturschnittstelle" #: C/keyboard.page:14(p) msgid "In command mode, the following keystrokes have special meanings:" msgstr "Im Befehlsmodus haben die folgenden Tastenkürzel besondere Bedeutungen:" #: C/keyboard.page:19(p) C/generalusage.page:34(p) msgid " or Space" msgstr " oder Leertaste" #: C/keyboard.page:20(p) C/generalusage.page:35(p) msgid "Go to the next match" msgstr "Zum nächsten Treffer gehen" #: C/keyboard.page:23(p) C/generalusage.page:38(p) msgid " or ShiftSpace" msgstr "" " oder UmschalttasteLeertaste" #: C/keyboard.page:26(p) C/generalusage.page:41(p) msgid "Go to the previous match" msgstr "Zum vorherigen Treffer gehen" #: C/keyboard.page:29(p) C/generalusage.page:44(p) msgid " or /" msgstr " oder /" #: C/keyboard.page:30(p) C/generalusage.page:45(p) msgid "Descend into an object with content" msgstr "Eintauchen in ein Objekt mit Inhalten" #: C/keyboard.page:33(key) C/generalusage.page:48(key) msgid "Backspace" msgstr "Löschtaste" #: C/keyboard.page:34(p) C/generalusage.page:49(p) msgid "Erase a character from the query. If the query is empty, go up a level" msgstr "" "Das Zeichen aus der Suche löschen. Falls die Suche leer ist, eine Ebene nach " "oben gehen." #: C/keyboard.page:39(key) C/keyboard.page:93(key) C/generalusage.page:54(key) msgid "." msgstr "." #: C/keyboard.page:40(p) C/generalusage.page:55(p) msgid "Activate free-text mode" msgstr "Aktivierung des freien Textmodus" #: C/keyboard.page:43(key) C/keyboard.page:97(key) C/generalusage.page:58(key) msgid "," msgstr "," #: C/keyboard.page:44(p) C/generalusage.page:59(p) msgid "Put selected object on the stack (\"Comma Trick\")" msgstr "Ausgewähltes Objekt zum Stapel hinzufügen (»Komma-Trick«)" #: C/keyboard.page:47(p) msgid "Quick access keys:" msgstr "Schnellzugriffe:" #: C/keyboard.page:53(key) msgid "=" msgstr "=" #: C/keyboard.page:55(p) msgid "" "Activate free-text mode with = prefix (for )" msgstr "" #: C/keyboard.page:61(key) msgid "/" msgstr "/" #: C/keyboard.page:63(p) msgid "" "Activate free-text mode (when nothing is selected) with / prefix " "(to input a rooted path)" msgstr "" #: C/keyboard.page:68(p) C/generalusage.page:62(p) msgid "Additionally:" msgstr "Zusätzlich:" #: C/keyboard.page:72(p) C/generalusage.page:66(p) msgid "" "Return activates the current selection: the command is executed." msgstr "" "Die Eingabetaste aktiviert die aktuelle Auswahl: der Befehl wird " "ausgeführt." #: C/keyboard.page:74(p) C/generalusage.page:68(p) msgid "Escape clears the current selection." msgstr "Die Esc-Taste löscht die aktuelle Auswahl." #: C/keyboard.page:75(p) C/generalusage.page:69(p) msgid "Tab switches between the object and the action pane." msgstr "" "Die Tabulatortaste schaltet zwischen dem Objekt und der " "Aktionsansicht um." #: C/keyboard.page:77(p) msgid "" "The meaning of the keys Space, ., ,, / and = can not be changed, but you can deactivate their " "special meaning with the checkbox Use single keystroke commands in " "Kupfer Preferences." msgstr "" #: C/keyboard.page:86(title) msgid "Kupfer's Keyboard Shortcuts" msgstr "Tastenkombinationen in Kupfer" #: C/keyboard.page:87(p) msgid "" "These keyboard shortcuts are used in Kupfer's interface. They have " "the following meanings and default shortcuts:" msgstr "" "Diese Tastenkürzel werden in der Benutzeroberfläche von Kupfer " "verwendet. Sie haben folgende Bedeutungen und Vorgabeeinstellungen:" #: C/keyboard.page:93(key) C/keyboard.page:97(key) C/keyboard.page:101(key) #: C/keyboard.page:105(key) C/keyboard.page:113(key) C/keyboard.page:117(key) #: C/keyboard.page:121(key) C/keyboard.page:125(key) C/keyboard.page:129(key) #: C/keyboard.page:174(key) msgid "Ctrl" msgstr "Strg" #: C/keyboard.page:94(p) msgid "Toggle text mode" msgstr "Textmodus umschalten" #: C/keyboard.page:98(p) msgid "The comma trick" msgstr "Der Komma-Trick" #: C/keyboard.page:101(key) msgid ";" msgstr ";" #: C/keyboard.page:102(p) msgid "Show preferences window" msgstr "Das Einstellungsfenster anzeigen" #: C/keyboard.page:105(key) msgid "R" msgstr "R" #: C/keyboard.page:106(p) msgid "Reset all" msgstr "Alle zurücksetzen" #: C/keyboard.page:109(key) msgid "Alt" msgstr "Alt" #: C/keyboard.page:109(key) msgid "A" msgstr "A" #: C/keyboard.page:110(p) msgid "Alternate activate" msgstr "Alternative Aktivierung" #: C/keyboard.page:113(key) msgid "Return" msgstr "Eingabe" #: C/keyboard.page:114(p) msgid "Compose command" msgstr "Compose-Befehl" #: C/keyboard.page:117(key) msgid "S" msgstr "S" #: C/keyboard.page:118(p) msgid "Switch to first pane" msgstr "Zur ersten Leiste wechseln" #: C/keyboard.page:121(key) msgid "Q" msgstr "Q" #: C/keyboard.page:122(p) msgid "Select 'Quit'" msgstr "»Beenden« wählen" #: C/keyboard.page:125(key) msgid "G" msgstr "G" #: C/keyboard.page:126(p) msgid "Select 'Selected File'" msgstr "»Ausgewählte Datei« wählen" #: C/keyboard.page:129(key) msgid "T" msgstr "T" #: C/keyboard.page:130(p) msgid "Select 'Selected Text'" msgstr "»Ausgewählter Text« wählen" #: C/keyboard.page:133(key) msgid "F1" msgstr "F1" #: C/keyboard.page:134(p) msgid "Show Help" msgstr "Hilfe anzeigen" #: C/keyboard.page:139(title) msgid "How to configure a keyboard shortcut" msgstr "Einrichtung einer Tastenkombination" #: C/keyboard.page:141(p) C/keyboard.page:185(p) msgid "Open Kupfer Preferences and go to the Keyboard tab." msgstr "" "Öffnen Sie die Kupfer-Einstellungen und wechseln Sie zum Reiter " "Tastatur." #: C/keyboard.page:147(p) msgid "" "Double-click the shorcut's row under Browser Keyboard Shortcuts." msgstr "" #: C/keyboard.page:153(p) msgid "" "Using the window that appears, press modifier keys and a letter or number key " "to set a shortcut. An example is pressing and holding Ctrl and " "then pressing and releasing T to bind CtrlT." msgstr "" #: C/keyboard.page:164(title) msgid "Global Keyboard Shortcuts" msgstr "Globale Tastenkombinationen" #: C/keyboard.page:165(p) msgid "" "Kupfer always listens to global shortcuts, even if it is not " "currently in the foreground." msgstr "" "Kupfer verfolgt stets die Verwendung globaler Tastenkürzel, selbst " "dann, wenn es sich nicht im Vordergrund befindet." #: C/keyboard.page:169(p) msgid "They have the following meanings and default shortcuts:" msgstr "" #: C/keyboard.page:174(key) msgid "Space" msgstr "Leertaste" #: C/keyboard.page:175(p) msgid "Show/hide Kupfer" msgstr "Kupfer anzeigen oder verbergen" #: C/keyboard.page:178(p) msgid "(not configured by default)" msgstr "(keine Voreinstellung)" #: C/keyboard.page:179(p) msgid "Show Kupfer with 'Selection' object focused" msgstr "" #: C/keyboard.page:183(title) msgid "How to configure a global keyboard shortcut" msgstr "Einrichtung einer globalen Tastenkombination" #: C/keyboard.page:191(p) msgid "Double-click the shorcut's row under Global Keyboard Shortcuts." msgstr "" #: C/keyboard.page:197(p) msgid "" "Using the window that appears, press modifier keys and a letter or number key " "to set a global shortcut. An example is pressing and holding Super " "and then pressing and releasing Space to bind SuperSpace." msgstr "" #: C/keyboard.page:206(p) msgid "" "Since these keyboard shortcuts are global, they can be used from any " "application. Select shortcuts with care so that they do not conflict with " "other functions." msgstr "" "Da diese Tastenkürzel globaler Natur sind, können sie von jeder Anwendung " "genutzt werden. Wählen Sie die Tastenkürzel mit Bedacht aus, so dass sie " "keine Konflikte mit anderen Funktionen verursachen." #: C/keyboard.page:214(p) msgid "" "The plugin Triggers allows to activate actions with global keyboard " "shortcuts. Trigger shortcuts do not appear in Kupfer Preferences." msgstr "" "Das Auslöser-Plugin ermöglicht die Aktivierung von Aktionen mit " "globalen Tastenkürzeln. Auslöser-Tastenkürzel werden nicht in den Kupfer-" "Einstellungen angezeigt." #: C/keyboard.page:220(p) msgid "See for more information." msgstr "Siehe für weitere Informationen." #: C/introduction.page:7(desc) msgid "Introduction to Kupfer." msgstr "Einführung in Kupfer." #: C/introduction.page:10(title) msgid "Introduction" msgstr "Einführung" #: C/introduction.page:12(p) msgid "" "Kupfer is an interface for quick and convenient access to " "applications and their documents." msgstr "" "Kupfer ist eine Schnittstelle für den bequemen und schnellen " "Zugriff auf Anwendungen und Dokumente." #: C/introduction.page:16(p) msgid "" "The most typical use is to find a specific application and launch it. We have " "tried to make Kupfer easy to extend with plugins so that this " "quick-access paradigm can be extended to many more objects than just " "applications." msgstr "" #: C/introduction.page:22(p) msgid "" "We hope that using Kupfer feels both very fun and " "different." msgstr "" #: C/introduction.page:26(p) msgid "" "For up-to-date information about Kupfer, visit its homepage." msgstr "" "Weitere Informationen über Kupfer finden Sie auf dessen Webseite." #: C/index.page:9(name) msgid "Ulrik Sverdrup" msgstr "Ulrik Sverdrup" #: C/index.page:10(email) msgid "ulrik.sverdrup@gmail.com" msgstr "ulrik.sverdrup@gmail.com" #: C/index.page:13(year) msgid "2009" msgstr "2009" #: C/index.page:14(name) msgid "Kupfer Development Team" msgstr "Kupfer-Entwicklungsteam" #: C/index.page:17(license) msgid "Creative Commons Share Alike 3.0" msgstr "Creative Commons Share Alike 3.0" #: C/index.page:21(title) msgid "Kupfer Manual" msgstr "Kupfer-Handbuch" #: C/index.page:24(title) msgid "Using Kupfer" msgstr "Kuper verwenden" #: C/index.page:27(title) msgid "About Specific Plugins" msgstr "Infos zu bestimmten Plugins" #: C/generalusage.page:7(desc) msgid "How to start using Kupfer." msgstr "Einführung in Kupfer." #: C/generalusage.page:14(p) msgid "" "Kupfer is to the largest part a keyboard-managed interface to " "applications and documents." msgstr "" "Kupfer ist zum größten Teil eine über die Tastatur bedienbare " "Schnittstelle zu Anwendungen und Dokumenten." #: C/generalusage.page:18(p) msgid "" "Kupfer's default mode is the command mode: If you type a query, kupfer will " "search for a match in its catalog." msgstr "" "Der Standardmodus von Kupfer ist der Befehlsmodus: Sobald Sie eine " "Suche eingeben, sucht Kupfer nach Treffern in seinem Katalog." #: C/generalusage.page:23(p) msgid "" "The arrow keys allow you to browse query matches quite naturally, going to " "the previous or next match, and going up and down in the subcatalogs." msgstr "" "Mit Hilfe der Pfeiltasten können Sie ganz einfach durch die Treffer " "navigieren, in dem Sie zum nächsten oder vorherigen Treffer gehen oder in den " "Unterkatalogen suchen." #: C/generalusage.page:29(p) msgid "In command mode, some keystrokes have special meanings:" msgstr "Im Befehlsmodus haben einige Tastenkürzel besondere Bedeutungen:" #: C/generalusage.page:71(p) msgid "" "By default you show Kupfer using the global keyboard shortcut " "CtrlSpace." msgstr "" "In der Standardeinstellung rufen Sie Kupfer mit der globalen " "Tastenkombination StrgLeertaste auf." #: C/generalusage.page:74(p) msgid "See for more information." msgstr "Siehe für weitere Informationen." #: C/generalusage.page:78(title) msgid "Learning Habits" msgstr "Grundlegendes Verhalten" #: C/generalusage.page:79(p) msgid "" "Kupfer remembers which objects and actions are used the most. When " "beginning to use it, you have to use the arrow keys at times to make it " "precise which object you want to find. After a few uses of that object, " "Kupfer will rank it higher. Objects marked as favorites are also ranked higher." msgstr "" #: C/generalusage.page:90(title) msgid "The Catalog" msgstr "Der Katalog" #: C/generalusage.page:91(p) msgid "" "The Catalog is the collection of objects you can access in Kupfer, such as " "documents and programs." msgstr "" "Der Katalog ist die Objektsammlung, auf die Sie in Kupfer zugreifen können, " "wie Dokumente und Programme." #: C/generalusage.page:96(p) msgid "" "Objects in the catalog that have content, like folders, are marked with an " "arrow. Pressing will enter these objects. Much of the catalog is " "composed of subcatalogs; plugin subcatalogs do in general list objects that " "are also available directly from the top level. Subcatalogs can be used for a " "narrower view or search scope, when using Kupfer." msgstr "" "Objekte im Katalog mit Inhalten, wie Ordner, werden mit einem Pfeil markiert. " "Durch Drücken der Pfeiltaste rechts öffnen Sie diese Objekte. Ein " "Großteil des Katalogs besteht aus Unterkatalogen. Das Einbinden von " "Unterkatalogen als allgemeine Listenobjekte in die oberste Ebene des " "Kataloges ist möglich. Unterkataloge können in Kupfer zur Eingrenzung der " "Ansicht oder des Suchbereichs genutzt werden." #: C/generalusage.page:105(p) msgid "" "Most subcatalogs update their content automatically. For example, the Desktop " "folder source is always up-to-date." msgstr "" "Die meisten Unterkataloge aktualisieren ihre Inhalte automatisch. " "Beispielsweise ist der Katalog für den »Arbeitsfläche«-Ordner immer auf dem " "neuesten Stand." #. Put one translator per line, in the form of NAME , YEAR1, YEAR2 #: C/index.page:0(None) msgid "translator-credits" msgstr "Mario Blättermann , 2009-2011" kupfer-328/help/el/000077500000000000000000000000001500175051100142075ustar00rootroot00000000000000kupfer-328/help/el/el.po000066400000000000000000002670501500175051100151610ustar00rootroot00000000000000# Greek translation for kupfer. # Copyright (C) 2014 kupfer's COPYRIGHT HOLDER # This file is distributed under the same license as the kupfer package. # MarMav , 2014. # Dimitris Spingos (Δημήτρης Σπίγγος) , 2014. msgid "" msgstr "" "Project-Id-Version: kupfer master\n" "POT-Creation-Date: 2014-04-07 21:56+0000\n" "PO-Revision-Date: 2014-04-08 11:03+0300\n" "Last-Translator: Dimitris Spingos (Δημήτρης Σπίγγος) \n" "Language-Team: team@lists.gnome.gr\n" "Language: el\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: Virtaal 0.7.0\n" #: C/plugin-websearch.page:7(desc) msgid "Using the search the web plugin." msgstr "Χρησιμοποιώντας το πρόσθετο αναζήτησης στον ιστό." #: C/plugin-websearch.page:10(app) msgid "Search the Web" msgstr "Αναζήτηση στον ιστό" #: C/plugin-websearch.page:13(title) C/plugin-triggers.page:23(title) #: C/plugin-notes.page:22(title) C/plugin-nautilusselection.page:13(title) #: C/plugin-gwibber.page:25(title) C/plugin-favorites.page:22(title) #: C/plugin-calculator.page:21(title) C/plugin-applications.page:19(title) #: C/generalusage.page:10(title) msgid "Basic Usage" msgstr "Βασική χρήση" #: C/plugin-websearch.page:15(p) msgid "Activate Kupfer and make sure it is in free-text mode (press period)" msgstr "" "Ενεργοποιήστε το Kupfer και βεβαιωθείτε ότι βρίσκεται σε λειτουργία " "ελεύθερου κειμένου (πατήστε το πλήκτρο της τελείας)" #: C/plugin-websearch.page:17(p) msgid "" "Type in a search query and tap Tab to switch to the action pane." msgstr "" "Πληκτρολογήστε ένα ερώτημα αναζήτησης και πατήστε Tab για να " "μεταβείτε στο ενεργό παράθυρο." #: C/plugin-websearch.page:19(p) msgid "" "Type \"Search With\" to find Search the Web's action and tap Tab " "again to switch to the third pane (indirect object)." msgstr "" "Πληκτρολογήστε \"Αναζήτηση με\" για να βρείτε τη καρτέλα αναζήτηση στον ιστό " "και επιλέξτε Tab ξανά για να μεταβείτε στο τρίτο παράθυρο (έμμεσο " "αντικείμενο)." #: C/plugin-websearch.page:22(p) msgid "" "Select search engine with the arrow keys and type Return to open " "the search in a web browser." msgstr "" "Επιλέξτε τη μηχανή αναζήτησης με τα βελάκια και πληκτρολογήστε " "Επιστροφή για να ανοίξετε την αναζήτηση σε έναv περιηγητή ιστού." #: C/plugin-websearch.page:29(title) msgid "Search Engines" msgstr "Μηχανές Αναζήτησης" #: C/plugin-websearch.page:30(p) msgid "" "The Search the Web plugin uses Firefox' search engines, so you " "can add Search Engines directly in Firefox and Kupfer " "will find them later." msgstr "" "Το πρόσθετο αναζήτηση στον ιστό χρησιμοποιεί μηχανές αναζήτησης του " "Firefox', έτσι ώστε να μπορείτε να προσθέσετε μηχανές αναζήτησης " "άμεσα και να τις βρείτε αργότερα στο Firefox και το Kupfer." #: C/plugin-websearch.page:35(p) msgid "" "You can also install custom search plugins directly, only for Kupfer, in the folder:" msgstr "" "Μπορείτε επίσης να εγκαταστήσετε προσαρμοσμένα πρόσθετα αναζήτησης άμεσα, " "μόνο για το Kupfer, στο φάκελο:" #: C/plugin-websearch.page:39(code) #, no-wrap msgid "~/.local/share/kupfer/searchplugins/" msgstr "~/.local/share/kupfer/searchplugins/" #: C/plugin-websearch.page:40(p) msgid "The search engine descriptions must written in OpenSearch format." msgstr "" "Οι περιγραφές των μηχανών αναζήτησης πρέπει να έχουν γραφτεί σε μορφή " "OpenSearch." #: C/plugin-triggers.page:7(desc) msgid "Using the triggers plugin." msgstr "Χρησιμοποιώντας το πρόσθετο εναύσματα." #: C/plugin-triggers.page:10(app) C/keyboard.page:213(title) msgid "Triggers" msgstr "Εναύσματα" #: C/plugin-triggers.page:13(title) msgid "Triggers Plugin" msgstr "Προσθετο Εναύσματα" #: C/plugin-triggers.page:14(p) msgid "" "With Triggers you can take a command you would normally perform " "in Kupfer, such as launching an application or opening a " "document, and bind a global key combination to run this command. As long as " "Kupfer is running, any application can have the current focus." msgstr "" "Με τα Εναύσματα μπορείτε να πάρετε μια εντολή που θα εκτελούσατε " "κανονικά στο Kupfer, όπως την εκκίνηση μιας εφαρμογής ή το " "άνοιγμα ενός εγγράφου, και να δεσμεύσετε ένα γενικό συνδυασμό πλήκτρων για " "να εκτελέσετε αυτήν την εντολή. Για όσο το Kupfer εκτελείται, " "οποιαδήποτε εφαρμογή μπορεί να έχει την τρέχουσα εστίαση." #: C/plugin-triggers.page:25(title) msgid "Creating a new trigger" msgstr "Δημιουργία ενός νέου εναύσματος" #: C/plugin-triggers.page:27(p) msgid "Set up a command in Kupfer that you want to run" msgstr "Ρύθμιση μιας εντολής στο Kupfer που θέλετε να εκτελέσετε" #: C/plugin-triggers.page:32(p) msgid "" "Press CtrlReturn to create a " "composed command." msgstr "" "Πατήστε CtrlΕπιστροφή για να " "δημιουργήσετε μια Εντολή σύνθεσης." #: C/plugin-triggers.page:38(p) msgid "" "Type Tab and select the action Add Trigger... and press " "Return" msgstr "" "Πατήστε Tab και επιλέξτε την ενέργεια Προσθήκη εναύσματος... και πιέστε Επιστροφή" #: C/plugin-triggers.page:44(p) msgid "" "Using the window that appears, press modifier keys and a letter or number " "key to set a global shortcut. An example is pressing and holding " "CtrlAlt and then pressing and " "releasing R to bind CtrlAltR." msgstr "" "Χρησιμοποιώντας το παράθυρο που εμφανίζεται, πατήστε τα πλήκτρα τροποποίησης " "και ένα γράμμα ή αριθμό για να ορίσετε μια γενική συντόμευση. Για παράδειγμα " "πατώντας και κρατώντας πατημένα τα CtrlAlt και, στη συνέχεια, πιέζοντας και αφήνοντας το R " "δεσμεύονται τα CtrlAltR." #: C/plugin-triggers.page:54(title) msgid "Removing a trigger" msgstr "Αφαίρεση εναύσματος" #: C/plugin-triggers.page:56(p) msgid "" "Find the source Triggers in Kupfer and press to see its contents." msgstr "" "Βρείτε τα πηγαία Εναύσματα στο Kupfer και πιέστε για να δείτε τα περιεχόμενά του." #: C/plugin-triggers.page:62(p) msgid "" "Find the active trigger in the list and use the action Remove Trigger." msgstr "" "Βρείτε το ενεργό έναυσμα στον κατάλογο και χρησιμοποιήσετε την ενέργεια " "Αφαίρεση εναύσματος." #: C/plugin-triggers.page:68(p) msgid "" "Since trigger keyboard shortcuts are global, they can be used from any " "application. Select shortcuts with care so that they do not conflict with " "other functions." msgstr "" "Δεδομένου ότι οι συντομεύσεις πληκτρολογίου των εναυσμάτων είναι γενικές, " "μπορούν να χρησιμοποιηθούν από οποιαδήποτε εφαρμογή. Επιλέξτε συντομεύσεις " "με προσοχή έτσι ώστε να μην έρχονται σε διένεξη με άλλες λειτουργίες." #: C/plugin-triggers.page:74(title) C/plugin-notes.page:60(title) #: C/plugin-gwibber.page:68(title) C/plugin-favorites.page:38(title) msgid "Power User Tips" msgstr "Συμβουλές για έμπειρους χρήστες" #: C/plugin-triggers.page:75(p) msgid "" "Proxy objects such as Selected Text, Selected File, Frontmost Window, Last Command et cetera allow very " "powerful triggers." msgstr "" "Αντικείμενα μεσολάβησης όπως Eπιλεγμένο κείμενο, " "Επιλεγμένο αρχείο, Το πιο μπροστινό παράθυρο, " "Τελευταία εντολή κ.λπ. επιτρέπουν τη χρήση πολύ ισχυρών εναυσμάτων." #: C/plugin-triggers.page:79(p) msgid "" "The application action Launch is special; if you bind a trigger " "using Launch, it will start the application if it is not running, " "but focus the application when it is already running. By contrast, Start " "Again will start the application if it is running or not." msgstr "" "Η χρήση της εφαρμογής Εκκίνηση είναι ειδική: εαν δευσμεύσετε ένα " "έναυσμα με την Εκκίνηση, θα ξεκινήσει η εφαρμογή, εάν δεν " "εκτελείται, αλλά θα εστιάσει στην εφαρμογή όταν εκτελείται ήδη. Αντίθετα, η " "Έναρξη εκ νέου θα ξεκινήσει την εφαρμογή είτε βρίσκεται σε " "λειτουργία είτε όχι." #: C/plugin-triggers.page:87(title) msgid "Example Triggers" msgstr "Παράδειγμα εναυσμάτων" #: C/plugin-triggers.page:90(em) msgid "Text Editor → Launch" msgstr "Επεξεργαστής κειμένου → Εκκίνηση" #: C/plugin-triggers.page:91(p) msgid "" "Start Text Editor or focus its window if it is already running." msgstr "" "Ξεκινήστε τον Επεξεργαστή κειμένου ή εστιάστε στο παράθυρό του, εάν " "είναι ήδη σε λειτουργία." #: C/plugin-triggers.page:97(em) msgid "Selected Text → Search With → Google" msgstr "Επιλεγμένο Κείμενο → Αναζήτηση με → Google" #: C/plugin-triggers.page:98(p) msgid "Search the web using the currently selected text." msgstr "Αναζήτηση στο διαδίκτυο χρησιμοποιώντας το επιλεγμένο κείμενο." #: C/plugin-triggers.page:100(em) msgid "Selected File → Move To → (Downloads Folder)" msgstr "Επιλεγμένο αρχείο → Μετακίνηση σε → (Φάκελος λήψεων)" #: C/plugin-triggers.page:101(p) msgid "Move the currently selected file to a specific folder" msgstr "Μετακινήστε το επιλεγμένο αρχείο σε ένα συγκεκριμένο φάκελο" #: C/plugin-triggers.page:105(em) msgid "Songs → Search Contents" msgstr "Τραγούδια → Αναζήτηση περιεχομένων" #: C/plugin-triggers.page:106(p) msgid "" "You may even add a trigger to open a specific subcatalog in Kupfer, for " "example Rhythmbox's songs." msgstr "" "Μπορείτε να προσθέσετε ακόμη και ένα έναυσμα για να ανοίξει ένα συγκεκριμένο " "υποκατάλογο στο Kupfer, για παράδειγμα, τα τραγούδια του Rhythmbox." #: C/plugin-notes.page:7(desc) msgid "Using the notes plugin." msgstr "Χρησιμοποιώντας το πρόσθετο σημειώσεις." #: C/plugin-notes.page:10(app) C/plugin-calculator.page:37(title) msgid "Notes" msgstr "Σημειώσεις" #: C/plugin-notes.page:13(title) msgid "Notes Plugin" msgstr "Πρόσθετο Σημειώσεις" #: C/plugin-notes.page:14(p) msgid "" "With Notes you can access or create new notes in either the " "program Gnote or Tomboy. Notes will work " "identically with either application—you can configure which one to use in " "the plugin's information pane in Kupfer Preferences." msgstr "" "Με το πρόσθετο Σημειώσεις μπορείτε να έχετε πρόσβαση ή να " "δημιουργήσετε νέες σημειώσεις είτε στο πρόγραμμα Gnote ή στο " "Tomboy. Το Σημειώσεις θα λειτουργήσει με τον ίδιο " "τρόπο και με τις δύο εφαρμογές: μπορείτε να ρυθμίσετε ποια να χρησιμοποιηθεί " "στο τμήμα πληροφοριών των πρόσθετων στο Προτιμήσεις Kupfer." #: C/plugin-notes.page:24(title) msgid "Creating a new note" msgstr "Δημιουργία νέας σημείωσης" #: C/plugin-notes.page:26(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "note title" msgstr "" "Ενεργοποιήστε το Kupfer και πληκτρολογήστε . για να εισέλθετε σε " "λειτουργία κειμένου, στη συνέχεια, πληκτρολογήστε έναν τίτλο σημείωσης" #: C/plugin-notes.page:32(p) msgid "" "Type Tab and select the action Create Note and press " "Return." msgstr "" "Πληκτρολογήστε Tab και επιλέξτε την ενέργεια Δημιουργία " "Σημείωσης και πιέστε Επιστροφή." #: C/plugin-notes.page:39(title) msgid "Finding a note by title" msgstr "Βρίσκοντας μια σημείωση από τον τίτλο" #: C/plugin-notes.page:41(p) msgid "Simply search for the note title in Kupfer" msgstr "Απλά κάνετε αναζήτηση στο Kupfer για τον τίτλο σημείωσης" #: C/plugin-notes.page:45(title) msgid "Finding a note by content" msgstr "Βρίσκοντας μια σημείωση από τον το περιεχόμενο" #: C/plugin-notes.page:47(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "search query" msgstr "" "Ενεργοποιήστε το Kupfer και πληκτρολογήστε . για να εισέλθετε στη " "λειτουργία κειμένου, στη συνέχεια, πληκτρολογήστε ένα ερώτημα αναζήτησης" #: C/plugin-notes.page:53(p) msgid "" "Type Tab and select the action Get Note Search Results... and press Return." msgstr "" "Πληκτρολογήστε Tab και επιλέξτε την ενέργεια Λήψη " "αποτελεσμάτων αναζήτησης σημείωσης... και πιέστε Επιστροφή." #: C/plugin-notes.page:63(p) msgid "" "You can use the Selected Text object and create a new note with the " "content of the selection." msgstr "" "Μπορείτε να χρησιμοποιήσετε το αντικείμενο Επιλεγμένο κείμενο και " "να δημιουργήσετε μια νέα σημείωση με το περιεχόμενο της επιλογής." #: C/plugin-nautilusselection.page:7(desc) msgid "Using the selected file plugin." msgstr "Χρησιμοποιώντας το πρόσθετο επιλεγμένου αρχείου." #: C/plugin-nautilusselection.page:10(app) msgid "Selected File" msgstr "Επιλεγμένο αρχείο" #: C/plugin-nautilusselection.page:14(p) msgid "" "Select a file in the file manager. Open Kupfer and search for the " "object Selected File, which represents the file or files that are " "selected." msgstr "" "Επιλέξτε ένα αρχείο στο διαχειριστή αρχείων. Ανοίξτε το Kupfer " "και αναζητήστε το αντικείμενο Επιλεγμένο αρχείο, το οποίο " "αντιπροσωπεύει το αρχείο ή τα αρχεία που έχουν επιλεγεί." #: C/plugin-nautilusselection.page:19(p) msgid "" "Instead of searching, you can press CtrlG to directly focus the selected file. See " "for more information." msgstr "" "Αντί της αναζήτησης, μπορείτε να πατήσετε CtrlG για να εστιάσει άμεσα στο επιλεγμένο αρχείο. Δείτε στο για περισσότερες πληροφορίες." #: C/plugin-nautilusselection.page:26(title) msgid "Selected File requires Nautilus" msgstr "" "Το πρόσθετο Επιλεγμένο αρχείο προϋποθέτει τον Nautilus" #: C/plugin-nautilusselection.page:27(p) msgid "" "The selected file plugin works with the Nautilus file browser and " "requires that the extension kupfer_provider.py is installed (it " "is normally installed together with Kupfer). After installing it " "for the first time, Nautilus must start anew before it is active." msgstr "" "Το πρόσθετο επιλεγμένο αρχείο λειτουργεί με τον περιηγητή αρχείων " "Nautilus και απαιτεί να είναι εγκατεστημένη η επέκταση " "kupfer_provider.py (εγκαθίσταται συνήθως μαζί με το Kupfer) . Μετά την εγκατάστασή του, για πρώτη φορά, ο Nautilus " "πρέπει να ξεκινήσει εκ νέου πριν να ενεργοποιηθεί." #: C/plugin-gwibber.page:7(desc) msgid "Using the Gwibber plugin." msgstr "Χρησιμοποιώντας το πρόσθετο Gwibber." #: C/plugin-gwibber.page:10(app) msgid "Gwibber" msgstr "Gwibber" #: C/plugin-gwibber.page:13(title) msgid "Gwibber Plugin" msgstr "Πρόσθετο Gwibber" #: C/plugin-gwibber.page:14(p) msgid "" "With the Gwibber plugin you can send messages to social networks " "such as Twitter or Identi.ca." msgstr "" "Με το πρόσθετο Gwibber μπορείτε να στείλετε μηνύματα σε κοινωνικά " "δίκτυα όπως το Twitter ή το Identi.ca." #: C/plugin-gwibber.page:18(p) msgid "" "The plugin requires that the application Gwibber is installed and " "configured for your user. Kupfer will start and use Gwibber's " "service in the background." msgstr "" "Το πρόσθετο προϋποθέτει ότι η εφαρμογή Gwibber έχει εγκατασταθεί " "και ρυθμιστεί για το δικό σας χρήστη. Το Kupfer θα ξεκινήσει και " "θα χρησιμοποιήσει την υπηρεσία Gwibber στο παρασκήνιο." #: C/plugin-gwibber.page:27(title) msgid "Sending a message to all services" msgstr "Αποστολή ενός μηνύματος σε όλες τις υπηρεσίες" #: C/plugin-gwibber.page:29(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "message." msgstr "" "Ενεργοποιήστε το Kupfer και πληκτρολογήστε . για να εισέλθετε στη " "λειτουργία κειμένου, στη συνέχεια, πληκτρολογήστε ένα μήνυμα." #: C/plugin-gwibber.page:35(p) msgid "" "Type Tab and select the action Send Message and press " "Return." msgstr "" "Πληκτρολογήστε Tab και επιλέξτε την ενέργεια Αποστολή " "μηνύματος και πιέστε Επιστροφή." #: C/plugin-gwibber.page:42(title) msgid "Sending a message to a specific service" msgstr "Αποστολή ενός μηνύματος σε μια συγκεκριμένη υπηρεσία" #: C/plugin-gwibber.page:44(p) msgid "" "Activate Kupfer and search for the service object, for example Identi." "ca" msgstr "" "Ενεργοποιήστε το Kupfer και αναζητήστε το αντικείμενο υπηρεσίας, για " "παράδειγμα, Identi.ca" #: C/plugin-gwibber.page:50(p) msgid "Type Tab and select the action Send Message." msgstr "" "Πληκτρολογήστε Tab και επιλέξτε την ενέργεια Αποστολή " "μηνύματος." #: C/plugin-gwibber.page:55(p) msgid "" "Type Tab to select the last pane, and type in a message. Press " "Return to send." msgstr "" "Πληκτρολογήστε Tab για να επιλέξετε το τελευταίο παράθυρο και " "πληκτρολογήστε ένα μήνυμα. Πατήστε Επιστροφή για να το στείλετε." #: C/plugin-gwibber.page:61(p) msgid "" "The plugin also provides a source for incoming messages, Gwibber " "Messages and more actions on messages such as Reply, Send " "Private Message etc." msgstr "" "Το πρόσθετο παρέχει επίσης μια πηγή για τα εισερχόμενα μηνύματα, " "Μηνύματα Gwibber και περισσότερες ενέργειες για μηνύματα όπως " "Απάντηση, Αποστολή προσωπικού μηνύματος κλπ." #: C/plugin-gwibber.page:71(p) msgid "" "You can use the comma trick if you want to send a message to more " "than one service, but not all, at the same time." msgstr "" "Μπορείτε να χρησιμοποιήσετε το Τέχνασμα κόμμα αν θέλετε να στείλετε " "ένα μήνυμα σε περισσότερες από μία υπηρεσίες, αλλά όχι σε όλες, την ίδια " "στιγμή." #: C/plugin-favorites.page:7(desc) msgid "Using the favorites plugin." msgstr "Χρησιμοποιώντας το πρόσθετο αγαπημένα." #: C/plugin-favorites.page:10(app) msgid "Favorites" msgstr "Αγαπημένα" #: C/plugin-favorites.page:13(title) msgid "Favorites Plugin" msgstr "Πρόσθετο αγαπημένων" #: C/plugin-favorites.page:14(p) msgid "" "With Favorites you mark objects, for example files, for quicker " "access. It is a sort of shelf on which you can store objects in Kupfer. " "Objects marked as favorites will also be ranked higher and are adorned with " "a star symbol." msgstr "" "Με το Αγαπημένα μαρκάρετε τα αντικείμενα, για παράδειγμα, τα " "αρχεία, για ταχύτερη πρόσβαση. Είναι ένα είδος ραφιού στο οποίο μπορείτε να " "αποθηκεύσετε αντικείμενα στο Kupfer. Αντικείμενα που χαρακτηρίζονται ως " "αγαπημένα θα κατατάσσονται επίσης σε υψηλότερη θέση και είναι διακοσμημένα " "με το σύμβολο αστέρι." #: C/plugin-favorites.page:25(p) msgid "Find an object in Kupfer" msgstr "Εύρεση αντικειμένου στο Kupfer" #: C/plugin-favorites.page:30(p) msgid "" "Type Tab and select either the action Add to Favorites " "or Remove from Favorites." msgstr "" "Πληκτρολογήστε Tab και επιλέξτε την ενέργεια Προσθήκη στα " "αγαπημένα ή Αφαίρεση από τα αγαπημένα." #: C/plugin-favorites.page:39(p) msgid "" "If you favorite an object, you can access it in more places. Not only in the " "\"Favorites\" subcatalog, but also as the indirect (secondary) object for " "some actions. For example:" msgstr "" "Αν προσθέσετε στα αγαπημένα ένα αντικείμενο, μπορείτε να έχετε πρόσβαση σε " "αυτό σε περισσότερα σημεία. Όχι μόνο στον υποκατάλογο \"Αγαπημένα\" , αλλά " "και ως έμμεσο (δευτερεύον) αντικείμενο για ορισμένες ενέργειες. Για " "παράδειγμα:" #: C/plugin-favorites.page:45(p) msgid "Command-lines from favorites are quick to access." msgstr "Γραμμές εντολών από τα αγαπημένα είναι άμεσα προσβάσιμα." #: C/plugin-favorites.page:46(p) msgid "" "When scaling images with the Scale... action from the Image " "Tools plugin. This action needs a size description as the third " "object, like \"1024\" or \"1200x800\". If you often scale to the same size, " "say \"1200x800\", add this to favorites, and it will always appear as a " "suggestion for the action." msgstr "" "Κλιμάκωση εικόνων με την ενέργεια Κλιμάκωση... από το πρόσθετο " "Εργαλεία εικόνας. Η ενέργεια αυτή χρειάζεται μια περιγραφή με το " "τρίτο αντικείμενο, όπως \"1024\" ή \"1200x800\". Αν έχετε συχνά κλιμάκωση " "στο ίδιο μέγεθος, για παράδειγμα \"1200x800\", προσθέστε την στα αγαπημένα, " "και θα εμφανίζεται πάντα ως προτεινόμενη για την ενέργεια." #: C/plugin-favorites.page:54(p) msgid "" "Actions needing an email address as the indirect object will pick up email " "addresses from favorites as well as well." msgstr "" "Ενέργειες που χρειάζονται μια διεύθυνση ηλεκτρονικού ταχυδρομείου ως έμμεσο " "αντικείμενο θα πάρουν επίσης τις διευθύνσεις ηλεκτρονικού ταχυδρομείου από " "τα αγαπημένα." #: C/plugin-calculator.page:7(desc) msgid "Using the calculator plugin." msgstr "Χρησιμοποιώντας το πρόσθετο αριθμομηχανής." #: C/plugin-calculator.page:10(app) msgid "Calculator" msgstr "Αριθμομηχανή" #: C/plugin-calculator.page:13(title) msgid "Calculator Plugin" msgstr "Πρόσθετο αριθμομηχανής" #: C/plugin-calculator.page:14(p) msgid "" "The calculator plugin lets you calculate expressions quickly. It can " "evaluate expressions entered as text starting with \"=\". Entering = from " "command mode will start text mode directly with = prefixed for quick access." msgstr "" "Το πρόσθετο αριθμομηχανής σας επιτρέπει να υπολογίσετε γρήγορα παραστάσεις. " "Μπορεί να αξιολογεί παραστάσεις που καταχωρούνται ως κείμενο αρχίζοντας με " "\"=\". Εισάγοντας = από την κατάσταση εντολών θα ξεκινήσει η λειτουργία " "κειμένου απευθείας με πρόθεμα = για γρήγορη πρόσβαση." #: C/plugin-calculator.page:23(p) msgid "Activate Kupfer and type =" msgstr "Ενεργοποιήστε το Kupfer και πληκτρολογήστε =" #: C/plugin-calculator.page:26(p) msgid "" "Type in a mathematical expression using +,-,/,* (and ** for exponentiation)" msgstr "" "Πληκτρολογήστε μια μαθηματική παράσταση χρησιμοποιώντας τα +," "-,/,* (και ** για εκθέτη)" #: C/plugin-calculator.page:30(p) msgid "Press Return to get the result." msgstr "Πατήστε το Επιστροφή για να λάβετε το αποτέλεσμα." #: C/plugin-calculator.page:38(p) msgid "" "The Calculator uses python's math and complex math modules, and parses " "expressions as Python expressions. You may use common mathematical " "functions, such as sqrt, sin, exp and " "log; the command =help will show a list of all defined " "functions and constants." msgstr "" "Η Αριθμομηχανή χρησιμοποιεί τις ενότητες μιγαδικών μαθηματικών και python " "και αναλύει τις παραστάσεις ως παραστάσεις Python. Μπορείτε να " "χρησιμοποιήσετε κοινές μαθηματικές συναρτήσεις, όπως sqrt, " "sin, exp και log· η εντολή =help " "θα εμφανίσει μια λίστα με όλες τις προσδιορισμένες συναρτήσεις και σταθερές." #: C/plugin-calculator.page:47(p) msgid "" "Notice that the power operator in Python is double stars, for example " "=3**3 will evaluate to 27." msgstr "" "Σημειώστε ότι ο τελεστής δύναμης στο Python είναι διπλά αστέρια, για " "παράδειγμα =3**3 θα αξιολογηθεί σε 27." #: C/plugin-calculator.page:53(p) msgid "To calculate trig functions for angles, convert to radians first:" msgstr "" "Για να υπολογίσετε τριγωνομετρικές συναρτήσεις για τις γωνίες, μετατρέψετε " "πρώτα σε ακτίνια:" #: C/plugin-calculator.page:56(code) #, no-wrap msgid "sin(radians(30)) -> 0.5" msgstr "sin(radians(30)) -> 0.5" #: C/plugin-calculator.page:59(p) msgid "" "The last result is stored as the name _ (an underscore, just like in the " "Python console)." msgstr "" "Το τελευταίο αποτέλεσμα αποθηκεύεται ως όνομα _ (ένα χαρακτήρα υπογράμμισης, " "όπως ακριβώς και στην κονσόλα Python)." #: C/plugin-calculator.page:65(p) msgid "" "The Calculator lets you also calculate expression without \"=\" on the " "beginning as long it have inside one of operators: +, -, *, /, ^, |, &, " "~." msgstr "" "Η Αριθμομηχανή σας επιτρέπει επίσης να υπολογίσετε μια παράσταση χωρίς \"=\" " "στην αρχή, εφόσον έχετε μέσα έναν από τους τελεστές: +, -, *, /, ^, |, , ~." #: C/plugin-applications.page:7(desc) msgid "Using the applications plugin." msgstr "Χρησιμοποιώντας το πρόσθετο εφαρμογές." #: C/plugin-applications.page:10(app) msgid "Applications" msgstr "Εφαρμογές" #: C/plugin-applications.page:13(title) msgid "Applications Plugin" msgstr "Πρόσθετο εφαρμογών" #: C/plugin-applications.page:14(p) msgid "Applications provides all installed programs." msgstr "Το Εφαρμογές παρέχει όλα τα εγκατεστημένα προγράμματα." #: C/plugin-applications.page:21(title) msgid "Launching an application" msgstr "Εκκίνηση μιας εφαρμογής" #: C/plugin-applications.page:23(p) msgid "Activate Kupfer and type an abbreviation of the application name" msgstr "" "Ενεργοποιήστε το Kupfer και πληκτρολογήστε μια συντομογραφία του ονόματος " "εφαρμογής" #: C/plugin-applications.page:28(p) msgid "Press Return to launch the application." msgstr "Πατήστε Επιστροφή για να ξεκινήσει η εφαρμογή." #: C/plugin-applications.page:34(title) msgid "Opening a file with a specific application" msgstr "Άνοιγμα ενός αρχείου με μια συγκεκριμένη εφαρμογή" #: C/plugin-applications.page:36(p) msgid "Select a file in Kupfer" msgstr "Επιλέξτε ένα αρχείο στο Kupfer" #: C/plugin-applications.page:41(p) msgid "Type Tab and select the action Open With..." msgstr "" "Πληκτρολογήστε Tab και επιλέξτε την ενέργεια Άνοιγμα με ..." #: C/plugin-applications.page:46(p) msgid "" "Type Tab to select the third (indirect object) pane and in it, " "select the application to open the file with." msgstr "" "Πληκτρολογήστε Tab για να επιλέξετε το τρίτο παράθυρο (έμμεσο " "αντικείμενο) και σε αυτό, επιλέξτε την εφαρμογή με την οποία να ανοίξει το " "αρχείο." #: C/plugin-applications.page:53(p) msgid "" "The action Open opens files and folders with the registered default " "application for that specific file type. This can be configured using the " "action Set Default Application...." msgstr "" "Η ενέργεια Άνοιγμα ανοίγει τα αρχεία και τους φακέλους με την " "εγγεγραμμένη προεπιλεγμένη εφαρμογή για το συγκεκριμένο τύπο αρχείου. Αυτό " "μπορεί να ρυθμιστεί χρησιμοποιώντας την ενέργεια Ορισμός προεπιλεγμένης " "εφαρμογής...." #: C/plugin-applications.page:58(p) msgid "" "The file type associations are provided by the desktop environment, and " "modifying them here will modify them on the desktop as well. This may not be " "true when not using GNOME or XFCE." msgstr "" "Οι συσχετισμοί του τύπου αρχείου παρέχονται από το περιβάλλον εργασίας, και " "η τροποποίηση τους εδώ θα τους τροποποιήσει επίσης και στην επιφάνεια " "εργασίας. Αυτό δεν μπορεί να είναι εφικτό όταν δεν χρησιμοποιείτε το GNOME ή " "το XFCE." #: C/plugin-applications.page:64(title) msgid "Selecting default application for a file type or folders" msgstr "Επιλέγοντας την προεπιλεγμένη εφαρμογή για έναν τύπο αρχείου ή φακέλων" #: C/plugin-applications.page:66(p) msgid "Select a file or folder in Kupfer" msgstr "Επιλέξτε ένα αρχείο ή φάκελο στο Kupfer" #: C/plugin-applications.page:71(p) msgid "" "Type Tab and select the action Set Default Application..." msgstr "" "Πληκτρολογήστε Tab και επιλέξτε την ενέργεια Ορισμός " "προεπιλεγμένης εφαρμογής..." #: C/plugin-applications.page:77(p) msgid "" "Type Tab to select the third (indirect object) pane and in it, " "select the application to always open the file type with." msgstr "" "Πληκτρολογήστε Tab για να επιλέξετε το τρίτο παράθυρο (έμμεσο " "αντικείμενο) και σε αυτό, επιλέξτε την εφαρμογή με την οποία θα ανοίγει " "πάντα ο τύπος του αρχείου." #: C/plugin-applications.page:85(title) msgid "Configuration" msgstr "Διαμόρφωση" #: C/plugin-applications.page:86(p) msgid "" "The configuration option Applications for Desktop Environment in " "the plugin's information pane in Kupfer Preferences determines " "how Kupfer should act with regard to the desktop environment " "configuration—certain applications request not to be shown depending on " "which desktop environment is used. By default, it behaves like GNOME." msgstr "" "Η επιλογή διαμόρφωσης Εφαρμογές για το περιβάλλον επιφάνειας εργασίας στο τμήμα πληροφοριών του πρόσθετου Προτιμήσεις Kupfer " "καθορίζει το πώς το Kupfer θα πρέπει να ενεργεί σε σχέση με τη " "διαμόρφωση του περιβάλλοντος εργασίας - ορισμένες εφαρμογές ζητείται να μην " "εμφανίζονται, ανάλογα με το περιβάλλον επιφάνειας εργασίας που " "χρησιμοποιείται. Από προεπιλογή, συμπεριφέρεται όπως το GNOME." #: C/moreusage.page:7(desc) msgid "More advanced usage information." msgstr "Περισσότερες προηγμένες πληροφορίες χρήσης." #: C/moreusage.page:10(title) msgid "Using Kupfer in Depth" msgstr "Χρησιμοποιώντας το Kupfer εις βάθος" #: C/moreusage.page:13(title) msgid "Adding Applications and Scripts" msgstr "Προσθέτοντας εφαρμογές και σενάρια" #: C/moreusage.page:14(p) msgid "" "Kupfer will show all applications that are configured visible in " "your menu editor." msgstr "" "Το Kupfer θα εμφανίσει όλες τις εφαρμογές που έχουν ρυθμιστεί ως " "ορατές στο μενού του επεξεργαστή σας." #: C/moreusage.page:18(p) msgid "" "If you want to add an application manually, you can create a new ." "desktop file and place it in one of the standard directories for " "applications, for example ~/.local/share/applications, where " "Kupfer will find it." msgstr "" "Αν θέλετε να προσθέσετε μια εφαρμογή χειροκίνητα, μπορείτε να δημιουργήσετε " "ένα νέο αρχείο .desktop και να το τοποθετήστε σε έναν από τους " "πρότυπους καταλόγους για εφαρμογές, για παράδειγμα στον ~/.local/share/" "applications, όπου το Kupfer θα το βρεί." #: C/moreusage.page:24(p) msgid "" "If you have a collection of scripts that you want to call from Kupfer, you can add the scripts folder as a catalog directory to Kupfer in the preferences. Scripts that you add to Kupfer's catalog " "this way can be run directly or in the terminal as long as they are " "executable." msgstr "" "Εάν έχετε μια συλλογή από σενάρια που θέλετε να καλέσετε από το Kupfer, μπορείτε να προσθέσετε το φάκελο σεναρίων ως μια λίστα καταλόγου στις " "προτιμήσεις του Kupfer. Σενάρια που θα προσθέσετε στον κατάλογο " "Kupfer με αυτόν τον τρόπο μπορούν να εκτελεσθούν απευθείας ή στο " "τερματικό για όσο διάστημα είναι εκτελέσιμα." #: C/moreusage.page:31(p) msgid "" "You can also save command-lines by using the action Add to Favorites." msgstr "" "Μπορείτε επίσης να αποθηκεύσετε γραμμές εντολών χρησιμοποιώντας την ενέργεια " "Προσθήκη στα αγαπημένα." #: C/moreusage.page:38(title) msgid "Opening Files and Folders" msgstr "Άνοιγμα αρχείων και φακέλων" #: C/moreusage.page:39(p) msgid "" "Using the action Open, files and folders are opened in their " "preferred application. The application associations can be changed, see " "." msgstr "" "Χρησιμοποιώντας την ενέργεια Άνοιγμα, τα αρχεία και οι φάκελοι " "ανοίγουν με την προτιμώμενη εφαρμογή τους. Οι συσχετισμοί εφαρμογής μπορεί " "να αλλάξουν, δείτε στο ." #: C/moreusage.page:47(title) msgid "The Comma Trick" msgstr "Το Τέχνασμα κόμμα" #: C/moreusage.page:48(p) msgid "" "The comma trick allows the user to use actions on many objects at the same " "time." msgstr "" "Το τέχνασμα κόμμα επιτρέπει στο χρήστη να χρησιμοποιήσει ενέργειες σε πολλά " "αντικείμενα ταυτόχρονα." #: C/moreusage.page:52(p) msgid "" "Simply press comma , when an object is selected. The object is " "put on a \"stack\", and you can find yet another file or object, press comma " "to put it on the stack. When you subsequently invoke an action, the action " "is carried out on all of the objects at the same time." msgstr "" "Απλά πατήστε το κόμμα , όταν ένα αντικείμενο είναι επιλεγμένο . " "Το αντικείμενο τοποθετείται σε μια \"στοίβα\", και για να μπορείτε να βρείτε " "ακόμη ένα άλλο αρχείο ή ένα αντικείμενο, πατήστε το κόμμα για να το " "προσθέσετε στη στοίβα. Όταν, στη συνέχεια επικαλεσθείτε μια ενέργεια, αυτή " "διεξάγεται σε όλα τα αντικείμενα ταυτόχρονα." #: C/moreusage.page:58(p) msgid "" "Some actions are only \"multiplied\" when used with many objects, other are " "smarter than that:" msgstr "" "Ορισμένες ενέργειες είναι μόνο \"πολλαπλασιαζόμενες\" όταν χρησιμοποιούνται " "με πολλά αντικείμενα, ενώ άλλες είναι πιο εξελιγμένες:" #: C/moreusage.page:61(p) msgid "" "Selecting many files and using the Create Archive action, all files will be " "packed into the same archive." msgstr "" "Επιλέγοντας πολλά αρχεία και χρησιμοποιώντας τη Δημιουργία ενέργειας " "αρχείου, όλα τα αρχεία θα πρέπει περιέχονται πλέον στο ίδιο αρχείο." #: C/moreusage.page:63(p) msgid "" "If you select multiple contacts and use a Send Email action, it creates one " "email directed at all the contacts." msgstr "" "Εάν επιλέξετε πολλαπλές επαφές και χρησιμοποιήσετε μια ενέργεια Αποστολής " "μηνύματος, θα δημιουργεί ένα μήνυμα που θα απευθύνεται σε όλες τις επαφές." #: C/moreusage.page:65(p) msgid "" "If you select multiple subcatalogs (For example Firefox Bookmarks and " "Epiphany Bookmarks) and use Search Contents.., you get a subcatalog search " "restricted to the objects of those two catalogs! You can even bind a trigger " "to this command(!)" msgstr "" "Αν επιλέξετε πολλαπλούς υποκαταλόγους (Για παράδειγμα, σελιδοδείκτες Firefox " "και σελιδοδείκτες Epiphany) και χρησιμοποιήσετε την Αναζήτηση " "Περιεχομένων..., μπορείτε να πάρετε μια αναζήτηση υποκαταλόγων που " "περιορίζεται στα αντικείμενα των δύο αυτών καταλόγων! Μπορείτε ακόμα και να " "συνδέσετε ένα έναυσμα για αυτήν την εντολή(!)" #: C/moreusage.page:71(p) msgid "" "The comma trick is directly taken from Quicksilver (the " "example given in the external article should work identically in Kupfer)." msgstr "" "Το τέχνασμα κόμμα λαμβάνεται απευθείας από το Quicksilver (το παράδειγμα που δίνεται στο εξωτερικό άρθρο θα πρέπει να δουλεύει " "με τον ίδιο τρόπο στο Kupfer)." #: C/moreusage.page:80(title) msgid "Grab Current Selection" msgstr "Πιάσιμο τρέχουσας επιλογής" #: C/moreusage.page:81(p) msgid "" "To use the current selected text, from any application, with Kupfer, you can configure a global keyboard shortcut for the action Show " "with Selection in Kupfer Preferences." msgstr "" "Για να χρησιμοποιήσετε το τρέχον επιλεγμένο κείμενο, από οποιαδήποτε " "εφαρμογή, με το Kupfer, μπορείτε να διαμορφώσετε μια γενική " "συντόμευση πληκτρολογίου για την ενέργεια Εμφάνιση με επιλογή στις " "Προτιμήσεις Kupfer." #: C/moreusage.page:85(p) msgid "" "If configured, pressing the global keyboard shortcut will summon " "Kupfer with the current selection as the focused object." msgstr "" "Εάν έχει ρυθμιστεί, πιέζοντας την γενική συντόμευση πληκτρολογίου θα καλέσει " "το Kupfer με την τρέχουσα επιλογή ως εστιασμένο αντικείμενο." #: C/moreusage.page:90(p) msgid "See " msgstr "Βλέπε " #: C/moreusage.page:94(title) msgid "Command-line Connection" msgstr "Σύνδεση γραμμής εντολών" #: C/moreusage.page:95(p) msgid "" "The command kupfer on the command-line will focus Kupfer if it's already running, otherwise it will start it." msgstr "" "Η εντολή kupfer στην γραμμή εντολών θα εστιάσει στο Kupfer αν είναι ήδη σε λειτουργία, διαφορετικά θα το ξεκινήσει." #: C/moreusage.page:99(p) msgid "" "The command kupfer can be used to send files or text from the " "command-line to Kupfer. For example, if you are using the shell " "in a directory where you have a file called \"report.pdf\", you can focus " "this file in Kupfer by running kupfer report.pdf." msgstr "" "Η εντολή kupfer μπορεί να χρησιμοποιηθεί για την αποστολή αρχείων " "ή κειμένου από τη γραμμή εντολών στο Kupfer. Για παράδειγμα, εάν " "χρησιμοποιείτε το κέλυφος σε έναν κατάλογο όπου έχετε ένα αρχείο που " "ονομάζεται \"αναφορά.pdf\", μπορείτε να εστιάσετε σε αυτό το αρχείο στο " "Kupfer εκτελώντας την εντολή kupfer αναφορά.pdf." #: C/moreusage.page:107(p) msgid "" "You can also send text if you pipe the output of a command into kupfer." msgstr "" "Μπορείτε επίσης να στείλετε το κείμενο, αν διοχετεύσετε την έξοδο μιας " "εντολής στο kupfer." #: C/moreusage.page:114(title) msgid "Managing Context and Current Selection" msgstr "Διαχείριση πλαισίου και τρέχουσας επιλογής" #: C/moreusage.page:115(p) msgid "" "If you find the object you want to use, then invoke an action, Kupfer goes away to perform the action (for example start a program or play a " "song). When you come back to Kupfer, it will still keep the same " "object and action selected. Some actions make sense to be repeated (like " "skipping to the next song) and it can be useful to perform different actions " "on the same object." msgstr "" "Εάν βρείτε το αντικείμενο που θέλετε να χρησιμοποιήσετε και στη συνέχεια να " "επικαλεστείτε μια ενέργεια, το Kupfer υποχωρεί για να εκτελέσει " "την ενέργεια (για παράδειγμα ξεκινάτε ένα πρόγραμμα ή μια αναπαραγωγή " "τραγουδιού). Όταν επιστρέψετε στο Kupfer, αυτό θα εξακολουθεί να " "διατηρεί το ίδιο αντικείμενο και την επιλεγμένη ενέργεια. Ορισμένες " "ενέργειες έχουν νόημα να επαναλαμβάνονται (όπως πηδώντας στο επόμενο " "τραγούδι), και μπορεί να είναι χρήσιμο να εκτελούνται διαφορετικές ενέργειες " "για το ίδιο αντικείμενο." #: C/moreusage.page:123(p) msgid "" "However, you always have the top level catalog reachable when you \"come back" "\" to Kupfer -- say you went into the subcatalog \"Albums\" to " "browse your albums only; you select an album to play, and play it. You come " "back with the album selected -- but your next search will still go over the " "top level catalog, not just albums." msgstr "" "Ωστόσο, έχετε πάντα τον κατάλογο του κορυφαίου επιπέδου προσβάσιμο όταν " "κάνετε \"επιστροφή\" στο Kupfer -- ας υποθέσουμε ότι πάτε στον " "υποκατάλογο \"Άλμπουμ\" για να περιηγηθείτε μόνο στα άλμπουμ σας: μπορείτε " "να επιλέξετε ένα άλμπουμ για να παίξει, και να το παίξετε. Επιστρέφετε με το " "άλμπουμ που επιλέξατε -- αλλά η επόμενη αναζήτηση σας θα εξακολουθήσει να " "γίνεται στον κατάλογο κορυφαίου επιπέδου και όχι μόνο στα άλμπουμ." #: C/moreusage.page:130(p) msgid "" "How to come back into the subcatalog you were in? You do that by simply " "browsing, not searching the first thing you do when you focus Kupfer again. A quick way is to press down-arrow or space to open the browse " "window; think of it as saying \"I want to stay in this subfolder\". With the " "browse window open, your next query will search the current subcatalog." msgstr "" "Πώς να επιστρέψετε στον υποκατάλογο που ήσασταν; Θα το κάνετε αυτό απλά " "κάνοντας περιήγηση και όχι αναζήτηση της πρώτης ενέργειας που κάνετε όταν " "εστιάσετε και πάλι στο Kupfer. Ένας γρήγορος τρόπος είναι να " "πατήσετε το κάτω βέλος ή το διάστημα για να ανοίξετε το παράθυρο αναζήτησης: " "είναι σαν λέμε \"Θέλω να μείνω σε αυτόν τον υποφάκελο\". Με ανοιχτό το " "παράθυρο αναζήτησης, το επόμενο ερώτημα σας θα ψάξει τον τρέχοντα " "υποκατάλογο." #: C/moreusage.page:137(p) msgid "" "This way you can work both ways -- you can quickly drill down into folders " "to find a file, and when you come back for the next action with Kupfer you can either summon any normal toplevel object (just start typing), " "or stay around where you were, deep in that folder (press space, then type a " "query)." msgstr "" "Απο εδώ μπορείτε να εργαστείτε με δύο τρόπους -- μπορείτε γρήγορα να " "εστιάσετε σε φακέλους για να βρείτε ένα αρχείο, και όταν επιστρέψετε για την " "επόμενη ενέργεια με το Kupfer μπορείτε είτε να καλέσετε " "οποιοδήποτε κανονικό αντικείμενο κορυφαίου επιπέδου (απλά πληκτρολογήστε), ή " "να μείνετε γύρω απο το σημείο που ήσασταν, βαθιά σε αυτόν το φάκελο (πιέστε " "διάστημα, στη συνέχεια, πληκτρολογήστε ένα ερώτημα)." #: C/moreusage.page:146(title) msgid "Saving Commands as Files" msgstr "Αποθήκευση εντολών ως αρχεία" #: C/moreusage.page:147(p) msgid "" "You can use keyboard shortcut for Compose Command (by default it is " "CtrlReturn) to create a command " "object out of the currently focused command in Kupfer. This object can be " "saved as a runnable file if you use the Save As... action. The " "resulting file will can be executed when opened from the file manager (it " "requires that Kupfer is already running)." msgstr "" "Μπορείτε να χρησιμοποιήσετε την συντόμευση πληκτρολογίου για την Εντολή " "σύνθεσης (εξ ορισμού είναι CtrlΕπιστροφή) για να δημιουργήσετε ένα αντικείμενο εντολής από την τρέχουσα " "εστιασμένη εντολή στο Kupfer. Αυτό το αντικείμενο μπορεί να αποθηκευτεί ως " "εκτελέσιμο αρχείο αν χρησιμοποιείσετε την ενέργεια Αποθήκευση ως .... Το αρχείο που προκύπτει θα μπορεί να εκτελεστεί όταν ανοίξει από τον " "διαχειριστή αρχείων (αυτό προϋποθέτει ότι το Kupfer εκτελείται ήδη)." #: C/managing-plugins.page:7(desc) msgid "Using plugins with Kupfer." msgstr "Χρησιμοποιώντας πρόσθετα με το Kupfer." #: C/managing-plugins.page:10(title) msgid "How to Configure Plugins" msgstr "Πως να ρυθμίσετε τα πρόσθετα" #: C/managing-plugins.page:12(p) msgid "" "Functionality in Kupfer is organized by extentsion modules called \"plugins" "\". Each plugin provides additional functionality, for example integration " "with an external application." msgstr "" "Η λειτουργικότητα στο Kupfer είναι οργανωμένη με ενότητες επεκτάσεων που " "ονομάζονται \"πρόσθετα\". Κάθε πρόσθετο παρέχει επιπλέον λειτουργίες, όπως " "για παράδειγμα την ενσωμάτωση με μια εξωτερική εφαρμογή." #: C/managing-plugins.page:19(title) msgid "Configuring Plugins" msgstr "Διαμόρφωση προσθέτων" #: C/managing-plugins.page:21(title) msgid "Open Kupfer Preferences to the Plugins tab" msgstr "Άνοιγμα του Προτιμήσεις Kupfer στην καρτέλα Πρόσθετα" #: C/managing-plugins.page:23(p) msgid "Use one of the following methods:" msgstr "Χρησιμοποιήστε μία από τις ακόλουθες μεθόδους:" #: C/managing-plugins.page:25(p) msgid "" "Click the Kupfer icon in the notification area and select the item " "Preferences" msgstr "" "Κάντε κλικ στο εικονίδιο Kupfer στην περιοχή ειδοποιήσεων και επιλέξτε το " "στοιχείο Προτιμήσεις" #: C/managing-plugins.page:25(item) msgid "." msgstr "." #: C/managing-plugins.page:29(p) msgid "" "Search for the object Kupfer Preferences in Kupfer itself. Press " "Return to open it." msgstr "" "Αναζητήστε το αντικείμενο Προτιμήσεις Kupfer στο ίδιο το Kupfer. " "Πατήστε Επιστροφή για να το ανοίξετε." #: C/managing-plugins.page:33(p) msgid "Use the keyboard shortcut Ctrl;" msgstr "" "Χρησιμοποιήστε τη συντόμευση πληκτρολογίου Ctrl;" #: C/managing-plugins.page:39(p) msgid "Select the tab Plugins" msgstr "Επιλέξτε την καρτέλα Πρόσθετα" #: C/managing-plugins.page:45(p) msgid "" "Select plugins in the list to read about them, and tick the box next to its " "name to activate the plugin, or untick to deactivate." msgstr "" "Επιλέξτε πρόσθετα στη λίστα για να διαβάσετε για αυτά, και τσεκάρετε το " "κουτάκι δίπλα στο όνομά του για να ενεργοποιήσετε το πρόσθετο, ή ξετσεκάρετε " "για την απενεργοποίησή του." #: C/managing-plugins.page:49(p) msgid "" "If the plugin has any configurable parameters, they will be visible below " "the plugin information." msgstr "" "Αν το πρόσθετο έχει κάποιες δυνατότητες ρύθμισης παραμέτρων, θα είναι ορατές " "κάτω από τις πληροφορίες του." #: C/managing-plugins.page:53(p) msgid "" "The plugin Kupfer Plugins allows fast access to each plugin's " "information page as well as the action \"Show Source Code\" which reveals " "the implementation." msgstr "" "Το πρόσθετο Πρόσθετα Kupfer επιτρέπει τη γρήγορη πρόσβαση στην " "σελίδα πληροφοριών κάθε πρόσθετου, καθώς και η ενέργεια \"Προβολή πηγαίου " "κώδικα\", η οποία αποκαλύπτει την εφαρμογή." #: C/managing-plugins.page:59(title) msgid "If a Plugin can not be Activated" msgstr "Εάν ένα Πρόσθετο δεν μπορεί να ενεργοποιηθεί" #: C/managing-plugins.page:60(p) msgid "" "If a plugin fails to activate because it requires a software module that is " "not available, its plugin information will display a message like this:" msgstr "" "Εάν ένα πρόσθετο αποτυγχάνει να ενεργοποιηθεί επειδή απαιτεί μια μονάδα " "λογισμικού που δεν είναι διαθέσιμη, οι πληροφορίες του θα εμφανίσουν ένα " "μήνυμα σαν αυτό:" #: C/managing-plugins.page:65(em) msgid "Plugin could not be read due to an error:" msgstr "Δεν ειναι δυνατή η ανάγνωση του πρόσθετου εξαιτίας κάποιου σφάλματος:" #: C/managing-plugins.page:66(em) msgid "Python module 'gdata' is needed" msgstr "Χρειάζεται η ενότητα Python 'gdata'" #: C/managing-plugins.page:67(p) msgid "" "This means that you need to install a needed python module from your " "distribution—and possibly the plugin documentation can tell you how." msgstr "" "Αυτό σημαίνει ότι θα πρέπει να εγκαταστήσετε μια αναγκαία ενότητα python από " "τη διανομή σας, και, ενδεχομένως, τα έγγραφα του πρόσθετου μπορούν να σας " "πουν πώς." #: C/managing-plugins.page:72(p) msgid "" "The plugin may also unexpectedly fail to load, and display a different error " "message. It may then be a program error in either the plugin or Kupfer." msgstr "" "Το πρόσθετο μπορεί επίσης απροσδόκητα να αποτύχει να φορτώσει, και να " "εμφανίσει ένα διαφορετικό μήνυμα λάθους. Τότε μπορεί να είναι ένα σφάλμα " "προγράμματος είτε του πρόσθετου ή του Kupfer." #: C/managing-plugins.page:79(title) msgid "Installing more Plugins" msgstr "Εγκατάσταση περισσότερων Πρόσθετων" #: C/managing-plugins.page:80(p) msgid "" "You can install custom plugins into the folder ~/.local/share/kupfer/" "plugins. Each plugin is either a single .py file or a " "python package (a folder directly containing a file called __init__." "py). Plugins in the package format can include icon files. Python " "packages can even be installed as .zip files." msgstr "" "Μπορείτε να εγκαταστήσετε προσαρμοσμένα πρόσθετα στο φάκελο ~/.local/" "share/kupfer/plugins. Κάθε πρόσθετο είναι είτε ένα μεμονωμένο αρχείο " ".py ή ένα πακέτο python (ένας φάκελος που περιέχει άμεσα ένα " "αρχείο που ονομάζεται __init__.py). Πρόσθετα σε μορφή πακέτου " "μπορεί να περιλαμβάνουν αρχεία εικονιδίων. Πακέτα Python μπορεί ακόμη να " "εγκατασταθούν και ως το αρχεία .zip." #: C/managing-plugins.page:88(p) msgid "" "Caution: Treat a plugin as a computer program. Do not install " "untrusted plugins." msgstr "" "Προσοχή: Αντιμετωπίστε ένα πρόσθετο όπως ένα πρόγραμμα υπολογιστή. " "Μην τοποθετείτε μη αξιόπιστα πρόσθετα." #: C/managing-plugins.page:95(title) msgid "Creating Plugins" msgstr "Δημιουργία Πρόσθετων" #: C/managing-plugins.page:96(p) msgid "" "Documentation for plugin creators is available in the file " "Documentation/Manual.rst in the source distribution on the " "webpage at Kupfer " "Manual. An easy way to start is to copy an existing plugin and " "experimenting with it." msgstr "" "Τεκμηρίωση για τους δημιουργούς των πρόσθετων είναι διαθέσιμη στο αρχείο " "Documentation/Manual.rst στη πηγαία διανομή της ιστοσελίδας στο " "Εγχειρίδιο Kupfer. Ένας εύκολος τρόπος για να ξεκινήσετε είναι να αντιγράψετε ένα " "υπάρχον πρόσθετο και να πειραματιστείτε με αυτό." #: C/managing-plugins.page:107(title) msgid "The Catalog Tab in Preferences" msgstr "Η καρτέλα Κατάλογος στις Προτιμήσεις" #: C/managing-plugins.page:108(p) msgid "" "Each plugin can export a number of sources which contain objects. Normally, " "all these objects are directly accessible from a top-level search. Some " "plugins export so specialized or so many objects that their catalogs should " "better not have their objects exported to the top level. To reach those " "objects, you have to first find the catalog by name, then enter the catalog " "using the action Search Contents." msgstr "" "Κάθε πρόσθετο μπορεί να εξάγει μια σειρά από πηγές που περιέχουν " "αντικείμενα. Κανονικά, όλα αυτά τα αντικείμενα είναι άμεσα προσβάσιμα από " "μια αναζήτηση κορυφαίου επιπέδου. Μερικά πρόσθετα εξάγουν τόσο εξειδικευμένα " "ή τόσα πολλά αντικείμενα που οι κατάλογοί τους θα πρέπει καλύτερα να μην " "έχουν τα αντικείμενα τους να εξάγονται στο κορυφαίο επίπεδο. Για να φτάσετε " "σε αυτά τα αντικείμενα, θα πρέπει να βρειτε πρώτα τον κατάλογο με βάση το " "όνομα, στη συνέχεια, πληκτρολογήστε τον κατάλογο με τη χρήση της ενέργειας " "Αναζήτηση περιεχομένων." #: C/managing-plugins.page:118(p) msgid "" "In the tab Catalog in Kupfer Preferences, a ticked box " "next to each source means that its objects are exported. An unticked box " "means that its contents are hidden from the top level." msgstr "" "Στην καρτέλα Κατάλογος στις Προτιμήσεις Kupfer, ένα " "τσεκαρισμένο πλαίσιο δίπλα σε κάθε πηγή σημαίνει ότι τα αντικείμενα της " "εξάγονται. Ένα ατσεκάριστο κουτί σημαίνει ότι το περιεχόμενό της είναι κρυφό " "από το κορυφαίο επίπεδο." #: C/managing-plugins.page:123(p) msgid "" "Note: Kupfer may become slow if large enough subcatalogs are " "exported to the top level." msgstr "" "Σημείωση: το Kupfer μπορεί να γίνει αργό, εάν αρκετά μεγάλοι " "υποκατάλογοι εξάγονται στο κορυφαίο επίπεδο." #: C/license.page:7(desc) msgid "You can copy, modify and share Kupfer." msgstr "" "Μπορείτε να αντιγράψετε, να τροποποιήσετε και να μοιραστείτε το Kupfer." #: C/license.page:10(title) msgid "License" msgstr "Άδεια" #: C/license.page:12(p) msgid "" "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." msgstr "" "Αυτό το πρόγραμμα είναι ελεύθερο λογισμικό: επιτρέπεται η αναδιανομή ή/και " "τροποποίησή του υπό τους όρους της Γενικής Άδειας Δημόσιας Χρήσης GNU " "(GPL), όπως αυτή έχει δημοσιευτεί από το Ίδρυμα Ελεύθερου Λογισμικού " "(FSF), είτε της έκδοσης 3 της Άδειας, είτε (κατ' επιλογήν σας) οποιασδήποτε " "μεταγενέστερης έκδοσης." #: C/license.page:18(p) msgid "" "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." msgstr "" "Το πρόγραμμα αυτό διανέμεται με την ελπίδα ότι θα αποδειχθεί χρήσιμο, παρόλα " "αυτά ΧΩΡΙΣ ΚΑΜΙΑ ΕΓΓΥΗΣΗ — χωρίς ούτε και την σιωπηρή εγγύηση " "ΕΜΠΟΡΕΥΣΙΜΟΤΗΤΑΣ ή ΚΑΤΑΛΛΗΛΟΤΗΤΑΣ ΓΙΑ ΕΙΔΙΚΟ ΣΚΟΠΟ. Για περισσότερες " "λεπτομέρειες ανατρέξτε στη Γενική Άδεια Δημόσιας Χρήσης GNU (GPL)." #: C/license.page:24(p) msgid "" "You should have received a copy of the GNU General Public License along with " "this program. If not, see gnu." "org/licenses." msgstr "" "Θα πρέπει να έχετε λάβει ένα αντίγραφο της Γενικής Άδειας Δημόσιας Χρήσης " "GNU μαζί με αυτό το πρόγραμμα. Αν όχι, δείτε στο gnu.org/licenses." #: C/license.page:30(p) msgid "" "This documentation is licensed under a Creative Commons Attribution-Share Alike 3.0 " "Unported License." msgstr "" "Αυτή η τεκμηρίωση είναι υπό την άδεια της Creative Commons Attribution-Share " "Alike 3.0 Unported License." #: C/license.page:36(p) msgid "" "As a special exception, the copyright holders give you permission to copy, " "modify, and distribute the example code contained in this document under the " "terms of your choosing, without restriction." msgstr "" "Ως ειδική εξαίρεση, οι κάτοχοι πνευματικών δικαιωμάτων σας δίνουν την άδεια " "να αντιγράψετε, να τροποποιήσετε και να διανείμετε το παράδειγμα του κώδικα " "που περιέχεται σε αυτό το έγγραφο σύμφωνα με τους όρους της επιλογής σας, " "χωρίς κανένα περιορισμό." #: C/keyboard.page:7(desc) msgid "Complete keyboard shortcuts reference." msgstr "Πλήρης αναφορά συντομεύσεων πληκτρολογίου." #: C/keyboard.page:10(title) msgid "Command Keys and Accelerator Keys" msgstr "Πλήκτρα εντολών και πλήκτρα επιτάχυνσης" #: C/keyboard.page:13(title) C/generalusage.page:12(title) msgid "Keyboard Interface" msgstr "Διεπαφή πληκτρολογίου" #: C/keyboard.page:14(p) msgid "In command mode, the following keystrokes have special meanings:" msgstr "" "Σε κατάσταση εντολών, οι ακόλουθες πληκτρολογήσεις έχουν ιδιαίτερη σημασία:" #: C/keyboard.page:19(p) C/generalusage.page:34(p) msgid " or Space" msgstr " ή Διάστημα" #: C/keyboard.page:20(p) C/generalusage.page:35(p) msgid "Go to the next match" msgstr "Μετάβαση στο επόμενο ταίριασμα" #: C/keyboard.page:23(p) C/generalusage.page:38(p) msgid " or ShiftSpace" msgstr " ή ShiftΔιάστημα" #: C/keyboard.page:26(p) C/generalusage.page:41(p) msgid "Go to the previous match" msgstr "Μετάβαση στο προηγούμενο ταίριασμα" #: C/keyboard.page:29(p) C/generalusage.page:44(p) msgid " or /" msgstr " ή /" #: C/keyboard.page:30(p) C/generalusage.page:45(p) msgid "Descend into an object with content" msgstr "Κατεβαίνει σε ένα αντικείμενο με περιεχόμενο" #: C/keyboard.page:33(key) C/generalusage.page:48(key) msgid "Backspace" msgstr "Πλήκτρο backspace" #: C/keyboard.page:34(p) C/generalusage.page:49(p) msgid "Erase a character from the query. If the query is empty, go up a level" msgstr "" "Διαγραφή ενός χαρακτήρα από το ερώτημα. Εάν το ερώτημα είναι άδειο, " "ανεβαίνει ένα επίπεδο προς τα πάνω" #: C/keyboard.page:39(key) C/keyboard.page:93(key) C/generalusage.page:54(key) msgid "." msgstr "." #: C/keyboard.page:40(p) C/generalusage.page:55(p) msgid "Activate free-text mode" msgstr "Ενεργοποίηση λειτουργίας ελεύθερου κειμένου" #: C/keyboard.page:43(key) C/keyboard.page:97(key) C/generalusage.page:58(key) msgid "," msgstr "," #: C/keyboard.page:44(p) C/generalusage.page:59(p) msgid "Put selected object on the stack (\"Comma Trick\")" msgstr "Τοποθετεί το επιλεγμένο αντικείμενο στη στοίβα (\"Τέχνασμα κόμμα\")" #: C/keyboard.page:47(p) msgid "Quick access keys:" msgstr "Πλήκτρα γρήγορης πρόσβασης:" #: C/keyboard.page:53(key) msgid "=" msgstr "=" #: C/keyboard.page:55(p) msgid "" "Activate free-text mode with = prefix (for )" msgstr "" "Ενεργοποίηση λειτουργίας ελεύθερου κειμένου με πρόθεμα = (για το )" #: C/keyboard.page:61(key) msgid "/" msgstr "/" #: C/keyboard.page:63(p) msgid "" "Activate free-text mode (when nothing is selected) with / " "prefix (to input a rooted path)" msgstr "" "Ενεργοποίηση λειτουργίας ελεύθερου κειμένου (όταν δεν έχει επιλεγεί τίποτα) " "με πρόθεμα / (για την είσοδο μιας ριζωμένης διαδρομής)" #: C/keyboard.page:68(p) C/generalusage.page:62(p) msgid "Additionally:" msgstr "Επιπλέον:" #: C/keyboard.page:72(p) C/generalusage.page:66(p) msgid "" "Return activates the current selection: the command is executed." msgstr "" "Το πλήκτρο Επιστροφή ενεργοποιεί την τρέχουσα επιλογή: η εντολή " "εκτελείται." #: C/keyboard.page:74(p) C/generalusage.page:68(p) msgid "Escape clears the current selection." msgstr "Το πλήκτρο Escape καθαρίζει την τρέχουσα επιλογή." #: C/keyboard.page:75(p) C/generalusage.page:69(p) msgid "Tab switches between the object and the action pane." msgstr "" "Το πλήκτρο Tab πραγματοποιεί εναλλαγή μεταξύ του αντικειμένου και " "του παραθύρου ενεργειών." #: C/keyboard.page:77(p) msgid "" "The meaning of the keys Space, ., ,, /" " and = can not be changed, but you can deactivate their " "special meaning with the checkbox Use single keystroke commands " "in Kupfer Preferences." msgstr "" "Η έννοια των πλήκτρων Space, ., ,, / και = δεν μπορεί να αλλάξει, αλλά μπορείτε να " "απενεργοποιήσετε την ειδική σημασία τους με το πλαίσιο ελέγχου Χρήση " "μονών εντολών πληκτρολόγησης στις Προτιμήσεις Kupfer." #: C/keyboard.page:86(title) msgid "Kupfer's Keyboard Shortcuts" msgstr "Συντομεύσεις πληκτρολογίου του Kupfer" #: C/keyboard.page:87(p) msgid "" "These keyboard shortcuts are used in Kupfer's interface. They " "have the following meanings and default shortcuts:" msgstr "" "Αυτές οι συντομεύσεις πληκτρολογίου χρησιμοποιούνται στη διεπαφή του " "Kupfer. Έχουν τις ακόλουθες σημασίες και προκαθορισμένες " "συντομεύσεις:" #: C/keyboard.page:93(key) C/keyboard.page:97(key) C/keyboard.page:101(key) #: C/keyboard.page:105(key) C/keyboard.page:113(key) C/keyboard.page:117(key) #: C/keyboard.page:121(key) C/keyboard.page:125(key) C/keyboard.page:129(key) #: C/keyboard.page:174(key) msgid "Ctrl" msgstr "Ctrl" #: C/keyboard.page:94(p) msgid "Toggle text mode" msgstr "Εναλλαγή μορφής κειμένου" #: C/keyboard.page:98(p) msgid "The comma trick" msgstr "Το τέχνασμα κόμμα" #: C/keyboard.page:101(key) msgid ";" msgstr ";" #: C/keyboard.page:102(p) msgid "Show preferences window" msgstr "Εμφάνιση παραθύρου προτιμήσεων" #: C/keyboard.page:105(key) msgid "R" msgstr "R" #: C/keyboard.page:106(p) msgid "Reset all" msgstr "Επαναφορά όλων" #: C/keyboard.page:109(key) msgid "Alt" msgstr "Alt" #: C/keyboard.page:109(key) msgid "A" msgstr "A" #: C/keyboard.page:110(p) msgid "Alternate activate" msgstr "Εναλλακτική ενεργοποίηση" #: C/keyboard.page:113(key) msgid "Return" msgstr "Επιστροφή" #: C/keyboard.page:114(p) msgid "Compose command" msgstr "Εντολή σύνθεσης" #: C/keyboard.page:117(key) msgid "S" msgstr "S" #: C/keyboard.page:118(p) msgid "Switch to first pane" msgstr "Μετάβαση σε πρώτο παράθυρο" #: C/keyboard.page:121(key) msgid "Q" msgstr "Q" #: C/keyboard.page:122(p) msgid "Select 'Quit'" msgstr "Επιλογή 'Κείσιμο'" #: C/keyboard.page:125(key) msgid "G" msgstr "G" #: C/keyboard.page:126(p) msgid "Select 'Selected File'" msgstr "Επιλογή 'επιλεγμένο αρχείο'" #: C/keyboard.page:129(key) msgid "T" msgstr "T" #: C/keyboard.page:130(p) msgid "Select 'Selected Text'" msgstr "Επιλογή 'επιλεγμένο κείμενο'" #: C/keyboard.page:133(key) msgid "F1" msgstr "F1" #: C/keyboard.page:134(p) msgid "Show Help" msgstr "Εμφάνιση βοήθειας" #: C/keyboard.page:139(title) msgid "How to configure a keyboard shortcut" msgstr "Πως να ρυθμίσετε μια συντόμευση πληκτρολογίου" #: C/keyboard.page:141(p) C/keyboard.page:185(p) msgid "Open Kupfer Preferences and go to the Keyboard tab." msgstr "" "Ανοίξτε τις Προτιμήσεις Kupfer και πηγαίνετε στην καρτέλα " "Πληκτρολόγιο." #: C/keyboard.page:147(p) msgid "" "Double-click the shorcut's row under Browser Keyboard Shortcuts." msgstr "" "Κάντε διπλό κλικ στη γραμμή της συντόμευσης Συντομεύσεις πληκτρολογίου " "περιηγητή." #: C/keyboard.page:153(p) msgid "" "Using the window that appears, press modifier keys and a letter or number " "key to set a shortcut. An example is pressing and holding Ctrl " "and then pressing and releasing T to bind CtrlT." msgstr "" "Χρησιμοποιώντας το παράθυρο που εμφανίζεται, πατήστε τα πλήκτρα τροποποίησης " "και ένα γράμμα ή αριθμό για να ορίσετε μια συντόμευση. Ένα παράδειγμα είναι " "πατώντας και κρατώντας πατημένο το Ctrl και, στη συνέχεια, " "πιέζοντας και αφήνοντας το T για να δεσμεύσετε τα " "CtrlT." #: C/keyboard.page:164(title) msgid "Global Keyboard Shortcuts" msgstr "Γενικές συντομεύσεις πληκτρολογίου" #: C/keyboard.page:165(p) msgid "" "Kupfer always listens to global shortcuts, even if it is not " "currently in the foreground." msgstr "" "Το Kupfer ακούει πάντα στις γενικές συντομεύσεις, ακόμη και αν " "δεν είναι στο προσκήνιο." #: C/keyboard.page:169(p) msgid "They have the following meanings and default shortcuts:" msgstr "Έχουν τις ακόλουθες σημασίες και προεπιλεγμένες συντομεύσεις:" #: C/keyboard.page:174(key) msgid "Space" msgstr "Διάστημα" #: C/keyboard.page:175(p) msgid "Show/hide Kupfer" msgstr "Εμφάνιση/απόκρυψη του Kupfer" #: C/keyboard.page:178(p) msgid "(not configured by default)" msgstr "(δεν έχει ρυθμιστεί από προεπιλογή)" #: C/keyboard.page:179(p) msgid "Show Kupfer with 'Selection' object focused" msgstr "Εμφάνιση του Kupfer με 'Επιλογή' εστιασμένο αντικείμενο" #: C/keyboard.page:183(title) msgid "How to configure a global keyboard shortcut" msgstr "Πως να ρυθμίσετε μια γενική συντόμευση πληκτρολογίου" #: C/keyboard.page:191(p) msgid "" "Double-click the shorcut's row under Global Keyboard Shortcuts." msgstr "" "Κάντε διπλό κλικ στη γραμμή της συντόμευσης Γενικές συντομεύσεις " "πληκτρολογίου." #: C/keyboard.page:197(p) msgid "" "Using the window that appears, press modifier keys and a letter or number " "key to set a global shortcut. An example is pressing and holding Super and then pressing and releasing Space to bind " "SuperSpace." msgstr "" "Χρησιμοποιώντας το παράθυρο που εμφανίζεται, πατήστε τα πλήκτρα τροποποίησης " "και ένα γράμμα ή αριθμό για να ορίσετε μια γενική συντόμευση. Ένα παράδειγμα " "είναι πατώντας και κρατώντας πατημένο το Super και, στη συνέχεια, " "πιέζοντας και αφήνοντας το Space για να δεσμεύσετε τα " "SuperSpace." #: C/keyboard.page:206(p) msgid "" "Since these keyboard shortcuts are global, they can be used from any " "application. Select shortcuts with care so that they do not conflict with " "other functions." msgstr "" "Δεδομένου ότι αυτές οι συντομεύσεις πληκτρολογίου είναι γενικές, μπορούν να " "χρησιμοποιηθούν από οποιαδήποτε εφαρμογή. Επιλέξτε συντομεύσεις με προσοχή " "έτσι ώστε να μην έρχονται σε αντίθεση με άλλες λειτουργίες." #: C/keyboard.page:214(p) msgid "" "The plugin Triggers allows to activate actions with global keyboard " "shortcuts. Trigger shortcuts do not appear in Kupfer Preferences." msgstr "" "Το πρόσθετο Εναύσματα σας επιτρέπει να ενεργοποιήσετε τις ενέργειες " "με τις γενικές συντομεύσεις πληκτρολογίου. Συντομεύσεις του Εναύσματα δεν " "εμφανίζονται στις Προτιμήσεις Kupfer." #: C/keyboard.page:220(p) msgid "See for more information." msgstr "" "Δείτε στο για περισσότερες πληροφορίες." #: C/introduction.page:7(desc) msgid "Introduction to Kupfer." msgstr "Εισαγωγή στο Kupfer." #: C/introduction.page:10(title) msgid "Introduction" msgstr "Εισαγωγή" #: C/introduction.page:12(p) msgid "" "Kupfer is an interface for quick and convenient access to " "applications and their documents." msgstr "" "Το Kupfer είναι μια διεπαφή για γρήγορη και εύκολη πρόσβαση σε " "εφαρμογές και τα έγγραφά τους." #: C/introduction.page:16(p) msgid "" "The most typical use is to find a specific application and launch it. We " "have tried to make Kupfer easy to extend with plugins so that " "this quick-access paradigm can be extended to many more objects than just " "applications." msgstr "" "Η πιο τυπική χρήση είναι να βρείτε μια συγκεκριμένη εφαρμογή και να την " "τρέξετε. Έχουμε προσπαθήσει να κάνουμε το Kupfer εύκολο να " "επεκταθεί με πρόσθετα, έτσι ώστε αυτό το παράδειγμα γρήγορης πρόσβασης να " "μπορεί να επεκταθεί και σε πολλά άλλα αντικείμενα εκτός των εφαρμογών." #: C/introduction.page:22(p) msgid "" "We hope that using Kupfer feels both very fun and " "different." msgstr "" "Ελπίζουμε ότι η χρήση του Kupfer σας δίνει την αίσθηση ότι είναι " "τόσο πολύ διασκεδαστική όσο και διαφορετική." #: C/introduction.page:26(p) msgid "" "For up-to-date information about Kupfer, visit its homepage." msgstr "" "Για ενημερωμένες πληροφορίες σχετικά με το Kupfer, επισκεφθείτε " "την αρχική σελίδα του." #: C/index.page:9(name) msgid "Ulrik Sverdrup" msgstr "Ulrik Sverdrup" #: C/index.page:10(email) msgid "ulrik.sverdrup@gmail.com" msgstr "ulrik.sverdrup@gmail.com" #: C/index.page:13(year) msgid "2009" msgstr "2009" #: C/index.page:14(name) msgid "Kupfer Development Team" msgstr "Ομάδα Ανάπτυξης Kupfer" #: C/index.page:17(license) msgid "Creative Commons Share Alike 3.0" msgstr "Creative Commons Share Alike 3.0" #: C/index.page:21(title) msgid "Kupfer Manual" msgstr "Εγχειρίδιο Kupfer" #: C/index.page:24(title) msgid "Using Kupfer" msgstr "Χρήση του Kupfer" #: C/index.page:27(title) msgid "About Specific Plugins" msgstr "Σχετικά με Ειδικά Πρόσθετα" #: C/generalusage.page:7(desc) msgid "How to start using Kupfer." msgstr "Πώς να αρχίσετε να χρησιμοποιείτε το Kupfer." #: C/generalusage.page:14(p) msgid "" "Kupfer is to the largest part a keyboard-managed interface to " "applications and documents." msgstr "" "Το Kupfer είναι στο μεγαλύτερο μέρος του μια διεπαφή " "διαχειριζόμενη απο το πληκτρολόγιο σε εφαρμογές και έγγραφα." #: C/generalusage.page:18(p) msgid "" "Kupfer's default mode is the command mode: If you type a query, kupfer will " "search for a match in its catalog." msgstr "" "Προεπιλεγμένη λειτουργία του Kupfer είναι η κατάσταση εντολών: Εάν " "πληκτρολογήσετε ένα ερώτημα, το kupfer θα ψάξει για ένα ταίριασμα στον " "κατάλογό του." #: C/generalusage.page:23(p) msgid "" "The arrow keys allow you to browse query matches quite naturally, going to " "the previous or next match, and going up and down in the subcatalogs." msgstr "" "Τα πλήκτρα βέλους σας επιτρέπουν να περιηγηθείτε σε συμφωνίες ερωτημάτων " "αρκετά φυσικά, πηγαίνοντας στο προηγούμενο ή το επόμενο ταίριασμα, και " "πηγαίνοντας πάνω-κάτω στους υποκαταλόγους." #: C/generalusage.page:29(p) msgid "In command mode, some keystrokes have special meanings:" msgstr "Σε κατάσταση εντολών, μερικές πληκτρολογήσεις έχουν ιδιαίτερη σημασία:" #: C/generalusage.page:71(p) msgid "" "By default you show Kupfer using the global keyboard shortcut " "CtrlSpace." msgstr "" "Από προεπιλογή θα επιδείξετε το Kupfer, χρησιμοποιώντας την " "γενική συντόμευση πληκτρολογίου CtrlSpace." #: C/generalusage.page:74(p) msgid "See for more information." msgstr "Δείτε στο για περισσότερες πληροφορίες." #: C/generalusage.page:78(title) msgid "Learning Habits" msgstr "Μαθαίνοντας συνήθειες" #: C/generalusage.page:79(p) msgid "" "Kupfer remembers which objects and actions are used the most. " "When beginning to use it, you have to use the arrow keys at times to make it " "precise which object you want to find. After a few uses of that object, " "Kupfer will rank it higher. Objects marked as favorites are also ranked higher." msgstr "" "Το Kupfer θυμάται ποια αντικείμενα και ενέργειες χρησιμοποίηθηκαν " "πιο πολύ. Όταν ξεκινήσετε τη χρήση του, θα πρέπει να χρησιμοποιείτε τα " "πλήκτρα βέλους κατά καιρούς για να καταστεί σαφές, ποιό αντικείμενο θέλετε " "να βρείτε. Μετά από μερικές χρήσεις ενός αντικειμένου, το Kupfer θα το " "κατατάξει σε υψηλότερη θέση. Αντικείμενα που χαρακτηρίζονται ως αγαπημένα, επίσης, κατατάσσεται ψηλότερα." #: C/generalusage.page:90(title) msgid "The Catalog" msgstr "Ο Κατάλογος" #: C/generalusage.page:91(p) msgid "" "The Catalog is the collection of objects you can access in Kupfer, such as " "documents and programs." msgstr "" "Ο Κατάλογος είναι η συλλογή των αντικειμένων στα οποία μπορείτε να έχετε " "πρόσβαση στο Kupfer, όπως έγγραφα και προγράμματα." #: C/generalusage.page:96(p) msgid "" "Objects in the catalog that have content, like folders, are marked with an " "arrow. Pressing will enter these objects. Much of the catalog " "is composed of subcatalogs; plugin subcatalogs do in general list objects " "that are also available directly from the top level. Subcatalogs can be used " "for a narrower view or search scope, when using Kupfer." msgstr "" "Αντικείμενα στον κατάλογο που έχουν περιεχόμενο, όπως φάκελοι, " "επισημαίνονται με ένα βέλος. Πατώντας το θα μπείτε σε αυτά τα " "αντικείμενα. Μεγάλο μέρος του καταλόγου αποτελείται από υποκαταλόγους: " "υποκατάλογοι πρόσθετων κάνουν γενικά οι λίστες αντικειμένων που είναι επίσης " "διαθέσιμες απευθείας από το κορυφαίο επίπεδο. Οι υποκατάλογοι μπορεί να " "χρησιμοποιηθούν για μια περιορισμένη προβολή ή μια ευρεία αναζήτηση, κατά τη " "χρήση του Kupfer." #: C/generalusage.page:105(p) msgid "" "Most subcatalogs update their content automatically. For example, the " "Desktop folder source is always up-to-date." msgstr "" "Οι περισσότεροι υποκατάλογοι ενημερώνουν το περιεχόμενό τους αυτόματα. Για " "παράδειγμα, η πηγή του φακέλου Επιφάνεια εργασίας είναι πάντα ενημερωμένη." #. Put one translator per line, in the form of NAME , YEAR1, YEAR2 #: C/generalusage.page:0(None) msgid "translator-credits" msgstr "Maria Mavridou , 2014" kupfer-328/help/es/000077500000000000000000000000001500175051100142165ustar00rootroot00000000000000kupfer-328/help/es/es.po000066400000000000000000002343651500175051100152020ustar00rootroot00000000000000# translation of kupfer.help.master.po to Español # Spanish translation for kupfer. # Copyright (C) 2010 kupfer's COPYRIGHT HOLDER # This file is distributed under the same license as the kupfer package. # Jorge González , 2010, 2011. # Daniel Mustieles , 2011, 2013, 2014. # msgid "" msgstr "" "Project-Id-Version: kupfer.help.master\n" "POT-Creation-Date: 2014-03-23 21:59+0000\n" "PO-Revision-Date: 2014-03-26 17:46+0100\n" "Last-Translator: Daniel Mustieles \n" "Language-Team: Español \n" "Language: \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: Gtranslator 2.91.5\n" #: C/plugin-websearch.page:7(desc) msgid "Using the search the web plugin." msgstr "Usar el complemento «Buscar en la web»." #: C/plugin-websearch.page:10(app) msgid "Search the Web" msgstr "Buscar en la web" #: C/plugin-websearch.page:13(title) C/plugin-triggers.page:23(title) #: C/plugin-notes.page:22(title) C/plugin-nautilusselection.page:13(title) #: C/plugin-gwibber.page:25(title) C/plugin-favorites.page:22(title) #: C/plugin-calculator.page:21(title) C/plugin-applications.page:19(title) #: C/generalusage.page:10(title) msgid "Basic Usage" msgstr "Uso básico" #: C/plugin-websearch.page:15(p) msgid "Activate Kupfer and make sure it is in free-text mode (press period)" msgstr "" "Active Kupfer y asegúrese de que está en modo de texto libre (pulse «.»)" #: C/plugin-websearch.page:17(p) msgid "" "Type in a search query and tap Tab to switch to the action pane." msgstr "" "Escriba una consulta de búsqueda y pulse Tab para cambiar al " "panel de acciones." #: C/plugin-websearch.page:19(p) msgid "" "Type \"Search With\" to find Search the Web's action and tap Tab " "again to switch to the third pane (indirect object)." msgstr "" "Escriba «Buscar con» para buscar la acción «Buscar en la web» y pulse " "Tab otra vez para cambiar al tercer panel (objeto indirecto)." #: C/plugin-websearch.page:22(p) msgid "" "Select search engine with the arrow keys and type Return to open " "the search in a web browser." msgstr "" "Seleccione el motor de búsqueda con las flechas y pulse Intro " "para abrir la búsqueda en un navegador web." #: C/plugin-websearch.page:29(title) msgid "Search Engines" msgstr "Motores de búsqueda" #: C/plugin-websearch.page:30(p) msgid "" "The Search the Web plugin uses Firefox' search engines, so you " "can add Search Engines directly in Firefox and Kupfer " "will find them later." msgstr "" "El complemento «Buscar en la web» usa los motores de búsqueda de " "Firefox por lo que puede añadir motores de búsqueda directamente " "en Firefox y luego Kupfer los encontrará." #: C/plugin-websearch.page:35(p) msgid "" "You can also install custom search plugins directly, only for Kupfer, in the folder:" msgstr "" "También puede instalar complementos de búsqueda personalizados directamente, " "sólo para Kupfer, en la carpeta:" #: C/plugin-websearch.page:39(code) #, no-wrap msgid "~/.local/share/kupfer/searchplugins/" msgstr "~/.local/share/kupfer/searchplugins/" #: C/plugin-websearch.page:40(p) msgid "The search engine descriptions must written in OpenSearch format." msgstr "" "Las descripciones del motor de búsqueda deben estar escritas en el formato " "OpenSearch." #: C/plugin-triggers.page:7(desc) msgid "Using the triggers plugin." msgstr "Usar el complemento «Disparadores»." #: C/plugin-triggers.page:10(app) C/keyboard.page:213(title) msgid "Triggers" msgstr "Disparadores" #: C/plugin-triggers.page:13(title) msgid "Triggers Plugin" msgstr "Complemento «Disparadores»" #: C/plugin-triggers.page:14(p) msgid "" "With Triggers you can take a command you would normally perform " "in Kupfer, such as launching an application or opening a " "document, and bind a global key combination to run this command. As long as " "Kupfer is running, any application can have the current focus." msgstr "" "Con Disparadores puede coger un comando que ejecute habitualmente " "en Kupfer, como lanzar una aplicación o abrir un documento, y " "asociarle una combinación global de teclas para ejecutarlo. Mientras " "Kupfer esté en ejecución, cualquier aplicación puede tener el " "foco actual." #: C/plugin-triggers.page:25(title) msgid "Creating a new trigger" msgstr "Crear un disparador nuevo" #: C/plugin-triggers.page:27(p) msgid "Set up a command in Kupfer that you want to run" msgstr "Configure en Kupfer el comando que quiere ejecutar" #: C/plugin-triggers.page:32(p) msgid "" "Press CtrlReturn to create a " "composed command." msgstr "" "Pulse CtrlIntro para crear un " "comando compuesto." #: C/plugin-triggers.page:38(p) msgid "" "Type Tab and select the action Add Trigger... and press " "Return" msgstr "" "Pulse Tab y seleccione la acción Añadir disparador... y " "pulse Intro." #: C/plugin-triggers.page:44(p) msgid "" "Using the window that appears, press modifier keys and a letter or number " "key to set a global shortcut. An example is pressing and holding " "CtrlAlt and then pressing and " "releasing R to bind CtrlAltR." msgstr "" "Usando la ventana que aparece, pulse las teclas modificadores y un número o " "una letra para establecer un atajo globa. Un ejemplo es pulsar y mantener " "CtrlAlt y entonces pulsar y soltar " "R para asociar CtrlAltR." #: C/plugin-triggers.page:54(title) msgid "Removing a trigger" msgstr "Quitar un disparador" #: C/plugin-triggers.page:56(p) msgid "" "Find the source Triggers in Kupfer and press to see its contents." msgstr "" "Encuentre la fuente de Disparadores en Kupfer y pulse " " para ver su contenido." #: C/plugin-triggers.page:62(p) msgid "" "Find the active trigger in the list and use the action Remove Trigger." msgstr "" "Busque el disparador activo en la lista y use la acción Quitar " "disparador." #: C/plugin-triggers.page:68(p) msgid "" "Since trigger keyboard shortcuts are global, they can be used from any " "application. Select shortcuts with care so that they do not conflict with " "other functions." msgstr "" "Ya que los disparadores de atajos de teclado son globales, se puede usar " "desde cualquier aplicación. Seleccione los atajos con cuidado para que no " "entren en conflicto con otras funciones." #: C/plugin-triggers.page:74(title) C/plugin-notes.page:60(title) #: C/plugin-gwibber.page:68(title) C/plugin-favorites.page:38(title) msgid "Power User Tips" msgstr "Consejos para usuarios avanzados" #: C/plugin-triggers.page:75(p) msgid "" "Proxy objects such as Selected Text, Selected File, Frontmost Window, Last Command et cetera allow very " "powerful triggers." msgstr "" "Los Objetos del proxy como Texto seleccionado, Archivo " "seleccionado, Ventana de primer plano, Último comando " "etc. admiten disparadores muy potentes." #: C/plugin-triggers.page:79(p) msgid "" "The application action Launch is special; if you bind a trigger " "using Launch, it will start the application if it is not running, " "but focus the application when it is already running. By contrast, Start " "Again will start the application if it is running or not." msgstr "" "La acción de aplicación Lanzar es especial; si asocia un disparador " "usando Lanzar, iniciará la aplicación si no está en ejecución, pero " "dará el foco a la aplicación cuando esté en ejecución. Por el contrario, " "Iniciar de nuevo iniciará la aplicación tanto si está ejecución " "como si no." #: C/plugin-triggers.page:87(title) msgid "Example Triggers" msgstr "Ejemplo de «Disparadores»" #: C/plugin-triggers.page:90(em) msgid "Text Editor → Launch" msgstr "Editor de texto → Lanzar" #: C/plugin-triggers.page:91(p) msgid "" "Start Text Editor or focus its window if it is already running." msgstr "" "Inicie el Editor de texto, o dé el foco a su ventana si ya está en " "ejecución." #: C/plugin-triggers.page:97(em) msgid "Selected Text → Search With → Google" msgstr "Text seleccionado → Buscar con → Google" #: C/plugin-triggers.page:98(p) msgid "Search the web using the currently selected text." msgstr "Buscar en la web usando el texto seleccionado actualmente." #: C/plugin-triggers.page:100(em) msgid "Selected File → Move To → (Downloads Folder)" msgstr "Archivo seleccionado → Mover a → (Carpeta de descargas)" #: C/plugin-triggers.page:101(p) msgid "Move the currently selected file to a specific folder" msgstr "Mover el archivo seleccionado actualmente a una carpeta específica" #: C/plugin-triggers.page:105(em) msgid "Songs → Search Contents" msgstr "Canciones → Buscar contenidos" #: C/plugin-triggers.page:106(p) msgid "" "You may even add a trigger to open a specific subcatalog in Kupfer, for " "example Rhythmbox's songs." msgstr "" "Incluso puede añadir un disparador para abrir un subcatálogo específico en " "Kupfer, por ejemplo, canciones de Rhythmbox." #: C/plugin-notes.page:7(desc) msgid "Using the notes plugin." msgstr "Usar el complemento «Notas»" #: C/plugin-notes.page:10(app) C/plugin-calculator.page:37(title) msgid "Notes" msgstr "Notas" #: C/plugin-notes.page:13(title) msgid "Notes Plugin" msgstr "Complemento «Notas»" #: C/plugin-notes.page:14(p) msgid "" "With Notes you can access or create new notes in either the " "program Gnote or Tomboy. Notes will work " "identically with either application—you can configure which one to use in " "the plugin's information pane in Kupfer Preferences." msgstr "" "Con Notas puede crear notas o acceder a ellas en Gnote " "o en Tomboy. Notas trabajará de manera idéntica con " "cada aplicación; puede configurar cuál de ellas usar en el panel de " "información del complemento en las Preferencias de Kupfer." #: C/plugin-notes.page:24(title) msgid "Creating a new note" msgstr "Crear una nota nueva" #: C/plugin-notes.page:26(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "note title" msgstr "" "Active Kupfer y escriba . para entrar en modo texto, y escriba el " "título de una nota." #: C/plugin-notes.page:32(p) msgid "" "Type Tab and select the action Create Note and press " "Return." msgstr "" "Pulse Tab y seleccione la acción Crear nota y pulse " "Intro." #: C/plugin-notes.page:39(title) msgid "Finding a note by title" msgstr "Buscar una nota por título" #: C/plugin-notes.page:41(p) msgid "Simply search for the note title in Kupfer" msgstr "Simplemente busque el título de la nota en Kupfer." #: C/plugin-notes.page:45(title) msgid "Finding a note by content" msgstr "Buscar una nota por contenido" #: C/plugin-notes.page:47(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "search query" msgstr "" "Active Kupfer y escriba . para entrar en modo texto, y escriba " "una consulta de búsqueda." #: C/plugin-notes.page:53(p) msgid "" "Type Tab and select the action Get Note Search Results... and press Return." msgstr "" "Pulse Tab y seleccione la acción Obtener los resultados de " "búsqueda de notas... y pulse Intro." #: C/plugin-notes.page:63(p) msgid "" "You can use the Selected Text object and create a new note with the " "content of the selection." msgstr "" "Puede usar el objeto Texto seleccionado para crear una nota nueva " "con el contenido de la selección." #: C/plugin-nautilusselection.page:7(desc) msgid "Using the selected file plugin." msgstr "Usar el complemento «Archivo seleccionado»." #: C/plugin-nautilusselection.page:10(app) msgid "Selected File" msgstr "Archivo seleccionado" #: C/plugin-nautilusselection.page:14(p) msgid "" "Select a file in the file manager. Open Kupfer and search for the " "object Selected File, which represents the file or files that are " "selected." msgstr "" "Seleccione un archivo en el gestor de archivos. Abra Kupfer y " "busque el objeto Archivo seleccionado, que representa el archivo " "o los archivos que están seleccionados." #: C/plugin-nautilusselection.page:19(p) msgid "" "Instead of searching, you can press CtrlG to directly focus the selected file. See " "for more information." msgstr "" "En vez de buscar, puede pulsar CtrlG " "para dar el foco directamente al archivo seleccionado. Consulte la para obtener más información." #: C/plugin-nautilusselection.page:26(title) msgid "Selected File requires Nautilus" msgstr "Archivo seleccionado requiere Nautilus" #: C/plugin-nautilusselection.page:27(p) msgid "" "The selected file plugin works with the Nautilus file browser and " "requires that the extension kupfer_provider.py is installed (it " "is normally installed together with Kupfer). After installing it " "for the first time, Nautilus must start anew before it is active." msgstr "" "El complemento «Archivo seleccionado» funciona con el explorador de archivos " "Nautilus y requiere que la extensión kupfer_provider.py esté instalada (normalmente se instala junto con Kupfer). " "Después de instalarla por primera vez, Nautilus debe iniciarse de " "nuevo antes de que esté activa." #: C/plugin-gwibber.page:7(desc) msgid "Using the Gwibber plugin." msgstr "Usar el complemento «Gwibber»." #: C/plugin-gwibber.page:10(app) msgid "Gwibber" msgstr "Gwibber" #: C/plugin-gwibber.page:13(title) msgid "Gwibber Plugin" msgstr "Complemento «Gwibber»" #: C/plugin-gwibber.page:14(p) msgid "" "With the Gwibber plugin you can send messages to social networks " "such as Twitter or Identi.ca." msgstr "" "Con el complemento Gwibber puede enviar mensajes a redes sociales " "como Twitter o Identi.ca." #: C/plugin-gwibber.page:18(p) msgid "" "The plugin requires that the application Gwibber is installed and " "configured for your user. Kupfer will start and use Gwibber's " "service in the background." msgstr "" "El complemento requiere que Gwibber esté instalado y configurado " "para su usuario. Kupfer iniciará y usará el servicio Gwibber en " "segundo plano." #: C/plugin-gwibber.page:27(title) msgid "Sending a message to all services" msgstr "Enviar un mensaje a todos los servicios" #: C/plugin-gwibber.page:29(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "message." msgstr "" "Active Kupfer y escriba . para entrar en modo texto, y escriba un " "mensaje." #: C/plugin-gwibber.page:35(p) msgid "" "Type Tab and select the action Send Message and press " "Return." msgstr "" "Pulse Tab y seleccione la acción Enviar mensaje y pulse " "Intro." #: C/plugin-gwibber.page:42(title) msgid "Sending a message to a specific service" msgstr "Enviar un mensaje un servicio específico" #: C/plugin-gwibber.page:44(p) msgid "" "Activate Kupfer and search for the service object, for example Identi." "ca" msgstr "" "Active Kupfer y busque un objeto del servicio, por ejemplo Identi.ca" #: C/plugin-gwibber.page:50(p) msgid "Type Tab and select the action Send Message." msgstr "Pulse Tab y seleccione la acción Enviar mensaje." #: C/plugin-gwibber.page:55(p) msgid "" "Type Tab to select the last pane, and type in a message. Press " "Return to send." msgstr "" "Pulse Tab para seleccionar el último panel y escriba un mensaje. " "Pulse Intro para enviarlo." #: C/plugin-gwibber.page:61(p) msgid "" "The plugin also provides a source for incoming messages, Gwibber " "Messages and more actions on messages such as Reply, Send " "Private Message etc." msgstr "" "El complemento también proporciona una fuente para mensajes entrantes, " "Mensajes de Gwibber y más acciones sobre mensajes, tales como " "Responder, Enviar mensaje privado etc." #: C/plugin-gwibber.page:71(p) msgid "" "You can use the comma trick if you want to send a message to more " "than one service, but not all, at the same time." msgstr "" "Puede usar el truco de la coma si quiere enviar un mensaje a más de " "un servicio, pero no a todos, al mismo tiempo." #: C/plugin-favorites.page:7(desc) msgid "Using the favorites plugin." msgstr "Usar el complemento «Favoritos»." #: C/plugin-favorites.page:10(app) msgid "Favorites" msgstr "Favoritos" #: C/plugin-favorites.page:13(title) msgid "Favorites Plugin" msgstr "Complemento «Favoritos»" #: C/plugin-favorites.page:14(p) msgid "" "With Favorites you mark objects, for example files, for quicker " "access. It is a sort of shelf on which you can store objects in Kupfer. " "Objects marked as favorites will also be ranked higher and are adorned with " "a star symbol." msgstr "" "Con Favoritos marca objetos, por ejemplo archivos, para un acceso " "más rápido. Es una especie de estantería en la que puede almacenar objetos " "en Kupfer. Los objetos marcados como favoritos se puntuarán más alto y se " "adornarán con una estrella." #: C/plugin-favorites.page:25(p) msgid "Find an object in Kupfer" msgstr "Buscar un objeto en Kupfer" #: C/plugin-favorites.page:30(p) msgid "" "Type Tab and select either the action Add to Favorites " "or Remove from Favorites." msgstr "" "Pulse Tab y elija la acción Añadir a favoritos o " "Quitar de favoritos." #: C/plugin-favorites.page:39(p) msgid "" "If you favorite an object, you can access it in more places. Not only in the " "\"Favorites\" subcatalog, but also as the indirect (secondary) object for " "some actions. For example:" msgstr "" "Si convierte un objeto en favorito, puede acceder a él en más lugares. No " "sólo en el subcatálogo «Favoritos», también como objeto indirecto " "(secundario) para algunas acciones. Por ejemplo:" #: C/plugin-favorites.page:45(p) msgid "Command-lines from favorites are quick to access." msgstr "Las líneas de comandos de los favoritos permiten un acceso rápido." #: C/plugin-favorites.page:46(p) msgid "" "When scaling images with the Scale... action from the Image " "Tools plugin. This action needs a size description as the third " "object, like \"1024\" or \"1200x800\". If you often scale to the same size, " "say \"1200x800\", add this to favorites, and it will always appear as a " "suggestion for the action." msgstr "" "Cuando escala imágenes con la acción Escalar... del complemento " "Herramientas de imagen. Esta acción necesita una descripción como " "tercer objeto, similar a «1024» o «1200x800». Si habitualmente escala al " "mismo tamaño, indique «1200x800», añádalo a favoritos, y aparecerá siempre " "como una sugerencia para la acción." #: C/plugin-favorites.page:54(p) msgid "" "Actions needing an email address as the indirect object will pick up email " "addresses from favorites as well as well." msgstr "" "Las acciones que necesiten una dirección de correo-e como objeto indirecto, " "cogerán las direcciones de correo-e de los favoritos." #: C/plugin-calculator.page:7(desc) msgid "Using the calculator plugin." msgstr "Usar el complemento «Calculadora»." #: C/plugin-calculator.page:10(app) msgid "Calculator" msgstr "Calculadora" #: C/plugin-calculator.page:13(title) msgid "Calculator Plugin" msgstr "Complemento «Calculadora»" #: C/plugin-calculator.page:14(p) msgid "" "The calculator plugin lets you calculate expressions quickly. It can " "evaluate expressions entered as text starting with \"=\". Entering = from " "command mode will start text mode directly with = prefixed for quick access." msgstr "" "El complemento «Calculadora» le permite calcular expresiones rápidamente. " "Puede evaluar expresiones introducidas como texto que comiencen por «=». Si " "introduce «=» en el modo comando se iniciará directamente el modo texto con " "el prefijo «=» para un acceso rápido." #: C/plugin-calculator.page:23(p) msgid "Activate Kupfer and type =" msgstr "Active Kupfer y escriba =." #: C/plugin-calculator.page:26(p) msgid "" "Type in a mathematical expression using +,-,/,* (and ** for exponentiation)" msgstr "" "Escriba una operación matemática usando +,-,/,* (y ** para potencias)." #: C/plugin-calculator.page:30(p) msgid "Press Return to get the result." msgstr "Pulse Intro para obtener el resultado." #: C/plugin-calculator.page:38(p) msgid "" "The Calculator uses python's math and complex math modules, and parses " "expressions as Python expressions. You may use common mathematical " "functions, such as sqrt, sin, exp and " "log; the command =help will show a list of all defined " "functions and constants." msgstr "" "El complemento «Calculadora» usa módulos matemáticos de python y complejos, " "y analiza expresiones como expresiones de Python. Puede usar funciones " "matemáticas comunes, como sqrt, sin, exp y " "log»; el comando =help mostrará una lista de todas las " "funciones y constantes definidas." #: C/plugin-calculator.page:47(p) msgid "" "Notice that the power operator in Python is double stars, for example " "=3**3 will evaluate to 27." msgstr "" "Tenga en cuenta que el operador exponencial en Python son dos asteriscos, " "por ejemplo =3**3 se evaluará como 27." #: C/plugin-calculator.page:53(p) msgid "To calculate trig functions for angles, convert to radians first:" msgstr "" "Para calcular funciones trigonométricas para ángulos, convierta primero a " "radianes:" #: C/plugin-calculator.page:56(code) #, no-wrap msgid "sin(radians(30)) -> 0.5" msgstr "sin(radians(30)) -> 0.5" #: C/plugin-calculator.page:59(p) msgid "" "The last result is stored as the name _ (an underscore, just like in the " "Python console)." msgstr "" "El último resultado se guarda como el nombre «_» (guión bajo, igual que en " "la consola de Python)." #: C/plugin-calculator.page:65(p) #| msgid "" #| "The Calculator lets you also calculate expression without \"=\" on the " #| "beginning as long it have inside one of operators: +, -, *, /, ^, |, , ~." msgid "" "The Calculator lets you also calculate expression without \"=\" on the " "beginning as long it have inside one of operators: +, -, *, /, ^, |, &, " "~." msgstr "" "La Calculadora también le permite calcular expresiones sin «=» al principio " "siempre y cuando tengan dentro uno de los siguientes operadores: +, -, *, /, " "^, |, &, ~." #: C/plugin-applications.page:7(desc) msgid "Using the applications plugin." msgstr "Usar el complemento «Aplicaciones»." #: C/plugin-applications.page:10(app) msgid "Applications" msgstr "Aplicaciones" #: C/plugin-applications.page:13(title) msgid "Applications Plugin" msgstr "Complemento «Aplicaciones»" #: C/plugin-applications.page:14(p) msgid "Applications provides all installed programs." msgstr "Aplicaciones proporciona todos los programas instalados." #: C/plugin-applications.page:21(title) msgid "Launching an application" msgstr "Lanzar una aplicación" #: C/plugin-applications.page:23(p) msgid "Activate Kupfer and type an abbreviation of the application name" msgstr "Active Kupfer y escriba la abreviatura del nombre de una aplicación." #: C/plugin-applications.page:28(p) msgid "Press Return to launch the application." msgstr "Pulse Intro para lanzar la aplicación." #: C/plugin-applications.page:34(title) msgid "Opening a file with a specific application" msgstr "Abrir un archivo con una aplicación específica" #: C/plugin-applications.page:36(p) msgid "Select a file in Kupfer" msgstr "Seleccione un archivo en Kupfer" #: C/plugin-applications.page:41(p) msgid "Type Tab and select the action Open With..." msgstr "Pulse Tab y seleccione la acción Abrir con..." #: C/plugin-applications.page:46(p) msgid "" "Type Tab to select the third (indirect object) pane and in it, " "select the application to open the file with." msgstr "" "Pulse Tab para seleccionar el tercer panel (objeto indirecto) y, " "en él, seleccione la aplicación con la que abrir el archivo." #: C/plugin-applications.page:53(p) msgid "" "The action Open opens files and folders with the registered default " "application for that specific file type. This can be configured using the " "action Set Default Application...." msgstr "" "La acción Abrir abre archivos y carpetas con la aplicación " "predeterminada que esté registrada para ese tipo de archivo concreto. Esto " "se puede configurar usando la acción Establecer aplicación " "predeterminada...." #: C/plugin-applications.page:58(p) msgid "" "The file type associations are provided by the desktop environment, and " "modifying them here will modify them on the desktop as well. This may not be " "true when not using GNOME or XFCE." msgstr "" "Las asociaciones de tipos de archivos las proporciona el entorno de " "escritorio, y si las modifica aquí también se modificarán en el escritorio. " "Esto puede no ser cierto cuando no se usa GNOME o XFCE." #: C/plugin-applications.page:64(title) msgid "Selecting default application for a file type or folders" msgstr "" "Seleccionar la aplicación predeterminada para un tipo de archivo o carpetas" #: C/plugin-applications.page:66(p) msgid "Select a file or folder in Kupfer" msgstr "Seleccione un archivo o una carpeta en Kupfer" #: C/plugin-applications.page:71(p) msgid "" "Type Tab and select the action Set Default Application..." msgstr "" "Pulse Tab y seleccione la acción Establecer aplicación " "predeterminada..." #: C/plugin-applications.page:77(p) msgid "" "Type Tab to select the third (indirect object) pane and in it, " "select the application to always open the file type with." msgstr "" "Pulse Tab para seleccionar el tercer panel (objeto indirecto) y, " "en él, seleccione la aplicación con la que abrir siempre el tipo de archivo." #: C/plugin-applications.page:85(title) msgid "Configuration" msgstr "Configuración" #: C/plugin-applications.page:86(p) msgid "" "The configuration option Applications for Desktop Environment in " "the plugin's information pane in Kupfer Preferences determines " "how Kupfer should act with regard to the desktop environment " "configuration—certain applications request not to be shown depending on " "which desktop environment is used. By default, it behaves like GNOME." msgstr "" "La opción de configuración Aplicaciones para el entorno de escritorio en el panel de información del complemento en las Preferencias de " "Kupfer determina cómo debería actuar Kupfer respecto a la " "configuración del entorno de escritorio; algunas solicitudes de aplicaciones " "pueden no mostrarse, dependiendo de qué entorno de escritorio se use. De " "manera predeterminada, se comporta como GNOME." #: C/moreusage.page:7(desc) msgid "More advanced usage information." msgstr "Más información de uso avanzado." #: C/moreusage.page:10(title) msgid "Using Kupfer in Depth" msgstr "Usar Kupfer en profundidad" #: C/moreusage.page:13(title) msgid "Adding Applications and Scripts" msgstr "Añadir aplicaciones y scripts" #: C/moreusage.page:14(p) msgid "" "Kupfer will show all applications that are configured visible in " "your menu editor." msgstr "" "Kupfer mostrará todas las aplicaciones que están configuradas " "como visibles en su editor del menú." #: C/moreusage.page:18(p) msgid "" "If you want to add an application manually, you can create a new ." "desktop file and place it in one of the standard directories for " "applications, for example ~/.local/share/applications, where " "Kupfer will find it." msgstr "" "Si quiere añadir una aplicación manualmente, puede crear un archivo ." "desktop nuevo y colocarlo en uno de las carpetas estándar para " "aplicaciones, por ejemplo ~/.local/share/applications, donde " "Kupfer lo encontrará." #: C/moreusage.page:24(p) msgid "" "If you have a collection of scripts that you want to call from Kupfer, you can add the scripts folder as a catalog directory to Kupfer in the preferences. Scripts that you add to Kupfer's catalog " "this way can be run directly or in the terminal as long as they are " "executable." msgstr "" "Si tiene una colección de scripts a los que quiere llamar desde Kupfer, puede añadir la carpeta de los scripts como un catálogo de carpeta a " "Kupfer en las preferencias. Los scripts que añada al catálogo " "Kupfer de esta manera se puede ejecutar directamente en la " "terminal, siempre y cuando sean ejecutables." #: C/moreusage.page:31(p) msgid "" "You can also save command-lines by using the action Add to Favorites." msgstr "" "También puede guardar líneas de comandos usando la acción Añadir a " "favoritos." #: C/moreusage.page:38(title) msgid "Opening Files and Folders" msgstr "Abrir archivos y carpetas" #: C/moreusage.page:39(p) msgid "" "Using the action Open, files and folders are opened in their " "preferred application. The application associations can be changed, see " "." msgstr "" "Al usar la acción Abrir, los archivos y carpetas se abren con su " "aplicación preferida. Las asociaciones de archivos se pueden cambiar, " "consulte la ." #: C/moreusage.page:47(title) msgid "The Comma Trick" msgstr "El truco de la coma" #: C/moreusage.page:48(p) msgid "" "The comma trick allows the user to use actions on many objects at the same " "time." msgstr "" "El «truco de la coma» permite al usuario utilizar acciones en varios objetos " "a la vez." #: C/moreusage.page:52(p) msgid "" "Simply press comma , when an object is selected. The object is " "put on a \"stack\", and you can find yet another file or object, press comma " "to put it on the stack. When you subsequently invoke an action, the action " "is carried out on all of the objects at the same time." msgstr "" "Simplemente pulse , (coma) cuando un objeto esté seleccionado. El " "objeto se pone en una «pila», y puede encontrar otro archivo u objeto y " "pulsar la coma para añadirlo a la pila. Cuando posteriormente invoca una " "acción, la acción se realiza en todos los objetos al mismo tiempo." #: C/moreusage.page:58(p) msgid "" "Some actions are only \"multiplied\" when used with many objects, other are " "smarter than that:" msgstr "" "Algunas acciones sólo se «multiplican» cuando se utilizan con muchos " "objetos, otras son más inteligentes que eso:" #: C/moreusage.page:61(p) msgid "" "Selecting many files and using the Create Archive action, all files will be " "packed into the same archive." msgstr "" "Al seleccionar varios archivos usando la acción «Crear archivador», todos " "los archivos se empaquetarán en el mismo archivo." #: C/moreusage.page:63(p) msgid "" "If you select multiple contacts and use a Send Email action, it creates one " "email directed at all the contacts." msgstr "" "Si selecciona varios contactos y usa la acción «Enviar correo-e», se crea un " "único correo-e dirigido a todos los contactos." #: C/moreusage.page:65(p) msgid "" "If you select multiple subcatalogs (For example Firefox Bookmarks and " "Epiphany Bookmarks) and use Search Contents.., you get a subcatalog search " "restricted to the objects of those two catalogs! You can even bind a trigger " "to this command(!)" msgstr "" "Si selecciona varios catálogos (por ejemplo, «Marcadores de Firefox» y " "«Marcadores de Epiphany») y usa «Buscar contenido...», obtiene una búsqueda " "de subcatálogo restringida a los objetos de estos dos catálogos. También " "puede asociar un disparador a este comando." #: C/moreusage.page:71(p) msgid "" "The comma trick is directly taken from Quicksilver (the " "example given in the external article should work identically in Kupfer)." msgstr "" "El «truco de la coma» se ha tomado directamente de Quicksilver (el " "ejemplo dado en el artículo interno debería funcionar idénticamente en " "Kupfer)." #: C/moreusage.page:80(title) msgid "Grab Current Selection" msgstr "Capturar la selección actual" #: C/moreusage.page:81(p) msgid "" "To use the current selected text, from any application, with Kupfer, you can configure a global keyboard shortcut for the action Show " "with Selection in Kupfer Preferences." msgstr "" "Para usar el texto seleccionado actualmente desde cualquier aplicación con " "Kupfer, puede configurar un atajo de teclado global para la " "acción Mostrar con selección en las Preferencias de Kupfer." #: C/moreusage.page:85(p) msgid "" "If configured, pressing the global keyboard shortcut will summon " "Kupfer with the current selection as the focused object." msgstr "" "Si está configurado, al pulsar el atajo de teclado global invocará a " "Kupfer con la selección actual como el objeto con el foco." #: C/moreusage.page:90(p) msgid "See " msgstr "Consulte la " #: C/moreusage.page:94(title) msgid "Command-line Connection" msgstr "Conexión con la línea de comandos" #: C/moreusage.page:95(p) msgid "" "The command kupfer on the command-line will focus Kupfer if it's already running, otherwise it will start it." msgstr "" "El comando kupfer en la línea de comandos dará el foco a " "Kupfer si ya está en ejecución, y si no lo está lo iniciará." #: C/moreusage.page:99(p) msgid "" "The command kupfer can be used to send files or text from the " "command-line to Kupfer. For example, if you are using the shell " "in a directory where you have a file called \"report.pdf\", you can focus " "this file in Kupfer by running kupfer report.pdf." msgstr "" "El comando kupfer se puede usar para enviar archivos o texto " "desde la línea de comandos a Kupfer. Por ejemplo, si está usando " "la terminal en una carpeta donde tiene un archivo llamado «informe.pdf» " "puede dar el foco a este archivo en Kupfer ejecutando kupfer " "report.pdf." #: C/moreusage.page:107(p) msgid "" "You can also send text if you pipe the output of a command into kupfer." msgstr "" "También puede enviar texto si redirige la salida de un comando hacia " "kupfer." #: C/moreusage.page:114(title) msgid "Managing Context and Current Selection" msgstr "Gestionar el contexto y la selección actual" #: C/moreusage.page:115(p) msgid "" "If you find the object you want to use, then invoke an action, Kupfer goes away to perform the action (for example start a program or play a " "song). When you come back to Kupfer, it will still keep the same " "object and action selected. Some actions make sense to be repeated (like " "skipping to the next song) and it can be useful to perform different actions " "on the same object." msgstr "" "Si encuentra el objeto que quiere usar, y ejecuta una acción, Kupfer realizará la acción (por ejemplo, ejecutar un programa o reproducir una " "canción). Cuando regrese a Kupfer, todavía mantendrá seleccionado " "el mismo objeto y la misma acción. Algunas acciones tienden a repetirse " "(como omitir la siguiente canción) y puede ser útil realizar diferentes " "acciones sobre un mismo objeto." #: C/moreusage.page:123(p) msgid "" "However, you always have the top level catalog reachable when you \"come back" "\" to Kupfer -- say you went into the subcatalog \"Albums\" to " "browse your albums only; you select an album to play, and play it. You come " "back with the album selected -- but your next search will still go over the " "top level catalog, not just albums." msgstr "" "Sin embargo, siempre tiene el catálogo de nivel superior disponible cuando " "«regresa» a Kupfer: por ejemplo, va al subcatálogo «Álbumes» para " "explorar sólo sus álbumes; selecciona un álbum que reproducir y lo " "reproduce. Vuelve con el álbum seleccionado; pero su siguiente búsqueda " "volverá a ser sobre el nivel superior del catálogo, no sólo sobre los " "álbumes." #: C/moreusage.page:130(p) msgid "" "How to come back into the subcatalog you were in? You do that by simply " "browsing, not searching the first thing you do when you focus Kupfer again. A quick way is to press down-arrow or space to open the browse " "window; think of it as saying \"I want to stay in this subfolder\". With the " "browse window open, your next query will search the current subcatalog." msgstr "" "¿Cómo volver al subcatálogo en el que estaba? Puede hacer simplemente " "navegando, sin buscar la primera cosa que hizo cuando abrió Kupfer otra vez. Una forma rápida es pulsar ↓ o espacio para abrir la ventana " "del navegador; piense en esto diciendo «quiero estar en esta subcarpeta». " "Mientras se abre la ventana del navegador, su siguiente consulta buscará el " "subcatálogo actual." #: C/moreusage.page:137(p) msgid "" "This way you can work both ways -- you can quickly drill down into folders " "to find a file, and when you come back for the next action with Kupfer you can either summon any normal toplevel object (just start typing), " "or stay around where you were, deep in that folder (press space, then type a " "query)." msgstr "" "De este modo, puede trabajar de ambas maneras; puede descender rápidamente " "por las carpetas para encontrar un archivo, y cuando vuelve para la " "siguiente acción con Kupfer también puede llamar a un objeto " "normal del nivel superior (simplemente empiece a escribir), o mantenerse " "donde está, en esa carpeta (pulse espacio y escriba una consulta)." #: C/moreusage.page:146(title) msgid "Saving Commands as Files" msgstr "Guardar comandos como archivos" #: C/moreusage.page:147(p) msgid "" "You can use keyboard shortcut for Compose Command (by default it is " "CtrlReturn) to create a command " "object out of the currently focused command in Kupfer. This object can be " "saved as a runnable file if you use the Save As... action. The " "resulting file will can be executed when opened from the file manager (it " "requires that Kupfer is already running)." msgstr "" "Puede usar un atajo de teclado para Editar comando (el " "predeterminado es CtrlIntro) para " "crear un objeto de comando fuera del comando que actualmente tiene el foco " "en Kupfer. Este objeto se puede guardar como un archivo ejecutable si usa la " "acción Guardar como.... El archivo resultante se puede ejecutar " "cuando se abra con el gestor de archivos (necesita que Kupfer esté en " "ejecución)." #: C/managing-plugins.page:7(desc) msgid "Using plugins with Kupfer." msgstr "Usar complementos con Kupfer." #: C/managing-plugins.page:10(title) msgid "How to Configure Plugins" msgstr "Cómo configurar los complementos" #: C/managing-plugins.page:12(p) msgid "" "Functionality in Kupfer is organized by extentsion modules called \"plugins" "\". Each plugin provides additional functionality, for example integration " "with an external application." msgstr "" "La funcionalidad en Kupfer está organizada por módulos de extensiones " "llamados «complementos». Cada complemento proporciona funcionalidad " "adicional, por ejemplo, integración con una aplicación externa." #: C/managing-plugins.page:19(title) msgid "Configuring Plugins" msgstr "Configurar complementos" #: C/managing-plugins.page:21(title) msgid "Open Kupfer Preferences to the Plugins tab" msgstr "" "Abra las Preferencias de Kupfer y vaya a la pestaña " "Complementos." #: C/managing-plugins.page:23(p) msgid "Use one of the following methods:" msgstr "Use uno de los siguientes métodos:" #: C/managing-plugins.page:25(p) msgid "" "Click the Kupfer icon in the notification area and select the item " "Preferences" msgstr "" "Pulse en el icono de Kupfer en el área de notificación y seleccione el " "elemento Preferencias." #: C/managing-plugins.page:25(item) msgid "." msgstr "." #: C/managing-plugins.page:29(p) msgid "" "Search for the object Kupfer Preferences in Kupfer itself. Press " "Return to open it." msgstr "" "Busque el objetoPreferencias de Kupfer en el propio Kupfer. Pulse " "Intro para abrirlo." #: C/managing-plugins.page:33(p) msgid "Use the keyboard shortcut Ctrl;" msgstr "Use el atajo de teclado Ctrl;" #: C/managing-plugins.page:39(p) msgid "Select the tab Plugins" msgstr "Seleccione la solapa Complementos." #: C/managing-plugins.page:45(p) msgid "" "Select plugins in the list to read about them, and tick the box next to its " "name to activate the plugin, or untick to deactivate." msgstr "" "Seleccione complementos en la lista para leer sobre ellos, y marque la " "casilla junto al nombre para activar el complemento, o desmárquela para " "desactivarlo." #: C/managing-plugins.page:49(p) msgid "" "If the plugin has any configurable parameters, they will be visible below " "the plugin information." msgstr "" "Si el complemento tiene parámetros configurables, estarán visibles debajo de " "la información del complemento." #: C/managing-plugins.page:53(p) msgid "" "The plugin Kupfer Plugins allows fast access to each plugin's " "information page as well as the action \"Show Source Code\" which reveals " "the implementation." msgstr "" "El complemento Complementos de Kupfer permite un acceso rápido a " "la información de cada complemento así como la opción «Mostrar código " "fuente», que muestra su implementación." #: C/managing-plugins.page:59(title) msgid "If a Plugin can not be Activated" msgstr "Si no se puede activar un complemento" #: C/managing-plugins.page:60(p) msgid "" "If a plugin fails to activate because it requires a software module that is " "not available, its plugin information will display a message like this:" msgstr "" "Si un complemento falla al activarlo porque requiere un módulo de software " "que no está disponible, la información del complemento mostrará un mensaje " "como este:" #: C/managing-plugins.page:65(em) msgid "Plugin could not be read due to an error:" msgstr "No se pudo leer el complemento debido a un error:" #: C/managing-plugins.page:66(em) msgid "Python module 'gdata' is needed" msgstr "Se necesita el módulo de Python «gdata»" #: C/managing-plugins.page:67(p) msgid "" "This means that you need to install a needed python module from your " "distribution—and possibly the plugin documentation can tell you how." msgstr "" "Esto significa que debe instalar el módulo de Python requerido para su " "distribución; y posiblemente la documentación del complemento le diga cómo " "hacerlo." #: C/managing-plugins.page:72(p) msgid "" "The plugin may also unexpectedly fail to load, and display a different error " "message. It may then be a program error in either the plugin or Kupfer." msgstr "" "El complemento también puede fallar inesperadamente al cargarse, y mostrar " "un mensaje de error diferente. Puede ser un error de programación, tanto en " "el complemento como en Kupfer." #: C/managing-plugins.page:79(title) msgid "Installing more Plugins" msgstr "Instalar más complementos" #: C/managing-plugins.page:80(p) msgid "" "You can install custom plugins into the folder ~/.local/share/kupfer/" "plugins. Each plugin is either a single .py file or a " "python package (a folder directly containing a file called __init__." "py). Plugins in the package format can include icon files. Python " "packages can even be installed as .zip files." msgstr "" "Puede instalar complementos personalizados en la carpeta ~/.local/" "share/kupfer/plugins. Cada complemento puede ser un único archivo " ".py o un paquete de Python (una carpeta que directamente " "contiene un archivo llamado __init__.py). Los complementos en " "forma de paquete pueden incluir archivos de iconos. Los paquetes de Python " "también se pueden instalar como archivos .zip." #: C/managing-plugins.page:88(p) msgid "" "Caution: Treat a plugin as a computer program. Do not install " "untrusted plugins." msgstr "" "Precaución: considere los complementos como programas. No instale " "complementos que no sean de confianza." #: C/managing-plugins.page:95(title) msgid "Creating Plugins" msgstr "Crear complementos" #: C/managing-plugins.page:96(p) msgid "" "Documentation for plugin creators is available in the file " "Documentation/Manual.rst in the source distribution on the " "webpage at Kupfer " "Manual. An easy way to start is to copy an existing plugin and " "experimenting with it." msgstr "" "La documentación para creadores de complementos está disponible en el " "archivo Documentation/Manual.rst en la distribución fuente o en " "la página web Manual de " "Kupfer. Una manera sencilla de empezar es copiar un complemento " "existente y experimentar con él." #: C/managing-plugins.page:107(title) msgid "The Catalog Tab in Preferences" msgstr "La pestaña Catálogo en «Preferencias»" #: C/managing-plugins.page:108(p) msgid "" "Each plugin can export a number of sources which contain objects. Normally, " "all these objects are directly accessible from a top-level search. Some " "plugins export so specialized or so many objects that their catalogs should " "better not have their objects exported to the top level. To reach those " "objects, you have to first find the catalog by name, then enter the catalog " "using the action Search Contents." msgstr "" "Cada complemento puede exportar un número de fuentes que contienen objetos. " "Normalmente, todos estos objetos son accesibles directamente desde un nivel " "de búsqueda superior. Algunos complementos exportan muchos objetos o muy " "especializados que sus catálogos no debería exportar al nivel superior. Para " "alcanzar esos objetos, primero debe encontrar el catálogo por nombre, y " "entrar en el catálogo usando la acción Buscar contenido." #: C/managing-plugins.page:118(p) msgid "" "In the tab Catalog in Kupfer Preferences, a ticked box " "next to each source means that its objects are exported. An unticked box " "means that its contents are hidden from the top level." msgstr "" "En la pestaña Catálogo en las Preferencias de Kupfer, " "una casilla marcada junto a cada fuente indica que ese objeto está " "exportado. Una casilla desmarcada indica que su contenido está oculto desde " "el nivel superior." #: C/managing-plugins.page:123(p) msgid "" "Note: Kupfer may become slow if large enough subcatalogs are " "exported to the top level." msgstr "" "Nota: Kupfer puede ralentizarse si se exportar muchos catálogos " "grandes al nivel superior." #: C/license.page:7(desc) msgid "You can copy, modify and share Kupfer." msgstr "Puede copiar, modificar y compartir Kupfer." #: C/license.page:10(title) msgid "License" msgstr "Licencia" #: C/license.page:12(p) msgid "" "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." msgstr "" "Este programa es software libre; puede redistribuirlo y/o modificarlo bajo " "los términos de la Licencia Pública General GNU tal como se publica " "por la Free Software Foundation; ya sea la versión 3 de la Licencia, o (a su " "elección) cualquier versión posterior." #: C/license.page:18(p) msgid "" "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." msgstr "" "Este programa se distribuye con la esperanza de que le sea útil, pero SIN " "NINGUNA GARANTÍA; sin incluso la garantía implícita de MERCANTILIDAD o " "IDONEIDAD PARA UN PROPÓSITO PARTICULAR. Para obtener más detalles consulte " "la Licencia Pública General GNU." #: C/license.page:24(p) msgid "" "You should have received a copy of the GNU General Public License along with " "this program. If not, see gnu." "org/licenses." msgstr "" "Debería haber recibido una copia de la Licencia Pública General de GNU junto " "con este programa. Si no es así, consulte gnu.org/licenses." #: C/license.page:30(p) msgid "" "This documentation is licensed under a Creative Commons Attribution-Share Alike 3.0 " "Unported License." msgstr "" "Este trabajo está licenciado bajo una Licencia Creative Commons atribución - compartir " "igual 3.0 sin soporte." #: C/license.page:36(p) msgid "" "As a special exception, the copyright holders give you permission to copy, " "modify, and distribute the example code contained in this document under the " "terms of your choosing, without restriction." msgstr "" "Como excepción especial, los poseedores de los derechos de autor le dan " "permiso para copiar, modificar y distribuir el ejemplo de código contenido " "en este documento bajo los términos que usted elija, sin restricción." #: C/keyboard.page:7(desc) msgid "Complete keyboard shortcuts reference." msgstr "Referencia completa de atajos de teclado." #: C/keyboard.page:10(title) msgid "Command Keys and Accelerator Keys" msgstr "Teclas de comandos y teclas aceleradoras" #: C/keyboard.page:13(title) C/generalusage.page:12(title) msgid "Keyboard Interface" msgstr "Interfaz de teclado" #: C/keyboard.page:14(p) msgid "In command mode, the following keystrokes have special meanings:" msgstr "" "En modo comando, las siguientes pulsaciones del teclado tienen un " "significado especial:" #: C/keyboard.page:19(p) C/generalusage.page:34(p) msgid " or Space" msgstr " o Espacio" #: C/keyboard.page:20(p) C/generalusage.page:35(p) msgid "Go to the next match" msgstr "Ir a la siguiente coincidencia" #: C/keyboard.page:23(p) C/generalusage.page:38(p) msgid " or ShiftSpace" msgstr " o MayúsEspacio" #: C/keyboard.page:26(p) C/generalusage.page:41(p) msgid "Go to the previous match" msgstr "Ir a la coincidencia anterior" #: C/keyboard.page:29(p) C/generalusage.page:44(p) msgid " or /" msgstr " o /" #: C/keyboard.page:30(p) C/generalusage.page:45(p) msgid "Descend into an object with content" msgstr "Descender a un objeto con contenido" #: C/keyboard.page:33(key) C/generalusage.page:48(key) msgid "Backspace" msgstr "Retroceso" #: C/keyboard.page:34(p) C/generalusage.page:49(p) msgid "Erase a character from the query. If the query is empty, go up a level" msgstr "" "Quitar un carácter de la consulta. Si la consulta está vacía, subir un nivel" #: C/keyboard.page:39(key) C/keyboard.page:93(key) C/generalusage.page:54(key) msgid "." msgstr "." #: C/keyboard.page:40(p) C/generalusage.page:55(p) msgid "Activate free-text mode" msgstr "Activar el modo de texto libre" #: C/keyboard.page:43(key) C/keyboard.page:97(key) C/generalusage.page:58(key) msgid "," msgstr "," #: C/keyboard.page:44(p) C/generalusage.page:59(p) msgid "Put selected object on the stack (\"Comma Trick\")" msgstr "Poner un objeto seleccionado en la pila («truco de la coma»)" #: C/keyboard.page:47(p) msgid "Quick access keys:" msgstr "Teclas de acceso rápido:" #: C/keyboard.page:53(key) msgid "=" msgstr "=" #: C/keyboard.page:55(p) msgid "" "Activate free-text mode with = prefix (for )" msgstr "" "Activar el modo de texto libre con el prefijo «=» (para la )" #: C/keyboard.page:61(key) msgid "/" msgstr "/" #: C/keyboard.page:63(p) msgid "" "Activate free-text mode (when nothing is selected) with / " "prefix (to input a rooted path)" msgstr "" "Activar el modo de texto libre (cuando no hay nada seleccionado) con el " "prefijo / (para indicar una ruta desde la raíz)" #: C/keyboard.page:68(p) C/generalusage.page:62(p) msgid "Additionally:" msgstr "Además:" #: C/keyboard.page:72(p) C/generalusage.page:66(p) msgid "" "Return activates the current selection: the command is executed." msgstr "Intro activa la selección actual: el comando se ejecuta." #: C/keyboard.page:74(p) C/generalusage.page:68(p) msgid "Escape clears the current selection." msgstr "Esc limpia la selección actual." #: C/keyboard.page:75(p) C/generalusage.page:69(p) msgid "Tab switches between the object and the action pane." msgstr "Tab cambia entre el objeto y el panel de acciones." #: C/keyboard.page:77(p) msgid "" "The meaning of the keys Space, ., ,, /" " and = can not be changed, but you can deactivate their " "special meaning with the checkbox Use single keystroke commands " "in Kupfer Preferences." msgstr "" "El significado de las teclas Espacio, ., ,, " "/ y = no se puede cambiar, pero puede desactivar su " "significado especial con la casilla Usar comandos de una sola tecla en las Preferencias de Kupfer." #: C/keyboard.page:86(title) msgid "Kupfer's Keyboard Shortcuts" msgstr "Atajos de teclado de Kupfer" #: C/keyboard.page:87(p) msgid "" "These keyboard shortcuts are used in Kupfer's interface. They " "have the following meanings and default shortcuts:" msgstr "" "Estos atajos de teclado se usan en la interfaz de Kupfer. Tienen " "el significado y los atajos siguientes:" #: C/keyboard.page:93(key) C/keyboard.page:97(key) C/keyboard.page:101(key) #: C/keyboard.page:105(key) C/keyboard.page:113(key) C/keyboard.page:117(key) #: C/keyboard.page:121(key) C/keyboard.page:125(key) C/keyboard.page:129(key) #: C/keyboard.page:174(key) msgid "Ctrl" msgstr "Ctrl" #: C/keyboard.page:94(p) msgid "Toggle text mode" msgstr "Alternar modo de texto" #: C/keyboard.page:98(p) msgid "The comma trick" msgstr "El «truco de la coma»" #: C/keyboard.page:101(key) msgid ";" msgstr ";" #: C/keyboard.page:102(p) msgid "Show preferences window" msgstr "Mostrar la ventana de preferencias" #: C/keyboard.page:105(key) msgid "R" msgstr "R" #: C/keyboard.page:106(p) msgid "Reset all" msgstr "Restablecer todo" #: C/keyboard.page:109(key) msgid "Alt" msgstr "Alt" #: C/keyboard.page:109(key) msgid "A" msgstr "A" #: C/keyboard.page:110(p) msgid "Alternate activate" msgstr "Activación alternativa" #: C/keyboard.page:113(key) msgid "Return" msgstr "Devolver" #: C/keyboard.page:114(p) msgid "Compose command" msgstr "Componer comando" #: C/keyboard.page:117(key) msgid "S" msgstr "S" #: C/keyboard.page:118(p) msgid "Switch to first pane" msgstr "Cambiar al primer panel" #: C/keyboard.page:121(key) msgid "Q" msgstr "Q" #: C/keyboard.page:122(p) msgid "Select 'Quit'" msgstr "Seleccionar «Salir»" #: C/keyboard.page:125(key) msgid "G" msgstr "G" #: C/keyboard.page:126(p) msgid "Select 'Selected File'" msgstr "Seleccionar «Archivo seleccionado»" #: C/keyboard.page:129(key) msgid "T" msgstr "T" #: C/keyboard.page:130(p) msgid "Select 'Selected Text'" msgstr "Seleccionar «Texto seleccionado»" #: C/keyboard.page:133(key) msgid "F1" msgstr "F1" #: C/keyboard.page:134(p) msgid "Show Help" msgstr "Mostrar ayuda" #: C/keyboard.page:139(title) msgid "How to configure a keyboard shortcut" msgstr "Cómo configurar un atajo de teclado" #: C/keyboard.page:141(p) C/keyboard.page:185(p) msgid "Open Kupfer Preferences and go to the Keyboard tab." msgstr "" "Abra las Preferencias de Kupfer y vaya a la pestaña Teclado." #: C/keyboard.page:147(p) msgid "" "Double-click the shorcut's row under Browser Keyboard Shortcuts." msgstr "" "Doble pulsación en la fila del atajo, en Atajos de teclado del " "examinador." #: C/keyboard.page:153(p) msgid "" "Using the window that appears, press modifier keys and a letter or number " "key to set a shortcut. An example is pressing and holding Ctrl " "and then pressing and releasing T to bind CtrlT." msgstr "" "Usando la ventana que aparece, pulse las teclas modificadoras y un número o " "una letra para establecer un atajo. Un ejemplo es pulsar y mantener " "Ctrl y entonces pulsar y soltar T para asociar " "CtrlT." #: C/keyboard.page:164(title) msgid "Global Keyboard Shortcuts" msgstr "Atajos de teclado globales" #: C/keyboard.page:165(p) msgid "" "Kupfer always listens to global shortcuts, even if it is not " "currently in the foreground." msgstr "" "Kupfer siempre escucha los atajos globales, aunque actualmente no " "esté en primer plano." #: C/keyboard.page:169(p) msgid "They have the following meanings and default shortcuts:" msgstr "" "Tienen el siguiente significado y los siguientes atajos predeterminados:" #: C/keyboard.page:174(key) msgid "Space" msgstr "Espacio" #: C/keyboard.page:175(p) msgid "Show/hide Kupfer" msgstr "Mostrar/ocultar Kupfer" #: C/keyboard.page:178(p) msgid "(not configured by default)" msgstr "(no configurado de manera predeterminada)" #: C/keyboard.page:179(p) msgid "Show Kupfer with 'Selection' object focused" msgstr "Mostrar Kupfer con el foco en el objeto «Selección»." #: C/keyboard.page:183(title) msgid "How to configure a global keyboard shortcut" msgstr "Cómo configurar un atajo de teclado global" #: C/keyboard.page:191(p) msgid "" "Double-click the shorcut's row under Global Keyboard Shortcuts." msgstr "" "Doble pulsación en la fila del atajo, en Atajos de teclado globales." #: C/keyboard.page:197(p) msgid "" "Using the window that appears, press modifier keys and a letter or number " "key to set a global shortcut. An example is pressing and holding Super and then pressing and releasing Space to bind " "SuperSpace." msgstr "" "Usando la ventana que aparece, pulse las teclas modificadoras y un número o " "una letra para establecer un atajo global. Un ejemplo es pulsar y mantener " "Super y entonces pulsar y soltar Espacio para asociar " "SuperEspacio." #: C/keyboard.page:206(p) msgid "" "Since these keyboard shortcuts are global, they can be used from any " "application. Select shortcuts with care so that they do not conflict with " "other functions." msgstr "" "Ya que estos atajos de teclado son globales, se puede usar desde cualquier " "aplicación. Seleccione los atajos con cuidado para que no entren en " "conflicto con otras funciones." #: C/keyboard.page:214(p) msgid "" "The plugin Triggers allows to activate actions with global keyboard " "shortcuts. Trigger shortcuts do not appear in Kupfer Preferences." msgstr "" "El complemento Disparadores permite activar acciones con atajos de " "teclado globales. Los atajos del disparador no aparecen en las " "Preferencias de Kupfer." #: C/keyboard.page:220(p) msgid "See for more information." msgstr "" "Consulte la para obtener más información." #: C/introduction.page:7(desc) msgid "Introduction to Kupfer." msgstr "Introducción a Kupfer." #: C/introduction.page:10(title) msgid "Introduction" msgstr "Introducción" #: C/introduction.page:12(p) msgid "" "Kupfer is an interface for quick and convenient access to " "applications and their documents." msgstr "" "Kupfer es una interfaz para acceder rápida y cómodamente a " "aplicaciones y a sus documentos." #: C/introduction.page:16(p) msgid "" "The most typical use is to find a specific application and launch it. We " "have tried to make Kupfer easy to extend with plugins so that " "this quick-access paradigm can be extended to many more objects than just " "applications." msgstr "" "El uso más común es para encontrar un aplicación específica y lanzarla. Se " "ha intentado que Kupfer sea fácil de extender con complementos, " "por lo que este paradigma de acceso rápido se puede extender a muchos más " "objetos que sólo aplicaciones." #: C/introduction.page:22(p) msgid "" "We hope that using Kupfer feels both very fun and " "different." msgstr "" "Se espera que usar Kupfer seamuy divertido y " "diferente." #: C/introduction.page:26(p) msgid "" "For up-to-date information about Kupfer, visit its homepage." msgstr "" "Para obtener información actualizada sobre Kupfer visite su página web." #: C/index.page:9(name) msgid "Ulrik Sverdrup" msgstr "Ulrik Sverdrup" #: C/index.page:10(email) msgid "ulrik.sverdrup@gmail.com" msgstr "ulrik.sverdrup@gmail.com" #: C/index.page:13(year) msgid "2009" msgstr "2009" #: C/index.page:14(name) msgid "Kupfer Development Team" msgstr "Equipo de desarrollo de Kupfer" #: C/index.page:17(license) msgid "Creative Commons Share Alike 3.0" msgstr "Creative Commons Share Alike 3.0" #: C/index.page:21(title) msgid "Kupfer Manual" msgstr "Manual de Kupfer" #: C/index.page:24(title) msgid "Using Kupfer" msgstr "Usar Kupfer" #: C/index.page:27(title) msgid "About Specific Plugins" msgstr "Acerca de los complementos específicos" #: C/generalusage.page:7(desc) msgid "How to start using Kupfer." msgstr "Cómo empezar a usar Kupfer." #: C/generalusage.page:14(p) msgid "" "Kupfer is to the largest part a keyboard-managed interface to " "applications and documents." msgstr "" "Kupfer es la parte más grande de una interfaz gestionada por " "teclado de aplicaciones y documentos." #: C/generalusage.page:18(p) msgid "" "Kupfer's default mode is the command mode: If you type a query, kupfer will " "search for a match in its catalog." msgstr "" "El modo predeterminado de Kupfer es en modo comandos: si escribe una " "consulta, Kupfer buscará una coincidencia en su catálogo." #: C/generalusage.page:23(p) msgid "" "The arrow keys allow you to browse query matches quite naturally, going to " "the previous or next match, and going up and down in the subcatalogs." msgstr "" "Las teclas de flechas le permiten examinar las coincidencias de las " "consultas de manera más natural, yendo a la coincidencia anterior o a la " "siguiente, y yendo arriba y abajo en los subcatálogos." #: C/generalusage.page:29(p) msgid "In command mode, some keystrokes have special meanings:" msgstr "" "En modo comando, algunas pulsaciones del teclado tienen un significado " "especial:" #: C/generalusage.page:71(p) msgid "" "By default you show Kupfer using the global keyboard shortcut " "CtrlSpace." msgstr "" "De manera predeterminada, muestre Kupfer usando el atajo de " "teclado global CtrlEspacio." #: C/generalusage.page:74(p) msgid "See for more information." msgstr "Consulte la para obtener más información." #: C/generalusage.page:78(title) msgid "Learning Habits" msgstr "Hábitos de aprendizaje" #: C/generalusage.page:79(p) msgid "" "Kupfer remembers which objects and actions are used the most. " "When beginning to use it, you have to use the arrow keys at times to make it " "precise which object you want to find. After a few uses of that object, " "Kupfer will rank it higher. Objects marked as favorites are also ranked higher." msgstr "" "Kupfer recuerda qué objetos y qué acciones se usan más. Cuando " "empieza a usarlo, a veces tiene que usar las flechas para precisar qué " "objeto quiere encontrar. Después de usar varias veces ese objeto, Kupfer lo " "puntuará más alto. Los objetos marcados como favoritos también se puntúan alto." #: C/generalusage.page:90(title) msgid "The Catalog" msgstr "El catálogo" #: C/generalusage.page:91(p) msgid "" "The Catalog is the collection of objects you can access in Kupfer, such as " "documents and programs." msgstr "" "El catálogo es la colección de objetos a la que puede acceder en Kupfer, " "como documentos y programas." #: C/generalusage.page:96(p) msgid "" "Objects in the catalog that have content, like folders, are marked with an " "arrow. Pressing will enter these objects. Much of the catalog " "is composed of subcatalogs; plugin subcatalogs do in general list objects " "that are also available directly from the top level. Subcatalogs can be used " "for a narrower view or search scope, when using Kupfer." msgstr "" "Los objetos del catálogo que tienen contenidos, como las carpetas, se marcan " "con una flecha. Pulsando entrará en estos objetos. La mayoría " "de los catálogos se componen de subcatálogos; los subcatálogos de " "complementos, en general, listan objetos que también están disponibles " "directamente desde el nivel superior. Al usar Kupfer, se pueden usar los " "subcatálogos para una vista estrecha o un rango de búsqueda." #: C/generalusage.page:105(p) msgid "" "Most subcatalogs update their content automatically. For example, the " "Desktop folder source is always up-to-date." msgstr "" "La mayoría de subcatálogos actualizan su contenido automáticamente. Por " "ejemplo, el catálogo de la carpeta «Escritorio» siempre está actualizado." #. Put one translator per line, in the form of NAME , YEAR1, YEAR2 #: C/generalusage.page:0(None) msgid "translator-credits" msgstr "" "Daniel Mustieles , 2011\n" "Jorge González , 2010" #~ msgid "Open Terminal Here" #~ msgstr "Abrir terminal aquí" #~| msgid "" #~| "Open terminal first calls xdg-terminal, then gnome-" #~| "terminal. xdg-terminal is a script to find the user's configured " #~| "terminal program for his/her Desktop Environment. Install xdg-" #~| "terminal if you need this (or install a symlink called " #~| "xdg-terminal)." #~ msgid "" #~ "Open terminal first calls xdg-terminal, then gnome-" #~ "terminal. xdg-terminal is a script to find the user's configured " #~ "terminal program for their Desktop Environment. Install xdg-" #~ "terminal if you need this (or install a symlink called xdg-" #~ "terminal)." #~ msgstr "" #~ "Al abrir una terminal se llama a xdg-terminal, y luego a " #~ "gnome-terminal. «xdg-terminal» es un script para encontrar el " #~ "programa de terminal configurado por el usuario para su entorno de " #~ "escritorio. Instale xdg-terminal si lo necesita (o cree un " #~ "enlace simbólico llamado «xdg-terminal»)." #~ msgid "" #~ "An example useful script is here which changes the rating of Rhythmbox's currently playing song; I have added five scriptlets calling " #~ "rhrating.py with numbers from 0 to 5 to my catalog to " #~ "quickly rate tracks. (This is something that might be integrated into " #~ "Kupfer later)" #~ msgstr "" #~ "Aquí hay un " #~ "ejemplo de script útil, que cambia la valoración de la canción que " #~ "actualmente se está reproduciendo en Rhythmbox; se han añadido " #~ "cinco scriptlets que llaman a rhrating.py con números de 0 a " #~ "5 para valorar canciones rápidamente. (Esto es algo que se debe integrar " #~ "en Kupfer más adelante)" #~ msgid "" #~ "Kupfer is its own remote control. When Kupfer is " #~ "already running, Kupfer on the command-line will focus its " #~ "window, but there is more you can do: If you invoke kupferQUERY where QUERY is a text string or a " #~ "filename, Kupfer will focus, and select this item. This way, " #~ "you can quickly invoke Kupfer actions even on objects from a " #~ "shell-based context." #~ msgstr "" #~ "Kupfer es su propio control remoto. Cuando Kupfer " #~ "ya está en ejecución, Kupfer en la línea de comandos enfocará " #~ "a su ventana, pero hay algo más que puede hacer: si ejecuta " #~ "kupferCONSULTA, donde CONSULTA es una cadena de texto o un nombre de archivo, Kupfer " #~ "enfocará y seleccionará este elemento. De este modo, puede ejecutar " #~ "acciones de Kupfer rápidamente incluso en objetos desde una " #~ "terminal." #~ msgid "" #~ "You can also pipe the output of a command into Kupfer to send " #~ "text to the already running instance of Kupfer." #~ msgstr "" #~ "También puede redirigir la salida de un comando hacia Kupfer " #~ "para enviar texto a la instancia de Kupfer en ejecución." #~ msgid "Additional Keyboard Shortcuts" #~ msgstr "Atajos de teclado adicionales" #, fuzzy #~| msgid "" #~| "The Triggers plugin allows to configure actions to be activated by " #~| "global shortcuts, but triggers can only be configured in that plugin." #~ msgid "" #~ "The plugin Triggers allows to " #~ "configure actions to be activated by global shortcuts, but triggers can " #~ "only be configured in that plugin." #~ msgstr "" #~ "El complemento «Triggers» le permite configurar acciones que se activarán " #~ "con atajos globales, pero los disparadores sólo se pueden configurar en " #~ "ese complemento." #~ msgid "Using Kupfer more conveniently." #~ msgstr "Usar Kupfer de una forma más conveniente." #~ msgid "" #~ "Kupfer listens to global shortcuts, even if Kupfer is not currently in " #~ "the foreground. The most important global shortcut is the shortcut to " #~ "show and hide Kupfer's command window which by default is " #~ "CtrlSpace." #~ msgstr "" #~ "Kupfer escucha los atajos globales, aunque no esté actualmente en primer " #~ "plano. El atajo global más importante es el que muestra y oculta la " #~ "ventana de comandos de Kupfer, que de manera predeterminada es " #~ "CtrlEspacio." #~ msgid "Global Keyboard Shortcuts are configured in Kupfer's preferences." #~ msgstr "" #~ "Los atajos globales de teclado están configurados en las preferencias de " #~ "Kupfer." #~ msgid "" #~ "Install custom plugins in the folder ~/.local/share/kupfer/plugins/" #~ "" #~ msgstr "" #~ "Instale los complementos personalizados en la carpeta ~/.local/" #~ "share/kupfer/plugins/" #~ msgid "" #~ "Kupfer cache, config and data are located in the directories ~/." #~ "cache/kupfer, ~/.config/kupfer and ~/.local/" #~ "share/kupfer." #~ msgstr "" #~ "La caché de Kupfer, la configuración y los datos se ubican en las " #~ "carpetas ~/.cache/kupfer, ~/.config/kupfer y " #~ "~/.local/share/kupfer." #~ msgid "" #~ "You can install custom plugins into ~/.local/share/kupfer/plugins; adding " #~ "to Kupfer's object knowledge can be surprisingly easy, just " #~ "look at the default plugins if you want to create new." #~ msgstr "" #~ "Puede instalar complementos personalizados en ~/.local/share/kupfer/" #~ "plugins; añadirlos al conocimiento de objetos de Kupfer puede " #~ "ser sorprendentemente fácil, simplemente mire los complementos " #~ "predeterminados si quiere crear uno nuevo." #~ msgid "" #~ "To use Kupfer like a pro, you can configure a \"Magic " #~ "Keybinding\" for Kupfer. GUI configuration is not yet " #~ "supported, but edit the configuration file ~/.config/kupfer/kupfer." #~ "cfg to include the following:" #~ msgstr "" #~ "Para usar Kupfer como un profesional, puede configurar una " #~ "«asociación de teclas mágica» para Kupfer. La configuración de " #~ "la IGU todavía no está soportada, pero edite el archivo de configuración " #~ "~/.config/kupfer/kupfer.cfg para incluir lo siguiente:" #~ msgid "" #~ "\n" #~ "[Kupfer]\n" #~ "keybinding = <Control>space\n" #~ "magickeybinding = <Ctrl><Alt>space\n" #~ " " #~ msgstr "" #~ "\n" #~ "[Kupfer]\n" #~ "keybinding = <Control>space\n" #~ "magickeybinding = <Ctrl><Alt>space\n" #~ " " #~ msgid "" #~ "Now, pressing CtrlAltSpace will summon Kupfer with the current selection in " #~ "focus. Make sure you have installed Kupfer's nautilus plugin, " #~ "then both the currently selected file in Nautilus, or the currently " #~ "selected text in the front application will be selected." #~ msgstr "" #~ "Ahora, pulsando CtrlAltEspacio se ejecutará Kupfer con el foco en la selección " #~ "actual. Asegúrese de que tiene instalado el complemento de Kupfer para Nautilus, y entonces se seleccionarán el archivo seleccionado " #~ "en Nautilus, o el texto seleccionado en la aplicación." #~ msgid "" #~ "Now you can select a word in, say, a web browser, use CtrlAltSpace, and select action Look " #~ "Up to look up the selected word. Or select an image file, use " #~ "CtrlAltSpace, select " #~ "action Scale with object 1000 to scale the image to " #~ "1000 pixels wide!" #~ msgstr "" #~ "Ahora puede seleccionar una palabra en, por ejemplo, un navegador web. " #~ "Use CtrlAltEspacio y " #~ "elija la acción Buscar para buscar la palabra seleccionada. O " #~ "seleccione un archivo de imagen, use CtrlAltEspacio, elija la acción Escalar con " #~ "el objeto 1000 para escalar la imagen a 1000 píxeles de " #~ "anchura." #~ msgid "Legal Information." #~ msgstr "Información legal." #~ msgid "" #~ "Kupfer is a program to change, speed up and make everything " #~ "about files and programs more fun on your computer. Kupfer is " #~ "a launcher; you typically use it to summon an application or a document " #~ "quickly by typing parts of its name. It can also do more than getting at " #~ "something quickly: there are different plugins for accessing more objects " #~ "and running custom commands." #~ msgstr "" #~ "Kupfer es un programa para cambiar, acelerar y hacer todo lo " #~ "referente a archivos y programas más ameno en su equioi. Kupfer es un lanzador; generalmente lo usa para lanzar un aplicación o un " #~ "documento rápidamente escribiendo partes de su nombre. También puede " #~ "hacer algo más que acelerar las cosas: hay diferentes complementos para " #~ "acceder a más objetos y ejecutar comandos personalizados." #~ msgid "" #~ "Kupfer is written using Python and has a flexible " #~ "architecture; the implementation is simple and makes the easy things work " #~ "first. One goal is that new plugins can be written quickly without too " #~ "much programming." #~ msgstr "" #~ "Kupfer está escrito en Python y tiene una arquitectura " #~ "flexible; la implementación es sencilla y hace que primero funcionen las " #~ "cosas fáciles. Un objetivo es que los complementos nuevos se puedan " #~ "escribir rápidamente sin demasiada programación." #~ msgid "" #~ "The program is very inspired by Quicksilver." #~ msgstr "" #~ "El programa está muy inspirado en Quicksilver." kupfer-328/help/fr/000077500000000000000000000000001500175051100142165ustar00rootroot00000000000000kupfer-328/help/fr/fr.po000066400000000000000000002142301500175051100151670ustar00rootroot00000000000000# French translation for kupfer help. # Copyright (C) 2010-12 kupfer's COPYRIGHT HOLDER # This file is distributed under the same license as the kupfer package. # # AlainLojewski , 2010. # Julien Hardelin , 2011. # Bruno Brouard , 2012. msgid "" msgstr "" "Project-Id-Version: kupfer help master\n" "POT-Creation-Date: 2012-02-17 20:31+0000\n" "PO-Revision-Date: 2012-02-18 12:50+0100\n" "Last-Translator: Bruno Brouard \n" "Language-Team: GNOME French Team \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" #: C/plugin-websearch.page:7(desc) msgid "Using the search the web plugin." msgstr "Utiliser le greffon « Rechercher sur le Web »." #: C/plugin-websearch.page:10(app) msgid "Search the Web" msgstr "Rechercher sur le Web" #: C/plugin-websearch.page:13(title) C/plugin-triggers.page:23(title) #: C/plugin-notes.page:22(title) C/plugin-nautilusselection.page:13(title) #: C/plugin-gwibber.page:25(title) C/plugin-favorites.page:22(title) #: C/plugin-calculator.page:21(title) C/plugin-applications.page:19(title) #: C/generalusage.page:10(title) msgid "Basic Usage" msgstr "Utilisation de base" #: C/plugin-websearch.page:15(p) msgid "Activate Kupfer and make sure it is in free-text mode (press period)" msgstr "" "Activez Kupfer et assurez-vous qu'il est en mode texte libre (appuyez sur la " "touche « point »)" #: C/plugin-websearch.page:17(p) msgid "" "Type in a search query and tap Tab to switch to the action pane." msgstr "" "Saisissez une demande de recherche et appuyez sur Tab pour passer " "dans le volet action." #: C/plugin-websearch.page:19(p) msgid "" "Type \"Search With\" to find Search the Web's action and tap Tab " "again to switch to the third pane (indirect object)." msgstr "" "Saisissez « rechercher avec » pour trouver l'action rechercher sur le Web et " "appuyez à nouveau sur Tab pour passer dans le troisième volet " "(objet indirect)." #: C/plugin-websearch.page:22(p) msgid "" "Select search engine with the arrow keys and type Return to open " "the search in a web browser." msgstr "" "Sélectionnez le moteur de recherche avec les touches fléchées et appuyez sur " "Entrée pour ouvrir la recherche dans un navigateur Web." #: C/plugin-websearch.page:29(title) msgid "Search Engines" msgstr "Moteurs de recherche" #: C/plugin-websearch.page:30(p) msgid "" "The Search the Web plugin uses Firefox' search engines, so you " "can add Search Engines directly in Firefox and Kupfer " "will find them later." msgstr "" "Le greffon « Rechercher sur le Web » utilise les moteurs de recherche de " "Firefox, de sorte que si vous ajoutez des moteurs de recherche " "directement dans Firefox, Kupfer les trouvera " "ultérieurement." #: C/plugin-websearch.page:35(p) msgid "" "You can also install custom search plugins directly, only for Kupfer, in the folder:" msgstr "" "Vous pouvez aussi placer des greffons de recherche personnalisés développés " "spécialement pour Kupfer directement dans le dossier :" #: C/plugin-websearch.page:39(code) #, no-wrap msgid "~/.local/share/kupfer/searchplugins/" msgstr "~/.local/share/kupfer/searchplugins/" #: C/plugin-websearch.page:40(p) msgid "The search engine descriptions must written in OpenSearch format." msgstr "" "Les descriptions du moteur de recherche doivent être écrites dans le format " "OpenSearch." #: C/plugin-triggers.page:7(desc) msgid "Using the triggers plugin." msgstr "Utiliser le greffon Raccourcis déclencheurs." #: C/plugin-triggers.page:10(app) C/keyboard.page:213(title) msgid "Triggers" msgstr "Raccourcis déclencheurs" #: C/plugin-triggers.page:13(title) msgid "Triggers Plugin" msgstr "Greffon « Raccourcis déclencheurs »" #: C/plugin-triggers.page:14(p) msgid "" "With Triggers you can take a command you would normally perform " "in Kupfer, such as launching an application or opening a " "document, and bind a global key combination to run this command. As long as " "Kupfer is running, any application can have the current focus." msgstr "" "Avec les Raccourcis déclencheurs, vous pouvez associer une " "combinaison de touches à une action que vous lanceriez normalement dans " "Kupfer, comme démarrer une application ou ouvrir un document. " "Tant que Kupfer est actif, toute application peut être au premier " "plan." #: C/plugin-triggers.page:25(title) msgid "Creating a new trigger" msgstr "Création d'un nouveau raccourci déclencheur" #: C/plugin-triggers.page:27(p) msgid "Set up a command in Kupfer that you want to run" msgstr "Configurez une commande que vous voulez lancer dans Kupfer." #: C/plugin-triggers.page:32(p) msgid "" "Press CtrlReturn to create a " "composed command." msgstr "" "Appuyez sur CtrlEntrée pour créer une " "commande composée." #: C/plugin-triggers.page:38(p) msgid "" "Type Tab and select the action Add Trigger... and press " "Return" msgstr "" "Appuyez sur Tab, sélectionnez l'action Ajouter un raccourci " "déclencheur... et appuyez sur Entrée." #: C/plugin-triggers.page:44(p) msgid "" "Using the window that appears, press modifier keys and a letter or number " "key to set a global shortcut. An example is pressing and holding " "CtrlAlt and then pressing and " "releasing R to bind CtrlAltR." msgstr "" "Dans la boîte de dialogue qui s'affiche, appuyez sur les touches de " "modification et sur une touche lettre ou chiffre pour définir un raccourci " "global (par exemple en maintenant la pression sur CtrlAlt puis en pressant et relâchant la touche R pour lier CtrlAltR)." #: C/plugin-triggers.page:54(title) msgid "Removing a trigger" msgstr "Suppression d'un raccourci déclencheur" #: C/plugin-triggers.page:56(p) msgid "" "Find the source Triggers in Kupfer and press to see its contents." msgstr "" "Recherchez les raccourcis déclencheurs sources dans Kupfer et appuyez sur pour afficher leurs contenus." #: C/plugin-triggers.page:62(p) msgid "" "Find the active trigger in the list and use the action Remove Trigger." msgstr "" "Recherchez le raccourci déclencheur actif dans la liste et utilisez l'action " "Supprimer le raccourci déclencheur." #: C/plugin-triggers.page:68(p) msgid "" "Since trigger keyboard shortcuts are global, they can be used from any " "application. Select shortcuts with care so that they do not conflict with " "other functions." msgstr "" "Puisque les raccourcis clavier déclencheurs sont globaux, on peut les " "utiliser à partir de n'importe quelle application. Choisissez les raccourcis " "avec soin, de façon à ce qu'ils n'entrent pas en conflit avec d'autres " "fonctions." #: C/plugin-triggers.page:74(title) C/plugin-notes.page:60(title) #: C/plugin-gwibber.page:68(title) C/plugin-favorites.page:38(title) msgid "Power User Tips" msgstr "Astuces utilisateur très puissantes" #: C/plugin-triggers.page:75(p) msgid "" "Proxy objects such as Selected Text, Selected File, Frontmost Window, Last Command et cetera allow very " "powerful triggers." msgstr "" "Les Objets de procuration comme Texte sélectionné, " "Fichier sélectionné, Fenêtre au premier plan, Dernière " "commande etc. permettent de très puissants raccourcis déclencheurs." #: C/plugin-triggers.page:79(p) msgid "" "The application action Launch is special; if you bind a trigger " "using Launch, it will start the application if it is not running, " "but focus the application when it is already running. By contrast, Start " "Again will start the application if it is running or not." msgstr "" "L'action Lancer est spéciale ; si vous constituez un raccourci " "déclencheur utilisant Lancer, il démarrera l'application si elle " "n'est pas encore effective, mais mettra l'application au premier plan si " "elle est déjà lancée. Par contre, Lancer à nouveau démarrera " "l'application qu'elle soit déjà en cours ou non." #: C/plugin-triggers.page:87(title) msgid "Example Triggers" msgstr "Exemples de raccourcis déclencheurs" #: C/plugin-triggers.page:90(em) msgid "Text Editor → Launch" msgstr "Éditeur de texte → Lancer" #: C/plugin-triggers.page:91(p) msgid "" "Start Text Editor or focus its window if it is already running." msgstr "" "Démarrer l'Éditeur de texte ou le mettre au premier plan s'il est " "déjà en cours." #: C/plugin-triggers.page:97(em) msgid "Selected Text → Search With → Google" msgstr "Texte sélectionné → Rechercher avec → Google" #: C/plugin-triggers.page:98(p) msgid "Search the web using the currently selected text." msgstr "Explorer le Web en utilisant le texte actuellement sélectionné." #: C/plugin-triggers.page:100(em) msgid "Selected File → Move To → (Downloads Folder)" msgstr "Fichier sélectionné → Déplacer vers → (Dossier Téléchargements)" #: C/plugin-triggers.page:101(p) msgid "Move the currently selected file to a specific folder" msgstr "" "Déplacer le fichier actuellement sélectionné vers un dossier particulier." #: C/plugin-triggers.page:105(em) msgid "Songs → Search Contents" msgstr "Chansons → Recherche de contenus" #: C/plugin-triggers.page:106(p) msgid "" "You may even add a trigger to open a specific subcatalog in Kupfer, for " "example Rhythmbox's songs." msgstr "" "Vous pouvez même ajouter un raccourci déclencheur pour ouvrir un sous-" "catalogue particulier dans Kupfer, par exemple les chansons de Rhythmbox." #: C/plugin-notes.page:7(desc) msgid "Using the notes plugin." msgstr "Utiliser le greffon « Notes »." #: C/plugin-notes.page:10(app) C/plugin-calculator.page:37(title) msgid "Notes" msgstr "Notes" #: C/plugin-notes.page:13(title) msgid "Notes Plugin" msgstr "Le greffon « Notes »" #: C/plugin-notes.page:14(p) msgid "" "With Notes you can access or create new notes in either the " "program Gnote or Tomboy. Notes will work " "identically with either application—you can configure which one to use in " "the plugin's information pane in Kupfer Preferences." msgstr "" "Avec Notes, vous pouvez accéder à (ou créer) de nouvelles notes " "avec les applications Gnote ou Tomboy. Notes fonctionne indifféremment avec l'une ou l'autre. Vous pouvez définir " "celle que vous souhaitez utiliser à partir du volet d'informations du " "greffon dans les Préférences de Kupfer." #: C/plugin-notes.page:24(title) msgid "Creating a new note" msgstr "Création d'une nouvelle note" #: C/plugin-notes.page:26(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "note title" msgstr "" "Activez Kupfer et appuyez sur . pour passer en mode texte, puis " "saisissez un titre de note." #: C/plugin-notes.page:32(p) msgid "" "Type Tab and select the action Create Note and press " "Return." msgstr "" "Appuyez sur Tab, sélectionnez l'action Notes et appuyez " "sur Entrée." #: C/plugin-notes.page:39(title) msgid "Finding a note by title" msgstr "Recherche d'une note à partir de son titre" #: C/plugin-notes.page:41(p) msgid "Simply search for the note title in Kupfer" msgstr "Recherchez simplement le titre de la note dans Kupfer" #: C/plugin-notes.page:45(title) msgid "Finding a note by content" msgstr "Recherche d'une note à partir de son contenu" #: C/plugin-notes.page:47(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "search query" msgstr "" "Activez Kupfer, appuyez sur . pour passer en mode " "texte, puis saisissez une demande de recherche" #: C/plugin-notes.page:53(p) msgid "" "Type Tab and select the action Get Note Search Results... and press Return." msgstr "" "Appuyez sur Tab, sélectionnez l'action Obtenir le résultat de " "la recherche dans les notes... et appuyez sur Entrée." #: C/plugin-notes.page:63(p) msgid "" "You can use the Selected Text object and create a new note with the " "content of the selection." msgstr "" "Vous pouvez utiliser l'objet Texte sélectionné et créer une " "nouvelle note avec le contenu de la sélection." #: C/plugin-nautilusselection.page:7(desc) msgid "Using the selected file plugin." msgstr "Utiliser le greffon « Fichier sélectionné »." #: C/plugin-nautilusselection.page:10(app) msgid "Selected File" msgstr "Fichier sélectionné" #: C/plugin-nautilusselection.page:14(p) msgid "" "Select a file in the file manager. Open Kupfer and search for the " "object Selected File, which represents the file or files that are " "selected." msgstr "" "Sélectionnez un fichier dans le gestionnaire de fichiers. Ouvrez " "Kupfer et recherchez l'objet Fichier Sélectionné qui " "représente le ou les fichiers sélectionnés." #: C/plugin-nautilusselection.page:19(p) msgid "" "Instead of searching, you can press CtrlG to directly focus the selected file. See " "for more information." msgstr "" "Au lieu de rechercher, vous pouvez appuyer sur CtrlG pour mettre le focus directement sur le fichier " "sélectionné. Consultez pour de plus amples " "informations." #: C/plugin-nautilusselection.page:26(title) msgid "Selected File requires Nautilus" msgstr "Fichier sélectionné a besoin de Nautilus" #: C/plugin-nautilusselection.page:27(p) msgid "" "The selected file plugin works with the Nautilus file browser and " "requires that the extension kupfer_provider.py is installed (it " "is normally installed together with Kupfer). After installing it " "for the first time, Nautilus must start anew before it is active." msgstr "" "Le greffon « Fichier sélectionné » fonctionne avec le navigateur de fichiers " "Nautilus et nécessite que le greffon kupfer_provider.py soit installé (il l'est normalement en même temps que Kupfer). Si vous l'installez pour la première fois, vous devez redémarrer " "Nautilus pour qu'il soit pris en compte." #: C/plugin-gwibber.page:7(desc) msgid "Using the Gwibber plugin." msgstr "Utiliser le greffon « Gwibber »." #: C/plugin-gwibber.page:10(app) msgid "Gwibber" msgstr "Gwibber" #: C/plugin-gwibber.page:13(title) msgid "Gwibber Plugin" msgstr "Le greffon « Gwibber »" #: C/plugin-gwibber.page:14(p) msgid "" "With the Gwibber plugin you can send messages to social networks " "such as Twitter or Identi.ca." msgstr "" "Le greffon Gwibber rend possible l'envoi de messages aux réseaux " "sociaux comme Twitter ou Identi.ca." #: C/plugin-gwibber.page:18(p) msgid "" "The plugin requires that the application Gwibber is installed and " "configured for your user. Kupfer will start and use Gwibber's " "service in the background." msgstr "" "Le greffon exige queGwibber soit installé et configuré avec votre " "compte utilisateur. Kupfer démarre et utilise les services de " "« Gwibber » en arrière-plan." #: C/plugin-gwibber.page:27(title) msgid "Sending a message to all services" msgstr "Envoi d'un message à tous les services" #: C/plugin-gwibber.page:29(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "message." msgstr "" "Activez Kupfer, appuyez sur . pour passer en mode texte, puis " "saisissez un message." #: C/plugin-gwibber.page:35(p) msgid "" "Type Tab and select the action Send Message and press " "Return." msgstr "" "Appuyez sur Tab, sélectionnez l'action Envoyer un message et appuyez sur Entrée." #: C/plugin-gwibber.page:42(title) msgid "Sending a message to a specific service" msgstr "Envoi d'un message à un service particulier" #: C/plugin-gwibber.page:44(p) msgid "" "Activate Kupfer and search for the service object, for example Identi." "ca" msgstr "" "Activez Kupfer et recherchez l'objet service, par exemple " "Identi.ca." #: C/plugin-gwibber.page:50(p) msgid "Type Tab and select the action Send Message." msgstr "" "Appuyez sur Tab et sélectionnez l'action Envoyer un message." #: C/plugin-gwibber.page:55(p) msgid "" "Type Tab to select the last pane, and type in a message. Press " "Return to send." msgstr "" "Appuyez sur Tab pour aller au dernier volet et saisissez-y un " "message. Appuyez sur Entrée pour l'envoyer." #: C/plugin-gwibber.page:61(p) msgid "" "The plugin also provides a source for incoming messages, Gwibber " "Messages and more actions on messages such as Reply, Send " "Private Message etc." msgstr "" "Le greffon fournit également une source pour les messages entrants, les " "Messages Gwibber et d'autres actions sur les messages telles que " "Répondre, Envoyer un message privé, etc." #: C/plugin-gwibber.page:71(p) msgid "" "You can use the comma trick if you want to send a message to more " "than one service, but not all, at the same time." msgstr "" "Utilisez l'Astuce virgule pour envoyer un message à plus d'un " "service, mais pas à tous, en même temps." #: C/plugin-favorites.page:7(desc) msgid "Using the favorites plugin." msgstr "Utiliser le greffon « Favoris »." #: C/plugin-favorites.page:10(app) msgid "Favorites" msgstr "Favoris" #: C/plugin-favorites.page:13(title) msgid "Favorites Plugin" msgstr "Le greffon « Favoris »" #: C/plugin-favorites.page:14(p) msgid "" "With Favorites you mark objects, for example files, for quicker " "access. It is a sort of shelf on which you can store objects in Kupfer. " "Objects marked as favorites will also be ranked higher and are adorned with " "a star symbol." msgstr "" "Avec Favoris vous marquez des objets, par exemple des fichiers, " "pour y accéder plus rapidement. C'est une sorte d'étagère sur laquelle vous " "rangez des objets dans Kupfer. Les objets marqués comme favoris sont aussi " "classés plus haut et sont ornés d'un symbole en forme d'étoile." #: C/plugin-favorites.page:25(p) msgid "Find an object in Kupfer" msgstr "Recherchez un objet dans Kupfer" #: C/plugin-favorites.page:30(p) msgid "" "Type Tab and select either the action Add to Favorites " "or Remove from Favorites." msgstr "" "Appuyez sur Tab et sélectionnez Ajouter aux favoris ou " "Supprimer des favoris." #: C/plugin-favorites.page:39(p) msgid "" "If you favorite an object, you can access it in more places. Not only in the " "\"Favorites\" subcatalog, but also as the indirect (secondary) object for " "some actions. For example:" msgstr "" "Si vous avez marqué un objet comme favori, vous pouvez le retrouver à " "plusieurs endroits ; pas seulement dans le sous-catalogue « Favoris », mais " "aussi comme objet indirect (secondaire) pour certaines actions. Par exemple :" #: C/plugin-favorites.page:45(p) msgid "Command-lines from favorites are quick to access." msgstr "Accès rapide aux lignes de commande des favoris." #: C/plugin-favorites.page:46(p) msgid "" "When scaling images with the Scale... action from the Image " "Tools plugin. This action needs a size description as the third " "object, like \"1024\" or \"1200x800\". If you often scale to the same size, " "say \"1200x800\", add this to favorites, and it will always appear as a " "suggestion for the action." msgstr "" "Mise à l'échelle d'images avec l'action Mise à l'échelle... du " "greffon Outils d'image. Cette action nécessite une définition de " "la taille de l'objet tiers, comme « 1024 » ou « 1200x800 ». Si vous mettez " "souvent à l'échelle à la même taille, disons « 1200x800 », ajoutez-la aux " "favoris et ainsi elle s'affichera toujours en suggestion pour cette action." #: C/plugin-favorites.page:54(p) msgid "" "Actions needing an email address as the indirect object will pick up email " "addresses from favorites as well as well." msgstr "" "Les actions qui nécessitent une adresse courriel comme objet indirect " "peuvent aussi bien la récupérer dans les favoris." #: C/plugin-calculator.page:7(desc) msgid "Using the calculator plugin." msgstr "Utiliser le greffon « Calculateur »." #: C/plugin-calculator.page:10(app) msgid "Calculator" msgstr "Calculateur" #: C/plugin-calculator.page:13(title) msgid "Calculator Plugin" msgstr "Le greffon « Calculateur »" #: C/plugin-calculator.page:14(p) msgid "" "The calculator plugin lets you calculate expressions quickly. It can " "evaluate expressions entered as text starting with \"=\". Entering = from " "command mode will start text mode directly with = prefixed for quick access." msgstr "" "Le greffon « Calculateur » vous permet de calculer rapidement des " "expressions. Il sait reconnaître les textes commençant par « = » comme une " "expression. Saisir « = » en ligne de commande démarre le mode texte avec le " "préfixe « = » pour un accès rapide." #: C/plugin-calculator.page:23(p) msgid "Activate Kupfer and type =" msgstr "Activez Kupfer et appuyez sur =" #: C/plugin-calculator.page:26(p) msgid "" "Type in a mathematical expression using +,-,/,* (and ** for exponentiation)" msgstr "" "Saisissez une expression mathématique avec +,-,/,* (et ** pour l'exponentiation)" #: C/plugin-calculator.page:30(p) msgid "Press Return to get the result." msgstr "Appuyez sur Entrée pour obtenir le résultat." #: C/plugin-calculator.page:38(p) msgid "" "The Calculator uses python's math and complex math modules, and parses " "expressions as Python expressions. You may use common mathematical " "functions, such as sqrt, sin, exp and " "log; the command =help will show a list of all defined " "functions and constants." msgstr "" "Le calculateur utilise les modules mathématiques et mathématiques complexes " "du langage Python et analyse les expressions comme étant des expressions " "Python. Vous pouvez utiliser les fonctions mathématiques standards, comme " "sqrt, sin, exp et log ; la " "commande =help affiche une liste de toutes les fonctions et de " "toutes les constantes disponibles." #: C/plugin-calculator.page:47(p) msgid "" "Notice that the power operator in Python is double stars, for example " "=3**3 will evaluate to 27." msgstr "" "Veuillez noter que l'opérateur de mise à la puissance en Python est deux " "étoiles ; par exemple, =3**3 donne 27." #: C/plugin-calculator.page:53(p) msgid "To calculate trig functions for angles, convert to radians first:" msgstr "" "Pour calculer les fonctions trigonométriques des angles, vous devez d'abord " "les convertir en radians :" #: C/plugin-calculator.page:56(code) #, no-wrap msgid "sin(radians(30)) -> 0.5" msgstr "sin(radians(30)) -> 0.5" #: C/plugin-calculator.page:59(p) msgid "" "The last result is stored as the name _ (an underscore, just like in the " "Python console)." msgstr "" "Le dernier résultat obtenu est enregistré dans la variable portant le nom _ " "(le caractère souligné, comme dans la console Python)." #: C/plugin-applications.page:7(desc) msgid "Using the applications plugin." msgstr "Utiliser le greffon « Applications »." #: C/plugin-applications.page:10(app) msgid "Applications" msgstr "Applications" #: C/plugin-applications.page:13(title) msgid "Applications Plugin" msgstr "Le greffon « Applications »" #: C/plugin-applications.page:14(p) msgid "Applications provides all installed programs." msgstr "Applications donne accès à tous les programmes installés." #: C/plugin-applications.page:21(title) msgid "Launching an application" msgstr "Lancement d'une application" #: C/plugin-applications.page:23(p) msgid "Activate Kupfer and type an abbreviation of the application name" msgstr "" "Activez Kupfer et saisissez les premières lettres du nom de " "l'application" #: C/plugin-applications.page:28(p) msgid "Press Return to launch the application." msgstr "Appuyez sur Entrée pour lancer l'application." #: C/plugin-applications.page:34(title) msgid "Opening a file with a specific application" msgstr "Ouverture d'un fichier avec une application particulière" #: C/plugin-applications.page:36(p) msgid "Select a file in Kupfer" msgstr "Sélectionnez un fichier dans Kupfer" #: C/plugin-applications.page:41(p) msgid "Type Tab and select the action Open With..." msgstr "" "Appuyez sur Tab et sélectionnez l'action Ouvrir avec..." #: C/plugin-applications.page:46(p) msgid "" "Type Tab to select the third (indirect object) pane and in it, " "select the application to open the file with." msgstr "" "Appuyez sur Tab pour aller au troisième volet (objet indirect) et " "sélectionnez l'application qui servira à ouvrir le fichier." #: C/plugin-applications.page:53(p) msgid "" "The action Open opens files and folders with the registered default " "application for that specific file type. This can be configured using the " "action Set Default Application...." msgstr "" "L'action Ouvrir ouvre des fichiers et des dossiers avec " "l'application enregistrée par défaut pour ce type particulier de fichiers. " "Vous pouvez la configurer avec l'action Définir l'application par " "défaut...." #: C/plugin-applications.page:58(p) msgid "" "The file type associations are provided by the desktop environment, and " "modifying them here will modify them on the desktop as well. This may not be " "true when not using GNOME or XFCE." msgstr "" "Les associations de type de fichiers sont fournies par l'environnement du " "bureau et leur modification ici les modifie aussi sur le bureau. Cela n'est " "peut-être pas le cas si vous n'utilisez pas GNOME ou XFCE." #: C/plugin-applications.page:64(title) msgid "Selecting default application for a file type or folders" msgstr "" "Sélection de l'application par défaut pour un type de fichiers ou de dossiers" #: C/plugin-applications.page:66(p) msgid "Select a file or folder in Kupfer" msgstr "Sélectionnez un fichier ou un dossier dans Kupfer" #: C/plugin-applications.page:71(p) msgid "" "Type Tab and select the action Set Default Application..." msgstr "" "Appuyez sur Tab et sélectionnez l'action Définir " "l'application par défaut..." #: C/plugin-applications.page:77(p) msgid "" "Type Tab to select the third (indirect object) pane and in it, " "select the application to always open the file type with." msgstr "" "Appuyez sur Tab pour aller au troisième volet (objet indirect) et " "sélectionnez l'application qui servira systématiquement à ouvrir ce type de " "fichiers." #: C/plugin-applications.page:85(title) msgid "Configuration" msgstr "Configuration" #: C/plugin-applications.page:86(p) msgid "" "The configuration option Applications for Desktop Environment in " "the plugin's information pane in Kupfer Preferences determines " "how Kupfer should act with regard to the desktop environment " "configuration—certain applications request not to be shown depending on " "which desktop environment is used. By default, it behaves like GNOME." msgstr "" "L'option de configuration Applications pour le bureau dans le volet " "d'informations sur les greffons dans les Préférences de Kupfer " "détermine comment Kupfer doit agir en fonction de la " "configuration du bureau. Selon le bureau utilisé, certaines applications ne " "doivent pas être affichées. Par défaut, le comportement est celui de GNOME." #: C/moreusage.page:7(desc) msgid "More advanced usage information." msgstr "Informations d'utilisation avancée." #: C/moreusage.page:10(title) msgid "Using Kupfer in Depth" msgstr "Utilisation de Kupfer de façon approfondie" #: C/moreusage.page:13(title) msgid "Adding Applications and Scripts" msgstr "Ajout d'applications et de scripts" #: C/moreusage.page:14(p) msgid "" "Kupfer will show all applications that are configured visible in " "your menu editor." msgstr "" "Kupfer affiche toutes les applications configurées comme visibles " "dans votre éditeur de menu." #: C/moreusage.page:18(p) msgid "" "If you want to add an application manually, you can create a new ." "desktop file and place it in one of the standard directories for " "applications, for example ~/.local/share/applications, where " "Kupfer will find it." msgstr "" "Si vous souhaitez ajouter une application manuellement, vous pouvez créer un " "nouveau fichier .desktop et le mettre dans un des répertoires " "standards dédiés aux applications comme, par exemple, dans ~/.local/" "share/applications, où Kupfer pourra le trouver." #: C/moreusage.page:24(p) msgid "" "If you have a collection of scripts that you want to call from Kupfer, you can add the scripts folder as a catalog directory to Kupfer in the preferences. Scripts that you add to Kupfer's catalog " "this way can be run directly or in the terminal as long as they are " "executable." msgstr "" "Si vous possédez une collection de scripts que vous souhaitez exécuter à " "partir de Kupfer, vous pouvez les placer dans un dossier en tant " "que répertoire catalogue dans les préférences de Kupfer. Les " "scripts que vous ajoutez de cette façon au catalogue de Kupfer " "peuvent être directement lancés dans un terminal pour autant qu'ils soient " "exécutables." #: C/moreusage.page:31(p) msgid "" "You can also save command-lines by using the action Add to Favorites." msgstr "" "Vous pouvez aussi enregistrer des lignes de commande avec l'action " "Ajouter aux favoris." #: C/moreusage.page:38(title) msgid "Opening Files and Folders" msgstr "Ouverture de fichiers et de dossiers" #: C/moreusage.page:39(p) msgid "" "Using the action Open, files and folders are opened in their " "preferred application. The application associations can be changed, see " "." msgstr "" "En utilisant l'action Ouvrir, les fichiers et les dossiers sont " "ouverts avec l'application associée. Les associations aux applications " "peuvent être modifiées ; consultez la section ." #: C/moreusage.page:47(title) msgid "The Comma Trick" msgstr "L'Astuce virgule" #: C/moreusage.page:48(p) msgid "" "The comma trick allows the user to use actions on many objects at the same " "time." msgstr "" "L'astuce virgule permet à l'utilisateur d'avoir recours à des actions sur " "plusieurs objets en même temps." #: C/moreusage.page:52(p) msgid "" "Simply press comma , when an object is selected. The object is " "put on a \"stack\", and you can find yet another file or object, press comma " "to put it on the stack. When you subsequently invoke an action, the action " "is carried out on all of the objects at the same time." msgstr "" "Sélectionnez un objet et appuyez sur la touche virgule ,. L'objet " "se retrouve sur une « pile » sur laquelle vous pouvez ajouter d'autres objets " "ou fichiers en appuyant sur virgule. Si par la suite vous appelez une " "action, elle s'appliquera à tous les objets de la pile en même temps." #: C/moreusage.page:58(p) msgid "" "Some actions are only \"multiplied\" when used with many objects, other are " "smarter than that:" msgstr "" "Certaines actions ne sont que « répétées » si elles sont utilisées avec " "plusieurs objets, d'autres sont plus intelligentes :" #: C/moreusage.page:61(p) msgid "" "Selecting many files and using the Create Archive action, all files will be " "packed into the same archive." msgstr "" "En sélectionnant plusieurs fichiers et en utilisant l'action Créer une " "archive, tous les fichiers sont regroupés dans la même archive." #: C/moreusage.page:63(p) msgid "" "If you select multiple contacts and use a Send Email action, it creates one " "email directed at all the contacts." msgstr "" "Si vous sélectionnez plusieurs contacts et que vous utilisez l'action " "Envoyer un courriel, un courriel adressé à tous les contacts est créé." #: C/moreusage.page:65(p) msgid "" "If you select multiple subcatalogs (For example Firefox Bookmarks and " "Epiphany Bookmarks) and use Search Contents.., you get a subcatalog search " "restricted to the objects of those two catalogs! You can even bind a trigger " "to this command(!)" msgstr "" "Si vous sélectionnez plusieurs sous-catalogues (par exemple les marque-pages " "de Firefox et d'Epiphany), l'action Rechercher le contenu... effectue une " "recherche de sous-catalogues limitée aux objets de ces deux catalogues ! " "Vous pouvez même associer un raccourci déclencheur à cette commande." #: C/moreusage.page:71(p) msgid "" "The comma trick is directly taken from Quicksilver (the " "example given in the external article should work identically in Kupfer)." msgstr "" "L'astuce virgule est directement tirée de Quicksilver " "(l'exemple donné dans l'article externe devrait fonctionner de la même " "manière dans Kupfer)." #: C/moreusage.page:80(title) msgid "Grab Current Selection" msgstr "Obtention de la sélection en cours" #: C/moreusage.page:81(p) msgid "" "To use the current selected text, from any application, with Kupfer, you can configure a global keyboard shortcut for the action Show " "with Selection in Kupfer Preferences." msgstr "" "Pour utiliser le texte sélectionné en cours à partir de n'importe quelle " "application avec Kupfer, vous pouvez configurer un raccourci " "clavier global dédié à l'action Afficher avec sélection dans les " "Préférences de Kupfer." #: C/moreusage.page:85(p) msgid "" "If configured, pressing the global keyboard shortcut will summon " "Kupfer with the current selection as the focused object." msgstr "" "S'il est configuré, le raccourci clavier appelle Kupfer avec la " "sélection en cours comme objet en premier plan." #: C/moreusage.page:90(p) msgid "See " msgstr "Consultez la section " #: C/moreusage.page:94(title) msgid "Command-line Connection" msgstr "Connexion en ligne de commande" #: C/moreusage.page:95(p) msgid "" "The command kupfer on the command-line will focus Kupfer if it's already running, otherwise it will start it." msgstr "" "La commande kupfer en ligne de commande met Kupfer au " "premier plan s'il est déjà lancé, sinon elle le démarre." #: C/moreusage.page:99(p) msgid "" "The command kupfer can be used to send files or text from the " "command-line to Kupfer. For example, if you are using the shell " "in a directory where you have a file called \"report.pdf\", you can focus " "this file in Kupfer by running kupfer report.pdf." msgstr "" "La commande kupfer peut être utilisée pour envoyer à Kupfer des fichiers ou du texte en ligne de commande. Par exemple, si vous " "utilisez l'interpréteur (le shell) dans un répertoire où il y a un fichier " "nommé « rapport.pdf », vous pouvez mettre le focus sur ce fichier dans " "Kupfer en exécutant kupfer rapport.pdf." #: C/moreusage.page:107(p) msgid "" "You can also send text if you pipe the output of a command into kupfer." msgstr "" "Vous pouvez aussi envoyer du texte si vous redirigez la sortie d'une " "commande vers kupfer." #: C/moreusage.page:114(title) msgid "Managing Context and Current Selection" msgstr "Gestion du contexte et de la sélection actuelle" #: C/moreusage.page:115(p) msgid "" "If you find the object you want to use, then invoke an action, Kupfer goes away to perform the action (for example start a program or play a " "song). When you come back to Kupfer, it will still keep the same " "object and action selected. Some actions make sense to be repeated (like " "skipping to the next song) and it can be useful to perform different actions " "on the same object." msgstr "" "Recherchez l'objet que vous souhaitez utiliser, sollicitez une action et " "Kupfer ouvre l'application correspondante (par exemple lancer un " "programme ou diffuser une chanson). Quand vous retournez dans Kupfer, il garde l'objet et l'application sélectionnés. La répétition de " "certaines actions (comme lire le morceau suivant) va de soi et il peut être " "utile d'appliquer différentes actions au même objet." #: C/moreusage.page:123(p) msgid "" "However, you always have the top level catalog reachable when you \"come back" "\" to Kupfer -- say you went into the subcatalog \"Albums\" to " "browse your albums only; you select an album to play, and play it. You come " "back with the album selected -- but your next search will still go over the " "top level catalog, not just albums." msgstr "" "Cependant, le haut du catalogue est toujours disponible pour l'accession aux " "objets quand vous retournez dans Kupfer : disons, par exemple, " "que vous étiez dans le sous-catalogue « Albums » pour seulement consulter vos " "albums ; vous choisissez un album et vous l'écoutez. Vous revenez dans " "Kupfer et votre album est toujours sélectionné, mais votre prochaine " "recherche passera quand même par le haut du catalogue, pas seulement par les " "albums." #: C/moreusage.page:130(p) msgid "" "How to come back into the subcatalog you were in? You do that by simply " "browsing, not searching the first thing you do when you focus Kupfer again. A quick way is to press down-arrow or space to open the browse " "window; think of it as saying \"I want to stay in this subfolder\". With the " "browse window open, your next query will search the current subcatalog." msgstr "" "Comment revenir dans le sous-catalogue où vous étiez ? Simplement en " "naviguant et non pas en recherchant, ce que vous faites habituellement en " "premier quand vous activez Kupfer. La méthode la plus rapide est " "de presser la touche flèche vers le bas, ou la barre d'espace pour ouvrir la " "fenêtre du navigateur ; pensez-y si vous « souhaitez rester dans ce sous-" "catalogue ». Une fois la fenêtre du navigateur ouverte, recherchez le sous-" "catalogue actuel." #: C/moreusage.page:137(p) msgid "" "This way you can work both ways -- you can quickly drill down into folders " "to find a file, and when you come back for the next action with Kupfer you can either summon any normal toplevel object (just start typing), " "or stay around where you were, deep in that folder (press space, then type a " "query)." msgstr "" "De cette façon, vous pouvez travailler de deux façons : vous pouvez explorer " "rapidement les dossiers à la recherche d'un fichier, et quand vous revenez " "dans Kupfer pour l'action suivante, vous pouvez soit appeler " "n'importe quel objet de premier plan (saisissez simplement votre demande), " "soit rester où vous étiez, dans les profondeurs de ce dossier (appuyez sur " "la barre d'espace et saisissez votre demande)." #: C/moreusage.page:146(title) msgid "Saving Commands as Files" msgstr "Enregistrement de commandes en tant que fichiers exécutables" #: C/moreusage.page:147(p) msgid "" "You can use keyboard shortcut for Compose Command (by default it is " "CtrlReturn) to create a command " "object out of the currently focused command in Kupfer. This object can be " "saved as a runnable file if you use the Save As... action. The " "resulting file will can be executed when opened from the file manager (it " "requires that Kupfer is already running)." msgstr "" "Vous pouvez utiliser un raccourci clavier de Composition de commande (par défaut, CtrlEntrée) pour " "créer un objet commande à partir de la commande actuellement active dans " "Kupfer. Cet objet peut être enregistré en tant que fichier " "exécutable si vous utilisez l'action Enregistrer sous.... Le " "fichier résultant peut être exécuté en l'ouvrant à partir du gestionnaire de " "fichiers (Kupfer doit être en cours d'exécution)." #: C/managing-plugins.page:7(desc) msgid "Using plugins with Kupfer." msgstr "Utiliser des greffons avec Kupfer." #: C/managing-plugins.page:10(title) msgid "How to Configure Plugins" msgstr "Configuration des greffons" #: C/managing-plugins.page:12(p) msgid "" "Functionality in Kupfer is organized by extentsion modules called \"plugins" "\". Each plugin provides additional functionality, for example integration " "with an external application." msgstr "" "Les fonctions de Kupfer sont organisées en modules d'extensions appelés " "« greffons » ou « extensions » ou encore « plugins ». Chaque greffon fournit " "une fonction supplémentaire, par exemple l'intégration dans une application " "externe." #: C/managing-plugins.page:19(title) msgid "Configuring Plugins" msgstr "Configuration des greffons" #: C/managing-plugins.page:21(title) msgid "Open Kupfer Preferences to the Plugins tab" msgstr "Ouverture des Préférences de Kupfer à l'onglet « Greffons »." #: C/managing-plugins.page:23(p) msgid "Use one of the following methods:" msgstr "Utilisez l'une des méthodes suivantes :" #: C/managing-plugins.page:25(p) msgid "" "Click the Kupfer icon in the notification area and select the item " "Preferences" msgstr "" "Cliquez sur l'icône « Kupfer » dans la zone de notification et sélectionnez " "l'élément Préférences" #: C/managing-plugins.page:25(item) msgid "." msgstr "." #: C/managing-plugins.page:29(p) msgid "" "Search for the object Kupfer Preferences in Kupfer itself. Press " "Return to open it." msgstr "" "Recherchez l'objet Préférences de Kupfer dans Kupfer lui-même. " "Appuyez sur Entrée pour l'ouvrir." #: C/managing-plugins.page:33(p) msgid "Use the keyboard shortcut Ctrl;" msgstr "" "Utilisez le raccourci clavier Ctrl;" #: C/managing-plugins.page:39(p) msgid "Select the tab Plugins" msgstr "Sélectionnez l'onglet Extensions" #: C/managing-plugins.page:45(p) msgid "" "Select plugins in the list to read about them, and tick the box next to its " "name to activate the plugin, or untick to deactivate." msgstr "" "Sélectionnez un greffon dans la liste pour afficher les informations le " "concernant et cochez la case adjacente pour l'activer. Décochez la case pour " "le désactiver." #: C/managing-plugins.page:49(p) msgid "" "If the plugin has any configurable parameters, they will be visible below " "the plugin information." msgstr "" "Si le greffon possède des paramètres, ils sont visibles en dessous des " "informations concernant le greffon." #: C/managing-plugins.page:53(p) msgid "" "The plugin Kupfer Plugins allows fast access to each plugin's " "information page as well as the action \"Show Source Code\" which reveals " "the implementation." msgstr "" "Le greffon Greffons Kupfer permet un accès rapide à chaque page " "d'informations sur les greffons ainsi qu'à l'action « Afficher le code " "source » qui laisse voir la mise en œuvre." #: C/managing-plugins.page:59(title) msgid "If a Plugin can not be Activated" msgstr "Impossibilité d'activer un greffon" #: C/managing-plugins.page:60(p) msgid "" "If a plugin fails to activate because it requires a software module that is " "not available, its plugin information will display a message like this:" msgstr "" "Si l'activation d'un greffon échoue à cause de l'absence d'un module " "logiciel, les informations du greffon affichent un message de ce type :" #: C/managing-plugins.page:65(em) msgid "Plugin could not be read due to an error:" msgstr "Le greffon n'a pas pu être lu à cause d'une erreur :" #: C/managing-plugins.page:66(em) msgid "Python module 'gdata' is needed" msgstr "Le module Python « gdata » est requis" #: C/managing-plugins.page:67(p) msgid "" "This means that you need to install a needed python module from your " "distribution—and possibly the plugin documentation can tell you how." msgstr "" "Cela signifie que vous devez installer un module python indispensable en " "fonction de votre distribution. La documentation du greffon vous indiquera " "probablement comment procéder." #: C/managing-plugins.page:72(p) msgid "" "The plugin may also unexpectedly fail to load, and display a different error " "message. It may then be a program error in either the plugin or Kupfer." msgstr "" "Le chargement du greffon peut aussi échouer de façon inattendue et afficher " "un message d'erreur différent. Il peut s'agir d'une erreur de programme dans " "le greffon ou dans Kupfer." #: C/managing-plugins.page:79(title) msgid "Installing more Plugins" msgstr "Installation de greffons supplémentaires" #: C/managing-plugins.page:80(p) msgid "" "You can install custom plugins into the folder ~/.local/share/kupfer/" "plugins. Each plugin is either a single .py file or a " "python package (a folder directly containing a file called __init__." "py). Plugins in the package format can include icon files. Python " "packages can even be installed as .zip files." msgstr "" "Vous pouvez installer des greffons personnalisés dans le dossier ~/." "local/share/kupfer/plugins. Chaque greffon est soit un simple fichier " ".py, soit un paquet Python (un dossier contenant un fichier " "appelé __init__.py). Les greffons sous forme de paquet peuvent " "inclure des fichiers d'icônes. Les paquets Python peuvent même être " "installés en tant que fichiers .zip." #: C/managing-plugins.page:88(p) msgid "" "Caution: Treat a plugin as a computer program. Do not install " "untrusted plugins." msgstr "" "Attention : traitez les greffons comme des programmes d'ordinateur. " "N'installez pas de greffons d'origine douteuse." #: C/managing-plugins.page:95(title) msgid "Creating Plugins" msgstr "Création de greffons" #: C/managing-plugins.page:96(p) msgid "" "Documentation for plugin creators is available in the file " "Documentation/Manual.rst in the source distribution on the " "webpage at Kupfer " "Manual. An easy way to start is to copy an existing plugin and " "experimenting with it." msgstr "" "La documentation pour les créateurs de greffons se trouve dans le fichier " "Documentation/Manual.rst de la distribution source sur la page " "Web du Manuel de " "Kupfer. Une manière facile de démarrer est de copier un greffon " "existant et de s'entraîner avec." #: C/managing-plugins.page:107(title) msgid "The Catalog Tab in Preferences" msgstr "L'onglet Catalogue dans les Préférences" #: C/managing-plugins.page:108(p) msgid "" "Each plugin can export a number of sources which contain objects. Normally, " "all these objects are directly accessible from a top-level search. Some " "plugins export so specialized or so many objects that their catalogs should " "better not have their objects exported to the top level. To reach those " "objects, you have to first find the catalog by name, then enter the catalog " "using the action Search Contents." msgstr "" "Chaque greffon peut exporter de nombreuses sources contenant des objets. " "Normalement, tous ces objets sont directement accessibles par une recherche " "dans le haut du catalogue. Certains greffons exportent des objets si " "spécialisés ou si nombreux qu'il vaut mieux qu'ils ne soient pas exportés " "vers le haut du catalogue. Dès lors, pour atteindre ces objets, vous devez " "d'abord rechercher le catalogue par son nom, puis l'ouvrir par l'action " "Recherche de contenu." #: C/managing-plugins.page:118(p) msgid "" "In the tab Catalog in Kupfer Preferences, a ticked box " "next to each source means that its objects are exported. An unticked box " "means that its contents are hidden from the top level." msgstr "" "Dans l'onglet Catalogue des Préférences de Kupfer, une " "case cochée à côté de chaque source signifie que ses objets sont exportés. " "Une case non cochée signifie que son contenu est masqué dans le haut du " "catalogue." #: C/managing-plugins.page:123(p) msgid "" "Note: Kupfer may become slow if large enough subcatalogs are " "exported to the top level." msgstr "" "Note : Kupfer peut ralentir si de trop gros sous-catalogues sont " "exportés vers le haut du catalogue." #: C/license.page:7(desc) msgid "You can copy, modify and share Kupfer." msgstr "Vous pouvez copier, modifier et partager Kupfer." #: C/license.page:10(title) msgid "License" msgstr "Licence" #: C/license.page:12(p) msgid "" "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." msgstr "" "Ce programme est un logiciel libre ; vous pouvez le redistribuer et/ou le " "modifier au titre des clauses de la Licence Publique Générale GNU, telle que " "publiée par la Free Software Foundation ; soit la version 2 de la Licence, " "ou (à votre discrétion) une version ultérieure quelconque." #: C/license.page:18(p) msgid "" "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." msgstr "" "Ce programme est distribué dans l'espoir qu'il sera utile, mais SANS AUCUNE " "GARANTIE ; sans même une garantie implicite de COMMERCIABILITÉ ou DE " "CONFORMITÉ À UNE UTILISATION PARTICULIÈRE. Voir la Licence Publique Générale " "GNU pour plus de détails." #: C/license.page:24(p) msgid "" "You should have received a copy of the GNU General Public License along with " "this program. If not, see gnu." "org/licenses." msgstr "" "Vous devriez avoir reçu un exemplaire de la Licence Publique Générale GNU " "avec ce programme ; si ce n'est pas le cas, écrivez à la Free Software " "Foundation Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." #: C/license.page:30(p) msgid "" "This documentation is licensed under a Creative Commons Attribution-Share Alike 3.0 " "Unported License." msgstr "" "Ce document est publié sous licence Creative Commons Paternité-Partage des " "Conditions Initiales à l'Identique 3.0 Unported." #: C/license.page:36(p) msgid "" "As a special exception, the copyright holders give you permission to copy, " "modify, and distribute the example code contained in this document under the " "terms of your choosing, without restriction." msgstr "" "À titre exceptionnel, les détenteurs des droits vous autorisent à copier, " "modifier et distribuer les exemples de code contenus dans ce document selon " "vos propres termes, sans restriction." #: C/keyboard.page:7(desc) msgid "Complete keyboard shortcuts reference." msgstr "Référence complète des raccourcis clavier." #: C/keyboard.page:10(title) msgid "Command Keys and Accelerator Keys" msgstr "Touches de commande et touches d'accélération" #: C/keyboard.page:13(title) C/generalusage.page:12(title) msgid "Keyboard Interface" msgstr "Interface du clavier" #: C/keyboard.page:14(p) msgid "In command mode, the following keystrokes have special meanings:" msgstr "En ligne de commande, les touches suivantes ont un sens particulier :" #: C/keyboard.page:19(p) C/generalusage.page:34(p) msgid " or Space" msgstr " ou Espace" #: C/keyboard.page:20(p) C/generalusage.page:35(p) msgid "Go to the next match" msgstr "va à la proposition suivante" #: C/keyboard.page:23(p) C/generalusage.page:38(p) msgid " or ShiftSpace" msgstr " ou MajEspace" #: C/keyboard.page:26(p) C/generalusage.page:41(p) msgid "Go to the previous match" msgstr "va à la proposition précédente" #: C/keyboard.page:29(p) C/generalusage.page:44(p) msgid " or /" msgstr " ou /" #: C/keyboard.page:30(p) C/generalusage.page:45(p) msgid "Descend into an object with content" msgstr "descend dans un objet avec un contenu" #: C/keyboard.page:33(key) C/generalusage.page:48(key) msgid "Backspace" msgstr "Retour Arrière" #: C/keyboard.page:34(p) C/generalusage.page:49(p) msgid "Erase a character from the query. If the query is empty, go up a level" msgstr "" "efface un caractère de la question. Si la question est vide, remonte d'un " "niveau" #: C/keyboard.page:39(key) C/keyboard.page:93(key) C/generalusage.page:54(key) msgid "." msgstr "." #: C/keyboard.page:40(p) C/generalusage.page:55(p) msgid "Activate free-text mode" msgstr "active le mode texte libre" #: C/keyboard.page:43(key) C/keyboard.page:97(key) C/generalusage.page:58(key) msgid "," msgstr "," #: C/keyboard.page:44(p) C/generalusage.page:59(p) msgid "Put selected object on the stack (\"Comma Trick\")" msgstr "dépose les objets sélectionnés sur la pile (« Astuce virgule »)" #: C/keyboard.page:47(p) msgid "Quick access keys:" msgstr "Touches d'accès rapide :" #: C/keyboard.page:53(key) msgid "=" msgstr "=" #: C/keyboard.page:55(p) msgid "" "Activate free-text mode with = prefix (for )" msgstr "" "active le mode texte libre avec le préfixe = (pour le greffon " ")." #: C/keyboard.page:61(key) msgid "/" msgstr "/" #: C/keyboard.page:63(p) msgid "" "Activate free-text mode (when nothing is selected) with / " "prefix (to input a rooted path)" msgstr "" "active le mode texte libre (quand rien n'est sélectionné) avec le préfixe " "/ (pour saisir un nom de chemin commençant à la racine)" #: C/keyboard.page:68(p) C/generalusage.page:62(p) msgid "Additionally:" msgstr "En outre :" #: C/keyboard.page:72(p) C/generalusage.page:66(p) msgid "" "Return activates the current selection: the command is executed." msgstr "" "La touche Entrée active la sélection en cours : la commande est " "exécutée." #: C/keyboard.page:74(p) C/generalusage.page:68(p) msgid "Escape clears the current selection." msgstr "La touche Échap supprime la sélection en cours." #: C/keyboard.page:75(p) C/generalusage.page:69(p) msgid "Tab switches between the object and the action pane." msgstr "" "La touche Tab bascule entre le volet objet et le volet action." #: C/keyboard.page:77(p) msgid "" "The meaning of the keys Space, ., ,, /" " and = can not be changed, but you can deactivate their " "special meaning with the checkbox Use single keystroke commands " "in Kupfer Preferences." msgstr "" "La signification des touches Espace, ., ,, " "/ et = ne peut être modifiée, mais vous pouvez " "désactiver leur signification spéciale avec la case à cocher Utiliser " "les commandes à l'aide d'une seule touche dans les Préférences de " "Kupfer." #: C/keyboard.page:86(title) msgid "Kupfer's Keyboard Shortcuts" msgstr "Raccourcis clavier de Kupfer" #: C/keyboard.page:87(p) msgid "" "These keyboard shortcuts are used in Kupfer's interface. They " "have the following meanings and default shortcuts:" msgstr "" "Ces raccourcis clavier sont utilisés dans l'interface de Kupfer. " "Ils ont les significations suivantes :" #: C/keyboard.page:93(key) C/keyboard.page:97(key) C/keyboard.page:101(key) #: C/keyboard.page:105(key) C/keyboard.page:113(key) C/keyboard.page:117(key) #: C/keyboard.page:121(key) C/keyboard.page:125(key) C/keyboard.page:129(key) #: C/keyboard.page:174(key) msgid "Ctrl" msgstr "Ctrl" #: C/keyboard.page:94(p) msgid "Toggle text mode" msgstr "bascule en mode texte" #: C/keyboard.page:98(p) msgid "The comma trick" msgstr "l'astuce virgule" #: C/keyboard.page:101(key) msgid ";" msgstr ";" #: C/keyboard.page:102(p) msgid "Show preferences window" msgstr "affiche la boîte de dialogue préférences" #: C/keyboard.page:105(key) msgid "R" msgstr "R" #: C/keyboard.page:106(p) msgid "Reset all" msgstr "réinitialise tout" #: C/keyboard.page:109(key) msgid "Alt" msgstr "Alt" #: C/keyboard.page:109(key) msgid "A" msgstr "A" #: C/keyboard.page:110(p) msgid "Alternate activate" msgstr "activation alternative" #: C/keyboard.page:113(key) msgid "Return" msgstr "Entrée" #: C/keyboard.page:114(p) msgid "Compose command" msgstr "commande de composition" #: C/keyboard.page:117(key) msgid "S" msgstr "S" #: C/keyboard.page:118(p) msgid "Switch to first pane" msgstr "passe au premier volet" #: C/keyboard.page:121(key) msgid "Q" msgstr "Q" #: C/keyboard.page:122(p) msgid "Select 'Quit'" msgstr "sélectionne « Quitter »" #: C/keyboard.page:125(key) msgid "G" msgstr "G" #: C/keyboard.page:126(p) msgid "Select 'Selected File'" msgstr "sélectionne « Fichier sélectionné »" #: C/keyboard.page:129(key) msgid "T" msgstr "T" #: C/keyboard.page:130(p) msgid "Select 'Selected Text'" msgstr "sélectionne « Texte sélectionné »" #: C/keyboard.page:133(key) msgid "F1" msgstr "F1" #: C/keyboard.page:134(p) msgid "Show Help" msgstr "affiche l'aide" #: C/keyboard.page:139(title) msgid "How to configure a keyboard shortcut" msgstr "Configuration d'un raccourci clavier" #: C/keyboard.page:141(p) C/keyboard.page:185(p) msgid "Open Kupfer Preferences and go to the Keyboard tab." msgstr "" "Ouvrez les Préférences de Kupfer et allez à l'onglet Clavier." #: C/keyboard.page:147(p) msgid "" "Double-click the shorcut's row under Browser Keyboard Shortcuts." msgstr "" "Faites un double clic sur la ligne du raccourci au-dessous de Raccourcis " "clavier du navigateur." #: C/keyboard.page:153(p) msgid "" "Using the window that appears, press modifier keys and a letter or number " "key to set a shortcut. An example is pressing and holding Ctrl " "and then pressing and releasing T to bind CtrlT." msgstr "" "Dans la boîte de dialogue qui s'affiche, appuyez sur les touches de " "modification et une touche lettre ou chiffre pour définir un raccourci. Par " "exemple, maintenez l'appui sur la touche Ctrl et appuyez puis " "relâchez la touche T pour lier CtrlT." #: C/keyboard.page:164(title) msgid "Global Keyboard Shortcuts" msgstr "Raccourcis clavier généraux" #: C/keyboard.page:165(p) msgid "" "Kupfer always listens to global shortcuts, even if it is not " "currently in the foreground." msgstr "" "Kupfer écoute en permanence les raccourcis clavier, même s'il est " "actuellement en arrière plan." #: C/keyboard.page:169(p) msgid "They have the following meanings and default shortcuts:" msgstr "Voici les raccourcis par défaut et leur signification :" #: C/keyboard.page:174(key) msgid "Space" msgstr "barre d'espace" #: C/keyboard.page:175(p) msgid "Show/hide Kupfer" msgstr "affiche/masque Kupfer" #: C/keyboard.page:178(p) msgid "(not configured by default)" msgstr "(non configuré par défaut)" #: C/keyboard.page:179(p) msgid "Show Kupfer with 'Selection' object focused" msgstr "affiche Kupfer avec l'objet « Sélection » au premier plan" #: C/keyboard.page:183(title) msgid "How to configure a global keyboard shortcut" msgstr "Configuration d'un raccourci clavier global" #: C/keyboard.page:191(p) msgid "" "Double-click the shorcut's row under Global Keyboard Shortcuts." msgstr "" "Faites un double clic sur la ligne du raccourci au-dessous de Raccourcis " "clavier globaux." #: C/keyboard.page:197(p) msgid "" "Using the window that appears, press modifier keys and a letter or number " "key to set a global shortcut. An example is pressing and holding Super and then pressing and releasing Space to bind " "SuperSpace." msgstr "" "Dans la boîte de dialogue qui s'affiche, appuyez sur les touches de " "modification et une touche lettre ou chiffre pour définir un raccourci " "global. Par exemple, en maintenant la pression sur Super puis en " "pressant et relâchant la barre d'espace pour lier " "Superbarre d'espace." #: C/keyboard.page:206(p) msgid "" "Since these keyboard shortcuts are global, they can be used from any " "application. Select shortcuts with care so that they do not conflict with " "other functions." msgstr "" "Puisque ces raccourcis clavier sont globaux, il est possible de les utiliser " "à partir de n'importe quelle application. Choisissez les raccourcis avec " "soin, de façon à ce qu'ils n'entrent pas en conflit avec d'autres fonctions." #: C/keyboard.page:214(p) msgid "" "The plugin Triggers allows to activate actions with global keyboard " "shortcuts. Trigger shortcuts do not appear in Kupfer Preferences." msgstr "" "Le greffon Raccourcis déclencheurs permet d'activer des actions " "avec des raccourcis clavier globaux. Les raccourcis déclencheurs " "n'apparaissent pas dans les Préférences de Kupfer." #: C/keyboard.page:220(p) msgid "See for more information." msgstr "" "Consultez la section pour plus " "d'informations." #: C/introduction.page:7(desc) msgid "Introduction to Kupfer." msgstr "Introduction à Kupfer." #: C/introduction.page:10(title) msgid "Introduction" msgstr "Introduction" #: C/introduction.page:12(p) msgid "" "Kupfer is an interface for quick and convenient access to " "applications and their documents." msgstr "" "Kupfer est une interface pour un accès rapide et pratique aux " "applications et à leurs documents." #: C/introduction.page:16(p) msgid "" "The most typical use is to find a specific application and launch it. We " "have tried to make Kupfer easy to extend with plugins so that " "this quick-access paradigm can be extended to many more objects than just " "applications." msgstr "" "Son usage le plus courant est la recherche d'une application particulière et " "son lancement. Nous nous sommes efforcés de rendre Kupfer facile " "à compléter avec des greffons pour que ce paradigme d'accès rapide puisse " "s'étendre à bien d'autres objets que les applications." #: C/introduction.page:22(p) msgid "" "We hope that using Kupfer feels both very fun and " "different." msgstr "" "Nous espérons que l'utilisation de Kupfer vous semble très " "amusante et différente." #: C/introduction.page:26(p) msgid "" "For up-to-date information about Kupfer, visit its homepage." msgstr "" "Pour obtenir des informations actualisées sur Kupfer, allez sur " "sa page d'accueil." #: C/index.page:9(name) msgid "Ulrik Sverdrup" msgstr "Ulrik Sverdrup" #: C/index.page:10(email) msgid "ulrik.sverdrup@gmail.com" msgstr "ulrik.sverdrup@gmail.com" #: C/index.page:13(year) msgid "2009" msgstr "2009" #: C/index.page:14(name) msgid "Kupfer Development Team" msgstr "Équipe de développement de Kupfer" #: C/index.page:17(license) msgid "Creative Commons Share Alike 3.0" msgstr "Creative Commons Partage des Conditions Initiales à l'Identique 3.0" #: C/index.page:21(title) msgid "Kupfer Manual" msgstr "Manuel de Kupfer" #: C/index.page:24(title) msgid "Using Kupfer" msgstr "Utilisation de Kupfer" #: C/index.page:27(title) msgid "About Specific Plugins" msgstr "À propos de greffons particuliers" #: C/generalusage.page:7(desc) msgid "How to start using Kupfer." msgstr "Comment débuter avec Kupfer." #: C/generalusage.page:14(p) msgid "" "Kupfer is to the largest part a keyboard-managed interface to " "applications and documents." msgstr "" "Kupfer est majoritairement une interface clavier qui gère les " "applications et les documents." #: C/generalusage.page:18(p) msgid "" "Kupfer's default mode is the command mode: If you type a query, kupfer will " "search for a match in its catalog." msgstr "" "Le mode par défaut de Kupfer est la ligne de commande : si vous saisissez " "une demande, Kupfer cherche une correspondance dans son catalogue." #: C/generalusage.page:23(p) msgid "" "The arrow keys allow you to browse query matches quite naturally, going to " "the previous or next match, and going up and down in the subcatalogs." msgstr "" "Les touches de direction vous permettent de naviguer tout naturellement " "parmi les réponses proposées, allant de la précédente à la suivante et de " "haut en bas dans les sous-catalogues." #: C/generalusage.page:29(p) msgid "In command mode, some keystrokes have special meanings:" msgstr "En ligne de commande, certaines touches ont un sens particulier :" #: C/generalusage.page:71(p) msgid "" "By default you show Kupfer using the global keyboard shortcut " "CtrlSpace." msgstr "" "Par défaut, vous affichez Kupfer avec le raccourci clavier " "CtrlEspace." #: C/generalusage.page:74(p) msgid "See for more information." msgstr "" "Consultez la section pour plus d'informations." #: C/generalusage.page:78(title) msgid "Learning Habits" msgstr "Apprentissage" #: C/generalusage.page:79(p) msgid "" "Kupfer remembers which objects and actions are used the most. " "When beginning to use it, you have to use the arrow keys at times to make it " "precise which object you want to find. After a few uses of that object, " "Kupfer will rank it higher. Objects marked as favorites are also ranked higher." msgstr "" "Kupfer se souvient des objets et des actions les plus utilisés. " "Au début de son utilisation, vous devez vous servir des touches fléchées " "souvent pour préciser quel objet vous recherchez dans une liste. Après " "quelques appels de cet objet, Kupfer le classera à un rang " "supérieur. Les objets marqués comme favoris ont aussi un rang supérieur." #: C/generalusage.page:90(title) msgid "The Catalog" msgstr "Le catalogue" #: C/generalusage.page:91(p) msgid "" "The Catalog is the collection of objects you can access in Kupfer, such as " "documents and programs." msgstr "" "Le catalogue est la collection d'objets auxquels vous pouvez accéder dans " "Kupfer, comme des documents et des programmes." #: C/generalusage.page:96(p) msgid "" "Objects in the catalog that have content, like folders, are marked with an " "arrow. Pressing will enter these objects. Much of the catalog " "is composed of subcatalogs; plugin subcatalogs do in general list objects " "that are also available directly from the top level. Subcatalogs can be used " "for a narrower view or search scope, when using Kupfer." msgstr "" "Les objets du catalogue qui ont un contenu, tels que des dossiers, sont " "marqués d'une flèche. Appuyer sur la touche ouvre ces objets. " "La plus grande partie du catalogue est constituée de sous-catalogues ; les " "sous-catalogues des greffons énumèrent des objets qui sont disponibles " "directement depuis le haut du catalogue. Les sous-catalogues sont utiles " "pour obtenir une vision plus restreinte ou une recherche limitée lors de " "l'utilisation de Kupfer." #: C/generalusage.page:105(p) msgid "" "Most subcatalogs update their content automatically. For example, the " "Desktop folder source is always up-to-date." msgstr "" "La plupart des sous-catalogues mettent automatiquement à jour leur contenu. " "Par exemple, la source du dossier Bureau est toujours maintenue à jour." #. Put one translator per line, in the form of NAME , YEAR1, YEAR2 #: C/index.page:0(None) msgid "translator-credits" msgstr "" "Alain Lojewski , 2010, 2012\n" "Julien Hardelin , 2011\n" "Bruno Brouard , 2012" kupfer-328/help/it/000077500000000000000000000000001500175051100142235ustar00rootroot00000000000000kupfer-328/help/it/it.po000066400000000000000000000671651500175051100152160ustar00rootroot00000000000000# Italian translation for the kupfer help # Copyright (C) 2009 Ulrik Sverdrup # This file is distributed under the same license as the kupfer package. (GPLv3) # Francesco Marella , 2010. # msgid "" msgstr "" "Project-Id-Version: kupfer beta\n" "POT-Creation-Date: 2010-07-11 16:18+0000\n" "PO-Revision-Date: 2010-08-19 09:51+0200\n" "Last-Translator: Francesco Marella \n" "Language-Team: Italian \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" #: C/tips.page:7(desc) msgid "Using Kupfer more conveniently." msgstr "Usare Kupfer opportunamente." #: C/tips.page:10(title) msgid "Basic Usage" msgstr "Uso di base" #: C/tips.page:13(title) msgid "The Catalog" msgstr "Il catalogo" #: C/tips.page:14(p) msgid "" "The Catalog is the collection of objects you can access in Kupfer, such as " "documents and programs." msgstr "" "Il catalogo è la raccolta di oggetti a cui puoi accedere in Kupfer, ad " "esempio documenti e programmi." #: C/tips.page:19(p) msgid "" "Objects in the catalog that have content, like folders, are marked with an " "arrow. Pressing right-arrow will enter these objects. Much of the " "catalog is composed of subcatalogs; plugin subcatalogs do in general list " "objects that are also available directly from the top level. Subcatalogs can " "be used for a narrower view or search scope, when using Kupfer." msgstr "" "Gli oggetti nel catalogo che hanno contenuto, come le cartelle, sono " "contrassegnati con una freccia. Premendo si entra nell'oggetto. " "Gran parte del catalogo è composta da sotto cataloghi; il plugin sotto " "catalogo generalmente cataloga oggetti che sono anche disponibili " "direttamente dal livello superiore. I sotto cataloghi possono essere usati " "per una vista o ambito di ricerca ristretto, quando si utilizza Kupfer." #: C/tips.page:28(p) msgid "" "Most subcatalogs update their content automatically. For example, the " "Desktop folder catalog is always uptodate." msgstr "" "La maggior parte dei sotto cataloghi aggiorna il loro contenuto " "automaticamente. Per esempio, il catalogo per la cartella Scrivania è sempre " "aggiornato." #: C/tips.page:35(title) msgid "Keyboard Interface" msgstr "Interfaccia da tastiera" #: C/tips.page:37(p) msgid "" "Kupfer is to the largest part a keyboard-managed interface to " "applications and documents." msgstr "" "Kupfer è grosso modo una interfaccia, gestita da tastiera, ad " "applicazioni e documenti." #: C/tips.page:41(p) msgid "" "Kupfer's default mode is the command mode: If you type a query, kupfer will " "search for a match in its catalog." msgstr "" "La modalità predefinita di Kupfer è quella a comando: se viene digitata " "l'interrogazione, Kupfer cercherà una corrispondenza nel suo catalogo." #: C/tips.page:46(p) msgid "" "The arrow keys allow you to browse query matches quite naturally, going to " "the previous or next match, and going up and down in the subcatalogs." msgstr "" "I tasti freccia permettono di scorrere tra i risultati dell'interrogazione " "naturalmente, andando alla corrispondenza precedente o a quella successiva e " "andando su e giù nei sotto cataloghi." #: C/tips.page:52(p) msgid "In command mode, some keystrokes have special meanings:" msgstr "" "In modalità comando, la pressione di alcuni tasti ha un significato speciale:" #: C/tips.page:57(p) msgid " or Space" msgstr " o Spazio" #: C/tips.page:58(p) msgid "Go to the next match" msgstr "Va alla prossima corrispondenza" #: C/tips.page:61(p) msgid " or ShiftSpace" msgstr " o MaiuscSpazio" #: C/tips.page:64(p) msgid "Go to the previous match" msgstr "Va alla precedente corrispondenza" #: C/tips.page:67(p) msgid " or /" msgstr " o /" #: C/tips.page:68(p) msgid "Descend into an object with content" msgstr "Discende in un oggetto con contenuto" #: C/tips.page:71(key) msgid "Backspace" msgstr "Backspace" #: C/tips.page:72(p) msgid "Erase a character from the query. If the query is empty, go up a level" msgstr "" "Elimina un carattere dall'interrogazione. Se l'interrogazione è vuota, " "salire di un livello" #: C/tips.page:77(key) msgid "." msgstr "." #: C/tips.page:78(p) msgid "Activate free-text mode" msgstr "Attiva la modalità testo libero" #: C/tips.page:81(key) msgid "," msgstr "," #: C/tips.page:82(p) msgid "Put selected object on the stack (\"Comma Trick\")" msgstr "Mette l'oggetto selezionato sulla pila (\"Comma Trick\")" #: C/tips.page:85(p) msgid "" "Additionally, the key Return activates the current selection: the " "command is executed. Escape clears the current selection." msgstr "" "Inoltre, il tasto Invio attiva la selezione corrente: il comando " "viene eseguito. Esc cancella la selezione corrente." #: C/tips.page:91(title) msgid "Global Keyboard Shortcuts" msgstr "Scorciatoie da tastiera globali" #: C/tips.page:92(p) msgid "" "Kupfer listens to global shortcuts, even if Kupfer is not currently in the " "foreground. The most important global shortcut is the shortcut to show and " "hide Kupfer's command window which by default is CtrlSpace." msgstr "" "Kupfer resta in ascolto per le scorciatoie globali, anche se Kupfer non è " "attualmente in primo piano. La scorciatoia globale più importante è quella " "per mostrare e nascondere la finestra di comando di Kupfer che in maniera " "predefinita è CtrlSpazio." #: C/tips.page:98(p) msgid "Global Keyboard Shortcuts are configured in Kupfer's preferences." msgstr "" "Collegamenti da tastiera globali vengono configurati nelle preferenze di " "Kupfer." #: C/tips.page:101(p) msgid "" "The Triggers plugin allows to configure actions to be activated by global " "shortcuts, but triggers can only be configured in that plugin." msgstr "" "Il plugin Trigger permette di configurare azioni da attivare con scorciatoie " "globali, ma i trigger possono essere solo configurati in questo plugin." #: C/tips.page:108(title) msgid "Additional Keyboard Shortcuts" msgstr "Scorciatoie da tastiera aggiuntive" #: C/tips.page:109(p) msgid "" "Additional keyboard shortcuts that work with Kupfer when it is in the " "foreground can be configured in Kupfer's preferences." msgstr "" "Scorciatoie da tastiera aggiuntive che funzionano con Kupfer quando esso è " "in primo piano possono essere configurate nelle preferenze di Kupfer." #: C/tips.page:119(title) msgid "Configuration files and paths" msgstr "File di configurazione e percorsi" #: C/tips.page:120(p) msgid "" "Install custom plugins in the folder ~/.local/share/kupfer/plugins/" msgstr "" "Installare plugin personalizzati nella cartella ~/.local/share/kupfer/" "plugins/" #: C/tips.page:124(p) msgid "" "Kupfer cache, config and data are located in the directories ~/.cache/" "kupfer, ~/.config/kupfer and ~/.local/share/" "kupfer." msgstr "" "La cache di Kupfer, configurazione e dati sono presenti nelle cartelle " "~/.cache/kupfer, ~/.config/kupfer e ~/.local/" "share/kupfer." #: C/plugins.page:7(desc) msgid "Using Kupfer plugins." msgstr "Utilizzo dei plugin di Kupfer." #: C/plugins.page:10(title) msgid "Plugins" msgstr "Plugin" #: C/plugins.page:12(p) msgid "" "You can install custom plugins into ~/.local/share/kupfer/plugins; adding to " "Kupfer's object knowledge can be surprisingly easy, just look at " "the default plugins if you want to create new." msgstr "" "Si possono installare plugin personalizzati in ~/.local/share/kupfer/" "plugins; aggiungere conoscenza agli oggetti di Kupfer può essere " "sorprendentemente facile, basta dare un'occhiata ai plugin predefiniti se si " "vuole crearne di nuovi." #: C/plugins.page:19(title) msgid "Search the Web Search Engines" msgstr "Motore di ricerca per il Web" #: C/plugins.page:20(p) msgid "" "The Search the Web plugin uses Firefox' search engines, so you " "can add Search Engines directly in Firefox and Kupfer " "will find them later." msgstr "" "Il plugin per la ricerca sul Web utilizza i motori di ricerca di " "Firefox, quindi si possono aggiungere motori di ricerca " "direttamente in Firefox e Kupfer li troverà in seguito." #: C/plugins.page:25(p) msgid "" "You can also install custom search plugins directly, only for Kupfer, in the folder:" msgstr "" "Si possono installare direttamente plugin per la ricerca personalizzata, " "solo per Kupfer, nella cartella:" #: C/plugins.page:29(code) #, no-wrap msgid "~/.local/share/kupfer/searchplugins/" msgstr "~/.local/share/kupfer/searchplugins/" #: C/plugins.page:34(title) msgid "Open Terminal Here" msgstr "Apri terminale qui" #: C/plugins.page:35(p) msgid "" "Open terminal first calls xdg-terminal, then gnome-terminal. xdg-terminal is a script to find the user's configured terminal " "program for his/her Desktop Environment. Install xdg-terminal if " "you need this (or install a symlink called xdg-terminal)." msgstr "" "Apri terminale interroga prima xdg-terminal, quindi gnome-" "terminal. xdg-terminal è uno script per individuare il terminale " "configurato dall'utente per il suo ambiente desktop. Installare xdg-" "terminal se necessario (oppure installare un collegamento con " "nome xdg-terminal)." #: C/plugins.page:44(title) msgid "Grab current selection" msgstr "Cattura la selezione corrente" #: C/plugins.page:45(p) msgid "" "To use Kupfer like a pro, you can configure a \"Magic Keybinding" "\" for Kupfer. GUI configuration is not yet supported, but edit " "the configuration file ~/.config/kupfer/kupfer.cfg to include " "the following:" msgstr "" "Per utilizzare Kupfer in modo professionale, si può configurare " "una \"associazione di tasti magica\" per Kupfer. Una " "configurazione grafica non è ancora supportata, ma è possibile modificare il " "file di configurazione ~/.config/kupfer/kupfer.cfg e includere " "quanto segue:" #: C/plugins.page:51(code) #, no-wrap msgid "" "\n" "[Kupfer]\n" "keybinding = <Control>space\n" "magickeybinding = <Ctrl><Alt>space\n" " " msgstr "" "\n" "[Kupfer]\n" "keybinding = <Control>space\n" "magickeybinding = <Ctrl><Alt>space\n" " " #: C/plugins.page:57(p) msgid "" "Now, pressing CtrlAltSpace " "will summon Kupfer with the current selection in focus. Make sure " "you have installed Kupfer's nautilus plugin, then both the " "currently selected file in Nautilus, or the currently selected text in the " "front application will be selected." msgstr "" "Ora, premendo CtrlAltSpazio verrà richiamato Kupfer con la selezione corrente in " "primo piano. Assicurarsi di avere installato il plugin per Nautilus di " "Kupfer, quindi sia il file attualmente selezionato in Nautilus, " "che il testo attualmente selezionato nell'applicazione in primo piano sarà " "selezionato." #: C/plugins.page:64(p) msgid "" "Now you can select a word in, say, a web browser, use CtrlAltSpace, and select action Look Up to look up the selected word. Or select an image file, use " "CtrlAltSpace, select " "action Scale with object 1000 to scale the image to " "1000 pixels wide!" msgstr "" "Ora si può selezionare una parola, ad esempio in un browser web usare " "CtrlAltSpazio, e " "selezionare l'azione Cerca per cercare la parola selezionata. " "Altrimenti selezionare un file immagine, usare CtrlAltSpazio, selezionare l'azione " "Scala con l'oggetto 1000 per scalare l'immagine a 1000 " "pixel di larghezza!" #: C/plugins.page:74(title) msgid "Adding your actions and scripts" msgstr "Aggiungere azioni e script personali" #: C/plugins.page:75(p) msgid "" "If you want to add a custom application, or an application called with " "special options, you can create a new launcher for it and place it in one of " "the standard places for applications, for example ~/.local/share/" "applications, where Kupfer will find it." msgstr "" "Se si vuole aggiungere una applicazione personalizzata, o una applicazione " "chiamata con opzioni speciali, si può creare un nuovo lanciatore e " "posizionarlo in una delle posizioni predefinite per le applicazioni, per " "esempio ~/.local/share/applications, dove Kupfer " "potrà trovarlo." #: C/plugins.page:81(p) msgid "" "If you have a collection of scripts that you want to call from Kupfer, you can add the scripts folder as a catalog directory to Kupfer in the preferences. Scripts that you add to Kupfer's catalog " "this way can be run directly or in the terminal as long as they are " "executable." msgstr "" "Se si ha una raccolta di script che si vuole chiamare da Kupfer, " "si può aggiungere la cartella degli script come un directory di cataloghi a " "Kupfer nelle preferenze. Gli script che vengono aggiunti nel " "catalogo di Kupfer in questo modo possono essere eseguiti " "direttamente o nel terminale a condizione che siano eseguibili." #: C/plugins.page:87(p) msgid "" "An example useful script is here which changes the rating of Rhythmbox's " "currently playing song; I have added five scriptlets calling rhrating." "py with numbers from 0 to 5 to my catalog to quickly rate tracks. " "(This is something that might be integrated into Kupfer later)" msgstr "" "Uno script di esempio utile è qui il quale cambia il giudizio di un brano " "attualmente in ascolto in Rhythmbox; ho aggiunto cinque scriptlet " "che chiamano rhrating.py con numeri da 0 a 5 per giudicare " "velocemente le tracce nel catalogo. (Questo potrebbe essere integrato in " "Kupfer successivamente)" #: C/plugins.page:97(title) msgid "Calculator Plugin" msgstr "Plugin calcolatrice" #: C/plugins.page:98(p) msgid "" "The calculator plugin lets you calculate expressions quickly. It can " "evaluate expressions entered as text starting with \"=\". Entering = from " "command mode will start text mode directly with = prefixed for quick access." msgstr "" "Il plugin calcolatrice permette di calcolare espressioni velocemente. Può " "valutare espressioni inserite come testo che iniziano con \"=\". Digitando = " "in modalità comando si entra direttamente in modalità testo con il prefisso " "= per l'accesso veloce." #: C/plugins.page:103(p) msgid "" "The Calculator uses python's math and complex math modules, and parses " "expressions as Python expressions. You may use common mathematical " "functions, such as sqrt, sin, exp and log; the command =help will " "show a list of all defined functions and constants." msgstr "" "La calcolatrice utilizza i moduli di matematica e matematica complessa di " "Python e analizza le espressioni come espressioni di Python. Si possono " "utilizzare funzioni matematiche comuni, come sqrt, sin, exp e log; il " "comando =help mostra una lista di tutte le funzioni e costanti " "definite." #: C/plugins.page:111(p) msgid "" "Notice that the power operator in Python is double stars, for example =3**3 " "will evaluate to 27." msgstr "" "Notare che l'operatore elevamento a potenza in Python è la doppia stella, " "per esempio =3**3 sarà valutato come 27." #: C/plugins.page:117(p) msgid "To calculate trig functions for angles, convert to radians first:" msgstr "" "Per calcolare le funzioni trigonometriche per gli angoli, prima convertire " "in radianti:" #: C/plugins.page:120(code) #, no-wrap msgid "sin(radians(30)) -> 0.5" msgstr "sin(radians(30)) -> 0.5" #: C/plugins.page:123(p) msgid "" "The last result is stored as the name _ (an underscore, just like in the " "Python console)." msgstr "" "L'ultimo risultato è memorizzato con il nome _ (un trattino basso, così come " "avviene in una console di Python)." #: C/plugins.page:133(title) msgid "Command line connection" msgstr "Connessione alla linea di comando" #: C/plugins.page:134(p) msgid "" "Kupfer is its own remote control. When Kupfer is " "already running, Kupfer on the command-line will focus its " "window, but there is more you can do: If you invoke kupferQUERY where QUERY is a text string or a " "filename, Kupfer will focus, and select this item. This way, you " "can quickly invoke Kupfer actions even on objects from a shell-" "based context." msgstr "" "Kupfer controlla a distanza se stesso. Quando Kupfer è " "già in esecuzione, Kupfer da riga di comando porta in primo piano " "la sua finestra, ma è possibile ottenere di più: se viene invocato " "kupferQUERY dove QUERY è una " "stringa di testo o il nome di un file, Kupfer porterà in primo " "piano e selezionerà questo elemento. In questo modo, si possono invocare " "velocemente le azioni di Kupfer persino su oggetti provenienti da " "un contesto basato su shell." #: C/plugins.page:142(p) msgid "" "For example, if you are using the shell in a directory where you have a file " "called \"report.pdf\", you can focus this file in Kupfer by " "running kupfer report.pdf." msgstr "" "Per esempio, se si utilizza la shell in una cartella in cui è presente un " "file chiamato \"report.pdf\", si può evidenziare questo file in Kupfer eseguendo kupfer report.pdf." #: C/plugins.page:147(p) msgid "" "You can also pipe the output of a command into Kupfer to send " "text to the already running instance of Kupfer." msgstr "" "Si può anche passare l'output di un comando in Kupfer per inviare " "il testo all'istanza in esecuzione di Kupfer." #: C/plugins.page:154(title) msgid "Managing Context and Current Selection" msgstr "Gestione del contesto e della selezione corrente" #: C/plugins.page:155(p) msgid "" "If you find the object you want to use, then invoke an action, Kupfer goes away to perform the action (for example start a program or play a " "song). When you come back to Kupfer, it will still keep the same " "object and action selected. Some actions make sense to be repeated (like " "skipping to the next song) and it can be useful to perform different actions " "on the same object." msgstr "" "Se è stato individuato l'oggetto da utilizzare, quindi si richiama " "un'azione, Kupfer scompare per eseguire l'azione (per esempio " "avviare un programma o riprodurre un brano). Quando si ritorna a " "Kupfer, verrà mantenuto lo stesso oggetto e l'azione selezionata. " "Alcune azioni hanno senso di essere ripetute (come saltare ad un brano " "successivo) e può essere utile eseguire azioni differenti sullo stesso " "oggetto." #: C/plugins.page:163(p) msgid "" "However, you always have the top level catalog reachable when you \"come back" "\" to Kupfer -- say you went into the subcatalog \"Albums\" to " "browse your albums only; you select and album to play, and play it. You come " "back with the album selected -- but your next search will still go over the " "top level catalog, not just albums." msgstr "" "Tuttavia, è sempre disponibile il livello superiore del catalogo " "raggiungibile quando \"si ritorna\" a Kupfer — per esempio si " "entra nel sotto catalogo \"Album\" per scorrere solo l'album selezionato; " "una volta selezionato l'album, esso viene riprodotto. Si ritorna all'album " "selezionato — ma la ricerca successiva andrà ancora al livello superiore del " "catalogo, non tra gli album." #: C/plugins.page:170(p) msgid "" "How to come back into the subcatalog you were in? You do that by simply " "browsing, not searching the first thing you do when you focus Kupfer again. A quick way is to press down-arrow or space to open the browse " "window; think of it as saying \"I want to stay in this subfolder\". With the " "browse window open, your next query will search the current subcatalog." msgstr "" "Come tornare nel sotto catalogo in cui si era in precedenza? Si può fare " "semplicemente sfogliando e non cercando nuovamente l'elemento in " "Kupfer. Un modo veloce è quello di premere la freccia verso il " "basso o spazio per aprire la finestra di navigazione; è come dire \"Voglio " "restare in questa sotto cartella\". Con la finestra di navigazione aperta, " "la prossima interrogazione cercherà nel sotto catalogo corrente." #: C/plugins.page:177(p) msgid "" "This way you can work both ways -- you can quickly drill down into folders " "to find a file, and when you come back for the next action with Kupfer you can either summon any normal toplevel object (just start typing), " "or stay around where you were, deep in that folder (press space, then type a " "query)." msgstr "" "In questo modo si può lavorare in entrambi i modi — si può rapidamente " "scendere nelle cartelle per trovare un file e quando si torna indietro per " "la prossima azione con Kupfer si può sia richiamare un oggetto " "qualsiasi dal livello superiore (iniziando a digitare), oppure rimanendo " "dove si era, scendendo in quella cartella (premere spazio, quindi digitare " "una interrogazione)." #: C/license.page:7(desc) msgid "Legal Information." msgstr "Informazioni legali." #: C/license.page:10(title) msgid "License" msgstr "Licenza" #: C/license.page:12(p) msgid "" "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." msgstr "" "Questo programma è software libero: è possibile ridistribuirlo o modificarlo " "secondo i termini della licenza GNU General Public License così " "come pubblicata dalla Free Software Foundation, nella versione 3 della " "Licenza, o (a vostra discrezione) successive." #: C/license.page:18(p) msgid "" "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." msgstr "" "Questo programma è distribuito con la speranza si dimostri utile, ma SENZA " "ALCUNA GARANZIA; si esclude anche l'implicita garanzia di COMMERCIABILITÀ o " "IDONEITÀ A UN PARTICOLARE SCOPO. Si consulti la licenza GNU General " "Public License per ulteriori dettagli." #: C/license.page:24(p) msgid "" "You should have received a copy of the GNU General Public License along with " "this program. If not, see gnu." "org/licenses." msgstr "" "Si dovrebbe ricevere una copia della licenza GNU General Public License con " "questo programma. In caso contrario, consultare gnu.org/licenses.\n" "La traduzione in Italiano di questa licenza non è ufficiale e da considerare " "solo a fini informativi." #: C/license.page:30(p) msgid "" "This documentation is licensed under a Creative Commons Attribution-Share Alike 3.0 " "Unported License." msgstr "" "Questa documentazione è sotto una licenza Creative Commons Attribution-Share " "Alike 3.0 Unported License." #: C/license.page:36(p) msgid "" "As a special exception, the copyright holders give you permission to copy, " "modify, and distribute the example code contained in this document under the " "terms of your choosing, without restriction." msgstr "" "Come eccezione, i detentori del copyright concedono il permesso di copiare, " "modificare e distribuire il codice di esempio contenuto in questo documento " "nei termini di tua scelta, senza restrizioni." #: C/introduction.page:7(desc) msgid "Introduction to Kupfer." msgstr "Introduzione a Kupfer." #: C/introduction.page:10(title) msgid "Introduction" msgstr "Introduzione" #: C/introduction.page:12(p) msgid "" "Kupfer is a program to change, speed up and make everything about " "files and programs more fun on your computer. Kupfer is a " "launcher; you typically use it to summon an application or a document " "quickly by typing parts of its name. It can also do more than getting at " "something quickly: there are different plugins for accessing more objects " "and running custom commands." msgstr "" "Kupfer è un programma per modificare, velocizzare e operare su " "file e programmi in modo più divertente sul tuo computer. Kupfer " "è un lanciatore; tipicamente viene utilizzato per richiamare un'applicazione " "o un documento velocemente digitando parti del suo nome. Può fare anche di " "più che ottenere qualcosa rapidamente: sono disponibili diversi plugin per " "accedere a più oggetti ed eseguire comandi personalizzati." #: C/introduction.page:22(p) msgid "" "Kupfer is written using Python and has a flexible architecture; " "the implementation is simple and makes the easy things work first. One goal " "is that new plugins can be written quickly without too much programming." msgstr "" "Kupfer è scritto in Python e ha una architettura flessibile; " "l'implementazione è semplice e fa funzionare prima le cose facili. " "L'obbiettivo principale è rendere la scrittura dei nuovi plugin veloce senza " "troppe conoscenze di programmazione." #: C/introduction.page:28(p) msgid "" "The program is very inspired by Quicksilver." msgstr "" "Il programma si ispira molto a Quicksilver." #: C/introduction.page:33(p) msgid "" "For more information about Kupfer, visit its homepage." msgstr "" "Per maggiori informazioni su Kupfer, visita la sua pagina web." #: C/index.page:9(name) msgid "Ulrik Sverdrup" msgstr "Ulrik Sverdrup" #: C/index.page:10(email) msgid "ulrik.sverdrup@gmail.com" msgstr "ulrik.sverdrup@gmail.com" #: C/index.page:13(year) msgid "2009" msgstr "2009" #: C/index.page:14(name) msgid "Kupfer Development Team" msgstr "Team di sviluppo di Kupfer" #: C/index.page:17(license) msgid "Creative Commons Share Alike 3.0" msgstr "Creative Commons Share Alike 3.0" #: C/index.page:21(title) msgid "Kupfer manual" msgstr "Manuale di Kupfer" #: C/index.page:24(title) msgid "Using Kupfer" msgstr "Utilizzo di Kupfer" #. Put one translator per line, in the form of NAME , YEAR1, YEAR2 #: C/index.page:0(None) msgid "translator-credits" msgstr "Francesco Marella , 2010" kupfer-328/help/kupfer.omf.in000066400000000000000000000004461500175051100162170ustar00rootroot00000000000000 manual kupfer-328/help/pl/000077500000000000000000000000001500175051100142225ustar00rootroot00000000000000kupfer-328/help/pl/pl.po000066400000000000000000002103261500175051100152010ustar00rootroot00000000000000# Polish translation for the kupfer help. # Copyright (C) Karol Będkowski , 2010. # This file is distributed under the same license as the kupfer package. (GPLv3) # Karol Będkowski , 2010, 2011. # msgid "" msgstr "" "Project-Id-Version: Kupfer\n" "POT-Creation-Date: 2013-01-22 20:43+0000\n" "PO-Revision-Date: 2013-03-20 19:30+0100\n" "Last-Translator: Karol Będkowski \n" "Language-Team: Polish <>\n" "Language: 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" #: C/plugin-websearch.page:7(desc) msgid "Using the search the web plugin." msgstr "Użycie wtyczki przeszukiwania web." #: C/plugin-websearch.page:10(app) msgid "Search the Web" msgstr "Przeszukiwanie web" #: C/plugin-websearch.page:13(title) C/plugin-triggers.page:23(title) #: C/plugin-notes.page:22(title) C/plugin-nautilusselection.page:13(title) #: C/plugin-gwibber.page:25(title) C/plugin-favorites.page:22(title) #: C/plugin-calculator.page:21(title) C/plugin-applications.page:19(title) #: C/generalusage.page:10(title) msgid "Basic Usage" msgstr "Podstawy obsługi" #: C/plugin-websearch.page:15(p) msgid "Activate Kupfer and make sure it is in free-text mode (press period)" msgstr "" "Aktywacja Kupfera i upewnienie się, że znajduje się w trybie tekstowym " "(naciśnięcie kropki)" #: C/plugin-websearch.page:17(p) msgid "" "Type in a search query and tap Tab to switch to the action pane." msgstr "" "Wpisanie szukanego zapytania i naciśnięcie klawisza Tab aby " "przełączyć się do panelu akcji." #: C/plugin-websearch.page:19(p) msgid "" "Type \"Search With\" to find Search the Web's action and tap Tab " "again to switch to the third pane (indirect object)." msgstr "" "Wpisanie \"Szukaj za pomocą\" aby znaleźć akcję \"Przeszukaj sieć..\" oraz " "naciśnięcie Tab aby przejść do trzeciego panelu (obiekt " "pośrednik)." #: C/plugin-websearch.page:22(p) msgid "" "Select search engine with the arrow keys and type Return to open " "the search in a web browser." msgstr "" "Wybranie wyszukiwarki za pomocą klawiszy strzałek i naciśnięcie klawisza " "Return w celu otwarcia wyników wyszukiwania w przeglądarce WWW." #: C/plugin-websearch.page:29(title) msgid "Search Engines" msgstr "Wyszukiwarki" #: C/plugin-websearch.page:30(p) msgid "" "The Search the Web plugin uses Firefox' search engines, so you " "can add Search Engines directly in Firefox and Kupfer " "will find them later." msgstr "" "Wtyczka \"Przeszukaj sieć WWW\" używa wyszukiwarek zdefiniowanych w " "programie Firefox. Dodanie nowej wyszukiwarki do programu " "Firefox pozwoli na ich późniejsze używanie w programie " "Kupfer." #: C/plugin-websearch.page:35(p) msgid "" "You can also install custom search plugins directly, only for Kupfer, in the folder:" msgstr "" "Dodatkowe wyszukiwarki mogą zostać zainstalowane bezpośrednio, tylko dla " "programu Kupfer, w katalogu:" #: C/plugin-websearch.page:39(code) #, no-wrap msgid "~/.local/share/kupfer/searchplugins/" msgstr "~/.local/share/kupfer/searchplugins/" #: C/plugin-websearch.page:40(p) msgid "The search engine descriptions must written in OpenSearch format." msgstr "Definicje wyszukiwarek muszą być zapisane w formacie OpenSearch." #: C/plugin-triggers.page:7(desc) msgid "Using the triggers plugin." msgstr "Użycie wtyczki wyzwalaczy." #: C/plugin-triggers.page:10(app) C/keyboard.page:213(title) msgid "Triggers" msgstr "Wyzwalacze" #: C/plugin-triggers.page:13(title) msgid "Triggers Plugin" msgstr "Wtyczka wyzwalaczy" #: C/plugin-triggers.page:14(p) msgid "" "With Triggers you can take a command you would normally perform " "in Kupfer, such as launching an application or opening a " "document, and bind a global key combination to run this command. As long as " "Kupfer is running, any application can have the current focus." msgstr "" "Za pomocą wyzwalaczy możliwe jest wywoływanie poleceń normalnie " "uruchamianych w Kupferze, takich jak uruchamianie programów lub " "otwieranie dokumentów, za pomocą zdefiniowanych, globalnych skrótów " "klawiszowych. Jak długo Kupfer jest uruchomiony, wyzwalacze będą " "działać niezależnie od aktualnie aktywnej aplikacji." #: C/plugin-triggers.page:25(title) msgid "Creating a new trigger" msgstr "Tworzenie nowego wyzwalacza" #: C/plugin-triggers.page:27(p) msgid "Set up a command in Kupfer that you want to run" msgstr "Wskazanie polecenia w Kupferze które ma być uruchamiane" #: C/plugin-triggers.page:32(p) msgid "" "Press CtrlReturn to create a " "composed command." msgstr "" "Naciśnięcie CtrlReturn w celu " "stworzenia skomponowanego polecenia." #: C/plugin-triggers.page:38(p) msgid "" "Type Tab and select the action Add Trigger... and press " "Return" msgstr "" "Naciśnięcie Tab, wybór akcji Dodaj wyzwalacz... i " "naciśnięcie Return" #: C/plugin-triggers.page:44(p) msgid "" "Using the window that appears, press modifier keys and a letter or number " "key to set a global shortcut. An example is pressing and holding " "CtrlAlt and then pressing and " "releasing R to bind CtrlAltR." msgstr "" "W oknie, które zostanie wyświetlone, naciśnięcie klawisza modyfikatora oraz " "litery lub cyfry w celu ustawienia globalnego skrótu. Przykładowo - " "naciśnięcie i przytrzymanie CtrlAlt i " "naciśnięcie i puszczenie R w celu przypisania CtrlAltR." #: C/plugin-triggers.page:54(title) msgid "Removing a trigger" msgstr "Usuwanie wyzwalaczy" #: C/plugin-triggers.page:56(p) msgid "" "Find the source Triggers in Kupfer and press to see its contents." msgstr "" "Znalezienie źródła Wyzwalacze w programie Kupfer i " "naciśnięcie klawisza w celu wyświetlenia zawartości." #: C/plugin-triggers.page:62(p) msgid "" "Find the active trigger in the list and use the action Remove Trigger." msgstr "" "Znalezienie aktywnego wyzwalacza na liście i użycie akcji Usuń " "wyzwalacz." #: C/plugin-triggers.page:68(p) msgid "" "Since trigger keyboard shortcuts are global, they can be used from any " "application. Select shortcuts with care so that they do not conflict with " "other functions." msgstr "" "Skróty klawiszowe wyzwalaczy są globalne - mogą być używane z poziomu innych " "programów. Skróty należy wybierać z rozwagą, tak aby nie powstały konflikty " "z innymi funkcjami." #: C/plugin-triggers.page:74(title) C/plugin-notes.page:60(title) #: C/plugin-gwibber.page:68(title) C/plugin-favorites.page:38(title) msgid "Power User Tips" msgstr "Porady dla zaawansowanych użytkowników" #: C/plugin-triggers.page:75(p) msgid "" "Proxy objects such as Selected Text, Selected File, Frontmost Window, Last Command et cetera allow very " "powerful triggers." msgstr "" "Obiekty pośredniczące takie jak zaznaczony tekst, " "wybrany plik, pierwszoplanowe okno, ostatnie " "polecenie itp pozwalają na tworzenie bardzo użytecznych wyzwalaczy." #: C/plugin-triggers.page:79(p) msgid "" "The application action Launch is special; if you bind a trigger " "using Launch, it will start the application if it is not running, " "but focus the application when it is already running. By contrast, Start " "Again will start the application if it is running or not." msgstr "" "Akcja programów uruchom jest specjalna. Utworzenie wyzwalacza z " "użyciem uruchom spowoduje uruchomienie programu, jeżeli nie jest " "uruchomiony lub uaktywnienie jego okna, gdy jest już uruchomiony. W " "przeciwieństwie uruchom ponownie uruchomi program niezależnie czy " "jest uruchomiony czy nie." #: C/plugin-triggers.page:87(title) msgid "Example Triggers" msgstr "Przykładowe wyzwalacze" #: C/plugin-triggers.page:90(em) msgid "Text Editor → Launch" msgstr "Edytor tekstu → Uruchom" #: C/plugin-triggers.page:91(p) msgid "" "Start Text Editor or focus its window if it is already running." msgstr "" "Uruchamia edytor tekstu lub uaktywnia jego okno, gdy jest już " "uruchomiony." #: C/plugin-triggers.page:97(em) msgid "Selected Text → Search With → Google" msgstr "Zaznaczony tekst → Szukaj za pomocą... → Google" #: C/plugin-triggers.page:98(p) msgid "Search the web using the currently selected text." msgstr "Przeszukuje sieć używając aktualnie zaznaczonego tekstu." #: C/plugin-triggers.page:100(em) msgid "Selected File → Move To → (Downloads Folder)" msgstr "Wybrany plik → Przenieś do → (Pobrane)" #: C/plugin-triggers.page:101(p) msgid "Move the currently selected file to a specific folder" msgstr "Przeniesienie zaznaczonego pliku do wskazanego katalogu" #: C/plugin-triggers.page:105(em) msgid "Songs → Search Contents" msgstr "Utwory → Przeszukaj zawartość" #: C/plugin-triggers.page:106(p) msgid "" "You may even add a trigger to open a specific subcatalog in Kupfer, for " "example Rhythmbox's songs." msgstr "" "Możliwe jest dodanie wyzwalacza w celu otwierania określonego podkatalogu w " "Kupferze, na przykład utworów w Rhythmboksie." #: C/plugin-notes.page:7(desc) msgid "Using the notes plugin." msgstr "Użycie wtyczki notatek" #: C/plugin-notes.page:10(app) C/plugin-calculator.page:37(title) msgid "Notes" msgstr "Notatki" #: C/plugin-notes.page:13(title) msgid "Notes Plugin" msgstr "Wtyczka notatek" #: C/plugin-notes.page:14(p) msgid "" "With Notes you can access or create new notes in either the " "program Gnote or Tomboy. Notes will work " "identically with either application—you can configure which one to use in " "the plugin's information pane in Kupfer Preferences." msgstr "" "Wtyczka Notatki umożliwia dostęp i tworzenie nowych notatek w " "programie Gnote lub Tomboy. Notatki " "działają identycznie w obu programach - wskazanie programu który ma być " "użyty możliwe jest na panelu informacyjnym wtyczki, w Preferencjach " "Kupfera" #: C/plugin-notes.page:24(title) msgid "Creating a new note" msgstr "Tworzenie nowej notatki" #: C/plugin-notes.page:26(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "note title" msgstr "" "Aktywacja Kupfera i naciśnięcie . w celu przejścia do trybu " "tekstowego. Następnie wpisanie tytułu notatki." #: C/plugin-notes.page:32(p) msgid "" "Type Tab and select the action Create Note and press " "Return." msgstr "" "Naciśnięcie Tab, wybranie akcji Utwórz notatkę i " "naciśnięcie Return." #: C/plugin-notes.page:39(title) msgid "Finding a note by title" msgstr "Szukanie notatek według tytułu" #: C/plugin-notes.page:41(p) msgid "Simply search for the note title in Kupfer" msgstr "" "Wyszukanie odbywa się przez proste wyszukanie tytułu notatki w " "Kupferze" #: C/plugin-notes.page:45(title) msgid "Finding a note by content" msgstr "Szukanie notatek według zawartości" #: C/plugin-notes.page:47(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "search query" msgstr "" "Aktywacje Kupfera, naciśnięcie . w celu przejścia do " "trybu tekstowego a następnie wpisanie szukanego tekstu." #: C/plugin-notes.page:53(p) msgid "" "Type Tab and select the action Get Note Search Results... and press Return." msgstr "" "Naciśnięcie Tab, wybranie akcji Wyszukaj wśród notatek .. i naciśnięcie Return." #: C/plugin-notes.page:63(p) msgid "" "You can use the Selected Text object and create a new note with the " "content of the selection." msgstr "" "Istnieje możliwość użycia obiektu Zaznaczony tekst i stworzenie " "nowej notatki z zaznaczeniem jako zawartością." #: C/plugin-nautilusselection.page:7(desc) msgid "Using the selected file plugin." msgstr "Użycie wtyczki \"wybrany plik\"" #: C/plugin-nautilusselection.page:10(app) msgid "Selected File" msgstr "Wybrany plik" #: C/plugin-nautilusselection.page:14(p) msgid "" "Select a file in the file manager. Open Kupfer and search for the " "object Selected File, which represents the file or files that are " "selected." msgstr "" "Zaznaczenie pliku w menadżerze plików, a następnie otwarcie Kupfera i wybranie obiektu Wybrany plik reprezentującego zaznaczony " "wcześniej plik lub pliki." #: C/plugin-nautilusselection.page:19(p) msgid "" "Instead of searching, you can press CtrlG to directly focus the selected file. See " "for more information." msgstr "" "Zamiast wyszukiwać obiekt, możliwe jest jego bezpośrednie wybranie przez " "naciśnięcie CtrlG. Więcej informacji " "można znaleźć w ." #: C/plugin-nautilusselection.page:26(title) msgid "Selected File requires Nautilus" msgstr "Wtyczka Wybrany plik wymaga programu Nautilus" #: C/plugin-nautilusselection.page:27(p) msgid "" "The selected file plugin works with the Nautilus file browser and " "requires that the extension kupfer_provider.py is installed (it " "is normally installed together with Kupfer). After installing it " "for the first time, Nautilus must start anew before it is active." msgstr "" "Wtyczka Wybrany plik działa z menadżerem plików Nautilius i wymaga rozszerzenia kupfer_provider.py, które jest " "standardowo instalowane z Kupferem. Po pierwszej instalacji " "Nautilus musi zostać zrestartowany w celu włączenia rozszerzenia." #: C/plugin-gwibber.page:7(desc) msgid "Using the Gwibber plugin." msgstr "Użycie wtyczki Gwibber." #: C/plugin-gwibber.page:10(app) msgid "Gwibber" msgstr "Gwibber" #: C/plugin-gwibber.page:13(title) msgid "Gwibber Plugin" msgstr "Wtyczka Gwibber" #: C/plugin-gwibber.page:14(p) msgid "" "With the Gwibber plugin you can send messages to social networks " "such as Twitter or Identi.ca." msgstr "" "Wtyczka Gwibber umożliwia wysyłanie wiadomości do sieci " "społecznościowych takich jak Twitter czy Identi.ca." #: C/plugin-gwibber.page:18(p) msgid "" "The plugin requires that the application Gwibber is installed and " "configured for your user. Kupfer will start and use Gwibber's " "service in the background." msgstr "" "Wtyczka wymaga zainstalowanej i skonfigurowanej aplikacji Gwibber. Kupfer podczas pracy uruchamia i używa w tle serwisu " "Gwibbera." #: C/plugin-gwibber.page:27(title) msgid "Sending a message to all services" msgstr "Wysyłanie wiadomości do wszystkich serwisów" #: C/plugin-gwibber.page:29(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "message." msgstr "" "Aktywacja Kupfera i naciśnięcie . w celu przejścia do trybu " "tekstowego. Następnie wpisanie wiadomości." #: C/plugin-gwibber.page:35(p) msgid "" "Type Tab and select the action Send Message and press " "Return." msgstr "" "Naciśnięcie Tab, wybór akcji Wyślij wiadomość i " "naciśnięcie Return" #: C/plugin-gwibber.page:42(title) msgid "Sending a message to a specific service" msgstr "Wysyłanie wiadomości do określonego serwisu" #: C/plugin-gwibber.page:44(p) msgid "" "Activate Kupfer and search for the service object, for example Identi." "ca" msgstr "" "Aktywacja Kupfera i wyszukanie obiektu serwisu - na przykład Identi.ca" #: C/plugin-gwibber.page:50(p) msgid "Type Tab and select the action Send Message." msgstr "Naciśnięcie Tab, wybór akcji Wyślij wiadomość." #: C/plugin-gwibber.page:55(p) msgid "" "Type Tab to select the last pane, and type in a message. Press " "Return to send." msgstr "" "Naciśnięcie Tab w celu wybrania ostatniego panelu a następnie " "wpisanie wiadomości. Naciśnięcie Return wysyła wiadomość." #: C/plugin-gwibber.page:61(p) msgid "" "The plugin also provides a source for incoming messages, Gwibber " "Messages and more actions on messages such as Reply, Send " "Private Message etc." msgstr "" "Wtyczka dostarcza także przychodzące wiadomości (Wiadomości Gwibber) oraz więcej akcji dla wiadomości, takich jak Odpowiedz, " "Wyślij prywatną wiadomość itd." #: C/plugin-gwibber.page:71(p) msgid "" "You can use the comma trick if you want to send a message to more " "than one service, but not all, at the same time." msgstr "" "Jest możliwe użycie triku z przecinkiem w celu wysłania wiadomości " "od razu do więcej niż jednego serwisu." #: C/plugin-favorites.page:7(desc) msgid "Using the favorites plugin." msgstr "Użycie wtyczki \"ulubione\"." #: C/plugin-favorites.page:10(app) msgid "Favorites" msgstr "Ulubione" #: C/plugin-favorites.page:13(title) msgid "Favorites Plugin" msgstr "Wtyczka ulubione" #: C/plugin-favorites.page:14(p) msgid "" "With Favorites you mark objects, for example files, for quicker " "access. It is a sort of shelf on which you can store objects in Kupfer. " "Objects marked as favorites will also be ranked higher and are adorned with " "a star symbol." msgstr "" "Wtyczka Ulubione umożliwia zaznaczenie obiektów, na przykład " "plików, w celu szybszego do nich dostępu. Jest to swego rodzaju półki na " "której można umieścić obiekty w Kupferze. Dodatkowo obiekty oznaczone jako " "ulubione umieszczane są wyżej w rankingu wyszukanych obiektów oraz oznaczane " "symbolem gwiazdki." #: C/plugin-favorites.page:25(p) msgid "Find an object in Kupfer" msgstr "Znalezienie obiektu w Kupferze" #: C/plugin-favorites.page:30(p) msgid "" "Type Tab and select either the action Add to Favorites " "or Remove from Favorites." msgstr "" "Naciśnięcie Tab i wybranie akcie Dodaj do ulubionych lub " "Usuń z ulubionych." #: C/plugin-favorites.page:39(p) msgid "" "If you favorite an object, you can access it in more places. Not only in the " "\"Favorites\" subcatalog, but also as the indirect (secondary) object for " "some actions. For example:" msgstr "" "Obiekty oznaczone jako ulubione dostępne są w wielu miejscach - nie tylko w " "podkatalogu \"Ulubione\", ale także jako obiekty pośrednika (drugie) dla " "niektórych akcji. Na przykład:" #: C/plugin-favorites.page:45(p) msgid "Command-lines from favorites are quick to access." msgstr "Dostęp do ulubionych poleceń jest szybszy." #: C/plugin-favorites.page:46(p) msgid "" "When scaling images with the Scale... action from the Image " "Tools plugin. This action needs a size description as the third " "object, like \"1024\" or \"1200x800\". If you often scale to the same size, " "say \"1200x800\", add this to favorites, and it will always appear as a " "suggestion for the action." msgstr "" "Podczas skalowania obrazów z użyciem akcji Przeskaluj z wtyczki " "Narzędzia do obrazów, akcja ta wymaga podania rozmiaru jako " "trzeci obiekt, np \"1024\" lub \"1200x800\". Jeżeli skalowanie odbywa się " "często do tego samego rozmiaru, na przykład \"1200x800\", dodanie go do " "ulubionych spowoduje, że będzie pojawiać się jako sugerowany dla tej akcji." #: C/plugin-favorites.page:54(p) msgid "" "Actions needing an email address as the indirect object will pick up email " "addresses from favorites as well as well." msgstr "" "Akcje wymagające adresu e-mail jako dodatkowego obiektu będą także pobierać " "adresy z ulubionych." #: C/plugin-calculator.page:7(desc) msgid "Using the calculator plugin." msgstr "Użycie wtyczki kalkulator" #: C/plugin-calculator.page:10(app) msgid "Calculator" msgstr "Kalkulator" #: C/plugin-calculator.page:13(title) msgid "Calculator Plugin" msgstr "Wtyczka kalkulator" #: C/plugin-calculator.page:14(p) msgid "" "The calculator plugin lets you calculate expressions quickly. It can " "evaluate expressions entered as text starting with \"=\". Entering = from " "command mode will start text mode directly with = prefixed for quick access." msgstr "" "Wtyczka \"Kalkulator\" umożliwia szybkie wykonywanie obliczeń, poprzez " "obliczanie wartości wyrażeń wpisanych jako ciągi rozpoczynające się od znaki " "\"=\". Dla szybszego dostępu wprowadzenie znaku \"=\" w trybie poleceń " "rozpoczyna od razu tryb tekstowy." #: C/plugin-calculator.page:23(p) msgid "Activate Kupfer and type =" msgstr "Aktywacja Kupfera i naciśnięcie =" #: C/plugin-calculator.page:26(p) msgid "" "Type in a mathematical expression using +,-,/,* (and ** for exponentiation)" msgstr "" "Wpisanie wyrażenie matematycznego używającego +,-," "/,* (dla ** dla potęgowania)" #: C/plugin-calculator.page:30(p) msgid "Press Return to get the result." msgstr "Naciśnięcie Return w celu obliczenia rezultatu." #: C/plugin-calculator.page:38(p) msgid "" "The Calculator uses python's math and complex math modules, and parses " "expressions as Python expressions. You may use common mathematical " "functions, such as sqrt, sin, exp and " "log; the command =help will show a list of all defined " "functions and constants." msgstr "" "Kalkulator używa modułów pythonowych \"math\" i \"complex math\" oraz " "interpretuje wyrażenia Pythona. Wtyczka umożliwia stosowanie standardowych " "funkcji matematycznych, takich jak sqrt, sin, " "exp oraz log. Polecenie =help wyświetla " "listę wszystkich dostępnych funkcji i stałych." #: C/plugin-calculator.page:47(p) msgid "" "Notice that the power operator in Python is double stars, for example " "=3**3 will evaluate to 27." msgstr "" "Proszę zauważyć, że operatorem potęgowania w Pytonie jest podwójna gwiazdka, " "na przykład wyrażenie =3**3 zostanie obliczone jako 27." #: C/plugin-calculator.page:53(p) msgid "To calculate trig functions for angles, convert to radians first:" msgstr "" "Aby obliczyć wartości funkcji trygonometrycznych dla kątów, muszą one zostać " "najpierw zamienione na radiany:" #: C/plugin-calculator.page:56(code) #, no-wrap msgid "sin(radians(30)) -> 0.5" msgstr "sin(radians(30)) -> 0.5" #: C/plugin-calculator.page:59(p) msgid "" "The last result is stored as the name _ (an underscore, just like in the " "Python console)." msgstr "" "Ostatni wynik jest zapisywany pod nazwą _ (podkreślenie, tak ja w konsoli " "pythonowej)" #: C/plugin-calculator.page:65(p) msgid "" "The Calculator lets you also calculate expression without \"=\" on the " "beginning as long it have inside one of operators: +, -, *, /, ^, |, , ~." msgstr "" #: C/plugin-applications.page:7(desc) msgid "Using the applications plugin." msgstr "Użycie wtyczki programów" #: C/plugin-applications.page:10(app) msgid "Applications" msgstr "Programy" #: C/plugin-applications.page:13(title) msgid "Applications Plugin" msgstr "Wtyczka programy" #: C/plugin-applications.page:14(p) msgid "Applications provides all installed programs." msgstr "" "Wtyczka Programy dostarcza listę wszystkich zainstalowanych " "programów." #: C/plugin-applications.page:21(title) msgid "Launching an application" msgstr "Uruchamianie programu" #: C/plugin-applications.page:23(p) msgid "Activate Kupfer and type an abbreviation of the application name" msgstr "Aktywacja Kupfera i wpisanie skrótu nazwy programu." #: C/plugin-applications.page:28(p) msgid "Press Return to launch the application." msgstr "Naciśnięcie Return w celu uruchomienia programu." #: C/plugin-applications.page:34(title) msgid "Opening a file with a specific application" msgstr "Otwieranie pliku z użyciem określonej aplikacji." #: C/plugin-applications.page:36(p) msgid "Select a file in Kupfer" msgstr "Wybranie pliku w Kupferze" #: C/plugin-applications.page:41(p) msgid "Type Tab and select the action Open With..." msgstr "Naciśnięcie Tab, wybór akcji Otwórz za pomocą." #: C/plugin-applications.page:46(p) #, fuzzy #| msgid "" #| "Type Tab to select the third (indirect object) pane and in it, " #| "select the application the file with." msgid "" "Type Tab to select the third (indirect object) pane and in it, " "select the application to open the file with." msgstr "" "Naciśnięcie Tab w celu przejścia do trzeciego panelu (obiekt " "pośrednik), a następnie wybranie programy dla pliku." #: C/plugin-applications.page:53(p) msgid "" "The action Open opens files and folders with the registered default " "application for that specific file type. This can be configured using the " "action Set Default Application...." msgstr "" #: C/plugin-applications.page:58(p) msgid "" "The file type associations are provided by the desktop environment, and " "modifying them here will modify them on the desktop as well. This may not be " "true when not using GNOME or XFCE." msgstr "" #: C/plugin-applications.page:64(title) msgid "Selecting default application for a file type or folders" msgstr "" #: C/plugin-applications.page:66(p) #, fuzzy #| msgid "Select a file in Kupfer" msgid "Select a file or folder in Kupfer" msgstr "Wybranie pliku w Kupferze" #: C/plugin-applications.page:71(p) #, fuzzy #| msgid "Type Tab and select the action Open With..." msgid "" "Type Tab and select the action Set Default Application..." msgstr "Naciśnięcie Tab, wybór akcji Otwórz za pomocą." #: C/plugin-applications.page:77(p) #, fuzzy #| msgid "" #| "Type Tab to select the third (indirect object) pane and in it, " #| "select the application the file with." msgid "" "Type Tab to select the third (indirect object) pane and in it, " "select the application to always open the file type with." msgstr "" "Naciśnięcie Tab w celu przejścia do trzeciego panelu (obiekt " "pośrednik), a następnie wybranie programy dla pliku." #: C/plugin-applications.page:85(title) msgid "Configuration" msgstr "Konfiguracja" #: C/plugin-applications.page:86(p) msgid "" "The configuration option Applications for Desktop Environment in " "the plugin's information pane in Kupfer Preferences determines " "how Kupfer should act with regard to the desktop environment " "configuration—certain applications request not to be shown depending on " "which desktop environment is used. By default, it behaves like GNOME." msgstr "" "Parametr konfiguracyjny Programy środowiska graficznego w panelu " "informacyjnym wtyczki w Preferencjach Kupfera określa jak " "Kupfer powinien zachowywać się przy pobieraniu konfiguracji " "środowiska graficznego - wiele aplikacji nie powinno być pokazywanych w " "zależności od aktualnie używanego środowiska graficznego. Domyślnym " "ustawieniem jest środowisko GNOME." #: C/moreusage.page:7(desc) msgid "More advanced usage information." msgstr "Informacje o zaawansowanym użyciu" #: C/moreusage.page:10(title) msgid "Using Kupfer in Depth" msgstr "Zaawansowane używanie Kupfera" #: C/moreusage.page:13(title) msgid "Adding Applications and Scripts" msgstr "Dodawanie programów i skryptów" #: C/moreusage.page:14(p) msgid "" "Kupfer will show all applications that are configured visible in " "your menu editor." msgstr "" "Kupfera będzie pokazywał wszystkie programy, które są oznaczone " "jako widoczne w edytorze menu." #: C/moreusage.page:18(p) msgid "" "If you want to add an application manually, you can create a new ." "desktop file and place it in one of the standard directories for " "applications, for example ~/.local/share/applications, where " "Kupfer will find it." msgstr "" "W przypadku potrzeby ręcznego dodania programu użytkownik może utworzyć nowy " "plik .desktop i umieścić go w jednym ze standardowych miejsc " "dla programów, np w ~/.local/share/applications. " #: C/moreusage.page:24(p) msgid "" "If you have a collection of scripts that you want to call from Kupfer, you can add the scripts folder as a catalog directory to Kupfer in the preferences. Scripts that you add to Kupfer's catalog " "this way can be run directly or in the terminal as long as they are " "executable." msgstr "" "Jeżeli użytkownik posiada kolekcję skryptów, które mają być uruchamiane " "poprzez Kupfera, katalog ze skryptami może zostać dodany " "bezpośrednio do Kupfera w oknie preferencji. Skrypty dodane w ten " "sposób do Kupfera mogą być uruchamiana bezpośrednio lub w " "terminalu pod warunkiem, że są one wykonywalne." #: C/moreusage.page:31(p) msgid "" "You can also save command-lines by using the action Add to Favorites." msgstr "" "Istnieje także możliwość zapisania poleceń wiersza poleceń używając akcji " "Dodaj do ulubionych." #: C/moreusage.page:38(title) msgid "Opening Files and Folders" msgstr "" #: C/moreusage.page:39(p) msgid "" "Using the action Open, files and folders are opened in their " "preferred application. The application associations can be changed, see " "." msgstr "" #: C/moreusage.page:47(title) msgid "The Comma Trick" msgstr "Trik z przecinkiem" #: C/moreusage.page:48(p) msgid "" "The comma trick allows the user to use actions on many objects at the same " "time." msgstr "" "Trik z przecinkiem umożliwia użytkownikowi użycie akcji od razu dla wielu " "obiektów." #: C/moreusage.page:52(p) msgid "" "Simply press comma , when an object is selected. The object is " "put on a \"stack\", and you can find yet another file or object, press comma " "to put it on the stack. When you subsequently invoke an action, the action " "is carried out on all of the objects at the same time." msgstr "" "Naciśnięcie przecinka , spowoduje umieszczenie zaznaczonego " "obiektu na \"stosie\". Kupfer umożliwia znalezienie kolejnego obiektu i " "dodanie go na stos przez ponowne naciśnięcie przecinka. Późniejsze wywołanie " "akcji uwzględni wszystkie obiekty umieszczone na stosie." #: C/moreusage.page:58(p) msgid "" "Some actions are only \"multiplied\" when used with many objects, other are " "smarter than that:" msgstr "" "Niektóre akcje są jedynie wywoływane wielokrotnie, gdy są uruchomione dla " "wielu obiektów. Inne są sprytniejsze:" #: C/moreusage.page:61(p) msgid "" "Selecting many files and using the Create Archive action, all files will be " "packed into the same archive." msgstr "" "Zaznaczenie wielu plików i użycie akcji \"Utwórz archiwum\" spowoduje " "dodanie wszystkich plików do jednego archiwum." #: C/moreusage.page:63(p) msgid "" "If you select multiple contacts and use a Send Email action, it creates one " "email directed at all the contacts." msgstr "" "Zaznaczenie wielu kontaktów i użycie akcji \"Wyślij e-mail\" utworzy jeden " "e-mail do wszystkich wybranych kontaktów." #: C/moreusage.page:65(p) msgid "" "If you select multiple subcatalogs (For example Firefox Bookmarks and " "Epiphany Bookmarks) and use Search Contents.., you get a subcatalog search " "restricted to the objects of those two catalogs! You can even bind a trigger " "to this command(!)" msgstr "" "Zaznaczenie wielu podkatalogów (np. Zakładki Firefoksa i Zakładki Epiphany) " "i użycie akcji \"Przeszukaj zawartość\" spowoduje umożliwi przeszukanie " "podkatalogu zbudowanego z obiektów pochodzących z tych dwóch katalogów. " "Kupfer umożliwia także przypisanie wyzwalacza do takiego polecenia." #: C/moreusage.page:71(p) msgid "" "The comma trick is directly taken from Quicksilver (the " "example given in the external article should work identically in Kupfer)." msgstr "" "Trik z kropką jest wzorowany bezpośrednio na programie " "Quicksilver (przykłady podane w zewnętrznym artykule powinny działać " "identycznie w Kupferze)." #: C/moreusage.page:80(title) msgid "Grab Current Selection" msgstr "Przechwyć aktualne zaznaczenie" #: C/moreusage.page:81(p) msgid "" "To use the current selected text, from any application, with Kupfer, you can configure a global keyboard shortcut for the action Show " "with Selection in Kupfer Preferences." msgstr "" "W celu użycia aktualnie zaznaczonego tekstu z dowolnego programu " "Kupfer umożliwia skonfigurowanie globalnego skrótu klawiszowego " "dla akcji Wyświetlenie zaznaczenia w Preferencjach Kupfera." #: C/moreusage.page:85(p) msgid "" "If configured, pressing the global keyboard shortcut will summon " "Kupfer with the current selection as the focused object." msgstr "" "Po skonfigurowaniu, naciśnięcie globalnego skrótu klawiszowego wywoła " "Kupfera z zaznaczeniem jako wybranym obiektem." #: C/moreusage.page:90(p) msgid "See " msgstr "Więcej informacji: " #: C/moreusage.page:94(title) msgid "Command-line Connection" msgstr "Powiązania z wierszem poleceń" #: C/moreusage.page:95(p) msgid "" "The command kupfer on the command-line will focus Kupfer if it's already running, otherwise it will start it." msgstr "" "Polecenie kupfer wykonana w wierszu poleceń wyświetli " "Kupfera, jeżeli jest już uruchomiony. W przeciwnym wypadku - " "Kupfer zostanie uruchomiony." #: C/moreusage.page:99(p) msgid "" "The command kupfer can be used to send files or text from the " "command-line to Kupfer. For example, if you are using the shell " "in a directory where you have a file called \"report.pdf\", you can focus " "this file in Kupfer by running kupfer report.pdf." msgstr "" "Polecenie kupfer może być użyta do przesyłania plików lub tekstu " "z programów uruchamianych z wiersza poleceń do Kupfera. Dla " "przykładu, jeżeli podczas pracy w powłoce w katalogu znajduje się plik " "\"raport.pdf\", możliwe jest wybranie tego pliku w Kupferze przez " "uruchomienie kupfer raport.pdf." #: C/moreusage.page:107(p) msgid "" "You can also send text if you pipe the output of a command into kupfer." msgstr "" "Istnieje możliwość przesłania wyniku wywołania programu do polecenia " "kupfer." #: C/moreusage.page:114(title) msgid "Managing Context and Current Selection" msgstr "Zarządzanie kontekstem i aktualnym zaznaczeniem" #: C/moreusage.page:115(p) msgid "" "If you find the object you want to use, then invoke an action, Kupfer goes away to perform the action (for example start a program or play a " "song). When you come back to Kupfer, it will still keep the same " "object and action selected. Some actions make sense to be repeated (like " "skipping to the next song) and it can be useful to perform different actions " "on the same object." msgstr "" "Po znalezieniu obiektu do użycia i wywołaniu akcji Kupfer znika w " "celu jej przeprowadzania (na przykład uruchomienie programu lub odtworzenie " "utworu). Po powrocie do Kupfera poprzednio wybrany obiekt i akcja " "nadal pozostają wybrane. Pozwala to na szybkie powtórzenie ostatnich akcji " "(dla akcji dla których to ma sens - na przykład przeskoczenie do kolejnego " "utworu muzycznego) a także może być użyteczne przy przeprowadzaniu innej " "akcji na tym samym obiekcie." #: C/moreusage.page:123(p) msgid "" "However, you always have the top level catalog reachable when you \"come back" "\" to Kupfer -- say you went into the subcatalog \"Albums\" to " "browse your albums only; you select an album to play, and play it. You come " "back with the album selected -- but your next search will still go over the " "top level catalog, not just albums." msgstr "" "Jednakże, kiedy użytkownik powraca do Kupfera ma zawsze dostępny " "najwyższy poziom katalogu. Przykładowo po wejściu do podkatalogu \"Albumy\" " "w celu przejrzenia albumów, użytkownik może wybrać album i włączyć jego " "odtwarzanie. Kiedy powróci do Kupfera album pozostanie wybrany, " "ale wyszukiwanie będzie odbywało się na najwyższym poziomie katalogu a nie " "albumu." #: C/moreusage.page:130(p) msgid "" "How to come back into the subcatalog you were in? You do that by simply " "browsing, not searching the first thing you do when you focus Kupfer again. A quick way is to press down-arrow or space to open the browse " "window; think of it as saying \"I want to stay in this subfolder\". With the " "browse window open, your next query will search the current subcatalog." msgstr "" "Aby powrócić do podkatalogu, który został poprzednio wybrany, należy wykonać " "najpierw przeglądanie katalogu (nie rozpoczynać od wyszukiwania). " "Najszybszym sposobem jest naciśniecie klawisza strzałki w dół lub spacji w " "celu otwarcia okna przeglądarki. Gdy okno przeglądarki zostanie otwarte, " "kolejne wyszukiwanie będzie odbywało się w aktualnym podkatalogu." #: C/moreusage.page:137(p) msgid "" "This way you can work both ways -- you can quickly drill down into folders " "to find a file, and when you come back for the next action with Kupfer you can either summon any normal toplevel object (just start typing), " "or stay around where you were, deep in that folder (press space, then type a " "query)." msgstr "" "Tym sposobem istnieje możliwość pracy na oba sposoby - można szybko zagłębić " "się w katalogi w celu znalezienia pliku, a po wykonaniu akcji i powrocie " "można albo dotrzeć do każdego, pierwszopoziomowego obiektów (przez " "rozpoczęcie pisania) lub pozostać w miejscu gdzie się było poprzednio, w " "zagnieżdżonym katalogu (przez naciśnięcie spacji, a później pisanie)." #: C/moreusage.page:146(title) msgid "Saving Commands as Files" msgstr "Zapisywanie poleceń jako pliki" #: C/moreusage.page:147(p) msgid "" "You can use keyboard shortcut for Compose Command (by default it is " "CtrlReturn) to create a command " "object out of the currently focused command in Kupfer. This object can be " "saved as a runnable file if you use the Save As... action. The " "resulting file will can be executed when opened from the file manager (it " "requires that Kupfer is already running)." msgstr "" "Kupfer umożliwia użycie skrótu klawiszowego dla polecenia " "komponuj (domyślnie CtrlReturn) w celu utworzenia obiektu polecenia na podstawie aktualnie " "podświetlonego polecenia w Kupferze. Obiekt taki może być zapisany jako " "uruchamialny plik przez użycie akcji Zapisz jako.... Plik, który w " "rezultacie zostanie utworzony, może zostać otwarty przez menadżer plików " "(wymaga uruchomionego Kupfera)." #: C/managing-plugins.page:7(desc) msgid "Using plugins with Kupfer." msgstr "Używanie wtyczek w Kupfera" #: C/managing-plugins.page:10(title) msgid "How to Configure Plugins" msgstr "Konfiguracja wtyczek" #: C/managing-plugins.page:12(p) msgid "" "Functionality in Kupfer is organized by extentsion modules called \"plugins" "\". Each plugin provides additional functionality, for example integration " "with an external application." msgstr "" "Funkcje w Kupferze są umieszczone w modułach rozszerzających zwanych " "\"wtyczkami\". Każda wtyczka dostarcza dodatkowe funkcje, na przykład - " "integrację z zewnętrznymi programami." #: C/managing-plugins.page:19(title) msgid "Configuring Plugins" msgstr "Konfiguracja wtyczek" #: C/managing-plugins.page:21(title) msgid "Open Kupfer Preferences to the Plugins tab" msgstr "Otwarcie Preferencji Kupfera i karty \"Wtyczki\"" #: C/managing-plugins.page:23(p) msgid "Use one of the following methods:" msgstr "Otwarcie okna preferencji jest możliwe poprzez:" #: C/managing-plugins.page:25(p) msgid "" "Click the Kupfer icon in the notification area and select the item " "Preferences" msgstr "" "Kliknięcie ikony Kupfera w obszarze powiadamiania i wybranie " "Preferencje" #: C/managing-plugins.page:25(item) msgid "." msgstr "." #: C/managing-plugins.page:29(p) msgid "" "Search for the object Kupfer Preferences in Kupfer itself. Press " "Return to open it." msgstr "" "Znalezienie obiektu Preferencje Kupfera w Kupferze. Naciśnięcie " "klawisza Return otwiera okno preferencji." #: C/managing-plugins.page:33(p) msgid "Use the keyboard shortcut Ctrl;" msgstr "" "Użycie skrótu klawiszowego Ctrl;" #: C/managing-plugins.page:39(p) msgid "Select the tab Plugins" msgstr "Wybranie karty Wtyczki" #: C/managing-plugins.page:45(p) msgid "" "Select plugins in the list to read about them, and tick the box next to its " "name to activate the plugin, or untick to deactivate." msgstr "" "Zaznaczenie wtyczki na liście wyświetli informacje o niej. Zaznaczenie pola " "obok nazwy wtyczki aktywuje ją, odznaczenie - wyłącza ją." #: C/managing-plugins.page:49(p) msgid "" "If the plugin has any configurable parameters, they will be visible below " "the plugin information." msgstr "" "Jeżeli wtyczka posiada konfigurowalne parametry, zostaną one wyświetlone " "poniżej informacji o wtyczce." #: C/managing-plugins.page:53(p) msgid "" "The plugin Kupfer Plugins allows fast access to each plugin's " "information page as well as the action \"Show Source Code\" which reveals " "the implementation." msgstr "" "Wtyczka Wtyczki Kupfera pozwala na szybki dostęp do informacji na " "temat poszczególnych wtyczek, a także udostępnia akcję \"Wyświetl kod " "źródłowy\" umożliwiającą podgląd implementacji." #: C/managing-plugins.page:59(title) msgid "If a Plugin can not be Activated" msgstr "Problemy z aktywacją wtyczki" #: C/managing-plugins.page:60(p) msgid "" "If a plugin fails to activate because it requires a software module that is " "not available, its plugin information will display a message like this:" msgstr "" "Jeżeli wtyczka nie może zostać włączona z powodu braku wymaganego, " "zewnętrznego modułu na panelu informacyjnym pokazuje się odpowiednia " "informacja, na przykład:" #: C/managing-plugins.page:65(em) msgid "Plugin could not be read due to an error:" msgstr "Wtyczka nie może być wczytana ze względu na błąd:" #: C/managing-plugins.page:66(em) msgid "Python module 'gdata' is needed" msgstr "Wymagany jest moduł Pythona 'gdata'." #: C/managing-plugins.page:67(p) msgid "" "This means that you need to install a needed python module from your " "distribution—and possibly the plugin documentation can tell you how." msgstr "" "Komunikat taki oznacza, że należy zainstalować wymagany moduł Pythona - " "prawdopodobnie dokumentacja wtyczki dostarcza więcej informacji jak to " "zrobić." #: C/managing-plugins.page:72(p) msgid "" "The plugin may also unexpectedly fail to load, and display a different error " "message. It may then be a program error in either the plugin or Kupfer." msgstr "" "Podczas ładowania wtyczki może także wystąpić nieoczekiwany błąd i pojawić " "się inny komunikat błędu. Może to oznaczać błąd programistyczny we wtyczce " "lub w Kupferze." #: C/managing-plugins.page:79(title) msgid "Installing more Plugins" msgstr "Instalacja kolejnych wtyczek" #: C/managing-plugins.page:80(p) msgid "" "You can install custom plugins into the folder ~/.local/share/kupfer/" "plugins. Each plugin is either a single .py file or a " "python package (a folder directly containing a file called __init__." "py). Plugins in the package format can include icon files. Python " "packages can even be installed as .zip files." msgstr "" "Użytkownik ma możliwość instalacji dodatkowych wtyczek w katalogu ~/." "local/share/kupfer/plugins. Każda wtyczka jest w postaci pojedynczego " "pliku .py lub w postaci pakietu Pythona (katalog zawierający " "przynajmniej plik __init__.py). Wtyczki w postaci pakietów mogą " "zawierać pliki ikon. Pakiety Pythona mogą być instalowane jako pliki ." "zip." #: C/managing-plugins.page:88(p) msgid "" "Caution: Treat a plugin as a computer program. Do not install " "untrusted plugins." msgstr "" "Uwaga: Wtyczki są programami komputerowymi. Nie należy instalować " "wtyczek z niezaufanych źródeł." #: C/managing-plugins.page:95(title) msgid "Creating Plugins" msgstr "Tworzenie wtyczek" #: C/managing-plugins.page:96(p) msgid "" "Documentation for plugin creators is available in the file " "Documentation/Manual.rst in the source distribution on the " "webpage at Kupfer " "Manual. An easy way to start is to copy an existing plugin and " "experimenting with it." msgstr "" "Dokumentacja dla twórców wtyczek jest dostępna w pliku Documentation/" "Manual.rst dostarczanym ze źródłami programu na stronie Kupfera. Najprostszą metodą " "na rozpoczęcie pracy jest skopiowanie istniejącej wtyczki i " "eksperymentowanie z nią." #: C/managing-plugins.page:107(title) msgid "The Catalog Tab in Preferences" msgstr "Karta Katalog w oknie preferencji" #: C/managing-plugins.page:108(p) msgid "" "Each plugin can export a number of sources which contain objects. Normally, " "all these objects are directly accessible from a top-level search. Some " "plugins export so specialized or so many objects that their catalogs should " "better not have their objects exported to the top level. To reach those " "objects, you have to first find the catalog by name, then enter the catalog " "using the action Search Contents." msgstr "" "Każda wtyczka ma możliwość eksportowania pewnej ilości źródeł zawierających " "obiekty. W normalnej sytuacji, wszystkie z tych obiektów są bezpośrednio " "dostępne na najwyższym poziomie listy wyszukiwania. Niektóre wtyczki " "eksportują bardzo wyspecjalizowane obiektu lub bardzo dużą ich ilość i " "niekoniecznie powinny być wyświetlone na najwyższym poziomie listy. Aby " "dostać się do tych obiektów należy najpierw wyszukać katalog na podstawie " "jego nazwy, a następnie wejść do niego używając akcji Przeszukaj " "zawartość." #: C/managing-plugins.page:118(p) msgid "" "In the tab Catalog in Kupfer Preferences, a ticked box " "next to each source means that its objects are exported. An unticked box " "means that its contents are hidden from the top level." msgstr "" "W karcie Katalog w Preferencjach Kupfera zaznaczenie " "pola przy poszczególnych źródłach oznacza, że jego obiekt będą eksportowane. " "Odznaczenie pola oznacza, że obiekty danego źródła są ukryte na najwyższym " "poziomie listy." #: C/managing-plugins.page:123(p) msgid "" "Note: Kupfer may become slow if large enough subcatalogs are " "exported to the top level." msgstr "" "Uwaga: Kupfer może zachowywać się wolno, jeżeli znacząca ilość " "podkatalogów jest eksportowana na najwyższy poziom listy." #: C/license.page:7(desc) msgid "You can copy, modify and share Kupfer." msgstr "Użytkownik może kopiować, modyfikować i dzielić się Kupferem." #: C/license.page:10(title) msgid "License" msgstr "Licencja" #: C/license.page:12(p) msgid "" "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." msgstr "" "Niniejszy program jest wolnym oprogramowaniem; możesz go rozprowadzać dalej " "i/lub modyfikować na warunkach Powszechnej Licencji Publicznej GNU, " "wydanej przez Fundację Wolnego Oprogramowania - według wersji 3 tej Licencji " "lub (według twojego wyboru) którejś z późniejszych wersji." #: C/license.page:18(p) msgid "" "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." msgstr "" "Niniejszy program rozpowszechniany jest z nadzieją, iż będzie on użyteczny - " "jednak BEZ JAKIEJKOLWIEK GWARANCJI, nawet domyślnej gwarancji PRZYDATNOŚCI " "HANDLOWEJ albo PRZYDATNOŚCI DO OKREŚLONYCH ZASTOSOWAŃ. W celu uzyskania " "bliższych informacji sięgnij do Powszechnej Licencji Publicznej GNU." #: C/license.page:24(p) msgid "" "You should have received a copy of the GNU General Public License along with " "this program. If not, see gnu." "org/licenses." msgstr "" "Z pewnością wraz z niniejszym programem otrzymałeś też egzemplarz " "Powszechnej Licencji Publicznej GNU (GNU General Public License); jeśli nie " "- wejdź na gnu.org/licenses." #: C/license.page:30(p) msgid "" "This documentation is licensed under a Creative Commons Attribution-Share Alike 3.0 " "Unported License." msgstr "" "Ta dokumentacja jest licencjonowana na zasadach Creative Commons Attribution-Share " "Alike 3.0 Unported License." #: C/license.page:36(p) msgid "" "As a special exception, the copyright holders give you permission to copy, " "modify, and distribute the example code contained in this document under the " "terms of your choosing, without restriction." msgstr "" "Jak specjalny wyjątek właściciel praw autorskich zezwala na kopiowanie, " "modyfikację i dystrybucję przykładowych kodów źródłowych zawartych w " "niniejszej dokumentacji pod dowolnie wybranymi warunkami, bez ograniczeń," #: C/keyboard.page:7(desc) msgid "Complete keyboard shortcuts reference." msgstr "Kompletna lista skrótów klawiszowych." #: C/keyboard.page:10(title) msgid "Command Keys and Accelerator Keys" msgstr "Klawisze poleceń oraz klawisze akceleratorów" #: C/keyboard.page:13(title) C/generalusage.page:12(title) msgid "Keyboard Interface" msgstr "Klawiatura" #: C/keyboard.page:14(p) msgid "In command mode, the following keystrokes have special meanings:" msgstr "W trybie poleceń następujące klawisze posiadają specjalne znaczenie:" #: C/keyboard.page:19(p) C/generalusage.page:34(p) msgid " or Space" msgstr " lub Spacja" #: C/keyboard.page:20(p) C/generalusage.page:35(p) msgid "Go to the next match" msgstr "Przejście do następnego znalezionego obiektu" #: C/keyboard.page:23(p) C/generalusage.page:38(p) msgid " or ShiftSpace" msgstr " lub ShiftSpacja" #: C/keyboard.page:26(p) C/generalusage.page:41(p) msgid "Go to the previous match" msgstr "Przejście do poprzedniego znalezionego elementu" #: C/keyboard.page:29(p) C/generalusage.page:44(p) msgid " or /" msgstr " lub /" #: C/keyboard.page:30(p) C/generalusage.page:45(p) msgid "Descend into an object with content" msgstr "Wejście do obiektu posiadającego zawartość" #: C/keyboard.page:33(key) C/generalusage.page:48(key) msgid "Backspace" msgstr "Backspace" #: C/keyboard.page:34(p) C/generalusage.page:49(p) msgid "Erase a character from the query. If the query is empty, go up a level" msgstr "" "Usunięcie znaku z zapytania. Jeżeli zapytanie jest puste - przejście na " "wyższy poziom." #: C/keyboard.page:39(key) C/keyboard.page:93(key) C/generalusage.page:54(key) msgid "." msgstr "." #: C/keyboard.page:40(p) C/generalusage.page:55(p) msgid "Activate free-text mode" msgstr "Aktywacja trybu \"tekstowego\"" #: C/keyboard.page:43(key) C/keyboard.page:97(key) C/generalusage.page:58(key) msgid "," msgstr "," #: C/keyboard.page:44(p) C/generalusage.page:59(p) msgid "Put selected object on the stack (\"Comma Trick\")" msgstr "Odłożenie zaznaczonego obiektu na stosie (\"trik z przecinkiem\")" #: C/keyboard.page:47(p) msgid "Quick access keys:" msgstr "Klawisze szybkiego dostępu:" #: C/keyboard.page:53(key) msgid "=" msgstr "=" #: C/keyboard.page:55(p) msgid "" "Activate free-text mode with = prefix (for )" msgstr "" "Aktywacja trybu tekstowego z przedrostkiem = (dla )" #: C/keyboard.page:61(key) msgid "/" msgstr "/" #: C/keyboard.page:63(p) msgid "" "Activate free-text mode (when nothing is selected) with / " "prefix (to input a rooted path)" msgstr "" "Aktywacja trybu tekstowego (gdy nic nie jest zaznaczone) z prefiksem /" " (dla wprowadzania ścieżki względem korzenia /)." #: C/keyboard.page:68(p) C/generalusage.page:62(p) msgid "Additionally:" msgstr "Dodatkowo:" #: C/keyboard.page:72(p) C/generalusage.page:66(p) msgid "" "Return activates the current selection: the command is executed." msgstr "" "Return aktywuje zaznaczony obiekt - polecenie jest wykonywane." #: C/keyboard.page:74(p) C/generalusage.page:68(p) msgid "Escape clears the current selection." msgstr "Escape usuwa aktualne zaznaczenie." #: C/keyboard.page:75(p) C/generalusage.page:69(p) msgid "Tab switches between the object and the action pane." msgstr "Tab przełącza między obiektem i panelem akcji." #: C/keyboard.page:77(p) msgid "" "The meaning of the keys Space, ., ,, /" " and = can not be changed, but you can deactivate their " "special meaning with the checkbox Use single keystroke commands " "in Kupfer Preferences." msgstr "" "Znaczenie klawiszy Spacja, ., ,, / oraz = może być zmienione, ale w tym celu należy najpierw " "wyłączyć ich specjalne działanie przez odznaczenie pola Włączenie jedno-" "klawiszowych poleceń w Preferencjach Kupfera." #: C/keyboard.page:86(title) msgid "Kupfer's Keyboard Shortcuts" msgstr "Skróty klawiszowe Kupfera" #: C/keyboard.page:87(p) msgid "" "These keyboard shortcuts are used in Kupfer's interface. They " "have the following meanings and default shortcuts:" msgstr "" "Poniższe skróty klawiszowe są użyte w interfejsie Kupfera i " "posiadają one domyślnie następujące znaczenie:" #: C/keyboard.page:93(key) C/keyboard.page:97(key) C/keyboard.page:101(key) #: C/keyboard.page:105(key) C/keyboard.page:113(key) C/keyboard.page:117(key) #: C/keyboard.page:121(key) C/keyboard.page:125(key) C/keyboard.page:129(key) #: C/keyboard.page:174(key) msgid "Ctrl" msgstr "Ctrl" #: C/keyboard.page:94(p) msgid "Toggle text mode" msgstr "Przełączenie trybu tekstowego" #: C/keyboard.page:98(p) msgid "The comma trick" msgstr "Trik z przecinkiem" #: C/keyboard.page:101(key) msgid ";" msgstr ";" #: C/keyboard.page:102(p) msgid "Show preferences window" msgstr "Wyświetlenie okna preferencji" #: C/keyboard.page:105(key) msgid "R" msgstr "R" #: C/keyboard.page:106(p) msgid "Reset all" msgstr "Resetuj wszystko" #: C/keyboard.page:109(key) msgid "Alt" msgstr "Alt" #: C/keyboard.page:109(key) msgid "A" msgstr "A" #: C/keyboard.page:110(p) msgid "Alternate activate" msgstr "Alternatywna aktywacja" #: C/keyboard.page:113(key) msgid "Return" msgstr "Return" #: C/keyboard.page:114(p) msgid "Compose command" msgstr "Polecenie \"komponuj\"" #: C/keyboard.page:117(key) msgid "S" msgstr "S" #: C/keyboard.page:118(p) msgid "Switch to first pane" msgstr "Przełączenie do pierwszego panelu" #: C/keyboard.page:121(key) msgid "Q" msgstr "Q" #: C/keyboard.page:122(p) msgid "Select 'Quit'" msgstr "Wybranie \"Zakończ\"" #: C/keyboard.page:125(key) msgid "G" msgstr "G" #: C/keyboard.page:126(p) msgid "Select 'Selected File'" msgstr "Wybranie \"Wybrany plik\"" #: C/keyboard.page:129(key) msgid "T" msgstr "T" #: C/keyboard.page:130(p) msgid "Select 'Selected Text'" msgstr "Wybranie \"Zaznaczony tekst\"" #: C/keyboard.page:133(key) msgid "F1" msgstr "F1" #: C/keyboard.page:134(p) msgid "Show Help" msgstr "Wyświetlenie pomocy" #: C/keyboard.page:139(title) msgid "How to configure a keyboard shortcut" msgstr "Konfiguracja skrótów klawiszowych" #: C/keyboard.page:141(p) C/keyboard.page:185(p) msgid "Open Kupfer Preferences and go to the Keyboard tab." msgstr "" "Otwarcie Preferencji Kupfera i przejście do karty Klawiatura." #: C/keyboard.page:147(p) msgid "" "Double-click the shorcut's row under Browser Keyboard Shortcuts." msgstr "" "Dwukrotne kliknięcie wiersza ze skrótem pod Skróty klawiszowe listy " "elementów." #: C/keyboard.page:153(p) msgid "" "Using the window that appears, press modifier keys and a letter or number " "key to set a shortcut. An example is pressing and holding Ctrl " "and then pressing and releasing T to bind CtrlT." msgstr "" "Za pomocą okna, które zostanie wyświetlone, nacisnąć klawisz modyfikatora i " "klawisz litery lub cyfry w celu ustawienia skrótu. Przykładowo naciskając i " "przytrzymując klawisz Ctrl oraz naciskając i puszczając klawisz " "T zostanie przypisany skrót CtrlT." #: C/keyboard.page:164(title) msgid "Global Keyboard Shortcuts" msgstr "Globalne skróty klawiszowe" #: C/keyboard.page:165(p) msgid "" "Kupfer always listens to global shortcuts, even if it is not " "currently in the foreground." msgstr "" "Kupfer zawsze reaguje na globalne skróty klawiszowe, nawet gdy " "nie jest w danej chwili aktywny." #: C/keyboard.page:169(p) msgid "They have the following meanings and default shortcuts:" msgstr "" "Globalne skróty klawiszowe obejmują następujące akcje i posiadają domyślne " "przypisania:" #: C/keyboard.page:174(key) msgid "Space" msgstr "Spacja" #: C/keyboard.page:175(p) msgid "Show/hide Kupfer" msgstr "Pokaż / ukryj Kupfera" #: C/keyboard.page:178(p) msgid "(not configured by default)" msgstr "(domyślnie nieskonfigurowane)" #: C/keyboard.page:179(p) msgid "Show Kupfer with 'Selection' object focused" msgstr "Pokazanie Kupfera z wybranym obiektem \"Zaznaczenie\"." #: C/keyboard.page:183(title) msgid "How to configure a global keyboard shortcut" msgstr "Konfiguracja globalnych skrótów klawiszowych" #: C/keyboard.page:191(p) msgid "" "Double-click the shorcut's row under Global Keyboard Shortcuts." msgstr "" "Dwukrotne kliknięcie wiersza skrótu pod Globalne skróty klawiszowe." #: C/keyboard.page:197(p) msgid "" "Using the window that appears, press modifier keys and a letter or number " "key to set a global shortcut. An example is pressing and holding Super and then pressing and releasing Space to bind " "SuperSpace." msgstr "" "Za pomocą okna, które zostanie wyświetlone, nacisnąć klawisz modyfikatora i " "klawisz litery lub cyfry w celu ustawienia skrótu. Przykładowo naciskając i " "przytrzymując klawisz Super oraz naciskając i puszczając klawisz " "Spacja zostanie przypisany skrót SuperSpacja." #: C/keyboard.page:206(p) msgid "" "Since these keyboard shortcuts are global, they can be used from any " "application. Select shortcuts with care so that they do not conflict with " "other functions." msgstr "" "Skróty klawiszowe są globalne co oznacza, że mogą być użyte z dowolnego " "programu. Należy uważnie wybierać skróty klawiszowe, tak aby nie spowodowały " "one problemów z innymi funkcjami." #: C/keyboard.page:214(p) msgid "" "The plugin Triggers allows to activate actions with global keyboard " "shortcuts. Trigger shortcuts do not appear in Kupfer Preferences." msgstr "" "Wtyczka Wyzwalacze pozwala na aktywację akcji za pomocą globalnych " "skrótów klawiszowych. Skróty klawiszowe wtyczki wyzwalaczy nie są " "wyświetlane w oknie Preferencji Kupfera." #: C/keyboard.page:220(p) msgid "See for more information." msgstr "Więcej informacji można znaleźć w ." #: C/introduction.page:7(desc) msgid "Introduction to Kupfer." msgstr "Wprowadzenie do Kupfera." #: C/introduction.page:10(title) msgid "Introduction" msgstr "Wprowadzenie" #: C/introduction.page:12(p) msgid "" "Kupfer is an interface for quick and convenient access to " "applications and their documents." msgstr "" "Kupfer jest interfejsem umożliwiającym szybki i wygodny dostęp " "dla programów i dokumentów." #: C/introduction.page:16(p) msgid "" "The most typical use is to find a specific application and launch it. We " "have tried to make Kupfer easy to extend with plugins so that " "this quick-access paradigm can be extended to many more objects than just " "applications." msgstr "" "Najbardziej podstawowym użyciem jest znalezienie określonego programu i " "uruchomienie go. Kupfer został zaprojektowany w sposób " "umożliwiający łatwe rozszerzanie go przez wtyczki, więc szybki dostęp może " "dotyczyć wielu różnych obiektów - nie tylko programów." #: C/introduction.page:22(p) msgid "" "We hope that using Kupfer feels both very fun and " "different." msgstr "" "Autorzy mają nadzieję, że używanie Kupfera sprawi dużo " "przyjemności i ułatwi życie użytkownikowi." #: C/introduction.page:26(p) msgid "" "For up-to-date information about Kupfer, visit its homepage." msgstr "" "Najświeższe informacje na temat Kupfera można znaleźć na jego " "stronie domowej." #: C/index.page:9(name) msgid "Ulrik Sverdrup" msgstr "Ulrik Sverdrup" #: C/index.page:10(email) msgid "ulrik.sverdrup@gmail.com" msgstr "ulrik.sverdrup@gmail.com" #: C/index.page:13(year) msgid "2009" msgstr "2009" #: C/index.page:14(name) msgid "Kupfer Development Team" msgstr "Kupfer Development Team" #: C/index.page:17(license) msgid "Creative Commons Share Alike 3.0" msgstr "Creative Commons Share Alike 3.0" #: C/index.page:21(title) msgid "Kupfer Manual" msgstr "Podręcznik Kupfera" #: C/index.page:24(title) msgid "Using Kupfer" msgstr "Używanie Kupfera" #: C/index.page:27(title) msgid "About Specific Plugins" msgstr "Informacje o niektórych wtyczkach" #: C/generalusage.page:7(desc) msgid "How to start using Kupfer." msgstr "Rozpoczęcie pracy z Kupferem" #: C/generalusage.page:14(p) msgid "" "Kupfer is to the largest part a keyboard-managed interface to " "applications and documents." msgstr "" "Kupfer jest głównie \"klawiaturowym interfejsem\" dla programów i " "dokumentów." #: C/generalusage.page:18(p) msgid "" "Kupfer's default mode is the command mode: If you type a query, kupfer will " "search for a match in its catalog." msgstr "" "Domyślnym trybem pracy Kupfera jest tryb poleceń - wpisanie ciągu znaków " "spowoduje, że Kufer wyszuka pasujące obiekty w jego katalogu." #: C/generalusage.page:23(p) msgid "" "The arrow keys allow you to browse query matches quite naturally, going to " "the previous or next match, and going up and down in the subcatalogs." msgstr "" "Klawisz strzałek pozwalają na przeglądanie wyszukanych elementów, " "przechodząc do poprzedniego lub następnego znalezionego obiektu oraz " "poruszając się w górę i w dół podkatalogu." #: C/generalusage.page:29(p) msgid "In command mode, some keystrokes have special meanings:" msgstr "W trybie poleceń pewne klawisze posiadają specjalne znaczenie:" #: C/generalusage.page:71(p) msgid "" "By default you show Kupfer using the global keyboard shortcut " "CtrlSpace." msgstr "" "Domyślnie wyświetlenie okna Kupfera następuje po naciśnięciu " "klawiszy CtrlSpacja." #: C/generalusage.page:74(p) msgid "See for more information." msgstr "Więcej informacji można znaleźć w ." #: C/generalusage.page:78(title) msgid "Learning Habits" msgstr "Nauka przyzwyczajeń" #: C/generalusage.page:79(p) msgid "" "Kupfer remembers which objects and actions are used the most. " "When beginning to use it, you have to use the arrow keys at times to make it " "precise which object you want to find. After a few uses of that object, " "Kupfer will rank it higher. Objects marked as favorites are also ranked higher." msgstr "" "Kupfer zapamiętuje które obiekty i akcje są używane najczęściej. " "Na początku używania konieczne będzie wielokrotne używanie klawiszy strzałek " "w celu znalezienia szukanego obiektu. Po kilku użyciach danego obiektu " "Kupfer umieści go wyżej na swojej liście. Obiekty zaznaczone jako ulubione również są umieszczane wyżej." #: C/generalusage.page:90(title) msgid "The Catalog" msgstr "Katalog" #: C/generalusage.page:91(p) msgid "" "The Catalog is the collection of objects you can access in Kupfer, such as " "documents and programs." msgstr "" "Katalog jest kolekcją obiektów, do których Kupfer umożliwia dostęp, takich " "jak dokumenty i programy." #: C/generalusage.page:96(p) msgid "" "Objects in the catalog that have content, like folders, are marked with an " "arrow. Pressing will enter these objects. Much of the catalog " "is composed of subcatalogs; plugin subcatalogs do in general list objects " "that are also available directly from the top level. Subcatalogs can be used " "for a narrower view or search scope, when using Kupfer." msgstr "" "Obiekty w katalogu, które posiadają zawartość (tak jak foldery), są " "oznaczone strzałką. Naciśnięcie pokazuje zawartość tych " "obiektów. Wiele z katalogów składa się z podkatalogów; wtyczka \"podkatalogi" "\" tworzy ogólną listę obiektów, które są także bezpośrednio dostępne na " "najwyższym poziomie. Podkatalogi mogą być użyte do zawężenia wyświetlania " "lub wyszukiwania elementów podczas używania Kupfera." #: C/generalusage.page:105(p) msgid "" "Most subcatalogs update their content automatically. For example, the " "Desktop folder source is always up-to-date." msgstr "" "Większość podkatalogów aktualizuje swoją zawartość automatycznie. Na " "przykład katalog \"Pulpit\" jest zawsze aktualny." #. Put one translator per line, in the form of NAME , YEAR1, YEAR2 #: C/index.page:0(None) msgid "translator-credits" msgstr "Karol Będkowski , 2010" kupfer-328/help/ro/000077500000000000000000000000001500175051100142275ustar00rootroot00000000000000kupfer-328/help/ro/ro.po000066400000000000000000001734471500175051100152270ustar00rootroot00000000000000# Romanian translation for kupfer. # Copyright (C) 2011 kupfer's COPYRIGHT HOLDER # This file is distributed under the same license as the kupfer package. # Cătălin Bălan , 2011. msgid "" msgstr "" "Project-Id-Version: kupfer master\n" "POT-Creation-Date: 2011-06-23 10:09+0000\n" "PO-Revision-Date: 2011-01-06 14:51+0300\n" "Last-Translator: Cătălin Bălan \n" "Language-Team: Romanian Gnome Team 0 && n%100 < " "20)) ? 1 : 2);;\n" "X-Generator: Virtaal 0.5.2\n" #: C/plugin-websearch.page:7(desc) msgid "Using the search the web plugin." msgstr "" #: C/plugin-websearch.page:10(app) #, fuzzy #| msgid "Search the Web Search Engines" msgid "Search the Web" msgstr "Motoare de căutare pentru Internet" #: C/plugin-websearch.page:13(title) C/plugin-triggers.page:23(title) #: C/plugin-notes.page:22(title) C/plugin-nautilusselection.page:13(title) #: C/plugin-gwibber.page:25(title) C/plugin-favorites.page:22(title) #: C/plugin-calculator.page:21(title) C/plugin-applications.page:19(title) #: C/generalusage.page:10(title) msgid "Basic Usage" msgstr "Folosire de bază" #: C/plugin-websearch.page:15(p) msgid "Activate Kupfer and make sure it is in free-text mode (press period)" msgstr "" #: C/plugin-websearch.page:17(p) msgid "" "Type in a search query and tap Tab to switch to the action pane." msgstr "" #: C/plugin-websearch.page:19(p) msgid "" "Type \"Search With\" to find Search the Web's action and tap Tab " "again to switch to the third pane (indirect object)." msgstr "" #: C/plugin-websearch.page:22(p) msgid "" "Select search engine with the arrow keys and type Return to open " "the search in a web browser." msgstr "" #: C/plugin-websearch.page:29(title) #, fuzzy #| msgid "Search the Web Search Engines" msgid "Search Engines" msgstr "Motoare de căutare pentru Internet" #: C/plugin-websearch.page:30(p) msgid "" "The Search the Web plugin uses Firefox' search engines, so you " "can add Search Engines directly in Firefox and Kupfer " "will find them later." msgstr "" "Modulul „Caută pe Internet” folosește motoarele de căutare din Firefox, așa că puteți adăuga motoare de căutare direct în Firefox " "și Kupfer le va găsi ulterior." #: C/plugin-websearch.page:35(p) msgid "" "You can also install custom search plugins directly, only for Kupfer, in the folder:" msgstr "" "De asemenea, puteți instala module de căutare direct, doar pentru " "Kupfer, în dosarul:" #: C/plugin-websearch.page:39(code) #, no-wrap msgid "~/.local/share/kupfer/searchplugins/" msgstr "~/.local/share/kupfer/searchplugins/" #: C/plugin-websearch.page:40(p) msgid "The search engine descriptions must written in OpenSearch format." msgstr "" #: C/plugin-triggers.page:7(desc) msgid "Using the triggers plugin." msgstr "" #: C/plugin-triggers.page:10(app) C/keyboard.page:213(title) msgid "Triggers" msgstr "" #: C/plugin-triggers.page:13(title) msgid "Triggers Plugin" msgstr "" #: C/plugin-triggers.page:14(p) msgid "" "With Triggers you can take a command you would normally perform " "in Kupfer, such as launching an application or opening a " "document, and bind a global key combination to run this command. As long as " "Kupfer is running, any application can have the current focus." msgstr "" #: C/plugin-triggers.page:25(title) msgid "Creating a new trigger" msgstr "" #: C/plugin-triggers.page:27(p) msgid "Set up a command in Kupfer that you want to run" msgstr "" #: C/plugin-triggers.page:32(p) msgid "" "Press CtrlReturn to create a " "composed command." msgstr "" #: C/plugin-triggers.page:38(p) msgid "" "Type Tab and select the action Add Trigger... and press " "Return" msgstr "" #: C/plugin-triggers.page:44(p) msgid "" "Using the window that appears, press modifier keys and a letter or number " "key to set a global shortcut. An example is pressing and holding " "CtrlAlt and then pressing and " "releasing R to bind CtrlAltR." msgstr "" #: C/plugin-triggers.page:54(title) msgid "Removing a trigger" msgstr "" #: C/plugin-triggers.page:56(p) msgid "" "Find the source Triggers in Kupfer and press to see its contents." msgstr "" #: C/plugin-triggers.page:62(p) msgid "" "Find the active trigger in the list and use the action Remove Trigger." msgstr "" #: C/plugin-triggers.page:68(p) msgid "" "Since trigger keyboard shortcuts are global, they can be used from any " "application. Select shortcuts with care so that they do not conflict with " "other functions." msgstr "" #: C/plugin-triggers.page:74(title) C/plugin-notes.page:60(title) #: C/plugin-gwibber.page:68(title) C/plugin-favorites.page:38(title) msgid "Power User Tips" msgstr "" #: C/plugin-triggers.page:75(p) msgid "" "Proxy objects such as Selected Text, Selected File, Frontmost Window, Last Command et cetera allow very " "powerful triggers." msgstr "" #: C/plugin-triggers.page:79(p) msgid "" "The application action Launch is special; if you bind a trigger " "using Launch, it will start the application if it is not running, " "but focus the application when it is already running. By contrast, Start " "Again will start the application if it is running or not." msgstr "" #: C/plugin-triggers.page:87(title) msgid "Example Triggers" msgstr "" #: C/plugin-triggers.page:90(em) msgid "Text Editor → Launch" msgstr "" #: C/plugin-triggers.page:91(p) msgid "" "Start Text Editor or focus its window if it is already running." msgstr "" #: C/plugin-triggers.page:97(em) msgid "Selected Text → Search With → Google" msgstr "" #: C/plugin-triggers.page:98(p) msgid "Search the web using the currently selected text." msgstr "" #: C/plugin-triggers.page:100(em) msgid "Selected File → Move To → (Downloads Folder)" msgstr "" #: C/plugin-triggers.page:101(p) msgid "Move the currently selected file to a specific folder" msgstr "" #: C/plugin-triggers.page:105(em) msgid "Songs → Search Contents" msgstr "" #: C/plugin-triggers.page:106(p) msgid "" "You may even add a trigger to open a specific subcatalog in Kupfer, for " "example Rhythmbox's songs." msgstr "" #: C/plugin-notes.page:7(desc) msgid "Using the notes plugin." msgstr "" #: C/plugin-notes.page:10(app) C/plugin-calculator.page:37(title) msgid "Notes" msgstr "" #: C/plugin-notes.page:13(title) #, fuzzy #| msgid "Plugins" msgid "Notes Plugin" msgstr "Module" #: C/plugin-notes.page:14(p) msgid "" "With Notes you can access or create new notes in either the " "program Gnote or Tomboy. Notes will work " "identically with either application—you can configure which one to use in " "the plugin's information pane in Kupfer Preferences." msgstr "" #: C/plugin-notes.page:24(title) msgid "Creating a new note" msgstr "" #: C/plugin-notes.page:26(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "note title" msgstr "" #: C/plugin-notes.page:32(p) msgid "" "Type Tab and select the action Create Note and press " "Return." msgstr "" #: C/plugin-notes.page:39(title) msgid "Finding a note by title" msgstr "" #: C/plugin-notes.page:41(p) msgid "Simply search for the note title in Kupfer" msgstr "" #: C/plugin-notes.page:45(title) #, fuzzy #| msgid "Descend into an object with content" msgid "Finding a note by content" msgstr "Coboară într-un obiect cu conținut" #: C/plugin-notes.page:47(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "search query" msgstr "" #: C/plugin-notes.page:53(p) msgid "" "Type Tab and select the action Get Note Search Results... and press Return." msgstr "" #: C/plugin-notes.page:63(p) msgid "" "You can use the Selected Text object and create a new note with the " "content of the selection." msgstr "" #: C/plugin-nautilusselection.page:7(desc) msgid "Using the selected file plugin." msgstr "" #: C/plugin-nautilusselection.page:10(app) msgid "Selected File" msgstr "" #: C/plugin-nautilusselection.page:14(p) msgid "" "Select a file in the file manager. Open Kupfer and search for the " "object Selected File, which represents the file or files that are " "selected." msgstr "" #: C/plugin-nautilusselection.page:19(p) msgid "" "Instead of searching, you can press CtrlG to directly focus the selected file. See " "for more information." msgstr "" #: C/plugin-nautilusselection.page:26(title) msgid "Selected File requires Nautilus" msgstr "" #: C/plugin-nautilusselection.page:27(p) msgid "" "The selected file plugin works with the Nautilus file browser and " "requires that the extension kupfer_provider.py is installed (it " "is normally installed together with Kupfer). After installing it " "for the first time, Nautilus must start anew before it is active." msgstr "" #: C/plugin-gwibber.page:7(desc) msgid "Using the Gwibber plugin." msgstr "" #: C/plugin-gwibber.page:10(app) msgid "Gwibber" msgstr "" #: C/plugin-gwibber.page:13(title) msgid "Gwibber Plugin" msgstr "" #: C/plugin-gwibber.page:14(p) msgid "" "With the Gwibber plugin you can send messages to social networks " "such as Twitter or Identi.ca." msgstr "" #: C/plugin-gwibber.page:18(p) msgid "" "The plugin requires that the application Gwibber is installed and " "configured for your user. Kupfer will start and use Gwibber's " "service in the background." msgstr "" #: C/plugin-gwibber.page:27(title) msgid "Sending a message to all services" msgstr "" #: C/plugin-gwibber.page:29(p) msgid "" "Activate Kupfer and type . to enter text mode, then type in a " "message." msgstr "" #: C/plugin-gwibber.page:35(p) msgid "" "Type Tab and select the action Send Message and press " "Return." msgstr "" #: C/plugin-gwibber.page:42(title) msgid "Sending a message to a specific service" msgstr "" #: C/plugin-gwibber.page:44(p) msgid "" "Activate Kupfer and search for the service object, for example Identi." "ca" msgstr "" #: C/plugin-gwibber.page:50(p) msgid "Type Tab and select the action Send Message." msgstr "" #: C/plugin-gwibber.page:55(p) msgid "" "Type Tab to select the last pane, and type in a message. Press " "Return to send." msgstr "" #: C/plugin-gwibber.page:61(p) msgid "" "The plugin also provides a source for incoming messages, Gwibber " "Messages and more actions on messages such as Reply, Send " "Private Message etc." msgstr "" #: C/plugin-gwibber.page:71(p) msgid "" "You can use the comma trick if you want to send a message to more " "than one service, but not all, at the same time." msgstr "" #: C/plugin-favorites.page:7(desc) msgid "Using the favorites plugin." msgstr "" #: C/plugin-favorites.page:10(app) msgid "Favorites" msgstr "" #: C/plugin-favorites.page:13(title) #, fuzzy #| msgid "Calculator Plugin" msgid "Favorites Plugin" msgstr "Modulul calculator" #: C/plugin-favorites.page:14(p) msgid "" "With Favorites you mark objects, for example files, for quicker " "access. It is a sort of shelf on which you can store objects in Kupfer. " "Objects marked as favorites will also be ranked higher and are adorned with " "a star symbol." msgstr "" #: C/plugin-favorites.page:25(p) #, fuzzy #| msgid "Introduction to Kupfer." msgid "Find an object in Kupfer" msgstr "Introducere în Kupfer." #: C/plugin-favorites.page:30(p) msgid "" "Type Tab and select either the action Add to Favorites " "or Remove from Favorites." msgstr "" #: C/plugin-favorites.page:39(p) msgid "" "If you favorite an object, you can access it in more places. Not only in the " "\"Favorites\" subcatalog, but also as the indirect (secondary) object for " "some actions. For example:" msgstr "" #: C/plugin-favorites.page:45(p) msgid "Command-lines from favorites are quick to access." msgstr "" #: C/plugin-favorites.page:46(p) msgid "" "When scaling images with the Scale... action from the Image " "Tools plugin. This action needs a size description as the third " "object, like \"1024\" or \"1200x800\". If you often scale to the same size, " "say \"1200x800\", add this to favorites, and it will always appear as a " "suggestion for the action." msgstr "" #: C/plugin-favorites.page:54(p) msgid "" "Actions needing an email address as the indirect object will pick up email " "addresses from favorites as well as well." msgstr "" #: C/plugin-calculator.page:7(desc) #, fuzzy #| msgid "Calculator Plugin" msgid "Using the calculator plugin." msgstr "Modulul calculator" #: C/plugin-calculator.page:10(app) #, fuzzy #| msgid "Calculator Plugin" msgid "Calculator" msgstr "Modulul calculator" #: C/plugin-calculator.page:13(title) msgid "Calculator Plugin" msgstr "Modulul calculator" #: C/plugin-calculator.page:14(p) msgid "" "The calculator plugin lets you calculate expressions quickly. It can " "evaluate expressions entered as text starting with \"=\". Entering = from " "command mode will start text mode directly with = prefixed for quick access." msgstr "" "Modulul calculator vă permite să calculați expresii rapid. Acesta poate " "evalua expresii introduse ca text ce începe cu „=”. Introducerea = din modul " "de comandă va porni modul text direct cu = ca prefix pentru acces rapid." #: C/plugin-calculator.page:23(p) msgid "Activate Kupfer and type =" msgstr "" #: C/plugin-calculator.page:26(p) msgid "" "Type in a mathematical expression using +,-,/,* (and ** for exponentiation)" msgstr "" #: C/plugin-calculator.page:30(p) msgid "Press Return to get the result." msgstr "" #: C/plugin-calculator.page:38(p) #, fuzzy #| msgid "" #| "The Calculator uses python's math and complex math modules, and parses " #| "expressions as Python expressions. You may use common mathematical " #| "functions, such as sqrt, sin, exp and log; the command =help " #| "will show a list of all defined functions and constants." msgid "" "The Calculator uses python's math and complex math modules, and parses " "expressions as Python expressions. You may use common mathematical " "functions, such as sqrt, sin, exp and " "log; the command =help will show a list of all defined " "functions and constants." msgstr "" "Calculatorul folosește modulele pentru matematică și matematică cu numere " "complexe din Python, și analizează textul ca o expresie Python. Puteți " "folosi funcții matematice comune, precum sqrt, sin, exp și log; comanda " "=help va afișa o listă cu toate funcțiile și constrângerile " "definite." #: C/plugin-calculator.page:47(p) #, fuzzy #| msgid "" #| "Notice that the power operator in Python is double stars, for example " #| "=3**3 will evaluate to 27." msgid "" "Notice that the power operator in Python is double stars, for example " "=3**3 will evaluate to 27." msgstr "" "Amintiți-vă că operația pentru ridicare la putere în Python este „**”, de " "exemplu =3**3 va rezulta 27." #: C/plugin-calculator.page:53(p) msgid "To calculate trig functions for angles, convert to radians first:" msgstr "" "Pentru a calcula funcții trigonometrice pentru unghiuri, transformați măsura " "unghiurilor în radiani întâi:" #: C/plugin-calculator.page:56(code) #, no-wrap msgid "sin(radians(30)) -> 0.5" msgstr "sin(radians(30)) -> 0.5" #: C/plugin-calculator.page:59(p) msgid "" "The last result is stored as the name _ (an underscore, just like in the " "Python console)." msgstr "" "Ultimul rezultat este stocat sub numele de _ (un underscore, ca și în " "consola Python)." #: C/plugin-applications.page:7(desc) msgid "Using the applications plugin." msgstr "" #: C/plugin-applications.page:10(app) msgid "Applications" msgstr "" #: C/plugin-applications.page:13(title) #, fuzzy #| msgid "Calculator Plugin" msgid "Applications Plugin" msgstr "Modulul calculator" #: C/plugin-applications.page:14(p) msgid "Applications provides all installed programs." msgstr "" #: C/plugin-applications.page:21(title) msgid "Launching an application" msgstr "" #: C/plugin-applications.page:23(p) msgid "Activate Kupfer and type an abbreviation of the application name" msgstr "" #: C/plugin-applications.page:28(p) msgid "Press Return to launch the application." msgstr "" #: C/plugin-applications.page:34(title) msgid "Opening a file with a specific application" msgstr "" #: C/plugin-applications.page:36(p) #, fuzzy #| msgid "Introduction to Kupfer." msgid "Select a file in Kupfer" msgstr "Introducere în Kupfer." #: C/plugin-applications.page:41(p) msgid "Type Tab and select the action Open With..." msgstr "" #: C/plugin-applications.page:46(p) msgid "" "Type Tab to select the third (indirect object) pane and in it, " "select the application to open the file with." msgstr "" #: C/plugin-applications.page:53(p) msgid "" "The action Open opens files and folders with the registered default " "application for that specific file type. This can be configured using the " "action Set Default Application...." msgstr "" #: C/plugin-applications.page:58(p) msgid "" "The file type associations are provided by the desktop environment, and " "modifying them here will modify them on the desktop as well. This may not be " "true when not using GNOME or XFCE." msgstr "" #: C/plugin-applications.page:64(title) msgid "Selecting default application for a file type or folders" msgstr "" #: C/plugin-applications.page:66(p) #, fuzzy #| msgid "Introduction to Kupfer." msgid "Select a file or folder in Kupfer" msgstr "Introducere în Kupfer." #: C/plugin-applications.page:71(p) msgid "" "Type Tab and select the action Set Default Application..." msgstr "" #: C/plugin-applications.page:77(p) msgid "" "Type Tab to select the third (indirect object) pane and in it, " "select the application to always open the file type with." msgstr "" #: C/plugin-applications.page:85(title) #, fuzzy #| msgid "Configuration files and paths" msgid "Configuration" msgstr "Fișiere și căi de configurare" #: C/plugin-applications.page:86(p) msgid "" "The configuration option Applications for Desktop Environment in " "the plugin's information pane in Kupfer Preferences determines " "how Kupfer should act with regard to the desktop environment " "configuration—certain applications request not to be shown depending on " "which desktop environment is used. By default, it behaves like GNOME." msgstr "" #: C/moreusage.page:7(desc) msgid "More advanced usage information." msgstr "" #: C/moreusage.page:10(title) #, fuzzy #| msgid "Using Kupfer plugins." msgid "Using Kupfer in Depth" msgstr "Folosirea modulelor Kupfer" #: C/moreusage.page:13(title) #, fuzzy #| msgid "Adding your actions and scripts" msgid "Adding Applications and Scripts" msgstr "Adăugarea de acțiuni și scripturi personalizate" #: C/moreusage.page:14(p) msgid "" "Kupfer will show all applications that are configured visible in " "your menu editor." msgstr "" #: C/moreusage.page:18(p) #, fuzzy #| msgid "" #| "If you want to add a custom application, or an application called with " #| "special options, you can create a new launcher for it and place it in one " #| "of the standard places for applications, for example ~/.local/share/" #| "applications, where Kupfer will find it." msgid "" "If you want to add an application manually, you can create a new ." "desktop file and place it in one of the standard directories for " "applications, for example ~/.local/share/applications, where " "Kupfer will find it." msgstr "" "Dacă doriți să adăugați o aplicație personalizată sau o aplicație apelată cu " "opțiuni speciale, puteți crea un lansator pentru ea și să-l plasați în unul " "dintre locurile standard pentru aplicații, de exemplu ~/.local/share/" "applications, unde Kupfer îl va găsi." #: C/moreusage.page:24(p) msgid "" "If you have a collection of scripts that you want to call from Kupfer, you can add the scripts folder as a catalog directory to Kupfer in the preferences. Scripts that you add to Kupfer's catalog " "this way can be run directly or in the terminal as long as they are " "executable." msgstr "" "Dacă aveți o colecție de scripturi ce care doriți să le apelați din " "Kupfer, puteți să le adăugați într-un dosar de scripturi ca și un " "dosar catalog în Kupfer la preferințe. Scripturile pe care le " "adăugați în catalogul Kupfer pot fi astfel rulate direct sau din " "terminal atât timp cât ele sunt executabile." #: C/moreusage.page:31(p) msgid "" "You can also save command-lines by using the action Add to Favorites." msgstr "" #: C/moreusage.page:38(title) msgid "Opening Files and Folders" msgstr "" #: C/moreusage.page:39(p) msgid "" "Using the action Open, files and folders are opened in their " "preferred application. The application associations can be changed, see " "." msgstr "" #: C/moreusage.page:47(title) msgid "The Comma Trick" msgstr "" #: C/moreusage.page:48(p) msgid "" "The comma trick allows the user to use actions on many objects at the same " "time." msgstr "" #: C/moreusage.page:52(p) msgid "" "Simply press comma , when an object is selected. The object is " "put on a \"stack\", and you can find yet another file or object, press comma " "to put it on the stack. When you subsequently invoke an action, the action " "is carried out on all of the objects at the same time." msgstr "" #: C/moreusage.page:58(p) msgid "" "Some actions are only \"multiplied\" when used with many objects, other are " "smarter than that:" msgstr "" #: C/moreusage.page:61(p) msgid "" "Selecting many files and using the Create Archive action, all files will be " "packed into the same archive." msgstr "" #: C/moreusage.page:63(p) msgid "" "If you select multiple contacts and use a Send Email action, it creates one " "email directed at all the contacts." msgstr "" #: C/moreusage.page:65(p) msgid "" "If you select multiple subcatalogs (For example Firefox Bookmarks and " "Epiphany Bookmarks) and use Search Contents.., you get a subcatalog search " "restricted to the objects of those two catalogs! You can even bind a trigger " "to this command(!)" msgstr "" #: C/moreusage.page:71(p) msgid "" "The comma trick is directly taken from Quicksilver (the " "example given in the external article should work identically in Kupfer)." msgstr "" #: C/moreusage.page:80(title) #, fuzzy #| msgid "Grab current selection" msgid "Grab Current Selection" msgstr "Prinderea selecției curente" #: C/moreusage.page:81(p) msgid "" "To use the current selected text, from any application, with Kupfer, you can configure a global keyboard shortcut for the action Show " "with Selection in Kupfer Preferences." msgstr "" #: C/moreusage.page:85(p) msgid "" "If configured, pressing the global keyboard shortcut will summon " "Kupfer with the current selection as the focused object." msgstr "" #: C/moreusage.page:90(p) msgid "See " msgstr "" #: C/moreusage.page:94(title) #, fuzzy #| msgid "Command line connection" msgid "Command-line Connection" msgstr "Conexiune cu linia de comandă" #: C/moreusage.page:95(p) msgid "" "The command kupfer on the command-line will focus Kupfer if it's already running, otherwise it will start it." msgstr "" #: C/moreusage.page:99(p) #, fuzzy #| msgid "" #| "For example, if you are using the shell in a directory where you have a " #| "file called \"report.pdf\", you can focus this file in Kupfer " #| "by running kupfer report.pdf." msgid "" "The command kupfer can be used to send files or text from the " "command-line to Kupfer. For example, if you are using the shell " "in a directory where you have a file called \"report.pdf\", you can focus " "this file in Kupfer by running kupfer report.pdf." msgstr "" "De exemplu, dacă folosiți shell-ul într-un dosar unde aveți un fișier numit " "„report.pdf”, puteți să focalizați acest fișier în Kupfer rulând " "kupfer report.pdf." #: C/moreusage.page:107(p) msgid "" "You can also send text if you pipe the output of a command into kupfer." msgstr "" #: C/moreusage.page:114(title) msgid "Managing Context and Current Selection" msgstr "Gestionarea contextului și a selecției curente" #: C/moreusage.page:115(p) msgid "" "If you find the object you want to use, then invoke an action, Kupfer goes away to perform the action (for example start a program or play a " "song). When you come back to Kupfer, it will still keep the same " "object and action selected. Some actions make sense to be repeated (like " "skipping to the next song) and it can be useful to perform different actions " "on the same object." msgstr "" "Dacă găsiți un obiect pe care doriți să-l folosiți, apoi să invocați o " "acțiune, Kupfer va pleca pentru a efectua acțiunea (de exemplu " "pentru a porni un program sau a reda o piesă). Când vă întoarceți la " "Kupfer, acesta va păstra același obiect sau acțiune selectată. " "Unele acțiuni au sens să fie repetate (de exemplu saltul la următoarea " "piesă). De asemenea, poate fi folosit pentru a efectua acțiuni diferite pe " "același obiect." #: C/moreusage.page:123(p) msgid "" "However, you always have the top level catalog reachable when you \"come back" "\" to Kupfer -- say you went into the subcatalog \"Albums\" to " "browse your albums only; you select an album to play, and play it. You come " "back with the album selected -- but your next search will still go over the " "top level catalog, not just albums." msgstr "" "Totuși, veți avea întotdeauna catalogul de cel mai înalt nivel accesibil " "când „vă întoarceți” la Kupfer -- De exemplu dacă ați coborât în " "subcatalogul „Albume” pentru a căuta doar albume; ați ales un album pentru a " "fi redat și ați executat acțiunea, la întoarcere veți găsi același album " "selectat, dar căutarea va continua de la catalogul de cel mai înalt nivel, " "nu doar la albume." #: C/moreusage.page:130(p) msgid "" "How to come back into the subcatalog you were in? You do that by simply " "browsing, not searching the first thing you do when you focus Kupfer again. A quick way is to press down-arrow or space to open the browse " "window; think of it as saying \"I want to stay in this subfolder\". With the " "browse window open, your next query will search the current subcatalog." msgstr "" "Cum să vă întoarceți la același subcatalog? Faceți asta prin simplu fapt că " "navigați întâi, nu căutați, când focalizați din nou pe Kupfer. Un " "mod rapid de a face asta e să apăsați săgeată-jos sau spațiu pentru a " "deschide fereastra de navigare. Puteți vedea această acțiune ca și „Vreau să " "stau în acest subdosar”. Cu fereastra de navigare deschisă, următoarea " "interogare va căuta în subcatalogul curent." #: C/moreusage.page:137(p) msgid "" "This way you can work both ways -- you can quickly drill down into folders " "to find a file, and when you come back for the next action with Kupfer you can either summon any normal toplevel object (just start typing), " "or stay around where you were, deep in that folder (press space, then type a " "query)." msgstr "" "În acest mod, puteți lucra în ambele moduri -- puteți ajunge repede în " "dosare pentru a găsi un fișier, și când vă întoarceți pentru următoarea " "acțiune, veți putea să chemați un obiect normal de la nivelul cel mai înalt " "(începeți pur și simplu să scrieți), sau reveniți unde erați, adânc în acel " "dosar (apăsați spațiu înainte de a scrie interogarea)." #: C/moreusage.page:146(title) msgid "Saving Commands as Files" msgstr "" #: C/moreusage.page:147(p) msgid "" "You can use keyboard shortcut for Compose Command (by default it is " "CtrlReturn) to create a command " "object out of the currently focused command in Kupfer. This object can be " "saved as a runnable file if you use the Save As... action. The " "resulting file will can be executed when opened from the file manager (it " "requires that Kupfer is already running)." msgstr "" #: C/managing-plugins.page:7(desc) #, fuzzy #| msgid "Introduction to Kupfer." msgid "Using plugins with Kupfer." msgstr "Introducere în Kupfer." #: C/managing-plugins.page:10(title) msgid "How to Configure Plugins" msgstr "" #: C/managing-plugins.page:12(p) msgid "" "Functionality in Kupfer is organized by extentsion modules called \"plugins" "\". Each plugin provides additional functionality, for example integration " "with an external application." msgstr "" #: C/managing-plugins.page:19(title) msgid "Configuring Plugins" msgstr "" #: C/managing-plugins.page:21(title) #, fuzzy #| msgid "Using Kupfer plugins." msgid "Open Kupfer Preferences to the Plugins tab" msgstr "Folosirea modulelor Kupfer" #: C/managing-plugins.page:23(p) msgid "Use one of the following methods:" msgstr "" #: C/managing-plugins.page:25(p) msgid "" "Click the Kupfer icon in the notification area and select the item " "Preferences" msgstr "" #: C/managing-plugins.page:25(item) msgid "." msgstr "" #: C/managing-plugins.page:29(p) msgid "" "Search for the object Kupfer Preferences in Kupfer itself. Press " "Return to open it." msgstr "" #: C/managing-plugins.page:33(p) #, fuzzy #| msgid " or ShiftSpace" msgid "Use the keyboard shortcut Ctrl;" msgstr " sau ShiftSpațiu" #: C/managing-plugins.page:39(p) msgid "Select the tab Plugins" msgstr "" #: C/managing-plugins.page:45(p) msgid "" "Select plugins in the list to read about them, and tick the box next to its " "name to activate the plugin, or untick to deactivate." msgstr "" #: C/managing-plugins.page:49(p) msgid "" "If the plugin has any configurable parameters, they will be visible below " "the plugin information." msgstr "" #: C/managing-plugins.page:53(p) msgid "" "The plugin Kupfer Plugins allows fast access to each plugin's " "information page as well as the action \"Show Source Code\" which reveals " "the implementation." msgstr "" #: C/managing-plugins.page:59(title) msgid "If a Plugin can not be Activated" msgstr "" #: C/managing-plugins.page:60(p) msgid "" "If a plugin fails to activate because it requires a software module that is " "not available, its plugin information will display a message like this:" msgstr "" #: C/managing-plugins.page:65(em) msgid "Plugin could not be read due to an error:" msgstr "" #: C/managing-plugins.page:66(em) msgid "Python module 'gdata' is needed" msgstr "" #: C/managing-plugins.page:67(p) msgid "" "This means that you need to install a needed python module from your " "distribution—and possibly the plugin documentation can tell you how." msgstr "" #: C/managing-plugins.page:72(p) msgid "" "The plugin may also unexpectedly fail to load, and display a different error " "message. It may then be a program error in either the plugin or Kupfer." msgstr "" #: C/managing-plugins.page:79(title) #, fuzzy #| msgid "Calculator Plugin" msgid "Installing more Plugins" msgstr "Modulul calculator" #: C/managing-plugins.page:80(p) msgid "" "You can install custom plugins into the folder ~/.local/share/kupfer/" "plugins. Each plugin is either a single .py file or a " "python package (a folder directly containing a file called __init__." "py). Plugins in the package format can include icon files. Python " "packages can even be installed as .zip files." msgstr "" #: C/managing-plugins.page:88(p) msgid "" "Caution: Treat a plugin as a computer program. Do not install " "untrusted plugins." msgstr "" #: C/managing-plugins.page:95(title) #, fuzzy #| msgid "Plugins" msgid "Creating Plugins" msgstr "Module" #: C/managing-plugins.page:96(p) msgid "" "Documentation for plugin creators is available in the file " "Documentation/Manual.rst in the source distribution on the " "webpage at Kupfer " "Manual. An easy way to start is to copy an existing plugin and " "experimenting with it." msgstr "" #: C/managing-plugins.page:107(title) msgid "The Catalog Tab in Preferences" msgstr "" #: C/managing-plugins.page:108(p) msgid "" "Each plugin can export a number of sources which contain objects. Normally, " "all these objects are directly accessible from a top-level search. Some " "plugins export so specialized or so many objects that their catalogs should " "better not have their objects exported to the top level. To reach those " "objects, you have to first find the catalog by name, then enter the catalog " "using the action Search Contents." msgstr "" #: C/managing-plugins.page:118(p) msgid "" "In the tab Catalog in Kupfer Preferences, a ticked box " "next to each source means that its objects are exported. An unticked box " "means that its contents are hidden from the top level." msgstr "" #: C/managing-plugins.page:123(p) msgid "" "Note: Kupfer may become slow if large enough subcatalogs are " "exported to the top level." msgstr "" #: C/license.page:7(desc) msgid "You can copy, modify and share Kupfer." msgstr "" #: C/license.page:10(title) msgid "License" msgstr "Licență" #: C/license.page:12(p) msgid "" "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." msgstr "" "Acest program este software liber: puteți să-l redistribuiți sau modificați " "luând în considerare termenii GNU General Public License publicată " "de Free Software Foundation, versiunea 3 a licenței, sau (la alegere) o altă " "versiune mai recentă." #: C/license.page:18(p) msgid "" "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." msgstr "" "Acest program este distribuit în speranța că va fi folositor, dar FĂRĂ " "GARANȚIE; fără vreun fel de garanție pe VANDABILITATE sau POTRIVIRE PENTRU " "UN SCOP SPECIFIC. Citiți GNU General Public License pentru mai " "multe detalii." #: C/license.page:24(p) msgid "" "You should have received a copy of the GNU General Public License along with " "this program. If not, see gnu." "org/licenses." msgstr "" "Ar fi trebui să primiți o copie a GNU General Public License împreună cu " "acest program. Dacă nu, vizitați gnu.org/licenses." #: C/license.page:30(p) msgid "" "This documentation is licensed under a Creative Commons Attribution-Share Alike 3.0 " "Unported License." msgstr "" "Această documentație este licențiată sub o licență neadaptată Creative Commons " "Atribuire-Distribuire în condiții identice 3.0" #: C/license.page:36(p) msgid "" "As a special exception, the copyright holders give you permission to copy, " "modify, and distribute the example code contained in this document under the " "terms of your choosing, without restriction." msgstr "" "Ca și o excepție specială, deținătorii de drepturi de autor vă dau " "permisiunea să copiați, modificați și distribuiți exemple de cod conținute " "în acest document luând în considerare termeni aleși de dumneavoastră, fără " "restricție. " #: C/keyboard.page:7(desc) #, fuzzy #| msgid "Global Keyboard Shortcuts" msgid "Complete keyboard shortcuts reference." msgstr "Scurtături globale de tastatură" #: C/keyboard.page:10(title) msgid "Command Keys and Accelerator Keys" msgstr "" #: C/keyboard.page:13(title) C/generalusage.page:12(title) #, fuzzy msgid "Keyboard Interface" msgstr "Interfața de tastatură" #: C/keyboard.page:14(p) #, fuzzy #| msgid "In command mode, some keystrokes have special meanings:" msgid "In command mode, the following keystrokes have special meanings:" msgstr "În modul de comandă, câteva taste au înțelesuri speciale:" #: C/keyboard.page:19(p) C/generalusage.page:34(p) msgid " or Space" msgstr " sau Spațiu" #: C/keyboard.page:20(p) C/generalusage.page:35(p) msgid "Go to the next match" msgstr "Salt la rezultatul următor" #: C/keyboard.page:23(p) C/generalusage.page:38(p) msgid " or ShiftSpace" msgstr " sau ShiftSpațiu" #: C/keyboard.page:26(p) C/generalusage.page:41(p) msgid "Go to the previous match" msgstr "Salt la rezultatul precedent" #: C/keyboard.page:29(p) C/generalusage.page:44(p) msgid " or /" msgstr " sau /" #: C/keyboard.page:30(p) C/generalusage.page:45(p) msgid "Descend into an object with content" msgstr "Coboară într-un obiect cu conținut" #: C/keyboard.page:33(key) C/generalusage.page:48(key) msgid "Backspace" msgstr "Backspace" #: C/keyboard.page:34(p) C/generalusage.page:49(p) msgid "Erase a character from the query. If the query is empty, go up a level" msgstr "" "Șterge un caracter din interogare. Dacă aceasta este goală, urcă un nivel" #: C/keyboard.page:39(key) C/keyboard.page:93(key) C/generalusage.page:54(key) msgid "." msgstr "." #: C/keyboard.page:40(p) C/generalusage.page:55(p) msgid "Activate free-text mode" msgstr "Activează modul text-liber" #: C/keyboard.page:43(key) C/keyboard.page:97(key) C/generalusage.page:58(key) msgid "," msgstr "," #: C/keyboard.page:44(p) C/generalusage.page:59(p) msgid "Put selected object on the stack (\"Comma Trick\")" msgstr "Pune obiectul selectat în stivă („Trucul virgulă”)" #: C/keyboard.page:47(p) msgid "Quick access keys:" msgstr "" #: C/keyboard.page:53(key) msgid "=" msgstr "" #: C/keyboard.page:55(p) msgid "" "Activate free-text mode with = prefix (for )" msgstr "" #: C/keyboard.page:61(key) msgid "/" msgstr "" #: C/keyboard.page:63(p) msgid "" "Activate free-text mode (when nothing is selected) with / " "prefix (to input a rooted path)" msgstr "" #: C/keyboard.page:68(p) C/generalusage.page:62(p) msgid "Additionally:" msgstr "" #: C/keyboard.page:72(p) C/generalusage.page:66(p) #, fuzzy #| msgid "" #| "Additionally, the key Return activates the current selection: " #| "the command is executed. Escape clears the current selection." msgid "" "Return activates the current selection: the command is executed." msgstr "" "Adițional, tasta Enter activează selecția curentă: această " "comandă este executată. Escape curăță selecția curentă." #: C/keyboard.page:74(p) C/generalusage.page:68(p) msgid "Escape clears the current selection." msgstr "" #: C/keyboard.page:75(p) C/generalusage.page:69(p) msgid "Tab switches between the object and the action pane." msgstr "" #: C/keyboard.page:77(p) msgid "" "The meaning of the keys Space, ., ,, /" " and = can not be changed, but you can deactivate their " "special meaning with the checkbox Use single keystroke commands " "in Kupfer Preferences." msgstr "" #: C/keyboard.page:86(title) #, fuzzy #| msgid "Global Keyboard Shortcuts" msgid "Kupfer's Keyboard Shortcuts" msgstr "Scurtături globale de tastatură" #: C/keyboard.page:87(p) msgid "" "These keyboard shortcuts are used in Kupfer's interface. They " "have the following meanings and default shortcuts:" msgstr "" #: C/keyboard.page:93(key) C/keyboard.page:97(key) C/keyboard.page:101(key) #: C/keyboard.page:105(key) C/keyboard.page:113(key) C/keyboard.page:117(key) #: C/keyboard.page:121(key) C/keyboard.page:125(key) C/keyboard.page:129(key) #: C/keyboard.page:174(key) msgid "Ctrl" msgstr "" #: C/keyboard.page:94(p) msgid "Toggle text mode" msgstr "" #: C/keyboard.page:98(p) msgid "The comma trick" msgstr "" #: C/keyboard.page:101(key) msgid ";" msgstr "" #: C/keyboard.page:102(p) msgid "Show preferences window" msgstr "" #: C/keyboard.page:105(key) msgid "R" msgstr "" #: C/keyboard.page:106(p) msgid "Reset all" msgstr "" #: C/keyboard.page:109(key) msgid "Alt" msgstr "" #: C/keyboard.page:109(key) msgid "A" msgstr "" #: C/keyboard.page:110(p) msgid "Alternate activate" msgstr "" #: C/keyboard.page:113(key) msgid "Return" msgstr "" #: C/keyboard.page:114(p) msgid "Compose command" msgstr "" #: C/keyboard.page:117(key) msgid "S" msgstr "" #: C/keyboard.page:118(p) msgid "Switch to first pane" msgstr "" #: C/keyboard.page:121(key) msgid "Q" msgstr "" #: C/keyboard.page:122(p) msgid "Select 'Quit'" msgstr "" #: C/keyboard.page:125(key) msgid "G" msgstr "" #: C/keyboard.page:126(p) msgid "Select 'Selected File'" msgstr "" #: C/keyboard.page:129(key) msgid "T" msgstr "" #: C/keyboard.page:130(p) msgid "Select 'Selected Text'" msgstr "" #: C/keyboard.page:133(key) msgid "F1" msgstr "" #: C/keyboard.page:134(p) msgid "Show Help" msgstr "" #: C/keyboard.page:139(title) #, fuzzy #| msgid "Additional Keyboard Shortcuts" msgid "How to configure a keyboard shortcut" msgstr "Scurtături adiționale de tastatură" #: C/keyboard.page:141(p) C/keyboard.page:185(p) msgid "Open Kupfer Preferences and go to the Keyboard tab." msgstr "" #: C/keyboard.page:147(p) msgid "" "Double-click the shorcut's row under Browser Keyboard Shortcuts." msgstr "" #: C/keyboard.page:153(p) msgid "" "Using the window that appears, press modifier keys and a letter or number " "key to set a shortcut. An example is pressing and holding Ctrl " "and then pressing and releasing T to bind CtrlT." msgstr "" #: C/keyboard.page:164(title) msgid "Global Keyboard Shortcuts" msgstr "Scurtături globale de tastatură" #: C/keyboard.page:165(p) msgid "" "Kupfer always listens to global shortcuts, even if it is not " "currently in the foreground." msgstr "" #: C/keyboard.page:169(p) msgid "They have the following meanings and default shortcuts:" msgstr "" #: C/keyboard.page:174(key) msgid "Space" msgstr "" #: C/keyboard.page:175(p) #, fuzzy #| msgid "Introduction to Kupfer." msgid "Show/hide Kupfer" msgstr "Introducere în Kupfer." #: C/keyboard.page:178(p) msgid "(not configured by default)" msgstr "" #: C/keyboard.page:179(p) msgid "Show Kupfer with 'Selection' object focused" msgstr "" #: C/keyboard.page:183(title) #, fuzzy #| msgid "Global Keyboard Shortcuts" msgid "How to configure a global keyboard shortcut" msgstr "Scurtături globale de tastatură" #: C/keyboard.page:191(p) msgid "" "Double-click the shorcut's row under Global Keyboard Shortcuts." msgstr "" #: C/keyboard.page:197(p) msgid "" "Using the window that appears, press modifier keys and a letter or number " "key to set a global shortcut. An example is pressing and holding Super and then pressing and releasing Space to bind " "SuperSpace." msgstr "" #: C/keyboard.page:206(p) msgid "" "Since these keyboard shortcuts are global, they can be used from any " "application. Select shortcuts with care so that they do not conflict with " "other functions." msgstr "" #: C/keyboard.page:214(p) msgid "" "The plugin Triggers allows to activate actions with global keyboard " "shortcuts. Trigger shortcuts do not appear in Kupfer Preferences." msgstr "" #: C/keyboard.page:220(p) msgid "See for more information." msgstr "" #: C/introduction.page:7(desc) msgid "Introduction to Kupfer." msgstr "Introducere în Kupfer." #: C/introduction.page:10(title) msgid "Introduction" msgstr "Introducere" #: C/introduction.page:12(p) #, fuzzy #| msgid "" #| "Kupfer is to the largest part a keyboard-managed interface to " #| "applications and documents." msgid "" "Kupfer is an interface for quick and convenient access to " "applications and their documents." msgstr "" "Kupfer este în mare parte o interfață controlată prin tastatură " "către aplicații și documente." #: C/introduction.page:16(p) msgid "" "The most typical use is to find a specific application and launch it. We " "have tried to make Kupfer easy to extend with plugins so that " "this quick-access paradigm can be extended to many more objects than just " "applications." msgstr "" #: C/introduction.page:22(p) msgid "" "We hope that using Kupfer feels both very fun and " "different." msgstr "" #: C/introduction.page:26(p) #, fuzzy #| msgid "" #| "For more information about Kupfer, visit its homepage." msgid "" "For up-to-date information about Kupfer, visit its homepage." msgstr "" "Pentru mai multe informații despre Kupfer, vizitați pagina web al acestuia." #: C/index.page:9(name) msgid "Ulrik Sverdrup" msgstr "Ulrik Sverdrup" #: C/index.page:10(email) msgid "ulrik.sverdrup@gmail.com" msgstr "ulrik.sverdrup@gmail.com" #: C/index.page:13(year) msgid "2009" msgstr "2009" #: C/index.page:14(name) msgid "Kupfer Development Team" msgstr "Echipa de dezvoltare Kupfer" #: C/index.page:17(license) msgid "Creative Commons Share Alike 3.0" msgstr "Creative Commons Distribuire în condiții identice 3.0" #: C/index.page:21(title) #, fuzzy #| msgid "Kupfer manual" msgid "Kupfer Manual" msgstr "Manual Kupfer" #: C/index.page:24(title) msgid "Using Kupfer" msgstr "Folosirea Kupfer" #: C/index.page:27(title) msgid "About Specific Plugins" msgstr "" #: C/generalusage.page:7(desc) #, fuzzy #| msgid "Introduction to Kupfer." msgid "How to start using Kupfer." msgstr "Introducere în Kupfer." #: C/generalusage.page:14(p) msgid "" "Kupfer is to the largest part a keyboard-managed interface to " "applications and documents." msgstr "" "Kupfer este în mare parte o interfață controlată prin tastatură " "către aplicații și documente." #: C/generalusage.page:18(p) msgid "" "Kupfer's default mode is the command mode: If you type a query, kupfer will " "search for a match in its catalog." msgstr "" "Modul implicit în Kupfer este modul de comandă: Dacă tastați o interogare, " "kupfer va căuta o potrivire în catalog." #: C/generalusage.page:23(p) msgid "" "The arrow keys allow you to browse query matches quite naturally, going to " "the previous or next match, and going up and down in the subcatalogs." msgstr "" "Folosind tastele direcționale puteți naviga prin rezultatele interogării în " "mod natural, trecând la rezultatul anterior sau următor și urcând sau " "coborând în subcataloage." #: C/generalusage.page:29(p) msgid "In command mode, some keystrokes have special meanings:" msgstr "În modul de comandă, câteva taste au înțelesuri speciale:" #: C/generalusage.page:71(p) #, fuzzy #| msgid " or ShiftSpace" msgid "" "By default you show Kupfer using the global keyboard shortcut " "CtrlSpace." msgstr " sau ShiftSpațiu" #: C/generalusage.page:74(p) msgid "See for more information." msgstr "" #: C/generalusage.page:78(title) msgid "Learning Habits" msgstr "" #: C/generalusage.page:79(p) msgid "" "Kupfer remembers which objects and actions are used the most. " "When beginning to use it, you have to use the arrow keys at times to make it " "precise which object you want to find. After a few uses of that object, " "Kupfer will rank it higher. Objects marked as favorites are also ranked higher." msgstr "" #: C/generalusage.page:90(title) msgid "The Catalog" msgstr "Catalogul" #: C/generalusage.page:91(p) msgid "" "The Catalog is the collection of objects you can access in Kupfer, such as " "documents and programs." msgstr "" "Catalogul este colecția de obiecte pe care o puteți accesa în Kupfer, " "obiecte precum documente și programe." #: C/generalusage.page:96(p) #, fuzzy #| msgid "" #| "Objects in the catalog that have content, like folders, are marked with " #| "an arrow. Pressing right-arrow will enter these objects. Much " #| "of the catalog is composed of subcatalogs; plugin subcatalogs do in " #| "general list objects that are also available directly from the top level. " #| "Subcatalogs can be used for a narrower view or search scope, when using " #| "Kupfer." msgid "" "Objects in the catalog that have content, like folders, are marked with an " "arrow. Pressing will enter these objects. Much of the catalog " "is composed of subcatalogs; plugin subcatalogs do in general list objects " "that are also available directly from the top level. Subcatalogs can be used " "for a narrower view or search scope, when using Kupfer." msgstr "" "Obiectele din catalog ce au conținut, precum dosarele, sunt marcate cu o " "săgeată. Tastarea săgeată-dreapta va intra în aceste obiecte. O " "parte mare din catalog este compus de subcataloage. Acestea în general " "conțin o listă restrânsă de obiecte ce sunt accesibile direct din nivelul " "cel mai înalt. Subcataloagele sunt folosite pentru a restrânge o căutare în " "Kupfer." #: C/generalusage.page:105(p) #, fuzzy #| msgid "" #| "Most subcatalogs update their content automatically. For example, the " #| "Desktop folder catalog is always uptodate." msgid "" "Most subcatalogs update their content automatically. For example, the " "Desktop folder source is always up-to-date." msgstr "" "Majoritatea subcataloagelor își actualizează conținutul automat. De exemplu, " "dosarul de Desktop este întotdeauna actualizat." #. Put one translator per line, in the form of NAME , YEAR1, YEAR2 #: C/index.page:0(None) msgid "translator-credits" msgstr "Cătălin Bălan 2011" #~ msgid "Using Kupfer more conveniently." #~ msgstr "Folosirea mai convenientă a Kupfer." #~ msgid "" #~ "Kupfer listens to global shortcuts, even if Kupfer is not currently in " #~ "the foreground. The most important global shortcut is the shortcut to " #~ "show and hide Kupfer's command window which by default is " #~ "CtrlSpace." #~ msgstr "" #~ "Kupfer ascultă scurtăturile globale, chiar dacă acesta nu este în prim " #~ "plan. Cea mai importantă scurtătură globală este cea folosită pentru a " #~ "arăta și a ascunde fereastra de comandă Kupfer. Scurtătura implicită este " #~ "CtrlSpațiu." #~ msgid "Global Keyboard Shortcuts are configured in Kupfer's preferences." #~ msgstr "" #~ "Scurtăturile globale de tastatură sunt configurate în preferințele din " #~ "Kupfer." #~ msgid "" #~ "The Triggers plugin allows to configure actions to be activated by global " #~ "shortcuts, but triggers can only be configured in that plugin." #~ msgstr "" #~ "Modulul de declanșatoare permite configurarea acțiunilor ce sunt activate " #~ "prin scurtături globale, dar declanșatoarele pot fi configurate doar în " #~ "acest modul." #~ msgid "" #~ "Additional keyboard shortcuts that work with Kupfer when it is in the " #~ "foreground can be configured in Kupfer's preferences." #~ msgstr "" #~ "Scurtăturile adiționale de tastatură ce funcționează cu Kupfer când " #~ "acesta este în prim plan pot fi configurate din preferințele din Kupfer." #~ msgid "" #~ "Install custom plugins in the folder ~/.local/share/kupfer/plugins/" #~ "" #~ msgstr "" #~ "Instalați module personalizate în dosarul ~/.local/share/kupfer/" #~ "plugins/" #~ msgid "" #~ "Kupfer cache, config and data are located in the directories ~/." #~ "cache/kupfer, ~/.config/kupfer and ~/.local/" #~ "share/kupfer." #~ msgstr "" #~ "Cacheul, fișierele de configurare și datele folosite de Kupfer se găsesc " #~ "în dosarele ~/.cache/kupfer, ~/.config/kupfer " #~ "și ~/.local/share/kupfer." #, fuzzy #~ msgid "" #~ "You can install custom plugins into ~/.local/share/kupfer/plugins; adding " #~ "to Kupfer's object knowledge can be surprisingly easy, just " #~ "look at the default plugins if you want to create new." #~ msgstr "" #~ "Puteți instala module personalizate în ~/.local/share/kupfer/plugins; " #~ "Adăugarea la obiectele cunoscute de Kupfer poate fi " #~ "surprinzător de ușoară, uitați-vă la modulele implicite dacă doriți să " #~ "creați altele noi." #~ msgid "Open Terminal Here" #~ msgstr "Deschide un terminal aici" #~ msgid "" #~ "Open terminal first calls xdg-terminal, then gnome-" #~ "terminal. xdg-terminal is a script to find the user's configured " #~ "terminal program for his/her Desktop Environment. Install xdg-" #~ "terminal if you need this (or install a symlink called xdg-" #~ "terminal)." #~ msgstr "" #~ "Deschide un terminal, apelează întâi xdg-terminal, apoi " #~ "gnome-terminal. xdg-terminal este un script folosit pentru a " #~ "găsi programul pentru terminal stabilit în preferințele de sistem ale " #~ "utilizatorului. Instalați xdg-terminal dacă doriți acest " #~ "comportament sau creați o legătură simbolică numită xdg-terminal." #~ msgid "" #~ "To use Kupfer like a pro, you can configure a \"Magic " #~ "Keybinding\" for Kupfer. GUI configuration is not yet " #~ "supported, but edit the configuration file ~/.config/kupfer/kupfer." #~ "cfg to include the following:" #~ msgstr "" #~ "Pentru a folosi Kupfer ca un profesionist, puteți configura o " #~ "„Combinație de taste magică” pentru Kupfer. Configurarea " #~ "acesteia din interfața vizuală nu este încă posibilă, dar puteți modifica " #~ "fișierul de configurare ~/.config/kupfer/kupfer.cfg pentru a " #~ "include următoarele:" #~ msgid "" #~ "\n" #~ "[Kupfer]\n" #~ "keybinding = <Control>space\n" #~ "magickeybinding = <Ctrl><Alt>space\n" #~ " " #~ msgstr "" #~ "\n" #~ "[Kupfer]\n" #~ "keybinding = <Control>space\n" #~ "magickeybinding = <Ctrl><Alt>space\n" #~ " " #~ msgid "" #~ "Now, pressing CtrlAltSpace will summon Kupfer with the current selection in " #~ "focus. Make sure you have installed Kupfer's nautilus plugin, " #~ "then both the currently selected file in Nautilus, or the currently " #~ "selected text in the front application will be selected." #~ msgstr "" #~ "Acum, apăsarea secvenței CtrlAltSpațiu va chema Kupfer cu selecția " #~ "curentă în prim plan. Asigurați-vă că aveți instalat modului nautilus în " #~ "Kupfer, apoi fișierul selectat în nautilus sau secvența de " #~ "text selectată în aplicația deschisă în prim plan vor fi selectate în " #~ "Kupfer." #~ msgid "" #~ "Now you can select a word in, say, a web browser, use CtrlAltSpace, and select action Look " #~ "Up to look up the selected word. Or select an image file, use " #~ "CtrlAltSpace, select " #~ "action Scale with object 1000 to scale the image to " #~ "1000 pixels wide!" #~ msgstr "" #~ "Acum puteți selecta un cuvânt, de exemplu, într-un navigator de Internet, " #~ "folosiți secvența CtrlAltSpațiu, și selectați acțiunea Caută în dicționar pentru a " #~ "căuta cuvântul selectat în dicționar. Sau selectați un fișier imagine, " #~ "folosiți secvența CtrlAltSpațiu, apoi alegeți acțiunea Scalare cu 1000 ca " #~ "obiect pentru a redimensiona imaginea la 1000 pixeli lățime!" #~ msgid "" #~ "An example useful script is here which changes the rating of Rhythmbox's currently playing song; I have added five scriptlets calling " #~ "rhrating.py with numbers from 0 to 5 to my catalog to " #~ "quickly rate tracks. (This is something that might be integrated into " #~ "Kupfer later)" #~ msgstr "" #~ "Un exemplu de script folositor poate fi găsit aici. Acesta schimbă nota piesei " #~ "curente din Rhythmbox; Puteți, de exemplu, adăuga șase " #~ "scripturi ce apelează rhrating.py cu numerele de la 0 la 5 " #~ "în catalog pentru a da note rapid pieselor. (Este posibil ca această " #~ "funcție să fie implementată într-o versiune viitoare a Kupfer)" #~ msgid "" #~ "Kupfer is its own remote control. When Kupfer is " #~ "already running, Kupfer on the command-line will focus its " #~ "window, but there is more you can do: If you invoke kupferQUERY where QUERY is a text string or a " #~ "filename, Kupfer will focus, and select this item. This way, " #~ "you can quickly invoke Kupfer actions even on objects from a " #~ "shell-based context." #~ msgstr "" #~ "Kupfer este propria sa telecomandă. Când Kupfer " #~ "este pornit, Kupfer în linia de comandă va aduce programul în " #~ "prim plan, dar poate face mai mult: Dacă invocați kupferINTEROGARE unde INTEROGARE este un text " #~ "sau un fișier, Kupfer se va focaliza în prim plan și va alege " #~ "acel element. Astfel, puteți invoca acțiuni specifice lui Kupfer pe obiecte dintr-un mediu bazat pe shell." #~ msgid "" #~ "You can also pipe the output of a command into Kupfer to send " #~ "text to the already running instance of Kupfer." #~ msgstr "" #~ "Puteți de asemenea să transmiteți datele de ieșire ale unei comenzi în " #~ "Kupfer pentru a trimite text unei instanțe Kupfer " #~ "ce rulează deja." #~ msgid "Legal Information." #~ msgstr "Informații legale." #~ msgid "" #~ "Kupfer is a program to change, speed up and make everything " #~ "about files and programs more fun on your computer. Kupfer is " #~ "a launcher; you typically use it to summon an application or a document " #~ "quickly by typing parts of its name. It can also do more than getting at " #~ "something quickly: there are different plugins for accessing more objects " #~ "and running custom commands." #~ msgstr "" #~ "Kupfer este un program folosit pentru a schimba, accelera și " #~ "transforma toate acțiunile legate de fișiere și programe în ceva " #~ "distractiv. Kupfer este un lansator; îl veți folosi în mod " #~ "normal pentru a chema o aplicație sau un document repede tastând părți " #~ "diferite din numele său. Poate de asemenea mult mai multe decât a găsi " #~ "ceva repede: există numeroase module concepute pentru accesarea mai " #~ "multor obiecte și rularea a unor comenzi personalizate." #~ msgid "" #~ "Kupfer is written using Python and has a flexible " #~ "architecture; the implementation is simple and makes the easy things work " #~ "first. One goal is that new plugins can be written quickly without too " #~ "much programming." #~ msgstr "" #~ "Kupfer este scris în Python și are o arhitectură flexibilă; " #~ "implementarea este simplă și face ca lucrurile ușoare să funcționeze " #~ "primele. Un scop al programului este ca noile module să fie scrie repede " #~ "și fără multă programare." #~ msgid "" #~ "The program is very inspired by Quicksilver." #~ msgstr "" #~ "Programul este inspirat puternic de către Quicksilver." kupfer-328/help/sl/000077500000000000000000000000001500175051100142255ustar00rootroot00000000000000kupfer-328/help/sl/sl.po000066400000000000000000002210231500175051100152030ustar00rootroot00000000000000# Slovenian translation for kupfer help. # Copyright (C) 2010 kupfer's COPYRIGHT HOLDER # This file is distributed under the same license as the kupfer package. # # Andrej Žnidaršič , 2010 - 2011. # msgid "" msgstr "" "Project-Id-Version: kupfer help master\n" "POT-Creation-Date: 2011-05-16 19:30+0000\n" "PO-Revision-Date: 2011-06-02 17:12+0100\n" "Last-Translator: Andrej Žnidaršič \n" "Language-Team: Slovenian GNOME Translation Team \n" "Language: \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%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0);\n" "X-Poedit-Country: SLOVENIA\n" "X-Poedit-Language: Slovenian\n" "X-Poedit-SourceCharset: utf-8\n" #: C/plugin-websearch.page:7(desc) msgid "Using the search the web plugin." msgstr "Uporaba vstavka spletnega brskanja." #: C/plugin-websearch.page:10(app) msgid "Search the Web" msgstr "Iskanje po spletu" #: C/plugin-websearch.page:13(title) #: C/plugin-triggers.page:23(title) #: C/plugin-notes.page:22(title) #: C/plugin-nautilusselection.page:13(title) #: C/plugin-gwibber.page:25(title) #: C/plugin-favorites.page:22(title) #: C/plugin-calculator.page:21(title) #: C/plugin-applications.page:19(title) #: C/generalusage.page:10(title) msgid "Basic Usage" msgstr "Osnovna uporaba" #: C/plugin-websearch.page:15(p) msgid "Activate Kupfer and make sure it is in free-text mode (press period)" msgstr "Omogočite Kupfer in se prepričajte, da ste v načinu prostega besedila (pritisnite piko)." #: C/plugin-websearch.page:17(p) msgid "Type in a search query and tap Tab to switch to the action pane." msgstr "Vnesite iskalno poizvedbo in pritisnite Tabulator za preklop na pladenj dejanj." #: C/plugin-websearch.page:19(p) msgid "Type \"Search With\" to find Search the Web's action and tap Tab again to switch to the third pane (indirect object)." msgstr "Vpišite \"Išči z\" za dejanje Išči po spletu in ponovno pritisnite Tabulator za preklop na tretji pladenj (posredni predmet)." #: C/plugin-websearch.page:22(p) msgid "Select search engine with the arrow keys and type Return to open the search in a web browser." msgstr "Izberite iskalnik s smernimi tipkami in pritisnite Enter za odprtje iskanja v spletnem brskalniku." #: C/plugin-websearch.page:29(title) msgid "Search Engines" msgstr "Iskalniki" #: C/plugin-websearch.page:30(p) msgid "The Search the Web plugin uses Firefox' search engines, so you can add Search Engines directly in Firefox and Kupfer will find them later." msgstr "Vstavek Išči po spletu uporablja iskalnike Firefox zato lahko iskalnike dodate neposredno v Firefox, saj jih bo Kupfer našel." #: C/plugin-websearch.page:35(p) msgid "You can also install custom search plugins directly, only for Kupfer, in the folder:" msgstr "Vstavke po meri lahko namestite neposredno samo za Kupfer v mapo:" #: C/plugin-websearch.page:39(code) #, no-wrap msgid "~/.local/share/kupfer/searchplugins/" msgstr "~/.local/share/kupfer/searchplugins/" #: C/plugin-websearch.page:40(p) msgid "The search engine descriptions must written in OpenSearch format." msgstr "Opisi iskalnika morajo biti napisani v obliki OpenSearch." #: C/plugin-triggers.page:7(desc) msgid "Using the triggers plugin." msgstr "Uporaba vstavka sprožilcev." #: C/plugin-triggers.page:10(app) #: C/keyboard.page:213(title) msgid "Triggers" msgstr "Sprožilci" #: C/plugin-triggers.page:13(title) msgid "Triggers Plugin" msgstr "Vstavek sprožilcev" #: C/plugin-triggers.page:14(p) msgid "With Triggers you can take a command you would normally perform in Kupfer, such as launching an application or opening a document, and bind a global key combination to run this command. As long as Kupfer is running, any application can have the current focus." msgstr "S Sprožilci lahko vzamete ukaz, ki bi ga ponavadi izvedli v Kupferju kot je zagon programa ali odpiranje dokumenta in na ta ukaz vežete splošno tipkovno bližnjico. Dokler se Kupfer izvaja je lahko v žarišču katerikoli program." #: C/plugin-triggers.page:25(title) msgid "Creating a new trigger" msgstr "Ustvarjanje novega sprožilca" #: C/plugin-triggers.page:27(p) msgid "Set up a command in Kupfer that you want to run" msgstr "Nastavitev ukaza, ki ga želite pognati v Kupferju" #: C/plugin-triggers.page:32(p) msgid "Press CtrlReturn to create a composed command." msgstr "Pritisnite CtrlEnter za ustvarjanje sestavljenega ukaza." #: C/plugin-triggers.page:38(p) msgid "Type Tab and select the action Add Trigger... and press Return" msgstr "Pritisnite Tabulator in izberite dejanje Dodaj sprožilec ... in pritisnite Enter." #: C/plugin-triggers.page:44(p) msgid "Using the window that appears, press modifier keys and a letter or number key to set a global shortcut. An example is pressing and holding CtrlAlt and then pressing and releasing R to bind CtrlAltR." msgstr "V oknu, ki se pojavi, za nastavitev tipkovne bližnjice pritisnite spremenilne tipke in črko ali številko. Primer je pritisk in držanje CtrlAlt in nato pritisk in spust R za vezavo CtrlAltR." #: C/plugin-triggers.page:54(title) msgid "Removing a trigger" msgstr "Odstranjevanje sprožilca" #: C/plugin-triggers.page:56(p) msgid "Find the source Triggers in Kupfer and press to see its contents." msgstr "Najdite vir Sprožilci v Kupfer in pritisnite za ogled njegove vsebine." #: C/plugin-triggers.page:62(p) msgid "Find the active trigger in the list and use the action Remove Trigger." msgstr "Na seznamu najdite dejavni sprožilec in uporabite dejanje Odstrani sprožilec. " #: C/plugin-triggers.page:68(p) msgid "Since trigger keyboard shortcuts are global, they can be used from any application. Select shortcuts with care so that they do not conflict with other functions." msgstr "Ker so tipkovne bližnjice sprožilca splošne, jih lahko uporabite iz kateregakoli programa. Bližnjice izberite previdno, da ne bodo v sporu z drugimi zmožnostmi." #: C/plugin-triggers.page:74(title) #: C/plugin-notes.page:60(title) #: C/plugin-gwibber.page:68(title) #: C/plugin-favorites.page:38(title) msgid "Power User Tips" msgstr "Namigi za napredne uporabnike" #: C/plugin-triggers.page:75(p) msgid "Proxy objects such as Selected Text, Selected File, Frontmost Window, Last Command et cetera allow very powerful triggers." msgstr "Posredniški predmeti kot so Izbrano besedilo, Izbrana datoteka, Sprednje okno, Zadnji ukaz in tako naprej omogočajo zelo zmogljive sprožilce." #: C/plugin-triggers.page:79(p) msgid "The application action Launch is special; if you bind a trigger using Launch, it will start the application if it is not running, but focus the application when it is already running. By contrast, Start Again will start the application if it is running or not." msgstr "Dejanje programa Zaženi je posebno. V primeru da vežete in sprožite z Zaženi, bo zagnal program, če se ne izvaja, v nasprotnem primeru pa bo preklopil na izvajajoči se program. Ukaz Zaženi znova bo zagnal program ne glede na to ali se izvaja ali ne." #: C/plugin-triggers.page:87(title) msgid "Example Triggers" msgstr "Primeri sprožilcev" #: C/plugin-triggers.page:90(em) msgid "Text Editor → Launch" msgstr "Urejevalnik besedil → zaženi" #: C/plugin-triggers.page:91(p) msgid "Start Text Editor or focus its window if it is already running." msgstr "Zaženite Urejevalnik besedila ali se osredotočite na njegovo okno, če se že izvaja." #: C/plugin-triggers.page:97(em) msgid "Selected Text → Search With → Google" msgstr "Izbrano besedilo → išči z → Google" #: C/plugin-triggers.page:98(p) msgid "Search the web using the currently selected text." msgstr "Iskanje po spletu z uporabo trenutno izbranega besedila." #: C/plugin-triggers.page:100(em) msgid "Selected File → Move To → (Downloads Folder)" msgstr "Izbrana datoteka → Premakni v → (Mapa prejemov)" #: C/plugin-triggers.page:101(p) msgid "Move the currently selected file to a specific folder" msgstr "Premakne trenutno izbrano datoteko v določeno mapo" #: C/plugin-triggers.page:105(em) msgid "Songs → Search Contents" msgstr "Skladbe → vsebine iskanja" #: C/plugin-triggers.page:106(p) msgid "You may even add a trigger to open a specific subcatalog in Kupfer, for example Rhythmbox's songs." msgstr "Dodate lahko celo sprožilec za odprtje določenega podkataloga v Kupferju na primer skladbe Rhythmbox." #: C/plugin-notes.page:7(desc) msgid "Using the notes plugin." msgstr "Uporaba vstavka sporočilc." #: C/plugin-notes.page:10(app) #: C/plugin-calculator.page:37(title) msgid "Notes" msgstr "Sporočilca" #: C/plugin-notes.page:13(title) msgid "Notes Plugin" msgstr "Vstavek sporočilc" #: C/plugin-notes.page:14(p) msgid "With Notes you can access or create new notes in either the program Gnote or Tomboy. Notes will work identically with either application—you can configure which one to use in the plugin's information pane in Kupfer Preferences." msgstr "S Sporočilci lahko dostopate do ali ustvarite nova sporočilca v programu Gnote ali Tomboy. Sporočilca bodo z obema programoma delovala enako -- katerega želite uporabiti lahko nastavite v Možnostih Kupfer." #: C/plugin-notes.page:24(title) msgid "Creating a new note" msgstr "Ustvarjanje novega sporočilca" #: C/plugin-notes.page:26(p) msgid "Activate Kupfer and type . to enter text mode, then type in a note title" msgstr "Omogočite Kupfer in vpišite . za vstop v besedilni način in nato vnesite naziv sporočilca" #: C/plugin-notes.page:32(p) msgid "Type Tab and select the action Create Note and press Return." msgstr "Vnesite Tabulator in izberite dejanje Ustvari sporočilce in pritisnite Enter." #: C/plugin-notes.page:39(title) msgid "Finding a note by title" msgstr "Iskanje sporočilca po naslovu" #: C/plugin-notes.page:41(p) msgid "Simply search for the note title in Kupfer" msgstr "Enostavno iskanje naziva sporočilca v Kupferju" #: C/plugin-notes.page:45(title) msgid "Finding a note by content" msgstr "Iskanje sporočilca po vsebini" #: C/plugin-notes.page:47(p) msgid "Activate Kupfer and type . to enter text mode, then type in a search query" msgstr "Omogočite Kupfer in vnesite . za vstop v besedilni način in nato vnesite iskalno poizvedbo" #: C/plugin-notes.page:53(p) msgid "Type Tab and select the action Get Note Search Results... and press Return." msgstr "Pritisnite Tabulator in izberite dejanje Dobi rezultate iskanja sporočilca ... in pritisnite Enter." #: C/plugin-notes.page:63(p) msgid "You can use the Selected Text object and create a new note with the content of the selection." msgstr "Uporabite lahko predmet Izbrano besedilo in ustvarite novo sporočilce z vsebino izbire." #: C/plugin-nautilusselection.page:7(desc) msgid "Using the selected file plugin." msgstr "Uporaba izbranega vstavka datoteke." #: C/plugin-nautilusselection.page:10(app) msgid "Selected File" msgstr "Izbrana datoteka" #: C/plugin-nautilusselection.page:14(p) msgid "Select a file in the file manager. Open Kupfer and search for the object Selected File, which represents the file or files that are selected." msgstr "Izberite datoteko v upravljalniku datotek. Odprite Kupfer in najdite predmet Izbrana datoteka, ki predstavlja izbrano datoteko ali datoteke." #: C/plugin-nautilusselection.page:19(p) msgid "Instead of searching, you can press CtrlG to directly focus the selected file. See for more information." msgstr "Namesto iskanje lahko pritisnete CtrlG za neposredno osredotočenje na izbrano datoteko. Za več podrobnosti si oglejte ." #: C/plugin-nautilusselection.page:26(title) msgid "Selected File requires Nautilus" msgstr "Izbrana datoteka zahteva Nautilus" #: C/plugin-nautilusselection.page:27(p) msgid "The selected file plugin works with the Nautilus file browser and requires that the extension kupfer_provider.py is installed (it is normally installed together with Kupfer). After installing it for the first time, Nautilus must start anew before it is active." msgstr "Vstavek izbrane datoteke deluje z brskalnikom datotek Nautilus in zahteva nameščeno razširitev kupfer_provider.py (običajno je nameščena skupaj s programom Kupfer). Po prvi namestitvi vstavka morate Nautilus znova zagnati, preden vstavek postane dejaven." #: C/plugin-gwibber.page:7(desc) msgid "Using the Gwibber plugin." msgstr "Uporaba vstavka Gwibber" #: C/plugin-gwibber.page:10(app) msgid "Gwibber" msgstr "Gwibber" #: C/plugin-gwibber.page:13(title) msgid "Gwibber Plugin" msgstr "Vstavek Gwibber" #: C/plugin-gwibber.page:14(p) msgid "With the Gwibber plugin you can send messages to social networks such as Twitter or Identi.ca." msgstr "Z vstavkom Gwibber lahko pošljete sporočila na družabna omrežja kot sta Twitter in Identi.ca." #: C/plugin-gwibber.page:18(p) msgid "The plugin requires that the application Gwibber is installed and configured for your user. Kupfer will start and use Gwibber's service in the background." msgstr "Vstavek zahteva, da je Gwibber nameščen in nastavljen za vašega uporabnika. Kupfer bo zagnal in uporabil Gwibberjevo storitev v ozadju." #: C/plugin-gwibber.page:27(title) msgid "Sending a message to all services" msgstr "Pošiljanje sporočila vsem storitvam" #: C/plugin-gwibber.page:29(p) msgid "Activate Kupfer and type . to enter text mode, then type in a message." msgstr "Omogočite Kupfer in vpišite . za vstop v besedilni način in nato vpišite sporočilo." #: C/plugin-gwibber.page:35(p) msgid "Type Tab and select the action Send Message and press Return." msgstr "Pritisnite Tabulator in izberite dejanje Pošlji sporočilo in pritisnite Enter." #: C/plugin-gwibber.page:42(title) msgid "Sending a message to a specific service" msgstr "Pošiljanje sporočila na določeno storitev" #: C/plugin-gwibber.page:44(p) msgid "Activate Kupfer and search for the service object, for example Identi.ca" msgstr "Omogočite Kupfer in iščite za predmet storitve, na primer Identi.ca" #: C/plugin-gwibber.page:50(p) msgid "Type Tab and select the action Send Message." msgstr "Pritisnite Tabulator in izberite dejanje Pošlji sporočilo." #: C/plugin-gwibber.page:55(p) msgid "Type Tab to select the last pane, and type in a message. Press Return to send." msgstr "Pritisnite Tabulator za izbiro zadnjega pladnja in vpišite sporočilo. Za pošiljanje pritisnite Enter." #: C/plugin-gwibber.page:61(p) msgid "The plugin also provides a source for incoming messages, Gwibber Messages and more actions on messages such as Reply, Send Private Message etc." msgstr "Vstavek vsebuje tudi vir za dohodna sporočila, Sporočila Gwibber in več dejanj za sporočila kot so Odgovori, Pošlji zasebno sporočilo itd." #: C/plugin-gwibber.page:71(p) msgid "You can use the comma trick if you want to send a message to more than one service, but not all, at the same time." msgstr "Če želite poslati sporočilo na več kot eno storitev, vendar ne na vse hkrati, uporabite trik z vejico." #: C/plugin-favorites.page:7(desc) msgid "Using the favorites plugin." msgstr "Uporaba vstavka priljubljenih." #: C/plugin-favorites.page:10(app) msgid "Favorites" msgstr "Priljubljene" #: C/plugin-favorites.page:13(title) msgid "Favorites Plugin" msgstr "Vstavek priljubljenih" #: C/plugin-favorites.page:14(p) msgid "With Favorites you mark objects, for example files, for quicker access. It is a sort of shelf on which you can store objects in Kupfer. Objects marked as favorites will also be ranked higher and are adorned with a star symbol." msgstr "S Priljubljenimi lahko označite predmete kot so na primer datoteke za hiter dostop. To je neke vrste polica na kateri lahko v Kupferju shranjujete dokumente. Predmeti označeni kot priljubljeni bodo ocenjeni višje in imeli poleg simbol zvezdice." #: C/plugin-favorites.page:25(p) msgid "Find an object in Kupfer" msgstr "Najdite predmet v programu Kupfer." #: C/plugin-favorites.page:30(p) msgid "Type Tab and select either the action Add to Favorites or Remove from Favorites." msgstr "Pritisnite Tabulator in izberite dejanje Dodaj med priljubljene ali Odstrani iz priljubljenih." #: C/plugin-favorites.page:39(p) msgid "If you favorite an object, you can access it in more places. Not only in the \"Favorites\" subcatalog, but also as the indirect (secondary) object for some actions. For example:" msgstr "V primeru da je predmet priljubljen, lahko do njega dostopate na več mestih. Pojavil se bo ne le v podkatalogu \"Priljubljene\" ampak tudi v posrednem (drugem) predmetu za nekatera dejanja. Na primer:" #: C/plugin-favorites.page:45(p) msgid "Command-lines from favorites are quick to access." msgstr "Do ukaznih vrstic iz priljubljenih lahko hitro dostopate." #: C/plugin-favorites.page:46(p) msgid "When scaling images with the Scale... action from the Image Tools plugin. This action needs a size description as the third object, like \"1024\" or \"1200x800\". If you often scale to the same size, say \"1200x800\", add this to favorites, and it will always appear as a suggestion for the action." msgstr "Velikost lahko spremenite z dejanjem Spremeni velikost... iz vstavka Slikovna orodja. To dejanje kot tretji predmet potrebuje opis velikosti kot je \"1024\" ali \"1200x800\". V primeru da velikost pogosto spremenite na isto vrednost kot je \"1200x800\", jo dodajte med priljubljene. Potem se bo vedno pojavila kot predlog za dejanje." #: C/plugin-favorites.page:54(p) msgid "Actions needing an email address as the indirect object will pick up email addresses from favorites as well as well." msgstr "Dejanja, ki kot neposredni predmet potrebujejo naslove e-pošte, jih bodo pobrale tudi iz priljubljenih. " #: C/plugin-calculator.page:7(desc) msgid "Using the calculator plugin." msgstr "Uporaba vstavka računala." #: C/plugin-calculator.page:10(app) msgid "Calculator" msgstr "Računalo" #: C/plugin-calculator.page:13(title) msgid "Calculator Plugin" msgstr "Vstavek računala" #: C/plugin-calculator.page:14(p) msgid "The calculator plugin lets you calculate expressions quickly. It can evaluate expressions entered as text starting with \"=\". Entering = from command mode will start text mode directly with = prefixed for quick access." msgstr "Vstavek računalo vam omogoča hiter izračun izrazov. Oceni lahko izraze, vnesene kot besedilo, ki se začne z \"=\". Vnos = v načinu ukaza bo začel besedilni način neposredno s predpono = za hiter dostop." #: C/plugin-calculator.page:23(p) msgid "Activate Kupfer and type =" msgstr "Omogočite Kupfer in pritisnite =" #: C/plugin-calculator.page:26(p) msgid "Type in a mathematical expression using +,-,/,* (and ** for exponentiation)" msgstr "Vnesite matematični izraz z uporabo +,-,/,* (in ** za potenco)" #: C/plugin-calculator.page:30(p) msgid "Press Return to get the result." msgstr "Za rezultat pritisnite Enter." #: C/plugin-calculator.page:38(p) msgid "The Calculator uses python's math and complex math modules, and parses expressions as Python expressions. You may use common mathematical functions, such as sqrt, sin, exp and log; the command =help will show a list of all defined functions and constants." msgstr "Računalo uporablja pythonove module matematike in kompleksne matematike in izraze razčleni kot izraze Python. Uporabite lahko pogoste matematične funkcije kot so sqrt, sin, exp in log. Ukaz =help vam bo prikazal seznam vseh definiranih funkcij in konstant." #: C/plugin-calculator.page:47(p) msgid "Notice that the power operator in Python is double stars, for example =3**3 will evaluate to 27." msgstr "Operator potenc v Pythonu so dvojne zvezdice. Vrednost izraza =3**3 je na primer 27." #: C/plugin-calculator.page:53(p) msgid "To calculate trig functions for angles, convert to radians first:" msgstr "Za izračun trigonometrijskih funkcij kote najprej pretvorite v radiane:" #: C/plugin-calculator.page:56(code) #, no-wrap msgid "sin(radians(30)) -> 0.5" msgstr "sin(radians(30)) -> 0.5" #: C/plugin-calculator.page:59(p) msgid "The last result is stored as the name _ (an underscore, just like in the Python console)." msgstr "Zadnji rezultat je shranjen kot ime _ (podčrtaj, takšen kot v konzoli Python)." #: C/plugin-applications.page:7(desc) msgid "Using the applications plugin." msgstr "Uporaba vstavka programov." #: C/plugin-applications.page:10(app) msgid "Applications" msgstr "Programi" #: C/plugin-applications.page:13(title) msgid "Applications Plugin" msgstr "Vstavek programov" #: C/plugin-applications.page:14(p) msgid "Applications provides all installed programs." msgstr "Applications zagotavlja vse nameščene programe." #: C/plugin-applications.page:21(title) msgid "Launching an application" msgstr "Zaganjanje programa" #: C/plugin-applications.page:23(p) msgid "Activate Kupfer and type an abbreviation of the application name" msgstr "Omogočite Kupfer in vtipkajte okrajšavo imena programa" #: C/plugin-applications.page:28(p) msgid "Press Return to launch the application." msgstr "Za zagon programa pritisnite Enter." #: C/plugin-applications.page:34(title) msgid "Opening a file with a specific application" msgstr "Odpiranje datoteke z določenim programom" #: C/plugin-applications.page:36(p) msgid "Select a file in Kupfer" msgstr "Izbor datoteke v Kupferju." #: C/plugin-applications.page:41(p) msgid "Type Tab and select the action Open With..." msgstr "Pritisnite Tabulator in izberite dejanje Odpri z ..." #: C/plugin-applications.page:46(p) msgid "Type Tab to select the third (indirect object) pane and in it, select the application to open the file with." msgstr "Pritisnite Tabulator za izbiro tretjega (neposrednega predmeta) pladnja in v njem izberite program s katerim želite odpreti datoteko." #: C/plugin-applications.page:53(p) msgid "The action Open opens files and folders with the registered default application for that specific file type. This can be configured using the action Set Default Application...." msgstr "Dejanje Odpri odpre datoteke in mape z vpisanimi privzetimi programi za določeno vrsto datotek. To lahko nastavite z dejanjem Nastavi privzeti program ...." #: C/plugin-applications.page:58(p) msgid "The file type associations are provided by the desktop environment, and modifying them here will modify them on the desktop as well. This may not be true when not using GNOME or XFCE." msgstr "Povezave vrst datotek zagotavlja namizno okolje in njihova sprememba tukaj jih bo spremenila tudi na namizju. To morda ne bo res pri uporabi GNOME ali XFCE." #: C/plugin-applications.page:64(title) msgid "Selecting default application for a file type or folders" msgstr "Izbira privzetega programa za vrsto datoteke ali mape" #: C/plugin-applications.page:66(p) msgid "Select a file or folder in Kupfer" msgstr "Izbor datoteke ali mape v Kupferju." #: C/plugin-applications.page:71(p) msgid "Type Tab and select the action Set Default Application..." msgstr "Pritisnite Tabulator in izberite dejanje Nastavi privzeti program ..." #: C/plugin-applications.page:77(p) msgid "Type Tab to select the third (indirect object) pane and in it, select the application to always open the file type with." msgstr "Vpišite Tabulator za izbiro tretjega (neposredni predlet) pladnja in v njem izberite program s katerim želite vedno odpreti to vrsto datoteke." #: C/plugin-applications.page:85(title) msgid "Configuration" msgstr "Nastavitev" #: C/plugin-applications.page:86(p) msgid "The configuration option Applications for Desktop Environment in the plugin's information pane in Kupfer Preferences determines how Kupfer should act with regard to the desktop environment configuration—certain applications request not to be shown depending on which desktop environment is used. By default, it behaves like GNOME." msgstr "Nastavitvena možnost Programi in namizno okolje v pladnju podrobnosti vstavka v Možnostih Kupfer določi, kako se naj Kupfer obnaša glede na nastavitev namiznega okolja—določeni programi zahtevajo, da niso prikazani glede na uporabljeno namizno okolje. Privzeto se obnaša kot GNOME." #: C/moreusage.page:7(desc) msgid "More advanced usage information." msgstr "Podati o naprednejši uporabi." #: C/moreusage.page:10(title) msgid "Using Kupfer in Depth" msgstr "Podrobnejša uporaba Kupferja." #: C/moreusage.page:13(title) msgid "Adding Applications and Scripts" msgstr "Dodajanje programov in skriptov" #: C/moreusage.page:14(p) msgid "Kupfer will show all applications that are configured visible in your menu editor." msgstr "Kupfer bo v urejevalniku menija prikazal vse programe, ki so nastavljeni kot vidni." #: C/moreusage.page:18(p) msgid "If you want to add an application manually, you can create a new .desktop file and place it in one of the standard directories for applications, for example ~/.local/share/applications, where Kupfer will find it." msgstr "Če želite dodati program ročno, lahko ustvarite novo datoteko .desktop in jo postavite v eno od standardnih mest za programe, na primer ~/.local/share/applications, kjer jo bo Kupfer našel." #: C/moreusage.page:24(p) msgid "If you have a collection of scripts that you want to call from Kupfer, you can add the scripts folder as a catalog directory to Kupfer in the preferences. Scripts that you add to Kupfer's catalog this way can be run directly or in the terminal as long as they are executable." msgstr "Če imate zbirko skriptov, ki jih želite poklicati v Kupferju, lahko v možnostih dodate mapo skriptov kot mapo katalogov v Kupfer. Skripte, ki jih dodate v Kupferjev katalog na ta način, je mogoče zagnati neposredno v terminalu, če so izvedljivi. " #: C/moreusage.page:31(p) msgid "You can also save command-lines by using the action Add to Favorites." msgstr "Ukazne vrstice lahko shranite z uporabo dejanja Dodaj med priljubljene." #: C/moreusage.page:38(title) msgid "Opening Files and Folders" msgstr "Odpiranje datotek in map" #: C/moreusage.page:39(p) msgid "Using the action Open, files and folders are opened in their preferred application. The application associations can be changed, see ." msgstr "Uporaba dejanja Odpri odpre datoteke in mape na njihovem prednostnem mestu. Povezave programov je mogoče spremeniti, oglejte si ." #: C/moreusage.page:47(title) msgid "The Comma Trick" msgstr "Trik z vejico" #: C/moreusage.page:48(p) msgid "The comma trick allows the user to use actions on many objects at the same time." msgstr "Trik z vejico uporabniku omogoča uporabo dejanj na več predmetih hkrati." #: C/moreusage.page:52(p) msgid "Simply press comma , when an object is selected. The object is put on a \"stack\", and you can find yet another file or object, press comma to put it on the stack. When you subsequently invoke an action, the action is carried out on all of the objects at the same time." msgstr "Pritisnite na ,, ko je predmet izbran. Predmet je postavljen na \"sklad\" in lahko najdete še eno datoteko ali predmet in pritisnete brskalnik za postavitev nazaj v sklad. Ko prikličete dejanje, je izvedeno na vseh predmetih hkrati." #: C/moreusage.page:58(p) msgid "Some actions are only \"multiplied\" when used with many objects, other are smarter than that:" msgstr "Nekatera dejanja so pri uporabi z več predmeti le večkrat izvedena, druga pa so pametnejša:" #: C/moreusage.page:61(p) msgid "Selecting many files and using the Create Archive action, all files will be packed into the same archive." msgstr "Izbira veliko datotek in uporaba dejanja Ustvari arhiv bo vse datoteke zapakirala v isti arhiv." #: C/moreusage.page:63(p) msgid "If you select multiple contacts and use a Send Email action, it creates one email directed at all the contacts." msgstr "V primeru da izberete več stikov in uporabite dejanje Pošlji e-pošto, ustvari eno e-pošto, ki je usmerjena k vsem stikom." #: C/moreusage.page:65(p) msgid "If you select multiple subcatalogs (For example Firefox Bookmarks and Epiphany Bookmarks) and use Search Contents.., you get a subcatalog search restricted to the objects of those two catalogs! You can even bind a trigger to this command(!)" msgstr "V primeru da izberete več podkatalogov (na primer zaznamke Firefox ali zaznamke Epiphany) in uporabite Vsebino iskanja ..., lahko dobite podkatalog iskanja, ki je omejen na predmete teh dveh podkatalogov! Na ta ukaz lahko celo vežete sprožitec(!)." #: C/moreusage.page:71(p) msgid "The comma trick is directly taken from Quicksilver (the example given in the external article should work identically in Kupfer)." msgstr "Trik z vejico je vzet neposredno iz programa Quicksilver (primer v zunanjem članku, bi moral v Kupferju delovati enako)." #: C/moreusage.page:80(title) msgid "Grab Current Selection" msgstr "Zgrabi trenutno izbiro" #: C/moreusage.page:81(p) msgid "To use the current selected text, from any application, with Kupfer, you can configure a global keyboard shortcut for the action Show with Selection in Kupfer Preferences." msgstr "Za uporabo trenutno izbranega besedila iz katregakoli programa s programom Kupfer lahko nastavite splošno tipkovno bližnjico za dejanje Pokaži z izbiro v Možnostih Kupfer." #: C/moreusage.page:85(p) msgid "If configured, pressing the global keyboard shortcut will summon Kupfer with the current selection as the focused object." msgstr "V primeru da je nastavljena, bo splošna tipkovna bližnjica priklicala Kupfer s trenutno izbiro kot predmetom v žarišču. " #: C/moreusage.page:90(p) msgid "See " msgstr "Oglejte si " #: C/moreusage.page:94(title) msgid "Command-line Connection" msgstr "Povezava z ukazno vrstico" #: C/moreusage.page:95(p) msgid "The command kupfer on the command-line will focus Kupfer if it's already running, otherwise it will start it." msgstr "Ukaz kupfer v ukazni vrstici bo v žarišču na Kupfer, če že teče. V nasprotnem primeru ga bo zagnal." #: C/moreusage.page:99(p) msgid "The command kupfer can be used to send files or text from the command-line to Kupfer. For example, if you are using the shell in a directory where you have a file called \"report.pdf\", you can focus this file in Kupfer by running kupfer report.pdf." msgstr "Ukaz kupfer lahko uporabite za pošiljanje datotek ali besedila iz ukazne vrstice programu Kupfer. Na primer, če uporabljate lupino v mapi, kjer imate datoteko \"poročilo.pdf\", lahko v Kupferju to datoteko spravite v žarišče s poganjanjem kupfer porocilo.pdf." #: C/moreusage.page:107(p) msgid "You can also send text if you pipe the output of a command into kupfer." msgstr "Besedilo lahko izberete tudi, če izhod ukaza vpišete v kupfer." #: C/moreusage.page:114(title) msgid "Managing Context and Current Selection" msgstr "Upravljanje vsebine in trenutne izbire" #: C/moreusage.page:115(p) msgid "If you find the object you want to use, then invoke an action, Kupfer goes away to perform the action (for example start a program or play a song). When you come back to Kupfer, it will still keep the same object and action selected. Some actions make sense to be repeated (like skipping to the next song) and it can be useful to perform different actions on the same object." msgstr "V primeru, da najdete predmet, ki ga želite uporabiti, prikličite dejanje. Kupfer bo odšel stran za izvedbo dejanja (na primer zagnal program ali predvajal skladbo). Ko pridete nazaj v Kupfer, bo le-ta obdržal izbiro istega predmeta in dejanja. Nekatera dejanja je smiselno ponavljati (na primer preskok na naslednjo skladbo), uporabno pa je lahko tudi izvajanje različnih dejanj na istem predmetu." #: C/moreusage.page:123(p) msgid "However, you always have the top level catalog reachable when you \"come back\" to Kupfer -- say you went into the subcatalog \"Albums\" to browse your albums only; you select an album to play, and play it. You come back with the album selected -- but your next search will still go over the top level catalog, not just albums." msgstr "Vendar pa je katalog zgornje ravni dosegljiv vedno, ko \"pridete nazaj\" h programu Kupfer -- recimo, da greste v podkatalog \"Albumi\" za brskanje le vaših albumov, izberete album za predvajanje in ga predvajate. Prišli ste nazaj z izbranim albumom -- toda vaše naslednje iskanje bo še vedno izvedeno na katalogu gornje ravni, ne samo v albumih. " #: C/moreusage.page:130(p) msgid "How to come back into the subcatalog you were in? You do that by simply browsing, not searching the first thing you do when you focus Kupfer again. A quick way is to press down-arrow or space to open the browse window; think of it as saying \"I want to stay in this subfolder\". With the browse window open, your next query will search the current subcatalog." msgstr "Kako priti nazaj v podkatalog v katerem ste bili? To lahko storite z enostavnim brskanjem in ne iskanje, ko je Kupfer znova v žarišču. Hiter način je pritisk na puščico navzdol ali preslednico za odprtje okna brskalnika. O tem mislite kot da bi rekli \"Želim ostati v tej podmapi\". Ko se odpre okno brskanja, bo vaša naslednja poizvedba iskala po trenutnem podkatalogu." #: C/moreusage.page:137(p) msgid "This way you can work both ways -- you can quickly drill down into folders to find a file, and when you come back for the next action with Kupfer you can either summon any normal toplevel object (just start typing), or stay around where you were, deep in that folder (press space, then type a query)." msgstr "Na ta način lahko delate na oba načina - hitro lahko raziščete mape za iskanje datoteke in ko pridete nazaj za naslednje dejanje s Kupferjem lahko pokličete katerikoli predmet zgornje ravni ali pa ostanete, kjer ste bili globoko v tisti mapi (pritisnite presledek in nato vpišite poizvedbo)." #: C/moreusage.page:146(title) msgid "Saving Commands as Files" msgstr "Shranjevanje ukazov kot datoteke" #: C/moreusage.page:147(p) msgid "You can use keyboard shortcut for Compose Command (by default it is CtrlReturn) to create a command object out of the currently focused command in Kupfer. This object can be saved as a runnable file if you use the Save As... action. The resulting file will can be executed when opened from the file manager (it requires that Kupfer is already running)." msgstr "Za ustvarjanje predmeta ukaza iz ukaza, ki je trenutno v žarišču v Kupferju, lahko uporabite tipkovno bližnjico Sestavi ukaz (privzeto je CtrlEnter). Ta predmet lahko shranite kot izvedljivo datoteko, če uporabite dejanje Shrani kot .... Nastala datoteka bo izvedena bo odprtju iz upravljalnika datotek (zahteva, da se Kupfer že izvaja)." #: C/managing-plugins.page:7(desc) msgid "Using plugins with Kupfer." msgstr "Uporaba vtavkov v programu Kupfer." #: C/managing-plugins.page:10(title) msgid "How to Configure Plugins" msgstr "Kako nastaviti vstavke" #: C/managing-plugins.page:12(p) msgid "Functionality in Kupfer is organized by extentsion modules called \"plugins\". Each plugin provides additional functionality, for example integration with an external application." msgstr "Zmožnost v Kupferju je organizirana po modulih razširitev, ki se imenujejo \"vstavki\". Vsak vstavek zagotavlja dodatno zmožnost na primer vključitev v zunanji program." #: C/managing-plugins.page:19(title) msgid "Configuring Plugins" msgstr "Nastavljanje vstavkov" #: C/managing-plugins.page:21(title) msgid "Open Kupfer Preferences to the Plugins tab" msgstr "Odprite zavihek Vstavki v Možnostih Kupfer" #: C/managing-plugins.page:23(p) msgid "Use one of the following methods:" msgstr "Uporabite enega od naslednjih načinov:" #: C/managing-plugins.page:25(p) msgid "Click the Kupfer icon in the notification area and select the item Preferences" msgstr "Kliknite na ikono Kupfer v obvestilnem področju in izberite predmet Možnosti" #: C/managing-plugins.page:25(item) msgid "." msgstr "." #: C/managing-plugins.page:29(p) msgid "Search for the object Kupfer Preferences in Kupfer itself. Press Return to open it." msgstr "Iščite predmet Možnosti Kupfer v Kupferju. Pritisnite Enter za odprtje." #: C/managing-plugins.page:33(p) msgid "Use the keyboard shortcut Ctrl;" msgstr "Uporabite tipkovno bližnjico Ctrl;" #: C/managing-plugins.page:39(p) msgid "Select the tab Plugins" msgstr "Izberite zavihek Vstavki" #: C/managing-plugins.page:45(p) msgid "Select plugins in the list to read about them, and tick the box next to its name to activate the plugin, or untick to deactivate." msgstr "Izberite vstavke s seznama za branje o njih in izberite polje poleg njegovega imena za njegovo omogočitev ali oznako odstranite za onemogočitev." #: C/managing-plugins.page:49(p) msgid "If the plugin has any configurable parameters, they will be visible below the plugin information." msgstr "V primeru da ima vstavek nastavljive parametre, bodo vidni pod podatki o vstavku." #: C/managing-plugins.page:53(p) msgid "The plugin Kupfer Plugins allows fast access to each plugin's information page as well as the action \"Show Source Code\" which reveals the implementation." msgstr "Vstavek Vstavki Kupfer omogoča hiter dostop do strani s podatki o vstavkih kot tudi do dejanja \"Pokaži izvorno kodo\", ki prikaže izvedbo." #: C/managing-plugins.page:59(title) msgid "If a Plugin can not be Activated" msgstr "V primeru da vstavka ni mogoče omogočiti" #: C/managing-plugins.page:60(p) msgid "If a plugin fails to activate because it requires a software module that is not available, its plugin information will display a message like this:" msgstr "V primeru da vstavka ni mogoče omogočiti, ker zahteva programski modul, ki ni na voljo, bodo podatki o vstavku prikazali sporočilo kot je:" #: C/managing-plugins.page:65(em) msgid "Plugin could not be read due to an error:" msgstr "Vstavka ni mogoče prebrati zaradi napake:" #: C/managing-plugins.page:66(em) msgid "Python module 'gdata' is needed" msgstr "Zahtevan je modul Python 'gdata'" #: C/managing-plugins.page:67(p) msgid "This means that you need to install a needed python module from your distribution—and possibly the plugin documentation can tell you how." msgstr "To pomeni, da morate namestiti zahtevan modul python s svoje distribucije -- morda vam dokumentacija vstavka lahko pove kako." #: C/managing-plugins.page:72(p) msgid "The plugin may also unexpectedly fail to load, and display a different error message. It may then be a program error in either the plugin or Kupfer." msgstr "Nalaganje vstavka lahko tudi nepričakovano spodleti in prikaže durgačno sporočilo o napaki. To je lahko programska napaka v vstavku ali v Kupferju." #: C/managing-plugins.page:79(title) msgid "Installing more Plugins" msgstr "Nameščanje več vstavkov" #: C/managing-plugins.page:80(p) msgid "You can install custom plugins into the folder ~/.local/share/kupfer/plugins. Each plugin is either a single .py file or a python package (a folder directly containing a file called __init__.py). Plugins in the package format can include icon files. Python packages can even be installed as .zip files." msgstr "Vstavke po meri lahko namestite v mapo ~/.local/share/kupfer/plugins. Vsak vstavek je ena datoteka .py ali paket python (mapa, ki vsebuje datoteko z imenom __init__.py). Vstavki v obliki paketa lahko vključujejo datoteke ikone. Pakete Python lahko namestite tudi kot datoteke .zip." #: C/managing-plugins.page:88(p) msgid "Caution: Treat a plugin as a computer program. Do not install untrusted plugins." msgstr "Pozor: Vstavek obravnavajte kot računalniški program. Vstavkov, ki jim ne zaupajte, ne nameščajte." #: C/managing-plugins.page:95(title) msgid "Creating Plugins" msgstr "Ustvarjanje vstavkov" #: C/managing-plugins.page:96(p) msgid "Documentation for plugin creators is available in the file Documentation/Manual.rst in the source distribution on the webpage at Kupfer Manual. An easy way to start is to copy an existing plugin and experimenting with it." msgstr "Dokumentacija za ustvarjalce vstavkov je na voljo v datoteki Documentation/Manual.rst v izvorni distribuciji na spletni strani priročnika Kupfer. Enostaven način za začetek je kopiranje obstoječega vstavka in njegovo preizkušanje." #: C/managing-plugins.page:107(title) msgid "The Catalog Tab in Preferences" msgstr "Zavihek Katalog v možnostih" #: C/managing-plugins.page:108(p) msgid "Each plugin can export a number of sources which contain objects. Normally, all these objects are directly accessible from a top-level search. Some plugins export so specialized or so many objects that their catalogs should better not have their objects exported to the top level. To reach those objects, you have to first find the catalog by name, then enter the catalog using the action Search Contents." msgstr "Vsak vstavek lahko izvozi številne vire, ki vsebujejo predmete. Običajno lahko do teh predmetov dostopate neposredno iz iskanja vrhne ravni. Nekateri vstavki izvozijo specializirane ali tako veliko predmetov, da je boljše, da njihovi katalogi predmetov ne izvažajo na vrhnjo raven. " #: C/managing-plugins.page:118(p) msgid "In the tab Catalog in Kupfer Preferences, a ticked box next to each source means that its objects are exported. An unticked box means that its contents are hidden from the top level." msgstr "V zavihku Katalog v Možnostih Kupfer je poleg vsakega vira izbrano polje, ki pomeni, da so njegovi predmeti izvoženi. Neizbrano polje pomeni, da je vsebina na vrhnji ravni skrita." #: C/managing-plugins.page:123(p) msgid "Note: Kupfer may become slow if large enough subcatalogs are exported to the top level." msgstr "Opomba: Kupfer lahko postane počasen, če v vrhnjo raven izvozite dovolj velike podkataloge." #: C/license.page:7(desc) msgid "You can copy, modify and share Kupfer." msgstr "Kupfer lahko kopirate, spreminjate in delite z drugimi." #: C/license.page:10(title) msgid "License" msgstr "Dovoljenje" #: C/license.page:12(p) msgid "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." msgstr "Ta program je prosta programska oprema; lahko ga širite in/ali spreminjate pod pogoji GNU General Public License, kot ga je objavila ustanova Free Software Foundation; bodisi različice 3 ali (po vaši izbiri) katerekoli poznejše različice." #: C/license.page:18(p) msgid "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." msgstr "Program je na voljo v upanju, da bo uporaben, vendar je BREZ VSAKRŠNEGA JAMSTVA; tudi brez jamstva o USTREZNOSTI ZA PRODAJO ali PRIMERNOSTI ZA DOLOČEN NAMEN. Za več podrobnosti si oglejte GNU General Public License." #: C/license.page:24(p) msgid "You should have received a copy of the GNU General Public License along with this program. If not, see gnu.org/licenses." msgstr "Kopijo GNU General Public License bi morali prejeti skupaj s tem programom. Če je niste, si oglejte gnu.org/licenses." #: C/license.page:30(p) msgid "This documentation is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License." msgstr "Ta dokument je licenciran pod licenco Dovoljenje Creative Commons - priznanje avtorstva - deljenje pod istimi pogoji 3.0 brez prenosa." #: C/license.page:36(p) msgid "As a special exception, the copyright holders give you permission to copy, modify, and distribute the example code contained in this document under the terms of your choosing, without restriction." msgstr "Kot posebno izjemo vam lastniki avtorskih pravic dajejo dovoljenje za kopiranje, spreminjanje in distribuiranje kode primerov, ki jo vsebuje ta dokument, pod svojimi pogoji brez omejitev." #: C/keyboard.page:7(desc) msgid "Complete keyboard shortcuts reference." msgstr "Celotna referenca tipkovnih bližnjic" #: C/keyboard.page:10(title) msgid "Command Keys and Accelerator Keys" msgstr "Tipke ukazov in pospeševalnikov" #: C/keyboard.page:13(title) #: C/generalusage.page:12(title) msgid "Keyboard Interface" msgstr "Vmesnik tipkovnice" #: C/keyboard.page:14(p) msgid "In command mode, the following keystrokes have special meanings:" msgstr "V načinu ukaza imajo nekatere tipke poseben pomen:" #: C/keyboard.page:19(p) #: C/generalusage.page:34(p) msgid " or Space" msgstr " ali Preslednica" #: C/keyboard.page:20(p) #: C/generalusage.page:35(p) msgid "Go to the next match" msgstr "Pojdi na naslednji zadetek" #: C/keyboard.page:23(p) #: C/generalusage.page:38(p) msgid " or ShiftSpace" msgstr " ali ShiftPreslednica" #: C/keyboard.page:26(p) #: C/generalusage.page:41(p) msgid "Go to the previous match" msgstr "Pojdi na predhodni zadetek" #: C/keyboard.page:29(p) #: C/generalusage.page:44(p) msgid " or /" msgstr " ali /" #: C/keyboard.page:30(p) #: C/generalusage.page:45(p) msgid "Descend into an object with content" msgstr "Spusti se v predmet z vsebino" #: C/keyboard.page:33(key) #: C/generalusage.page:48(key) msgid "Backspace" msgstr "Vračalka" #: C/keyboard.page:34(p) #: C/generalusage.page:49(p) msgid "Erase a character from the query. If the query is empty, go up a level" msgstr "Izbriše znak iz poizvedbe. Če je poizvedba prazna, gre eno raven navzgor" #: C/keyboard.page:39(key) #: C/keyboard.page:93(key) #: C/generalusage.page:54(key) msgid "." msgstr "." #: C/keyboard.page:40(p) #: C/generalusage.page:55(p) msgid "Activate free-text mode" msgstr "Omogočite način prostega besedila" #: C/keyboard.page:43(key) #: C/keyboard.page:97(key) #: C/generalusage.page:58(key) msgid "," msgstr "," #: C/keyboard.page:44(p) #: C/generalusage.page:59(p) msgid "Put selected object on the stack (\"Comma Trick\")" msgstr "Postavi izbran predmet v sklad (\"Trik z vejico\")" #: C/keyboard.page:47(p) msgid "Quick access keys:" msgstr "Tipke hitrega dostopa:" #: C/keyboard.page:53(key) msgid "=" msgstr "=" #: C/keyboard.page:55(p) msgid "Activate free-text mode with = prefix (for )" msgstr "Omogoči način prostega besedila s predpono = (za )" #: C/keyboard.page:61(key) msgid "/" msgstr "/" #: C/keyboard.page:63(p) msgid "Activate free-text mode (when nothing is selected) with / prefix (to input a rooted path)" msgstr "Omogoči način prostega besedila (ko ni nič izbrano) s predpono / (za vnos korenske poti)" #: C/keyboard.page:68(p) #: C/generalusage.page:62(p) msgid "Additionally:" msgstr "Dodatno:" #: C/keyboard.page:72(p) #: C/generalusage.page:66(p) msgid "Return activates the current selection: the command is executed." msgstr "Enter omogoči trenutno izbiro: ukaz je izveden." #: C/keyboard.page:74(p) #: C/generalusage.page:68(p) msgid "Escape clears the current selection." msgstr "Escape počisti trenutno izbiro." #: C/keyboard.page:75(p) #: C/generalusage.page:69(p) msgid "Tab switches between the object and the action pane." msgstr "Tab preklopi med predmetom in pladnjem dejanj." #: C/keyboard.page:77(p) msgid "The meaning of the keys Space, ., ,, / and = can not be changed, but you can deactivate their special meaning with the checkbox Use single keystroke commands in Kupfer Preferences." msgstr "Pomena tipk Preslednica, ., ,, / and = ne morete spremeniti, vendar lahko onemogočite njihov poseben pomen z izbirnim polje Uporabi posamezne ukaze pritiskov tipk v Možnostih Kupfer." #: C/keyboard.page:86(title) msgid "Kupfer's Keyboard Shortcuts" msgstr "Tipkovne bližnjice Kupfer" #: C/keyboard.page:87(p) msgid "These keyboard shortcuts are used in Kupfer's interface. They have the following meanings and default shortcuts:" msgstr "Te tipkovne bližnjice se uporabljajo v vmesniku Kupfer. Imajo naslednje pomene in privzete bližnjice:" #: C/keyboard.page:93(key) #: C/keyboard.page:97(key) #: C/keyboard.page:101(key) #: C/keyboard.page:105(key) #: C/keyboard.page:113(key) #: C/keyboard.page:117(key) #: C/keyboard.page:121(key) #: C/keyboard.page:125(key) #: C/keyboard.page:129(key) #: C/keyboard.page:174(key) msgid "Ctrl" msgstr "Ctrl" #: C/keyboard.page:94(p) msgid "Toggle text mode" msgstr "Preklopi besedilni način" #: C/keyboard.page:98(p) msgid "The comma trick" msgstr "Trik z vejico" #: C/keyboard.page:101(key) msgid ";" msgstr ";" #: C/keyboard.page:102(p) msgid "Show preferences window" msgstr "Pokaže okno zmožnosti" #: C/keyboard.page:105(key) msgid "R" msgstr "R" #: C/keyboard.page:106(p) msgid "Reset all" msgstr "Ponastavi vse" #: C/keyboard.page:109(key) msgid "Alt" msgstr "Alt" #: C/keyboard.page:109(key) msgid "A" msgstr "A" #: C/keyboard.page:110(p) msgid "Alternate activate" msgstr "Dodatno omogoči" #: C/keyboard.page:113(key) msgid "Return" msgstr "Enter" #: C/keyboard.page:114(p) msgid "Compose command" msgstr "Sestavi ukaz" #: C/keyboard.page:117(key) msgid "S" msgstr "S" #: C/keyboard.page:118(p) msgid "Switch to first pane" msgstr "Preklopi na prvi pladenj" #: C/keyboard.page:121(key) msgid "Q" msgstr "Q" #: C/keyboard.page:122(p) msgid "Select 'Quit'" msgstr "Izberi 'končaj'" #: C/keyboard.page:125(key) msgid "G" msgstr "G" #: C/keyboard.page:126(p) msgid "Select 'Selected File'" msgstr "Izberi 'izbrano datoteko'" #: C/keyboard.page:129(key) msgid "T" msgstr "T" #: C/keyboard.page:130(p) msgid "Select 'Selected Text'" msgstr "Izberi 'izbrano besedilo'" #: C/keyboard.page:133(key) msgid "F1" msgstr "F1" #: C/keyboard.page:134(p) msgid "Show Help" msgstr "Pokaži pomoč" #: C/keyboard.page:139(title) msgid "How to configure a keyboard shortcut" msgstr "Kako nastaviti tipkovno bližnjico" #: C/keyboard.page:141(p) #: C/keyboard.page:185(p) msgid "Open Kupfer Preferences and go to the Keyboard tab." msgstr "Odprite Možnosti Kupfer in pojdite v zavihek Tipkovnica." #: C/keyboard.page:147(p) msgid "Double-click the shorcut's row under Browser Keyboard Shortcuts." msgstr "Dvokliknite na vrstico bližnjice pod Tipkovne bližnjice brskalnika." #: C/keyboard.page:153(p) msgid "Using the window that appears, press modifier keys and a letter or number key to set a shortcut. An example is pressing and holding Ctrl and then pressing and releasing T to bind CtrlT." msgstr "V oknu, ki se pojavi, za nastavitev splošne bližnjice pritisnite na spremenilne tipke in črko ali število. Primer je pritisk in držanje na tipko Ctrl in nato pritisk in izpust tipke T za vezavo CtrlT." #: C/keyboard.page:164(title) msgid "Global Keyboard Shortcuts" msgstr "Splošne tipkovne bližnjice" #: C/keyboard.page:165(p) msgid "Kupfer always listens to global shortcuts, even if it is not currently in the foreground." msgstr "Kupfer vedno posluša za splošne bližnjice, tudi če ni v ospredju." #: C/keyboard.page:169(p) msgid "They have the following meanings and default shortcuts:" msgstr "Imajo naslednje pomene in privzete bližnjice:" #: C/keyboard.page:174(key) msgid "Space" msgstr "Preslednica" #: C/keyboard.page:175(p) msgid "Show/hide Kupfer" msgstr "Pokaže/skrije Kupfer." #: C/keyboard.page:178(p) msgid "(not configured by default)" msgstr "(ni privzeto nastavljeno)" #: C/keyboard.page:179(p) msgid "Show Kupfer with 'Selection' object focused" msgstr "Pokaže Kupfer s predmetom 'Izbira' v žarišču" #: C/keyboard.page:183(title) msgid "How to configure a global keyboard shortcut" msgstr "Kako nastaviti splošno tipkovno bližnjico" #: C/keyboard.page:191(p) msgid "Double-click the shorcut's row under Global Keyboard Shortcuts." msgstr "Dvokliknite na vrstico bližnjice pod Splošne tipkovne bližnjice." #: C/keyboard.page:197(p) msgid "Using the window that appears, press modifier keys and a letter or number key to set a global shortcut. An example is pressing and holding Super and then pressing and releasing Space to bind SuperSpace." msgstr "V oknu, ki se pojavi, za nastavitev splošne bližnjice pritisnite na spremenilne tipke in črko ali število. Primer je pritisk in držanje na tipko Super in nato pritisk in izpust tipke Preslednica za vezavo SuperPreslednica." #: C/keyboard.page:206(p) msgid "Since these keyboard shortcuts are global, they can be used from any application. Select shortcuts with care so that they do not conflict with other functions." msgstr "Ker so te tipkovne bližnjice splošne, jih lahko uporabite v kateremkoli programu. Bližnjice izberite previdno, da ne bodo v sporu z drugimi zmožnostmi." #: C/keyboard.page:214(p) msgid "The plugin Triggers allows to activate actions with global keyboard shortcuts. Trigger shortcuts do not appear in Kupfer Preferences." msgstr "Vstavek Sprožilci vam omogoča omogočitev dejanj s splošnimi tipkovnimi bližnjicami. Bližnjice sprožilca se ne pojavijo v Možnostih Kupfer." #: C/keyboard.page:220(p) msgid "See for more information." msgstr "Za več podrobnosti si oglejte ." #: C/introduction.page:7(desc) msgid "Introduction to Kupfer." msgstr "Uvod v Kupfer." #: C/introduction.page:10(title) msgid "Introduction" msgstr "Uvod" #: C/introduction.page:12(p) msgid "Kupfer is an interface for quick and convenient access to applications and their documents." msgstr "Kupfer je vmesnik za hiter in priročen dostop programov in njihovih dokumentov." #: C/introduction.page:16(p) msgid "The most typical use is to find a specific application and launch it. We have tried to make Kupfer easy to extend with plugins so that this quick-access paradigm can be extended to many more objects than just applications." msgstr "Najbolj običajna uporaba je iskanje določenega program in njegov zagon. Kupfer lahko enostavno razširite z vstavki zato lahko paradigmo hitrega dostopa razširite na več predmetov kot samo programe." #: C/introduction.page:22(p) msgid "We hope that using Kupfer feels both very fun and different." msgstr "Upamo, da se vam zdi uporaba Kupferja tako zelo zabavna kot drugačna." #: C/introduction.page:26(p) msgid "For up-to-date information about Kupfer, visit its homepage." msgstr "Za več podrobnosti o programu Kupfer obiščite njegovo domačo stran." #: C/index.page:9(name) msgid "Ulrik Sverdrup" msgstr "Ulrik Sverdrup" #: C/index.page:10(email) msgid "ulrik.sverdrup@gmail.com" msgstr "ulrik.sverdrup@gmail.com" #: C/index.page:13(year) msgid "2009" msgstr "2009" #: C/index.page:14(name) msgid "Kupfer Development Team" msgstr "Razvijalska ekipa Kupfer" #: C/index.page:17(license) msgid "Creative Commons Share Alike 3.0" msgstr "Dovoljenje Creative Commons - priznanje avtorstva - deljenje pod istimi pogoji 3.0" #: C/index.page:21(title) msgid "Kupfer Manual" msgstr "Priročnik Kupfer" #: C/index.page:24(title) msgid "Using Kupfer" msgstr "Uporabljanje programa Kupfer" #: C/index.page:27(title) msgid "About Specific Plugins" msgstr "O določenih vstavkih" #: C/generalusage.page:7(desc) msgid "How to start using Kupfer." msgstr "Uvod v Kupfer." #: C/generalusage.page:14(p) msgid "Kupfer is to the largest part a keyboard-managed interface to applications and documents." msgstr "Kupfer je večinoma s tipkovnico upravljan vmesnik do programov in dokumentov." #: C/generalusage.page:18(p) msgid "Kupfer's default mode is the command mode: If you type a query, kupfer will search for a match in its catalog." msgstr "Privzeti način Kupferja je način ukaza: če vnesete poizvedbo, bo kupfer iskal ujemanje v svojem katalogu." #: C/generalusage.page:23(p) msgid "The arrow keys allow you to browse query matches quite naturally, going to the previous or next match, and going up and down in the subcatalogs." msgstr "Smerne tipke vam omogočajo naravno brskanje ujemajočih poizvedb, premik na predhodno ali naslednje ujemanja in navzgor ali navzdol po podkatalogih." #: C/generalusage.page:29(p) msgid "In command mode, some keystrokes have special meanings:" msgstr "V načinu ukaza imajo nekatere tipke poseben pomen:" #: C/generalusage.page:71(p) msgid "By default you show Kupfer using the global keyboard shortcut CtrlSpace." msgstr "Privzeto lahko Kupfer prikažete s splošno tipkovno bližnjico CtrlPreslednica." #: C/generalusage.page:74(p) msgid "See for more information." msgstr "Za več podrobnosti si oglejte ." #: C/generalusage.page:78(title) msgid "Learning Habits" msgstr "Učenje navad" #: C/generalusage.page:79(p) msgid "Kupfer remembers which objects and actions are used the most. When beginning to use it, you have to use the arrow keys at times to make it precise which object you want to find. After a few uses of that object, Kupfer will rank it higher. Objects marked as favorites are also ranked higher." msgstr "Kupfer si zapomni katere predmete in dejanja največkrat uporabljate. Ko ga boste začeli uporabljati, boste morali včasih uporabiti smerne tipke, da bo natančen s predmeti, ki jih želite najti. Po nekaj uporabah tega predmeta ga bo Kupfer višje ocenil. Višje so ocenjeni tudi predmeti označeni kot priljubljeni." #: C/generalusage.page:90(title) msgid "The Catalog" msgstr "Katalog" #: C/generalusage.page:91(p) msgid "The Catalog is the collection of objects you can access in Kupfer, such as documents and programs." msgstr "Katalog je zbirka predmetov do katerih lahko dostopate v Kupferju, kot so dokumenti in programi." #: C/generalusage.page:96(p) msgid "Objects in the catalog that have content, like folders, are marked with an arrow. Pressing will enter these objects. Much of the catalog is composed of subcatalogs; plugin subcatalogs do in general list objects that are also available directly from the top level. Subcatalogs can be used for a narrower view or search scope, when using Kupfer." msgstr "Predmeti v katalogu, ki imajo vsebino (kot na primer mape) so označeni s puščico. Pritiskanje bo vneslo te predmete. Večina kataloga je sestavljena iz podkatalogov, vstavki podkatalogov v splošnem naštejejo predmete, ki so na voljo tudi neposredno iz zgornje ravni. Podkataloge je mogoče uporabiti za ožji pogled ali iskalni obseg pri uporabi Kupferja." #: C/generalusage.page:105(p) msgid "Most subcatalogs update their content automatically. For example, the Desktop folder source is always up-to-date." msgstr "Večina podkatalogov svojo vsebino samodejno posodobi. Na primer, katalog mape Namizje se vedno samodejno posodablja." #. Put one translator per line, in the form of NAME , YEAR1, YEAR2 #: C/index.page:0(None) msgid "translator-credits" msgstr "Andrej Žnidaršič" #~ msgid "Using Kupfer more conveniently." #~ msgstr "Priročnejša uporaba Kupferja." #~ msgid "" #~ "Kupfer listens to global shortcuts, even if Kupfer is not currently in " #~ "the foreground. The most important global shortcut is the shortcut to " #~ "show and hide Kupfer's command window which by default is " #~ "CtrlSpace." #~ msgstr "" #~ "Kupfer čaka na splošne bližnjice tudi če trenutni ni v ospredju. Najbolj " #~ "pomembna splošna bližnjica je bližnjica za prikaz in skritje Kupferjevega " #~ "okna ukazov, ki je privzeto CtrlPreslednica." #~ msgid "Global Keyboard Shortcuts are configured in Kupfer's preferences." #~ msgstr "" #~ "Splošne tipkovne bližnjice je mogoče nastaviti v možnostih Kupferja." #~ msgid "" #~ "The Triggers plugin allows to configure actions to be activated by global " #~ "shortcuts, but triggers can only be configured in that plugin." #~ msgstr "" #~ "Vstavek sprožilci omogoča nastavitev dejanj, ki jih sprožijo splošne " #~ "bližnjice, vendar jih je mogoče nastaviti le v tem vstavku." #~ msgid "" #~ "Additional keyboard shortcuts that work with Kupfer when it is in the " #~ "foreground can be configured in Kupfer's preferences." #~ msgstr "" #~ "Dodatne tipkovne bližnjice, ki delujejo s Kupferjem kadar je v ospredju " #~ "in jih je mogoče nastaviti v možnostih Kupferja." #~ msgid "" #~ "Install custom plugins in the folder ~/.local/share/kupfer/plugins/" #~ "" #~ msgstr "" #~ "Namestite vstavke po meri v mapo ~/.local/share/kupfer/plugins/" #~ msgid "" #~ "Kupfer cache, config and data are located in the directories ~/." #~ "cache/kupfer, ~/.config/kupfer and ~/.local/" #~ "share/kupfer." #~ msgstr "" #~ "Predpomnilnik Kupfer, nastavitve in podatki so v mapah ~/.cache/" #~ "kupfer, ~/.config/kupfer in ~/.local/share/" #~ "kupfer." #~ msgid "" #~ "You can install custom plugins into ~/.local/share/kupfer/plugins; adding " #~ "to Kupfer's object knowledge can be surprisingly easy, just " #~ "look at the default plugins if you want to create new." #~ msgstr "" #~ "Vstavke po meri lahko namestite v ~/.local/share/kupfer/plugins. " #~ "Dodajanje Kupferjevemu poznavanju predmetov je lahko " #~ "presenetljivo enostavno. Če želite ustvariti nove vstavke, si poglejte " #~ "kako delujejo privzeti vstavki." #~ msgid "Open Terminal Here" #~ msgstr "Odpri terminal tukaj" #~ msgid "" #~ "Open terminal first calls xdg-terminal, then gnome-" #~ "terminal. xdg-terminal is a script to find the user's configured " #~ "terminal program for his/her Desktop Environment. Install xdg-" #~ "terminal if you need this (or install a symlink called xdg-" #~ "terminal)." #~ msgstr "" #~ "Ukaz odpri terminal najprej pokliče xdg-terminal, nato pa " #~ "gnome-terminal. xdg-terminal je skript za iskanje uporabniško " #~ "določenega programa terminala za njegovo/njeno namizno okolje. Če to " #~ "potrebujete, namestite xdg-terminal (ali namestite simbolno " #~ "povezavo z imenom xdg-terminal)." #~ msgid "" #~ "To use Kupfer like a pro, you can configure a \"Magic " #~ "Keybinding\" for Kupfer. GUI configuration is not yet " #~ "supported, but edit the configuration file ~/.config/kupfer/kupfer." #~ "cfg to include the following:" #~ msgstr "" #~ "Za uporabo Kupferja kot profesionalec lahko za Kupfer nastavite \"Čarobno tipkovno bližnjico\". Grafična nastavitev še ni " #~ "podprta, zato morate urediti nastavitveno datoteko ~/.config/kupfer/" #~ "kupfer.cfg tako, da bo vključevala naslednje:" #~ msgid "" #~ "\n" #~ "[Kupfer]\n" #~ "keybinding = <Control>space\n" #~ "magickeybinding = <Ctrl><Alt>space\n" #~ " " #~ msgstr "" #~ "\n" #~ "[Kupfer]\n" #~ "tipkovna bližnica = <Control>preslednica\n" #~ "čarobna tipkovna bližnica = <Ctrl><Alt>preslednica\n" #~ " " #~ msgid "" #~ "Now, pressing CtrlAltSpace will summon Kupfer with the current selection in " #~ "focus. Make sure you have installed Kupfer's nautilus plugin, " #~ "then both the currently selected file in Nautilus, or the currently " #~ "selected text in the front application will be selected." #~ msgstr "" #~ "Sedaj pritisnite CtrlAltPreslednica, ki bo priklicala Kupfer s trenutno izbiro v " #~ "žarišču. Prepričajte se, da imate nameščen Kupferjev vstavek " #~ "nautilus. V tem primeru, bosta tako izbrana datoteka v Nautilusu ali " #~ "trenutno izbrano besedilo v sprednjem programu izbrana. " #~ msgid "" #~ "Now you can select a word in, say, a web browser, use CtrlAltSpace, and select action Look " #~ "Up to look up the selected word. Or select an image file, use " #~ "CtrlAltSpace, select " #~ "action Scale with object 1000 to scale the image to " #~ "1000 pixels wide!" #~ msgstr "" #~ "Sedaj lahko izberete besedo, na primer v spletnem brskalniku, uporabite " #~ "CtrlAltPreslednica in " #~ "izberete dejanje Poišči za iskanje izbrane besede. Ali pa " #~ "izberite slikovno datoteko, uporabite CtrlAltPreslednica, izberite Prilagodi velikost s predmetom 1000 za spremembo velikosti slike na širino " #~ "1000 točk. " #~ msgid "" #~ "An example useful script is here which changes the rating of Rhythmbox's currently playing song; I have added five scriptlets calling " #~ "rhrating.py with numbers from 0 to 5 to my catalog to " #~ "quickly rate tracks. (This is something that might be integrated into " #~ "Kupfer later)" #~ msgstr "" #~ "Primer uporabnega skripta je tukaj, ki spremeni oceno trenutno predvajajoče se " #~ "skladbe v programu Rhythmbox. Dodanih je bilo pet majhnih " #~ "skript rhrating.py s števili od 0 to 5 za hitro ocenjevanje " #~ "skladb. (To bo morda kasneje vključeno v Kupfer)" #~ msgid "" #~ "Kupfer is its own remote control. When Kupfer is " #~ "already running, Kupfer on the command-line will focus its " #~ "window, but there is more you can do: If you invoke kupferQUERY where QUERY is a text string or a " #~ "filename, Kupfer will focus, and select this item. This way, " #~ "you can quickly invoke Kupfer actions even on objects from a " #~ "shell-based context." #~ msgstr "" #~ "Kupfer je svoj lasten daljinski upravljalnik. Ko Kupfer že teče, bo Kupfer v ukazni vrstici spravil njegovo okno " #~ "v žarišče. Storite pa lahko še več: če prikličete kupferPOIZVEDBA, kjer je POIZVEDBA besedilni " #~ "niz ali ime datoteke, bo Kupfer prišel v žarišče in izbral ta " #~ "predmet. Na ta način lahko hitro prikličete dejanja Kupfer na " #~ "predmetih tudi iz lupine." #~ msgid "" #~ "You can also pipe the output of a command into Kupfer to send " #~ "text to the already running instance of Kupfer." #~ msgstr "" #~ "Izhod ukaza lahko preusmerite v Kupfer za pošiljanje besedila " #~ "že delujočemu primerku programa Kupfer." #~ msgid "Legal Information." #~ msgstr "Pravne podrobnosti." #~ msgid "" #~ "Kupfer is a program to change, speed up and make everything " #~ "about files and programs more fun on your computer. Kupfer is " #~ "a launcher; you typically use it to summon an application or a document " #~ "quickly by typing parts of its name. It can also do more than getting at " #~ "something quickly: there are different plugins for accessing more objects " #~ "and running custom commands." #~ msgstr "" #~ "Kupfer je program za spreminjanje, pohitritev in delanje " #~ "datotek in programov na vašem računalniku bolj zabavnih. Kupfer je zaganjalnik. Običajno ga uporabite za hiter zagon programa ali " #~ "dokumenta s tipkanjem dela njegovega imena. Naredi lahko veliko več kot " #~ "nekaj hitro zažene - obstajajo različni vstavki za dostop do več " #~ "predmetov in zagon ukazov po meri." #~ msgid "" #~ "Kupfer is written using Python and has a flexible " #~ "architecture; the implementation is simple and makes the easy things work " #~ "first. One goal is that new plugins can be written quickly without too " #~ "much programming." #~ msgstr "" #~ "Kupfer je napisan v Pythonu in ima prilagodljivo arhitekturo. " #~ "Podpora je enostavna in najprej omogoča delovanje enostavnih stvari. Eden " #~ "od ciljev programa je možnost hitrega pisanja novih vstavkov brez preveč " #~ "programiranja." #~ msgid "" #~ "The program is very inspired by Quicksilver." #~ msgstr "" #~ "Ta program je močno navdihnil Quicksilver." kupfer-328/help/wscript000066400000000000000000000067341500175051100152370ustar00rootroot00000000000000#!/usr/bin/env python # Mallard waf adaptor written by Ulrik Sverdrup # may be distributed, changed, used, etc freely for any purpose ## Mallard functionality definitions ## import os from pathlib import Path from waflib import Task, TaskGen, Utils # FIXME: Support for figures def _read_makefile_am(filename): """Read a Makefile.am file for HELP_* variable definitions, return tuples (key, value) """ varstring = Path(filename).read_text(encoding="UTF-8") varstring = varstring.replace("\\\n", " ") for line in varstring.splitlines(): if line.startswith("HELP"): key, _d, value = line.partition("=") yield key.strip(), value.strip() def init_mallard(self): mf_am = self.path.find_resource(self.variable_definitions) help_var = dict(_read_makefile_am(mf_am.abspath())) require_vars = "HELP_ID HELP_LINGUAS HELP_FILES".split() have_vars = set(var for var, val in help_var.items() if val) if missing_vars := set(require_vars).difference(have_vars): print(f"Missing HELP variable declarations in {mf_am.abspath()}:") print("\n".join(missing_vars)) self.bld.env.update(help_var) self.help_install_prefix = "${PREFIX}/share/help/" def apply_mallard(self): bld = self.bld lst = self.to_list(bld.env["HELP_LINGUAS"]) cnode = self.path.find_dir("C") pages = cnode.ant_glob("*.page") legal_xml = cnode.ant_glob("legal.xml") self.install_path = Utils.subst_vars(self.help_install_prefix, self.env) # Check if the declared page list is consistent declared_pages = self.to_list(bld.env["HELP_FILES"]) pages = [os.path.basename(str(p)) for p in pages] if missing_pages := set(pages).difference(declared_pages): print("Warning: Some pages not declared:") print("\n".join(missing_pages)) for lang in lst: lang_install_path = os.path.join( self.install_path, lang, bld.env["HELP_ID"] ) node = self.path.find_resource(f"{lang}/{lang}.po") mo = self.path.find_or_declare(f"{lang}/{lang}.mo") bld( name="msgfmt", color="BLUE", rule="${MSGFMT} ${SRC} -o ${TGT}", source=node, target=mo, ) for page in pages: tsk = self.create_task("itstool") out = self.path.find_or_declare(f"{lang}/{page}") src = self.path.find_resource(f"C/{page}") tsk.set_inputs([mo, src]) tsk.set_outputs(out) bld.install_files(lang_install_path, tsk.outputs) bld.install_files(lang_install_path, legal_xml) c_install_path = os.path.join(self.install_path, "C", bld.env["HELP_ID"]) for page in cnode.ant_glob("*.page"): bld.install_files(c_install_path, page) bld.install_files(c_install_path, legal_xml) Task.task_factory( "itstool", "${ITSTOOL} ${ITSTOOLFLAGS} ${SRC} -o ${TGT}", color="BLUE" ) TaskGen.feature("mallard")(init_mallard) TaskGen.feature("mallard")(apply_mallard) TaskGen.after("init_mallard")(apply_mallard) ## End Mallard functionality ## # Build Configuration def options(opt): pass def configure(ctx): try: ctx.find_program("msgfmt", var="MSGFMT") ctx.find_program("itstool", var="ITSTOOL") ctx.env["ITSTOOLFLAGS"] = "-m" except ctx.errors.ConfigurationError: pass def build(bld): if bld.env["ITSTOOL"]: bld( features="mallard", variable_definitions="Makefile.am", ) kupfer-328/kupfer-run000077700000000000000000000000001500175051100172672bin/kupfer.inustar00rootroot00000000000000kupfer-328/kupfer.py000077500000000000000000000026361500175051100145370ustar00rootroot00000000000000#!/usr/bin/python3 """ kupfer A convenient command and access tool Copyright 2007-–2023 Ulrik Sverdrup and other Kupfer authors 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 . """ if __name__ == "__main__": from pathlib import Path from kupfer import main # if kupfer is installed in this same dir should be defaults.cfg if not Path(__file__).with_name("defaults.cfg").is_file(): print("!!!!!!!!!!!!!! WARN !!!!!!!!!!!!!!") print( "Launching Kupfer by kupfer.py is dedicated only for development. " "This may totally broke some plugins, and some parts may not not " "work as expected." ) print("Also Kupfer may run much slower.") print("Please install and run Kupfer as described in documentation.") print("!!!!!!!!!!!!!! WARN !!!!!!!!!!!!!!") main.main() kupfer-328/kupfer/000077500000000000000000000000001500175051100141535ustar00rootroot00000000000000kupfer-328/kupfer/__init__.py000066400000000000000000000004011500175051100162570ustar00rootroot00000000000000from contextlib import suppress import gi gi.require_version("Gtk", "3.0") gi.require_version("Gdk", "3.0") with suppress(ValueError): gi.require_version("Wnck", "3.0") with suppress(ValueError): gi.require_version("AyatanaAppIndicator3", "0.1") kupfer-328/kupfer/config.py000066400000000000000000000100001500175051100157610ustar00rootroot00000000000000""" Module for configuration and misc things """ from __future__ import annotations import os import typing as ty from pathlib import Path from xdg import BaseDirectory try: from kupfer import version_subst # type:ignore except ImportError: version_subst = None PACKAGE_NAME = "kupfer" __all__ = ( "ResourceLookupError", "get_cache_file", "get_cache_home", "get_config_file", "get_config_files", "get_data_dirs", "get_data_file", "get_data_home", "get_kupfer_env", "has_capability", "save_config_file", "save_data_file", ) class ResourceLookupError(Exception): pass def has_capability(cap: str) -> bool: """Check is @cap capability is not disabled by environment variable""" return not bool(os.getenv(f"KUPFER_NO_{cap}")) def get_kupfer_env(name: str, default: str = "") -> str: """Get valaue of KUPFER_ environment variable or default""" return os.getenv(f"KUPFER_{name}", default) def get_cache_home() -> str | None: """Directory where cache files should be put. Guaranteed to exist.""" cache_home = BaseDirectory.xdg_cache_home or os.path.expanduser("~/.cache") cache_dir = Path(cache_home, PACKAGE_NAME) if not cache_dir.exists(): try: cache_dir.mkdir(mode=0o700) except OSError as exc: print(exc) return None return str(cache_dir) def get_cache_file(path: tuple[str, ...] = ()) -> str | None: """Get file by @path from cache directory. Return None when no exists.""" cache_home = BaseDirectory.xdg_cache_home or os.path.expanduser("~/.cache") cache_path = Path(cache_home, *path) if not cache_path.exists(): return None return str(cache_path) def get_data_file(filename: str, package: str = PACKAGE_NAME) -> str: """Return path to @filename if it exists anywhere in the data paths, else raise ResourceLookupError.""" if version_subst: first_datadir = os.path.join(version_subst.DATADIR, package) else: first_datadir = "./data" file_path = Path(first_datadir, filename) if file_path.exists(): return str(file_path) for data_path in BaseDirectory.load_data_paths(package): file_path = Path(data_path, filename) if file_path.exists(): return str(file_path) if package == PACKAGE_NAME: raise ResourceLookupError(f"Resource {filename} not found") raise ResourceLookupError( f"Resource {filename} in package {package} not found" ) def save_data_file(filename: str) -> str | None: """Return filename in the XDG data home directory, where the directory is guaranteed to exist.""" if direc := BaseDirectory.save_data_path(PACKAGE_NAME): return os.path.join(direc, filename) return None def get_data_home() -> str: """Directory where data is to be saved. Guaranteed to exist.""" return BaseDirectory.save_data_path(PACKAGE_NAME) # type: ignore def get_data_dirs( name: str = "", package: str = PACKAGE_NAME ) -> ty.Iterable[str]: """Iterate over all data dirs of @name that exist.""" return ty.cast( "ty.Iterable[str]", BaseDirectory.load_data_paths(os.path.join(package, name)), ) def get_config_file(filename: str, package: str = PACKAGE_NAME) -> str | None: """Return path to @package/@filename if it exists anywhere in the config paths, else return None""" return ty.cast( "ty.Union[str, None]", BaseDirectory.load_first_config(package, filename), ) def get_config_files(filename: str) -> ty.Iterable[str]: """Iterator to @filename in all config paths, with most important (takes precedence) files first.""" return BaseDirectory.load_config_paths(PACKAGE_NAME, filename) or () def save_config_file(filename: str) -> str | None: """Return filename in the XDG data home directory, where the directory is guaranteed to exist.""" if direc := BaseDirectory.save_config_path(PACKAGE_NAME): return os.path.join(direc, filename) return None kupfer-328/kupfer/core/000077500000000000000000000000001500175051100151035ustar00rootroot00000000000000kupfer-328/kupfer/core/__init__.py000066400000000000000000000001211500175051100172060ustar00rootroot00000000000000""" Core Kupfer objects. Should not be imported in plugins (in most cases). """ kupfer-328/kupfer/core/_support.py000066400000000000000000000015071500175051100173330ustar00rootroot00000000000000""" Helper functions - common code for core module. This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ from __future__ import annotations import typing as ty if ty.TYPE_CHECKING: from kupfer.obj import Leaf __all__ = ("get_leaf_members", "is_multiple_leaf") def get_leaf_members(leaf: Leaf) -> ty.Sequence[Leaf]: """Return an iterator to members of @leaf, if it is a multiple leaf.""" if hasattr(leaf, "get_multiple_leaf_representation"): return leaf.get_multiple_leaf_representation() # type: ignore return (leaf,) def is_multiple_leaf(leaf: Leaf | None) -> bool: """Check is leaf represent multiple leaves.""" return hasattr(leaf, "get_multiple_leaf_representation") kupfer-328/kupfer/core/actionaccel.py000066400000000000000000000071711500175051100177300ustar00rootroot00000000000000""" Accelerators configuration. This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ from __future__ import annotations import json import typing as ty from kupfer import config from kupfer.support import pretty _repr_key = repr __all__ = ("AccelConfig",) # AcceleratorValidator check is given accelerator is valid AcceleratorValidator = ty.Callable[[str], bool] class AccelConfig(pretty.OutputMixin): """Action Accelerator configuration""" def __init__(self): self._accels: dict[str, str] = {} # is configuration loaded self._loaded: bool = False # is configuration changed and not saved self._changed: bool = False def _filename(self) -> str | None: if ret := config.save_config_file("action_accels.json"): return ret self.output_error("Can't find XDG_CONFIG_HOME") return None def load(self, validate_func: AcceleratorValidator) -> bool: """Load accelerators configuration. If configuration is already loaded - do nothing. After loading `validate_func` is used for each accelerator; if function return false - accelerator is ignored. Return True on success. """ if self._loaded: return True self._loaded = True data_file = self._filename() if data_file is None: return False self._accels.clear() try: with open(data_file, encoding="UTF-8") as dfp: accels = json.load(dfp) self.output_debug("Read", data_file) except FileNotFoundError: return False except Exception: self.output_error("Failed to read:", data_file) self.output_exc() return False try: self._valid_accel(accels, validate_func) except Exception: self.output_exc() self.output_debug("Loaded", self._accels) return True def _valid_accel( self, accels: dict[ty.Any, ty.Any], validate_func: AcceleratorValidator ) -> None: """Validate loaded data.""" if not isinstance(self._accels, dict): raise TypeError("Accelerators must be a dictionary") for obj, key in accels.items(): # make sure object and key are strings key = str(key) # noqa:PLW2901 if validate_func(key): self._accels[str(obj)] = key else: self.output_error("Ignoring invalid accel", key, "for", obj) def get(self, obj: ty.Any) -> str | None: """Return accel key for @obj or None""" return self._accels.get(_repr_key(obj)) def set(self, obj: ty.Any, key: str) -> None: """Set accelerator `key` for `obj`.""" self.output_debug("Set", key, "for", _repr_key(obj)) assert hasattr(obj, "activate") assert isinstance(key, str) self._accels[_repr_key(obj)] = key self._changed = True def store(self) -> None: """Write all accelerator into configuration file.""" if not self._changed: return data_file = self._filename() if data_file is None: return self.output_debug("Writing to", data_file) try: with open(data_file, "w", encoding="UTF-8") as dfp: json.dump(self._accels, dfp, indent=4, sort_keys=True) except Exception: self.output_error("Failed to write:", data_file) self.output_exc() self._changed = False kupfer-328/kupfer/core/actioncompat.py000066400000000000000000000052311500175051100201370ustar00rootroot00000000000000from __future__ import annotations import typing as ty from kupfer.core._support import get_leaf_members from kupfer.obj import Action, AnySource, KupferObject, Leaf if ty.TYPE_CHECKING: from kupfer.core.sources import SourceController __all__ = ( "action_valid_for_item", "actions_for_item", "iobject_source_for_action", "iobjects_valid_for_action", ) def action_valid_for_item(action: Action, leaf: Leaf) -> bool: """Check is `action` is valid for all `leaf` representation. Note: valid_for_item MUST return bool. """ return all(action.valid_for_item(L) for L in get_leaf_members(leaf)) def actions_for_item( leaf: Leaf | None, sourcecontroller: SourceController ) -> set[Action]: """Get list of actions for `leaf` from `sourcecontroller`.""" if leaf is None: return set() actions: set[Action] | None = None for member in get_leaf_members(leaf): l_actions = set(member.get_actions()) l_actions.update(sourcecontroller.get_actions_for_leaf(member)) if actions is None: actions = l_actions else: actions.intersection_update(l_actions) return actions or set() def iobject_source_for_action( action: Action, for_item: Leaf ) -> tuple[AnySource | None, bool]: """Get iobjects source for `action` for `for_item`. Simply call `Action.object_source` and 'Action.object_source_and_catalog` for first representation of `for_item`. Return (src, use_catalog) where src: object source or None, use_catalog: True to use catalog in addition. """ leaf, *_rest = get_leaf_members(for_item) if not leaf: return None, False return action.object_source(leaf), action.object_source_and_catalog(leaf) FilteringFunction = ty.Callable[ [ty.Iterable[KupferObject]], ty.Iterable[ty.Union[Action, Leaf]] ] def iobjects_valid_for_action( action: Action, for_item: Leaf ) -> FilteringFunction: """Return a filtering *function* that will let through those leaves that are good iobjects for @action and @for_item. """ types = tuple(action.object_types()) if not hasattr(action, "valid_object"): def type_check(items): return (i for i in items if isinstance(i, types)) return type_check _valid_object = action.valid_object def type_obj_check(iobjs): return ( i for i in iobjs if isinstance(i, types) and all( _valid_object(leaf, for_item=item) for leaf in get_leaf_members(i) for item in get_leaf_members(for_item) ) ) return type_obj_check kupfer-328/kupfer/core/commandexec.py000066400000000000000000000531411500175051100177440ustar00rootroot00000000000000""" The main logic for executing constructed commands. A command is normally a tuple of (object, action, indirect object). Where, of course, the indirect object is often not needed (in this module we then pass None in its stead). This code was once a shining machine; While adding the "comma trick" and support for "multiple dispatch" was easy in the rest of the program, it shed its casualties here: While the main process is simple, we deal here with all the exceptions that are, at the moment, tacked on. The ActionExecutionContext (ACE) keeps track of its nested invocation, so that we can catch the results of commands executed inside other commands. The delegation mechanism allows a user of the ACE to indicate that the result of the command should be passed on from the earlier (more nested) invocation. Multiple dispatch is straightforward if the action implements the multiple dispatch protocol. Is the protocol not implemented, the command is simply "multiplied out": executed once for each object, or once for each combination of object and indirect object. With multiple command execution (and delegation), we must then process and merge multiple return values. This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. TODO: delegation, run, combine_action_result_multiple need rethink / rebuild. It's work quite well but is too complicated. """ from __future__ import annotations import collections import contextlib import itertools import sys import typing as ty from enum import IntEnum from functools import partial from gi.repository import GObject from kupfer.core._support import get_leaf_members, is_multiple_leaf from kupfer.obj import ( Action, KupferObject, Leaf, OperationError, Source, SourceLeaf, ) from kupfer.obj.compose import MultipleLeaf from kupfer.obj.sources import MultiSource from kupfer.support import pretty, task from kupfer.ui import uiutils if ty.TYPE_CHECKING: from gettext import gettext as _ from kupfer.support.types import ExecInfo from kupfer.ui.uievents import GUIEnvironmentContext __all__ = ( "ActionExecutionContext", "ActionExecutionError", "ExecResult", "ExecutionToken", "default_action_execution_context", ) class ExecResult(IntEnum): ZERO = 0 # when delegate NONE = 1 OBJECT = 2 SOURCE = 3 ASYNC = 4 REFRESH = 5 @property def is_sync(self): return self in (ExecResult.OBJECT, ExecResult.SOURCE) _MAX_LAST_RESULTS: ty.Final = 10 ## CmdTuple keep information about command arguments (leaf, action and optional ## iobj) CmdTuple = tuple[Leaf, Action, ty.Optional[Leaf]] ## Token keep information about (command id, and optional CmdTuple) Token = tuple[int, ty.Optional[CmdTuple]] ## ActionResult is result (content) of action ActionResult = ty.Union[Source, Leaf, task.Task, None] # ActionResultRefresh is special leaf used as result of action that # want refresh current leaves list. ActionResultRefresh = Leaf(None, "ActionResultRefresh") class ActionExecutionError(Exception): pass class ExecutionToken: """A token object that an `Action` carries with it from `activate`. Must be used for access to current execution context, and to access the environment. """ def __init__( self, aectx: ActionExecutionContext, async_token: Token, ui_ctx: GUIEnvironmentContext | None, ) -> None: """Initialize `ExecutionToken`. `aectx` is context of execution. `async_token` keeps data returned with late result `ui_ctx` is optional gui context """ self._aectx: ActionExecutionContext = aectx self._token = async_token self._ui_ctx = ui_ctx def register_late_result( self, result_object: KupferObject, show: bool = True ) -> None: """Put execution result (`result_object`) into action execution context. If `show` it True - try to show result to the user. """ self._aectx.register_late_result( self._token, result_object, show=show, ctxenv=self._ui_ctx ) def register_late_error( self, exc_info: ExecInfo | BaseException | None = None ) -> None: """Put error (`exc_info`) from failed execution into action execution context.""" self._aectx.register_late_error(self._token, exc_info) def delegated_run( self, obj: Leaf, action: Action, iobj: Leaf | None ) -> tuple[ExecResult, ty.Any]: """Activate action execution context - run it for `obj`, `action` and `iobj`.""" return self._aectx.run( obj, action, iobj, delegate=True, ui_ctx=self._ui_ctx ) @property def environment(self) -> GUIEnvironmentContext: """This is a property for the current environment, access env variables like this:: ctx.environment.get_timestamp() Raises RuntimeError when not available. """ if self._ui_ctx is not None: return self._ui_ctx raise RuntimeError("Environment Context not available") class ActionExecutionContext(GObject.GObject, pretty.OutputMixin): # type: ignore """The ActionExecutionContext (ACE) keeps track of its nested invocation, so that we can catch the results of commands executed inside other commands. The delegation mechanism allows a user of the ACE to indicate that the result of the command should be passed on from the earlier (more nested) invocation. ActionExecutionContext is singleton; to get it use `ActionExecutionContext.instance()` or `default_action_execution_context()`. command-result (result_type, result) Emitted when a command is carried out, with its resulting value """ __gtype_name__ = "ActionExecutionContext" _instance: ActionExecutionContext | None = None @classmethod def instance(cls) -> ActionExecutionContext: if cls._instance is None: cls._instance = ActionExecutionContext() assert cls._instance return cls._instance def __init__(self) -> None: GObject.GObject.__init__(self) self._task_runner = task.TaskRunner(end_on_finish=False) self._nest_level = 0 self._delegate = False self._command_counter = itertools.count() self.last_command_id = -1 self.last_command: CmdTuple | None = None self._last_executed_command: CmdTuple | None = None self.last_results: collections.deque[ty.Any] = collections.deque( [], _MAX_LAST_RESULTS ) @contextlib.contextmanager def _nesting(self): try: self._nest_level += 1 self._delegate = False yield finally: self._nest_level -= 1 @property def _is_nested(self) -> bool: return bool(self._nest_level) @contextlib.contextmanager def _error_conversion(self, cmdtuple: CmdTuple) -> ty.Any: try: yield except OperationError: self._do_error_conversion(cmdtuple, sys.exc_info()) def _do_error_conversion( self, cmdtuple: CmdTuple, exc_info: ExecInfo ) -> None: if not self._operation_error(exc_info, cmdtuple): raise exc_info[1] # type: ignore _etype, value, traceback = exc_info raise ActionExecutionError(value).with_traceback(traceback) def _get_async_token(self) -> Token: """Get an action execution for current execution Return a token for the currently active command execution. The token must be used for posting late results or late errors. """ assert self.last_command_id is not None return (self.last_command_id, self._last_executed_command) def make_execution_token( self, ui_ctx: GUIEnvironmentContext | None ) -> ExecutionToken: """Return an ExecutionToken for @self and @ui_ctx.""" return ExecutionToken(self, self._get_async_token(), ui_ctx) def _operation_error( self, exc_info: ExecInfo, cmdtuple: CmdTuple ) -> int | None: """Error when executing action - show notification to the user. Nested error are ignored.""" if self._is_nested: return None _etype, value, _tb = exc_info _obj, action, _iobj = cmdtuple # TRANS: When an error occurs in an action to be carried out, # TRANS: then this is the heading of the error notification return uiutils.show_notification( _("Could not to carry out '%s'") % action, str(value), icon_name="kupfer", ) def register_late_error( self, token: Token, exc_info: ExecInfo | BaseException | None = None ) -> None: """Register an error in exc_info. The error must be an OperationError. ActionExecutionError is raised. """ if exc_info is None: exc_info = sys.exc_info() elif isinstance(exc_info, BaseException): exc_info = (type(exc_info), exc_info, None) _command_id, cmdtuple = token assert exc_info assert cmdtuple self._do_error_conversion(cmdtuple, exc_info) def register_late_result( self, token: Token, result: ty.Any, show: bool = True, ctxenv: GUIEnvironmentContext | None = None, ) -> None: """Register a late result. Result must be a Leaf (as in result object, not factory or async). If `show`, possibly display the result to the user (show leaf). Desktop notification is always displayed when there is any result. """ self.output_debug("Late result", result, "for", token) assert token and token[1] command_id, (_ign1, action, _ign2) = token # type: ignore if result is None: raise ActionExecutionError(f"Late result from {action} was None") assert isinstance(result, (Leaf, Source)) description = res_name = str(result) if res_desc := result.get_description(): description = f"{res_name} ({res_desc})" # If only registration was requested, remove the command id info if not show: command_id = -1 result_type = _parse_late_action_result(action, result) self.output_debug( "late-command-result", command_id, result_type, result, ctxenv ) if result_type == ExecResult.NONE: return if result_type != ExecResult.REFRESH: uiutils.show_notification( _('"%s" produced a result') % action, description ) self.emit( "late-command-result", command_id, result_type, result, ctxenv ) self._append_result(result_type, result) def _append_result(self, res_type: int, result: ty.Any) -> None: if res_type == ExecResult.OBJECT: self.last_results.append(result) def run( self, obj: Leaf, action: Action, iobj: Leaf | None, delegate: bool = False, ui_ctx: GUIEnvironmentContext | None = None, ) -> tuple[ExecResult, ty.Any]: """ Activate the command (obj, action, iobj), where @iobj may be None Return a tuple (DESCRIPTION; RESULT) If a command carries out another command as part of its execution, and wishes to delegate to it, pass True for @delegate. """ self.last_command_id = next(self._command_counter) self._last_executed_command = (obj, action, iobj) if not action or not obj: raise ActionExecutionError("Primary Object and Action required") if iobj is None and action.requires_object(): raise ActionExecutionError(f"{action} requires indirect object") self.output_debug(obj, action, iobj, ui_ctx) # The execution token object for the current invocation execution_token = self.make_execution_token(ui_ctx) with self._error_conversion((obj, action, iobj)), self._nesting(): ret = activate_action(execution_token, obj, action, iobj) # remember last command, but not delegated commands. if not delegate: self.last_command = self._last_executed_command # Delegated command execution was previously requested: we take # the result of the nested execution context if self._delegate: assert not ret or isinstance(ret, tuple) res, ret = ty.cast("tuple[ExecResult, ty.Any]", ret) return self._return_result(res, ret, ui_ctx) assert not ret or isinstance(ret, (Source, Leaf, task.Task)) res = parse_action_result(action, ret) if res == ExecResult.ASYNC: # Register the task then "clear" the result self.output_debug("Registering async task", ret) assert isinstance(ret, task.Task) self._task_runner.add_task(ret) res, ret = ExecResult.NONE, None # Delegated command execution was requested: we pass # through the result of the action to the parent execution context if delegate and self._is_nested: self._delegate = True return self._return_result(res, ret, ui_ctx) def _return_result( self, res: ExecResult, ret: ty.Any, ui_ctx: GUIEnvironmentContext | None, ) -> tuple[ExecResult, ty.Any]: if not self._is_nested: self._append_result(res, ret) self.emit("command-result", res, ret, ui_ctx) return res, ret def combine_action_result_multiple( self, action: Action, retvals: ty.Iterable[tuple[ExecResult, ActionResult] | ActionResult], ) -> tuple[ExecResult, ActionResult] | ActionResult: """ When delegate is False `retvals` is list of `ActionResult` and function return `ActionResult`. When delegate it True `retvals` is list of (ExecResult, ActionResult) and function return (ExecResult, ActionResult) """ self.output_debug( "Combining", action, retvals, f"delegate={self._delegate}" ) retvals_not_empty = filter(None, retvals) if self._delegate: return self._combine_action_result_multiple_delegate( action, ty.cast( "list[tuple[ExecResult, ActionResult]]", retvals_not_empty ), ) return self._combine_action_result_multiple_non_delegate( action, ty.cast("list[ActionResult]", retvals_not_empty) ) def _combine_action_result_multiple_non_delegate( self, action: Action, retvals: ty.Iterable[ActionResult], ) -> ActionResult: values: list[ActionResult] = [] res = ExecResult.NONE for ret in retvals: res_type = parse_action_result(action, ret) if res_type != ExecResult.NONE: values.append(ret) res = res_type return self._make_retvalue(res, values) def _combine_action_result_multiple_delegate( self, action: Action, retvals: list[tuple[ExecResult, ActionResult]], ) -> tuple[ExecResult, ActionResult]: # Re-parse result values resmap: dict[ExecResult, list[ActionResult]] = collections.defaultdict( list ) for res_type, ret_obj in retvals: if res_type != ExecResult.NONE: resmap[res_type].append(ret_obj) # register tasks if tasks := resmap.pop(ExecResult.ASYNC, None): self._make_retvalue(ExecResult.ASYNC, tasks) if len(resmap) == 1: # Return the only of the Source or Object case key, values = resmap.popitem() return key, self._make_retvalue(key, values) if len(resmap) > 1: # Put the source in a leaf and return a multiple leaf source = self._make_retvalue( ExecResult.SOURCE, resmap[ExecResult.SOURCE] ) assert isinstance(source, Source) objects = resmap[ExecResult.OBJECT] objects.append(SourceLeaf(source)) return ExecResult.OBJECT, self._make_retvalue( ExecResult.OBJECT, objects ) return ExecResult.NONE, None def _make_retvalue( self, res: ExecResult, values: list[ActionResult] ) -> ActionResult: """Construct a return value for type res. If Result is source or object construct MultpileSource/MultipleLeaf for many results or simple return first result. For async result register async task. """ if res == ExecResult.SOURCE: return ( values[0] if len(values) == 1 else MultiSource(ty.cast("ty.Collection[Source]", values)) ) if res == ExecResult.OBJECT: return values[0] if len(values) == 1 else MultipleLeaf(values) if res == ExecResult.ASYNC: # Register all tasks now, and return None upwards for task_ in values: assert isinstance(task_, task.Task) self.output_debug("Registering async task", task_) self._task_runner.add_task(task_) return None # Signature: Action result type, action result, gui_context GObject.signal_new( "command-result", ActionExecutionContext, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_INT, GObject.TYPE_PYOBJECT, GObject.TYPE_PYOBJECT), ) # Signature: Command ID, Action result type, action result, gui_context GObject.signal_new( "late-command-result", ActionExecutionContext, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, ( GObject.TYPE_INT, GObject.TYPE_INT, GObject.TYPE_PYOBJECT, GObject.TYPE_PYOBJECT, ), ) ## Get ActionExecutionContext instance default_action_execution_context = ActionExecutionContext.instance # pylint: disable=too-few-public-methods @ty.runtime_checkable class ActionActivateFunc(ty.Protocol): def __call__( self, leaf: Leaf, iobj: Leaf | None = None, ctx: ExecutionToken | None = None, ) -> ActionResult: ... # pylint: disable=too-few-public-methods @ty.runtime_checkable class ActionActivateMultipleFunc(ty.Protocol): def __call__( self, leaf: ty.Iterable[Leaf], iobj: ty.Iterable[Leaf | None] | None = None, ctx: ExecutionToken | None = None, ) -> ActionResult: ... def activate_action( context: ExecutionToken | None, obj: Leaf, action: Action, iobj: Leaf | None, ) -> tuple[ExecResult, ActionResult] | ActionResult: """Activate @action in simplest manner""" if not action.wants_context(): context = None if not is_multiple_leaf(obj) and not is_multiple_leaf(iobj): return _activate_action_single(obj, action, iobj, context) return _activate_action_multiple(obj, action, iobj, context) def _activate_action_single( obj: Leaf, action: Action, iobj: Leaf | None, ctx: ExecutionToken | None ) -> tuple[ExecResult, ActionResult] | ActionResult: func: ActionActivateFunc = action.activate if ctx: # set context to action.activate call func = partial(func, ctx=ctx) if action.requires_object(): return func(obj, iobj) return func(obj) def _activate_action_multiple( obj: Leaf, action: Action, iobj: Leaf | None, ctx: ExecutionToken | None ) -> tuple[ExecResult, ActionResult] | ActionResult | None: objs = get_leaf_members(obj) if not hasattr(action, "activate_multiple"): iobjs = (None,) if iobj is None else get_leaf_members(iobj) return _activate_action_multiple_multiplied(objs, action, iobjs, ctx) func: ActionActivateMultipleFunc = action.activate_multiple if ctx: func = partial(func, ctx=ctx) if action.requires_object(): iobjs = (None,) if iobj is None else get_leaf_members(iobj) return func(objs, iobjs) return func(objs) def _activate_action_multiple_multiplied( objs: ty.Iterable[Leaf], action: Action, iobjs: ty.Iterable[Leaf | None], ctx: ExecutionToken | None, ) -> tuple[ExecResult, ActionResult] | ActionResult | None: """ Multiple dispatch by "multiplied" invocation of the simple activation When action is delegated return (ExecResult, ActionResult), otherwise return ActionResult """ rets = [ _activate_action_single(leaf, action, item, ctx) for leaf in objs for item in iobjs ] actx = default_action_execution_context() return actx.combine_action_result_multiple(action, rets) def parse_action_result(action: Action, ret: ActionResult) -> ExecResult: """Return result type for @action and return value @ret""" if ret is ActionResultRefresh: return ExecResult.REFRESH if not ret or (hasattr(ret, "is_valid") and not ret.is_valid()): return ExecResult.NONE # handle actions returning "new contexts" res = ExecResult.NONE if action.is_factory(): res = ExecResult.SOURCE if action.has_result(): res = ExecResult.OBJECT elif action.is_async(): res = ExecResult.ASYNC return res def _parse_late_action_result(action: Action, ret: ty.Any) -> int: # Late result is assumed to be a Leaf (Object) result # by default for backward compat. # # It is also allowed to be a Source if ret is ActionResultRefresh: return ExecResult.REFRESH if not ret or (hasattr(ret, "is_valid") and not ret.is_valid()): return ExecResult.NONE if isinstance(ret, Source): return ExecResult.SOURCE return ExecResult.OBJECT kupfer-328/kupfer/core/datactrl.py000066400000000000000000000722471500175051100172670ustar00rootroot00000000000000"""DataController""" from __future__ import annotations import itertools import os import sys import typing as ty from collections import defaultdict from contextlib import suppress from enum import IntEnum from pathlib import Path from gi.repository import GLib, GObject from kupfer.core import ( commandexec, execfile, learn, pluginload, qfurl, search, settings, ) from kupfer.core.panes import ( LeafPane, Pane, PrimaryActionPane, SearchContext, SecondaryObjectPane, ) from kupfer.core.sources import get_source_controller from kupfer.obj import compose from kupfer.obj import objects as kobjects from kupfer.obj.base import ( Action, ActionGenerator, AnySource, KupferObject, Leaf, Source, TextSource, ) from kupfer.obj.filesrc import DirectorySource, FileSource from kupfer.support import pretty, scheduler if ty.TYPE_CHECKING: from kupfer.core.search import Rankable from kupfer.support.types import ExecInfo from kupfer.ui.uievents import GUIEnvironmentContext __all__ = ("DataController", "PaneMode", "PaneSel") DATA_SAVE_INTERVAL_S = 3660 # "Enums" # Which pane class PaneSel(IntEnum): SOURCE = 1 ACTION = 2 OBJECT = 3 # In two-pane or three-pane mode class PaneMode(IntEnum): # two-panels mode: source -> action SOURCE_ACTION = 1 # three panels mode: source -> action -> indirect object SOURCE_ACTION_OBJECT = 2 # two-panels mode: action -> object (source); in this mode we cheat - # for specific leaf (ActionLeaf) which have only one action (ExecuteAction) # we by default select this action and hide panel with actions, so user # must select indirect object. ACTION_OBJECT = 3 # pylint: disable=too-many-public-methods class DataController(GObject.GObject, pretty.OutputMixin): # type:ignore """Sources <-> Actions controller. The data controller must be created before main program commences, so it can register itself at the scheduler correctly. """ _instance: DataController | None = None @classmethod def instance(cls) -> DataController: """Get instance of DataController.""" if cls._instance is None: cls._instance = DataController() return cls._instance __gtype_name__ = "DataController" def __init__(self): super().__init__() self._source_pane = LeafPane() self._source_pane.connect("new-source", self._on_new_source) self._object_pane = SecondaryObjectPane() self._object_pane.connect("new-source", self._on_new_source) self._action_pane = PrimaryActionPane() for pane, ctl in self._all_pane_ctl(): ctl.connect("search-result", self._on_pane_search_result, pane) self._mode: PaneMode | None = None self._search_ids = itertools.count(1) self._latest_interaction = -1 self._execution_context = ( commandexec.default_action_execution_context() ) self._execution_context.connect( "command-result", self._on_command_execution_result ) self._execution_context.connect( "late-command-result", self._on_late_command_execution_result ) self._save_data_timer = scheduler.Timer() sch = scheduler.get_scheduler() sch.connect("load", self._on_load) sch.connect("display", self._on_display) sch.connect("finish", self._on_finish) def _get_panectl(self, pane: PaneSel) -> Pane[Leaf] | Pane[Action]: if pane == PaneSel.SOURCE: return self._source_pane if pane == PaneSel.ACTION: return self._action_pane if pane == PaneSel.OBJECT: return self._object_pane raise ValueError(f"invalid pane {pane}") def _all_pane_ctl( self, ) -> ty.Iterator[tuple[PaneSel, Pane[Leaf] | Pane[Action]]]: yield PaneSel.SOURCE, self._source_pane yield PaneSel.ACTION, self._action_pane yield PaneSel.OBJECT, self._object_pane def _register_text_sources( self, plugin_id: str, srcs: ty.Iterable[TextSource] ) -> None: """Pass in text sources as @srcs we register text sources""" sctr = get_source_controller() sctr.add_text_sources(plugin_id, srcs) def _register_action_decorators( self, plugin_id: str, actions: list[Action] ) -> None: # Keep a mapping: Decorated Leaf Type -> List of actions decorate_types: defaultdict[type[Leaf], list[Action]] = defaultdict( list ) for action in actions: for appl_type in action.item_types(): decorate_types[appl_type].append(action) if not decorate_types: return sctr = get_source_controller() sctr.add_action_decorators(plugin_id, decorate_types) def _register_content_decorators( self, plugin_id: str, contents: ty.Collection[ty.Type[Source]] ) -> None: """Register the sequence of classes @contents as potential content decorators. Classes not conforming to the decoration protocol (most importantly, ``.decorates_type()``) will be skipped.""" # Keep a mapping: # Decorated Leaf Type -> Set of content decorator types decorate_item_types: defaultdict[ ty.Type[Leaf], set[ty.Type[Source]] ] = defaultdict(set) for content in contents: with suppress(AttributeError): applies = content.decorates_type() # type: ignore decorate_item_types[applies].add(content) if not decorate_item_types: return sctr = get_source_controller() sctr.add_content_decorators(plugin_id, decorate_item_types) def _register_action_generators( self, plugin_id: str, generators: ty.Iterable[ActionGenerator] ) -> None: sctr = get_source_controller() for generator in generators: sctr.add_action_generator(plugin_id, generator) def _on_load(self, _sched: ty.Any) -> None: """Begin Data Controller work when we get application 'load' signal. Load the data model from saved configuration and caches """ setctl = settings.get_settings_controller() setctl.connect("plugin-enabled-changed", self._on_plugin_enabled) setctl.connect( "plugin-toplevel-changed", self._on_plugin_catalog_changed ) self._load_all_plugins() dir_src, indir_src = self._get_directory_sources() sctr = get_source_controller() sctr.add(None, dir_src, toplevel=True) sctr.add(None, indir_src, toplevel=False) sctr.initialize() learn.load() def _on_display(self, _sched: ty.Any) -> None: self._reload_source_root() self._save_data_timer.set(DATA_SAVE_INTERVAL_S, self._save_data) def _get_directory_sources( self, ) -> tuple[tuple[DirectorySource, ...], tuple[DirectorySource, ...]]: """Return a tuple of dir_sources, indir_sources for directory sources directly included and for catalog inclusion respectively.""" setctl = settings.get_settings_controller() source_config = setctl.get_config dir_depth = source_config("DeepDirectories", "Depth") def file_source(opt, depth=1): abs_path = os.path.abspath(os.path.expanduser(opt)) return FileSource([abs_path], depth) indir_sources = itertools.chain( ( DirectorySource(item, toplevel=True) for item in setctl.get_directories(False) if Path(item).is_dir() ), ( file_source(item, dir_depth) for item in source_config("DeepDirectories", "Catalog") ), ) dir_sources = itertools.chain( ( DirectorySource(item, toplevel=True) for item in setctl.get_directories(True) if Path(item).is_dir() ), ( file_source(item, dir_depth) for item in source_config("DeepDirectories", "Direct") ), ) return tuple(dir_sources), tuple(indir_sources) def _load_all_plugins(self): """Insert all plugin sources into the catalog.""" # pylint: disable=import-outside-toplevel from kupfer.core import plugins setctl = settings.get_settings_controller() for item in sorted(plugins.get_plugin_ids()): if setctl.get_plugin_enabled(item): sources_ = self._load_plugin(item) self._insert_sources(item, sources_, initialize=False) def _load_plugin(self, plugin_id: str) -> set[Source]: """Load @plugin_id, register all its Actions, Content and TextSources. Return its sources.""" with pluginload.exception_guard(plugin_id): plugin = pluginload.load_plugin(plugin_id) self._register_text_sources(plugin_id, plugin.text_sources) self._register_action_decorators( plugin_id, plugin.action_decorators ) self._register_content_decorators( plugin_id, plugin.content_decorators ) self._register_action_generators( plugin_id, plugin.action_generators ) return set(plugin.sources) return set() def _on_plugin_enabled( self, _setctl: ty.Any, plugin_id: str, enabled: bool | int ) -> None: """Enable plugin, load if necessary.""" # pylint: disable=import-outside-toplevel from kupfer.core import plugins if enabled and not plugins.is_plugin_loaded(plugin_id): srcs = self._load_plugin(plugin_id) self._insert_sources(plugin_id, srcs, initialize=True) # force update sources after plugin enable for src in srcs: src.mark_for_update() elif not enabled: self._remove_plugin(plugin_id) def _remove_plugin(self, plugin_id: str) -> None: sctl = get_source_controller() if sctl.remove_objects_for_plugin_id(plugin_id): self._reload_source_root() pluginload.remove_plugin(plugin_id) def _reload_source_root(self) -> None: """Reload items from root sources.""" self.output_debug("Reloading source root") sctl = get_source_controller() if sctl.root: self._source_pane.source_rebase(sctl.root) def _on_plugin_catalog_changed( self, _setctl: ty.Any, _plugin_id: str, _toplevel: ty.Any ) -> None: self._reload_source_root() def _insert_sources( self, plugin_id: str, sources_: ty.Iterable[Source], initialize: bool = True, ) -> None: """Insert `sources_` into catalog. `Initialize` when True, initialize plugin and reload catalog root.""" if not sources_: return sctl = get_source_controller() setctl = settings.get_settings_controller() for src in sources_: is_toplevel = setctl.get_source_is_toplevel(plugin_id, src) sctl.add( plugin_id, (src,), toplevel=is_toplevel, initialize=initialize ) if initialize: self._reload_source_root() def _on_finish(self, _sched: ty.Any) -> None: "Close down the data model, save user data, and write caches to disk" get_source_controller().finalize() self._save_data(final_invocation=True) self.output_info("Saving cache...") get_source_controller().save_cache() def _save_data(self, final_invocation: bool = False) -> None: """Save Learning data and User's configuration data in sources (Recurring timer).""" self.output_info("Saving data...") learn.save() get_source_controller().save_data() if not final_invocation: self._save_data_timer.set(DATA_SAVE_INTERVAL_S, self._save_data) def _on_new_source( self, ctr: Pane[KupferObject], src: AnySource | None, select: ty.Any ) -> None: """Update leaf or secondary object panel on sources changes.""" if not src: return if ctr is self._source_pane: pane = PaneSel.SOURCE elif ctr is self._object_pane: pane = PaneSel.OBJECT else: raise AttributeError root = ctr.is_at_source_root() self.emit("source-changed", pane, src, root, select) def reset(self) -> None: self._source_pane.reset() self._action_pane.reset() self._object_pane.reset() def soft_reset(self, pane: PaneSel) -> AnySource | None: if pane == PaneSel.ACTION: return None panectl: LeafPane = self._get_panectl(pane) return panectl.soft_reset() def cancel_search(self, pane: PaneSel | None = None) -> None: """Cancel any outstanding search, or the search for @pane""" panes = ( (pane,) if pane else (PaneSel.SOURCE, PaneSel.ACTION, PaneSel.OBJECT) ) for pane_ in panes: ctl = self._get_panectl(pane_) if ctl.outstanding_search > 0: GLib.source_remove(ctl.outstanding_search) ctl.outstanding_search = -1 def search( self, pane: PaneSel, key: str = "", context: str | None = None, interactive: bool = False, lazy: bool = False, text_mode: bool = False, ) -> None: """Search: Register the search method in the event loop Will search in @pane's base using @key, promising to return @context in the notification about the result. if @interactive, the search result will return immediately if @lazy, will slow down search result reporting """ self.cancel_search(pane) self._latest_interaction = self._execution_context.last_command_id ctl = self._get_panectl(pane) ctl.outstanding_search_id = next(self._search_ids) wrapcontext = (ctl.outstanding_search_id, context) if interactive: ctl.search(key, wrapcontext, text_mode) return timeout = 300 if lazy else 0 if not key else 50 // len(key) def ctl_search(*args): ctl.outstanding_search = -1 return ctl.search(*args) ctl.outstanding_search = GLib.timeout_add( timeout, ctl_search, key, wrapcontext, text_mode ) def _on_pane_search_result( self, panectl: Pane[ty.Any], match: Rankable | None, match_iter: ty.Iterable[Rankable], wrapcontext: SearchContext, pane: PaneSel, ) -> bool: search_id, context = wrapcontext if search_id == panectl.outstanding_search_id: self.emit("search-result", pane, match, match_iter, context) return False self.output_debug("Skipping late search", match, context) return True def select(self, pane: PaneSel, item: Leaf | Action | None) -> None: """Select @item in @pane to self-update relevant places""" # If already selected, do nothing panectl = self._get_panectl(pane) if item == panectl.get_selection(): return self.cancel_search() if pane == PaneSel.SOURCE: assert isinstance(panectl, LeafPane) assert item is None or isinstance(item, Leaf) panectl.select(item) # populate actions citem = self._get_pane_object_composed(self._source_pane) self._action_pane.set_item(citem) self.search(PaneSel.ACTION, interactive=True) # change mode according to selected in first panel leaf newmode = self._mode if isinstance(item, kobjects.ActionLeaf): newmode = PaneMode.ACTION_OBJECT elif self._mode == PaneMode.ACTION_OBJECT: newmode = PaneMode.SOURCE_ACTION if newmode != self._mode: self._mode = newmode self.emit("mode-changed", self._mode, item) if self._mode == PaneMode.SOURCE_ACTION_OBJECT: self.object_stack_clear(PaneSel.OBJECT) self._populate_third_pane() elif pane == PaneSel.ACTION: assert isinstance(panectl, PrimaryActionPane) assert item is None or isinstance(item, Action), str(type(item)) panectl.select(item) self.object_stack_clear(PaneSel.OBJECT) if item and item.requires_object(): newmode = PaneMode.SOURCE_ACTION_OBJECT else: newmode = PaneMode.SOURCE_ACTION if newmode != self._mode: self._mode = newmode self.emit("mode-changed", self._mode, item) if self._mode == PaneMode.SOURCE_ACTION_OBJECT: self._populate_third_pane() else: # OBJECT assert isinstance(panectl, SecondaryObjectPane) assert item is None or isinstance(item, Leaf) panectl.select(item) def _populate_third_pane(self) -> None: citem = self._get_pane_object_composed(self._source_pane) action = self._action_pane.get_selection() assert isinstance(action, Action) self._object_pane.set_item_and_action(citem, action) self.search(PaneSel.OBJECT, lazy=True) def get_can_enter_text_mode(self, pane: PaneSel) -> bool: panectl = self._get_panectl(pane) return panectl.get_can_enter_text_mode() def get_should_enter_text_mode(self, pane: PaneSel) -> bool: panectl = self._get_panectl(pane) return panectl.get_should_enter_text_mode() def validate(self) -> None: """Check if all selected items are still valid (for example after being spawned again, old item still focused). This will trigger .select() with None if items are not valid.. """ def valid_check(obj): return not (hasattr(obj, "is_valid") and not obj.is_valid()) for pane, panectl in self._all_pane_ctl(): sel = panectl.get_selection() if not valid_check(sel): self.emit("pane-reset", pane, None) self.select(pane, None) if self._has_object_stack(pane): new_stack = list(filter(valid_check, panectl.object_stack)) if new_stack != panectl.object_stack: self._set_object_stack(pane, new_stack) def browse_up(self, pane: PaneSel) -> bool: """Try to browse up to previous sources, from current source""" if pane == PaneSel.SOURCE: return self._source_pane.browse_up() if pane == PaneSel.OBJECT: return self._object_pane.browse_up() return False def browse_down(self, pane: PaneSel, alternate: bool = False) -> None: """Browse into @leaf if it's possible and save away the previous sources in the stack. If @alternate, use the Source's alternate method""" if pane == PaneSel.ACTION: return # record used object if we browse down panectl = self._get_panectl(pane) sel, key = panectl.get_selection(), panectl.get_latest_key() if panectl.browse_down(alternate=alternate): learn.record_search_hit(sel, key) def activate(self, ui_ctx: GUIEnvironmentContext) -> None: """Activate current selection. @ui_ctx: GUI environment context object """ leaf, action, sobject = self._get_current_command_objects() # register search to learning database learn.record_search_hit(leaf, self._source_pane.get_latest_key()) learn.record_search_hit(action, self._action_pane.get_latest_key()) if sobject and self._mode == PaneMode.SOURCE_ACTION_OBJECT: learn.record_search_hit( sobject, self._object_pane.get_latest_key() ) if not leaf or not action: return learn.record_action_activations(action, leaf) try: ctx = self._execution_context res, _ret = ctx.run(leaf, action, sobject, ui_ctx=ui_ctx) except commandexec.ActionExecutionError: self.output_exc() return if not res.is_sync: self.emit("launched-action", leaf, action, sobject) def execute_file( self, filepath: str, ui_ctx: GUIEnvironmentContext, on_error: ty.Callable[[ExecInfo], None], ) -> bool: """Execute a .kfcom file""" ctx = self._execution_context try: cmd_objs = execfile.parse_kfcom_file(filepath) assert len(cmd_objs) <= 3 # noqa:PLR2004 ctx.run(*cmd_objs, ui_ctx=ui_ctx) # type: ignore return True except commandexec.ActionExecutionError: self.output_exc() except execfile.ExecutionError: on_error(sys.exc_info()) return False def _insert_object(self, pane: PaneSel, obj: Leaf) -> None: """Insert @obj in @pane: prepare the object, then emit pane-reset""" if pane == PaneSel.SOURCE: self._decorate_object(obj) self.emit("pane-reset", pane, search.wrap_rankable(obj)) def _decorate_object(self, *objects: Leaf) -> None: sctl = get_source_controller() for obj in objects: sctl.decorate_object(obj) def insert_objects(self, pane: PaneSel, objects: list[Leaf]) -> None: """Select @objects in @pane""" if pane != PaneSel.SOURCE: raise ValueError("Can only insert in first pane") self._decorate_object(*objects[:-1]) self._set_object_stack(pane, objects[:-1]) self._insert_object(pane, objects[-1]) def _on_command_execution_result( self, ctx: commandexec.ActionExecutionContext, result_type: commandexec.ExecResult | int, ret: ty.Any, uictx: GUIEnvironmentContext, ) -> None: result_type = commandexec.ExecResult(result_type) if result_type == commandexec.ExecResult.SOURCE: self.object_stack_clear_all() self._source_pane.push_source(ret) elif result_type == commandexec.ExecResult.OBJECT: self.object_stack_clear_all() self._insert_object(PaneSel.SOURCE, ret) elif result_type == commandexec.ExecResult.REFRESH: pass else: return self.emit("command-result", result_type, uictx) def _on_late_command_execution_result( self, ctx: commandexec.ActionExecutionContext, id_: int, result_type: commandexec.ExecResult | int, ret: ty.Any, uictx: GUIEnvironmentContext, ) -> None: """Receive late command result""" if self._latest_interaction < id_: self._on_command_execution_result(ctx, result_type, ret, uictx) def find_object(self, url: str) -> None: """Find object with URI @url and select it in the first pane""" sctrl = get_source_controller() qfu = qfurl.Qfurl(url=url) found = qfu.resolve_in_catalog(sctrl.get_sources()) if found and found != self._source_pane.get_selection(): self._insert_object(PaneSel.SOURCE, found) def mark_as_default(self, pane: PaneSel) -> None: """Make the object selected on @pane as default for the selection in previous pane.""" if pane in (PaneSel.SOURCE, PaneSel.OBJECT): raise RuntimeError("Setting default on pane 1 or 3 not supported") obj = ty.cast("Leaf", self._source_pane.get_selection()) act = ty.cast("Action", self._action_pane.get_selection()) assert obj and act learn.set_correlation(act, obj) def get_object_has_affinity(self, pane: PaneSel) -> bool: """Return ``True`` if we have any recorded affinity for the object selected in @pane""" panectl = self._get_panectl(pane) if selection := panectl.get_selection(): assert isinstance(selection, Leaf) return learn.get_object_has_affinity(selection) return False def erase_object_affinity(self, pane: PaneSel) -> None: """Erase all learned and configured affinity for the selection of @pane.""" panectl = self._get_panectl(pane) if selection := panectl.get_selection(): assert isinstance(selection, Leaf) learn.erase_object_affinity(selection) def compose_selection(self) -> None: leaf, action, iobj = self._get_current_command_objects() if leaf is None: return self.object_stack_clear_all() assert action obj = compose.ComposedLeaf(leaf, action, iobj) self._insert_object(PaneSel.SOURCE, obj) def _get_pane_object_composed(self, pane: Pane[Leaf]) -> Leaf | None: objects: list[Leaf] = list(pane.object_stack) sel = pane.get_selection() if sel and sel not in objects: objects.append(sel) if not objects: return None if len(objects) == 1: return objects[0] return compose.MultipleLeaf(objects) def _get_current_command_objects( self, ) -> tuple[Leaf, Action, Leaf | None] | tuple[None, None, None]: """Return a tuple of current (obj, action, iobj).""" objects = self._get_pane_object_composed(self._source_pane) action: Action | None = self._action_pane.get_selection() if objects is None or action is None: return (None, None, None) iobjects = self._get_pane_object_composed(self._object_pane) if self._mode in ( PaneMode.SOURCE_ACTION_OBJECT, PaneMode.ACTION_OBJECT, ): if not iobjects: return (None, None, None) else: iobjects = None return (objects, action, iobjects) def _has_object_stack(self, pane: PaneSel) -> bool: return pane in (PaneSel.SOURCE, PaneSel.OBJECT) def _set_object_stack(self, pane: PaneSel, newstack: list[Leaf]) -> None: panectl = self._get_panectl(pane) panectl.object_stack = newstack self.emit("object-stack-changed", pane) def object_stack_push(self, pane: PaneSel, object_: KupferObject) -> bool: """Push @object_ onto the stack.""" if not self._has_object_stack(pane): return False panectl = self._get_panectl(pane) if object_ not in panectl.object_stack: panectl.object_stack_push(object_) self.emit("object-stack-changed", pane) return True def object_stack_pop(self, pane: PaneSel) -> bool: if not self._has_object_stack(pane): return False panectl = self._get_panectl(pane) obj = panectl.object_stack_pop() self._insert_object(pane, obj) self.emit("object-stack-changed", pane) return True def object_stack_clear(self, pane: PaneSel) -> None: if not self._has_object_stack(pane): return panectl = self._get_panectl(pane) panectl.object_stack.clear() self.emit("object-stack-changed", pane) def object_stack_clear_all(self) -> None: """Clear the object stack for all panes.""" # action don't have stack # self.object_stack_clear(PaneSel.ACTION) self.object_stack_clear(PaneSel.OBJECT) self.object_stack_clear(PaneSel.SOURCE) def get_object_stack(self, pane: PaneSel) -> list[Leaf]: if not self._has_object_stack(pane): return [] panectl = self._get_panectl(pane) assert isinstance(panectl, (LeafPane, SecondaryObjectPane)) return panectl.object_stack # pane cleared or set with new item # pane, item GObject.signal_new( "pane-reset", DataController, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, ( GObject.TYPE_INT, GObject.TYPE_PYOBJECT, ), ) # pane, match, iter to matches, context GObject.signal_new( "search-result", DataController, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, ( GObject.TYPE_INT, GObject.TYPE_PYOBJECT, GObject.TYPE_PYOBJECT, GObject.TYPE_PYOBJECT, ), ) GObject.signal_new( "source-changed", DataController, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (int, object, bool, GObject.TYPE_PYOBJECT), ) # mode, None(?) GObject.signal_new( "mode-changed", DataController, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, ( GObject.TYPE_INT, GObject.TYPE_PYOBJECT, ), ) # object stack update signal # arguments: pane GObject.signal_new( "object-stack-changed", DataController, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_INT,), ) # when an command returned a result # arguments: result type, gui_context GObject.signal_new( "command-result", DataController, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_INT, GObject.TYPE_PYOBJECT), ) # when an action was launched # arguments: leaf, action, secondary leaf GObject.signal_new( "launched-action", DataController, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_PYOBJECT, GObject.TYPE_PYOBJECT, GObject.TYPE_PYOBJECT), ) kupfer-328/kupfer/core/execfile.py000066400000000000000000000074271500175051100172530ustar00rootroot00000000000000import hashlib import os import pickle import typing as ty from pathlib import Path from gi.repository import GdkPixbuf, Gio, GLib from kupfer import puid from kupfer.obj.base import KupferObject from kupfer.support import conspickle, pretty if ty.TYPE_CHECKING: from gettext import gettext as _ KUPFER_COMMAND_SHEBANG = b"#!/usr/bin/env kupfer-exec\n" __all__ = ( "ExecutionError", "parse_kfcom_file", "save_to_file", "update_icon", ) class ExecutionError(Exception): pass def parse_kfcom_file(filepath: str) -> tuple[ty.Any, ...]: """Extract the serialized command inside @filepath The file must be executable (comparable to a shell script) >>> parse_kfcom_file(__file__) # doctest: +ELLIPSIS Traceback (most recent call last): ... ExecutionError: ... (not executable) Return commands triple """ if not os.access(filepath, os.X_OK): raise ExecutionError( _('No permission to run "%s" (not executable)') % GLib.filename_display_basename(filepath) ) data = Path(filepath).read_bytes() # strip shebang away if data.startswith(b"#!") and b"\n" in data: _shebang, data = data.split(b"\n", 1) try: id_ = conspickle.BasicUnpickler.loads(data) command_object = puid.resolve_unique_id(id_) except pickle.UnpicklingError as err: raise ExecutionError(f"Could not parse: {err}") from err except Exception as err: raise ExecutionError( f'"{os.path.basename(filepath)}" is not a saved command' ) from err if command_object is None: raise ExecutionError( _('Command in "%s" is not available') % GLib.filename_display_basename(filepath) ) try: return tuple(command_object.object) # type: ignore except (AttributeError, TypeError) as exe: raise ExecutionError( f'"{os.path.basename(filepath)}" is not a saved command' ) from exe finally: GLib.idle_add(update_icon, command_object, filepath) def save_to_file(command_leaf: ty.Any, filename: str) -> None: ofd = os.open(filename, os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0o777) with os.fdopen(ofd, "wb") as wfile: wfile.write(KUPFER_COMMAND_SHEBANG) pickle.dump(puid.get_unique_id(command_leaf), wfile, protocol=3) def _write_thumbnail(gfile: Gio.File, pixbuf: GdkPixbuf.Pixbuf) -> Path: uri = gfile.get_uri() hashname = hashlib.md5(uri.encode("utf-8")).hexdigest() thumb_dir = Path("~/.thumbnails/normal").expanduser() thumb_dir.mkdir(mode=0o700, parents=True, exist_ok=True) thumb_filename = thumb_dir.joinpath(hashname + ".png") pixbuf.savev(str(thumb_filename), "png", [], []) return thumb_filename def update_icon(kobj: KupferObject, filepath: str) -> None: """Give @filepath a custom icon taken from @kobj""" icon_key = "metadata::custom-icon" gfile = Gio.File.new_for_path(filepath) finfo = gfile.query_info(icon_key, Gio.FileQueryInfoFlags.NONE, None) custom_icon_uri = finfo.get_attribute_string(icon_key) if ( custom_icon_uri and Gio.File.new_for_uri(custom_icon_uri).query_exists() ): return namespace = gfile.query_writable_namespaces() # FileAttributeInfoList if namespace.n_infos > 0: pretty.print_debug(__name__, "Updating icon for", filepath) thumb_filename = _write_thumbnail(gfile, kobj.get_pixbuf(128)) try: gfile.set_attribute_string( icon_key, Gio.File.new_for_path(str(thumb_filename)).get_uri(), Gio.FileQueryInfoFlags.NONE, None, ) except GLib.GError: pretty.print_exc(__name__) if __name__ == "__main__": import doctest doctest.testmod() kupfer-328/kupfer/core/learn.py000066400000000000000000000273641500175051100165720ustar00rootroot00000000000000from __future__ import annotations import os import pickle import random import time import typing as ty from collections import defaultdict from pathlib import Path from kupfer import config from kupfer.support import conspickle, pretty if ty.TYPE_CHECKING: from kupfer.obj.base import Action, KupferObject, Leaf __all__ = ( "add_favorite", "erase_object_affinity", "get_correlation_bonus", "get_object_has_affinity", "get_record_score", "is_favorite", "load", "record_action_activations", "record_search_hit", "remove_favorite", "replace_favorites", "save", "set_correlation", "unregister", ) _MNEMONICS_FILENAME = "mnemonics.pickle" _CORRELATION_KEY: ty.Final = "kupfer.bonus.correlation" _ACTIVATIONS_KEY: ty.Final = "kupfer.bonus.activations" ## this is a harmless default _DEFAULT_ACTIONS: ty.Final = { "": "", "": "", } ## Favorites is set of favorites (repr(obj)) _FAVORITES: ty.Final[set[str]] = set() ## _PLUG_FAVS are favorites by plugin; to use must be merged to _FAVORITES _PLUG_FAVS: ty.Final[dict[str, list[str]]] = {} class Mnemonics: """Class to describe a collection of mnemonics as well as the total count.""" __slots__ = ("count", "last_ts_used", "mnemonics") def __init__(self) -> None: self.mnemonics: defaultdict[str, int] = defaultdict(int) self.count: int = 0 self.last_ts_used: int = 0 def __repr__(self) -> str: mnm = ", ".join(f"{m}:{c}" for m, c in self.mnemonics.items()) return ( f"<{self.__class__.__name__} cnt={self.count} mnm={mnm}" f" ts={self.last_ts_used}>" ) def increment(self, mnemonic: str | None = None) -> None: if mnemonic: self.mnemonics[mnemonic] += 1 self.count += 1 self.last_ts_used = int(time.time()) def decrement(self) -> None: """Decrement total count and the least mnemonic""" if self.mnemonics: key = min(self.mnemonics.keys(), key=lambda k: self.mnemonics[k]) if (mcount := self.mnemonics[key]) > 1: self.mnemonics[key] = mcount - 1 else: self.mnemonics.pop(key) self.count = max(self.count - 1, 0) def __bool__(self) -> bool: return self.count > 0 def __getstate__(self) -> dict[str, ty.Any]: return { "count": self.count, "mnemonics": dict(self.mnemonics), "last_ts_used": self.last_ts_used, } def __setstate__(self, state: dict[str, ty.Any]) -> None: self.count = state.get("count", 0) self.last_ts_used = state.get("last_ts_used", 0) self.mnemonics = defaultdict(int) self.mnemonics.update(state.get("mnemonics", {})) class Learning: @classmethod def unpickle_register(cls, pickle_file: str) -> dict[str, ty.Any] | None: try: pfile = Path(pickle_file).read_bytes() data = conspickle.ConservativeUnpickler.loads(pfile) assert isinstance(data, dict), "Stored object not a dict" pretty.print_debug(__name__, f"Reading from {pickle_file}") return data except OSError: pass except (pickle.PickleError, Exception) as exc: pretty.print_error(__name__, f"Error loading {pickle_file}: {exc}") return None @classmethod def pickle_register(cls, reg: dict[str, ty.Any], pickle_file: str) -> bool: ## Write to tmp then rename over for atomicity tmp_pickle_file = f"{pickle_file}.{os.getpid()}" pretty.print_debug(__name__, f"Saving to {pickle_file}") Path(tmp_pickle_file).write_bytes( pickle.dumps(reg, pickle.HIGHEST_PROTOCOL) ) os.rename(tmp_pickle_file, pickle_file) return True # under _CORRELATION_KEY is {str:str}: # map repr(action) -> repr(object) # under _ACTIVATIONS_KEY is {str:(str, int)}: # map repr(action) -> (repr(leaf),last usage timestamp) # other keys keeps Mnemonics _REGISTER: dict[ str, Mnemonics | dict[str, str] | dict[str, tuple[str, int]] ] = {} def _get_register_mnemonics() -> ty.Iterator[tuple[str, Mnemonics]]: for leaf, mne in _REGISTER.items(): if isinstance(mne, Mnemonics): yield leaf, mne def record_search_hit(obj: ty.Any, key: str | None = None) -> None: """Record that KupferObject @obj was used, with the optional search term @key recording. When key is None - skip registration (this is only valid when action is performed by accelerator).""" if key is None: return name = repr(obj) mns = _REGISTER.get(name) if not mns: mns = _REGISTER[name] = Mnemonics() assert isinstance(mns, Mnemonics) mns.increment(key or "") def get_record_score(obj: ty.Any, key: str = "") -> int: """Get total score for KupferObject @obj, bonus score is given for @key matches""" name = repr(obj) fav = 7 if name in _FAVORITES else 0 mns = _REGISTER.get(name) if mns is None: return fav assert isinstance(mns, Mnemonics) if not key: return fav + 50 - int(50.0 / (mns.count + 1)) stats = mns.mnemonics closescr = sum(val for m, val in stats.items() if m.startswith(key)) exact = stats[key] mnscore = 80 - int(50.0 / (closescr + 1) + 30.0 / (exact + 1)) return fav + mnscore def get_correlation_bonus(obj: Action, for_leaf: Leaf | None) -> int: """Get the bonus rank for @obj when used with @for_leaf.""" # favorites rval = ty.cast("dict[str, str]", _REGISTER[_CORRELATION_KEY]) repr_obj = repr(obj) repr_leaf = repr(for_leaf) if rval.get(repr_leaf) == repr_obj: return 50 raval = ty.cast("dict[str, tuple[str, int]]", _REGISTER[_ACTIVATIONS_KEY]) # bonus for last used action for object if (val := raval.get(repr_leaf)) and val[0] == repr_obj: return 20 # bonus for last used action for object type if (val := raval.get(repr(type(for_leaf)))) and val[0] == repr_obj: return 7 return 0 def set_correlation(obj: Action, for_leaf: Leaf) -> None: """Register @obj to get a bonus when used with @for_leaf.""" rval = ty.cast("dict[str, str]", _REGISTER[_CORRELATION_KEY]) rval[repr(for_leaf)] = repr(obj) def record_action_activations(obj: Action, for_leaf: Leaf) -> None: """Record action activation for leaf that boost this action in next search. Also registered is object class so using this action for similar object also get some (smaller) bonus.""" rval = ty.cast("dict[str, tuple[str, int]]", _REGISTER[_ACTIVATIONS_KEY]) repr_obj = repr(obj) now = int(time.time()) rval[repr(for_leaf)] = (repr_obj, now) rval[repr(type(for_leaf))] = (repr_obj, now) def get_object_has_affinity(obj: Leaf) -> bool: """Return if @obj has any positive score in the register.""" robj = repr(obj) return bool( _REGISTER.get(robj) or _REGISTER[_CORRELATION_KEY].get(robj) # type: ignore ) def erase_object_affinity(obj: Leaf) -> None: """Remove all track of affinity for @obj.""" robj = repr(obj) _REGISTER.pop(robj, None) _REGISTER[_CORRELATION_KEY].pop(robj, None) # type: ignore def _prune_register(goalitems: int = 500) -> None: """Try to reduce number of mnemonic to `goalitems`. in first pass try to delete oldest mnemonics with score == 1. Then, remove items with chance (len/25000) Assuming homogeneous records (all with score one) we keep: x_n+1 := x_n * (1 - chance) To this we have to add the expected number of added mnemonics per invocation, est. 10, and we can estimate a target number of saved mnemonics. """ # get all items sorted by last used time items: list[tuple[int, str, Mnemonics]] = sorted( (mne.last_ts_used, leaf, mne) for leaf, mne in _get_register_mnemonics() ) to_del = [] to_del_cnt = len(items) - goalitems for _ts, leaf, mne in items: mne.decrement() if not mne: to_del.append(leaf) to_del_cnt -= 1 if not to_del_cnt: break for leaf in to_del: _REGISTER.pop(leaf) pretty.print_debug( __name__, f"Pruned register ({len(_REGISTER)} mnemonics, {len(to_del)} oldest deleted)", ) if len(_REGISTER) <= goalitems: return random.seed() rand = random.random flux = 2.0 alpha = flux / goalitems**2 chance = min(0.1, len(_REGISTER) * alpha) to_del = [] for leaf, mne in _get_register_mnemonics(): if rand() <= chance: assert isinstance(mne, Mnemonics) mne.decrement() if not mne: to_del.append(leaf) for leaf in to_del: _REGISTER.pop(leaf) pretty.print_debug( __name__, f"Pruned register ({len(_REGISTER)} mnemonics, {len(to_del)} deleted)", ) def _purge_action_reg(goalitems: int) -> None: """Purge action usage - remove oldest items up to `goalitems` count""" raval = ty.cast("dict[str, tuple[str, int]]", _REGISTER[_ACTIVATIONS_KEY]) if len(raval) <= goalitems: return to_delkv = sorted((ts, key) for key, (_obj, ts) in raval.items()) # delete oldest entries up to goalitems for _ts, key in to_delkv[: len(raval) - goalitems]: raval.pop(key) def load() -> None: """Load learning database.""" _REGISTER.clear() if (filepath := config.get_config_file(_MNEMONICS_FILENAME)) and ( reg := Learning.unpickle_register(filepath) ): _REGISTER.update(reg) if _CORRELATION_KEY not in _REGISTER: _REGISTER[_CORRELATION_KEY] = _DEFAULT_ACTIONS if _ACTIVATIONS_KEY not in _REGISTER: _REGISTER[_ACTIVATIONS_KEY] = ty.cast("dict[str, tuple[str, int]]", {}) _MAX_REGISTER_SIZE: ty.Final[int] = 500 def save() -> None: """Save the learning record.""" if not _REGISTER: pretty.print_debug(__name__, "Not writing empty register") return _purge_action_reg(_MAX_REGISTER_SIZE) if len(_REGISTER) > _MAX_REGISTER_SIZE: _prune_register(_MAX_REGISTER_SIZE) filepath = config.save_config_file(_MNEMONICS_FILENAME) assert filepath Learning.pickle_register(_REGISTER, filepath) def _rebuild_favorites(): """Build _FAVORITES set from _PLUG_FAVS buckets.""" _FAVORITES.clear() for favs in _PLUG_FAVS.values(): _FAVORITES.update(favs) def add_favorite(plugin_id: str, *objs: KupferObject) -> None: """Add favorites `objs` to `plugin_id` bucket.""" fset = _PLUG_FAVS.get(plugin_id) if fset: # filter and add new obj nfset = [obj for obj in map(repr, objs) if obj not in fset] fset.extend(nfset) else: nfset = _PLUG_FAVS[plugin_id] = list(map(repr, objs)) _FAVORITES.update(nfset) def replace_favorites(plugin_id: str, *objs: KupferObject) -> None: """Replace favorites in `plugin_id` bucket. If no `objs` remove all favorites for `plugin_id`.""" if not objs: if plugin_id in _PLUG_FAVS: del _PLUG_FAVS[plugin_id] _rebuild_favorites() return fset = _PLUG_FAVS[plugin_id] = list(map(repr, objs)) _FAVORITES.update(fset) def remove_favorite(plugin_id: str, obj: KupferObject) -> None: """Remove `obj` from favorites in `plugin_id` bucket.""" if fset := _PLUG_FAVS.get(plugin_id): try: fset.remove(repr(obj)) except ValueError: return if fset: _PLUG_FAVS[plugin_id] = fset else: del _PLUG_FAVS[plugin_id] _rebuild_favorites() def is_favorite(obj: KupferObject) -> bool: return repr(obj) in _FAVORITES def unregister(obj): _REGISTER.pop(obj, None) kupfer-328/kupfer/core/panes.py000066400000000000000000000310751500175051100165710ustar00rootroot00000000000000"""Pane objects definition. This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ from __future__ import annotations import itertools import typing as ty from gi.repository import GObject from kupfer.core import actioncompat from kupfer.core.searcher import Searcher from kupfer.core.sources import get_source_controller from kupfer.obj import objects from kupfer.obj.base import Action, AnySource, KupferObject, Leaf, Source from kupfer.support import pretty if ty.TYPE_CHECKING: from kupfer.core.search import Rankable __all__ = ( "LeafPane", "Pane", "PrimaryActionPane", "SearchContext", "SecondaryObjectPane", ) SearchContext = tuple[int, ty.Any] def _dress_leaves( seq: ty.Iterable[Rankable], action: Action | None ) -> ty.Iterable[Rankable]: """yield items of @seq "dressed" by the source controller""" sctr = get_source_controller() decorate_object = sctr.decorate_object for itm in seq: decorate_object(itm.object, action=action) # type:ignore yield itm # Pane Object type definition PO = ty.TypeVar("PO", bound=KupferObject) class Pane(GObject.GObject, ty.Generic[PO]): # type:ignore """Pane with `PO` type objects. signals: search-result (match, match_iter, context) """ __gtype_name__ = "Pane" def __init__(self): super().__init__() self._selection: PO | None = None self._latest_key: str | None = None self.outstanding_search: int = -1 self.outstanding_search_id: int = -1 self._searcher = Searcher() def select(self, item: PO | None) -> None: self._selection = item def get_selection(self) -> PO | None: return self._selection def reset(self) -> None: self._selection = None self._latest_key = None def get_latest_key(self) -> str | None: return self._latest_key def get_can_enter_text_mode(self) -> bool: return False def get_should_enter_text_mode(self) -> bool: return False def emit_search_result( self, match: Rankable | None, match_iter: ty.Iterable[Rankable], context: SearchContext | None, ) -> None: self.emit("search-result", match, match_iter, context) GObject.signal_new( "search-result", Pane, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_PYOBJECT, GObject.TYPE_PYOBJECT, GObject.TYPE_PYOBJECT), ) class LeafPane(Pane[Leaf], pretty.OutputMixin): __gtype_name__ = "LeafPane" def __init__(self): super().__init__() # source_stack keep track on history selected sources and leaves self._source_stack: list[tuple[AnySource, Leaf | None]] = [] self._source: AnySource | None = None # object_stack is used by "comma trick" self.object_stack: list[Leaf] = [] def select(self, item: Leaf | None) -> None: assert item is None or isinstance(item, Leaf), ( "New selection for object pane is not a Leaf!" ) super().select(item) def _load_source(self, src: AnySource) -> AnySource: """Try to get a source from the SourceController, if it is already loaded we get it from there, else returns @src""" sctr = get_source_controller() return sctr.get_canonical_source(src) def get_source(self) -> AnySource | None: return self._source def source_rebase(self, src: AnySource) -> None: self._source_stack.clear() self._source = self._load_source(src) self.refresh_data() def push_source(self, src: AnySource) -> None: if self._source: self._source_stack.append((self._source, self._selection)) self._source = self._load_source(src) self.refresh_data() def _pop_source(self) -> bool: """Remove source from stack. Return True if succeeded""" if self._source_stack: self._source, self._selection = self._source_stack.pop() return True return False def is_at_source_root(self) -> bool: """Return True if we have no source stack""" return not self._source_stack def object_stack_push(self, obj: Leaf) -> None: self.object_stack.append(obj) def object_stack_pop(self) -> Leaf: return self.object_stack.pop() def get_can_enter_text_mode(self) -> bool: return self.is_at_source_root() def get_should_enter_text_mode(self) -> bool: return False def refresh_data(self, select: ty.Any = None) -> None: self.emit("new-source", self._source, select) def browse_up(self) -> bool: """Try to browse up to previous sources, from current source""" succ = self._pop_source() if not succ: assert self._source if self._source.has_parent(): self.source_rebase(self._source.get_parent()) # type:ignore succ = True if succ: sel = self._selection # select again only leaves that have some content (as we go from # source we can back only to source) if sel and hasattr(sel, "has_content") and sel.has_content(): self.refresh_data(select=sel) else: self.refresh_data() return succ def browse_down(self, alternate: bool = False) -> bool: """Browse into @leaf if it's possible and save away the previous sources in the stack. If @alternate, use the Source's alternate method.""" leaf: Leaf | None = self.get_selection() if ( leaf and leaf.has_content() and (csrc := leaf.content_source(alternate=alternate)) ): self.push_source(csrc) return True return False def reset(self) -> None: """Pop all sources and go back to top level""" Pane.reset(self) while self._pop_source(): pass self.refresh_data() def soft_reset(self) -> AnySource | None: Pane.reset(self) while self._pop_source(): pass return self._source def search( self, key: str = "", context: SearchContext | None = None, text_mode: bool = False, ) -> None: """Search for `key`""" self._latest_key = key sources_: ty.Iterable[AnySource] = () if not text_mode and (srcs := self.get_source()): sources_ = (srcs,) if key and self.is_at_source_root(): # Only use text sources when we are at root catalog sctr = get_source_controller() textsrcs = sctr.get_text_sources() sources_ = itertools.chain(sources_, textsrcs) def _decorator(seq): return _dress_leaves(seq, action=None) match, match_iter = self._searcher.search( sources_, key, score=bool(key), decorator=_decorator ) self.emit_search_result(match, match_iter, context) GObject.signal_new( "new-source", LeafPane, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_PYOBJECT, GObject.TYPE_PYOBJECT), ) class PrimaryActionPane(Pane[Action]): def __init__(self): super().__init__() self._action_valid_cache: dict[int, bool] = {} self.set_item(None) def select(self, item: Action | None) -> None: assert not item or isinstance(item, Action), ( "Selection in action pane is not an Action!" ) super().select(item) def set_item(self, item: Leaf | None) -> None: """Set which @item we are currently listing actions for""" self._current_item = item self._action_valid_cache.clear() def search( self, key: str = "", context: SearchContext | None = None, text_mode: bool = False, ) -> None: """Search: Register the search method in the event loop using @key, promising to return @context in the notification about the result, having selected @item in PaneSel.SOURCE If we already have a call to search, we remove the "source" so that we always use the most recently requested search.""" self._latest_key = key leaf = self._current_item if not leaf: self.emit_search_result(None, (), context) return if isinstance(leaf, objects.ActionLeaf): # for ActionLeaf get only actions defined in leaf (should be one, # ignore other actions). actions = leaf.get_actions() match, match_iter = self._searcher.rank_actions(actions, "", leaf) else: actions = actioncompat.actions_for_item( leaf, get_source_controller() ) cache = self._action_valid_cache def valid_decorator(seq): """Check if actions are valid before access""" assert leaf for obj in seq: action = obj.object action_hash = hash(action) valid = cache.get(action_hash) if valid is None: valid = actioncompat.action_valid_for_item( action, leaf ) cache[action_hash] = valid if valid: yield obj match, match_iter = self._searcher.rank_actions( actions, key, leaf, decorator=valid_decorator ) self.emit_search_result(match, match_iter, context) class SecondaryObjectPane(LeafPane): __gtype_name__ = "SecondaryObjectPane" def __init__(self): LeafPane.__init__(self) self._current_item: Leaf | None = None self._current_action: Action | None = None def reset(self) -> None: LeafPane.reset(self) self._searcher.reset() def set_item_and_action( self, item: Leaf | None, act: Action | None ) -> None: self._current_item = item self._current_action = act if item and act: ownsrc, use_catalog = actioncompat.iobject_source_for_action( act, item ) if ownsrc and not use_catalog: self.source_rebase(ownsrc) else: extra_sources = ( ty.cast("list[Source]", [ownsrc]) if ownsrc else None ) sctr = get_source_controller() self.source_rebase( sctr.root_for_types(act.object_types(), extra_sources) ) else: self.reset() def get_can_enter_text_mode(self) -> bool: """Check if there are any reasonable text sources for this action""" assert self._current_action atroot = self.is_at_source_root() types = tuple(self._current_action.object_types()) sctr = get_source_controller() textsrcs = sctr.get_text_sources() return atroot and any( sctr.good_source_for_types(s, types) for s in textsrcs ) def get_should_enter_text_mode(self): return self.is_at_source_root() and hasattr( self.get_source(), "get_text_items" ) def search( self, key: str = "", context: SearchContext | None = None, text_mode: bool = False, ) -> None: """ filter for action @item """ self._latest_key = key assert self._current_action if not self._current_item: self.emit_search_result(None, (), context) return sources_: ty.Iterable[AnySource] = [] if ( not text_mode or hasattr(self.get_source(), "get_text_items") ) and (srcs := self.get_source()): sources_ = itertools.chain(sources_, (srcs,)) if key and self.is_at_source_root(): # Only use text sources when we are at root catalog sctr = get_source_controller() if textsrcs := sctr.get_text_sources(): sources_ = itertools.chain(sources_, textsrcs) item_check = actioncompat.iobjects_valid_for_action( self._current_action, self._current_item ) def decorator(seq): return _dress_leaves(seq, action=self._current_action) match, match_iter = self._searcher.search( sources_, key, score=True, item_check=item_check, decorator=decorator, ) self.emit_search_result(match, match_iter, context) kupfer-328/kupfer/core/pluginload.py000066400000000000000000000054211500175051100176150ustar00rootroot00000000000000import contextlib import traceback import typing as ty from kupfer.core import plugins from kupfer.core.plugins import ( PluginAttr, initialize_plugin, load_plugin_objects, ) from kupfer.support import pretty if ty.TYPE_CHECKING: from kupfer.obj.base import Action, ActionGenerator, Source, TextSource __all__ = ("exception_guard", "load_plugin", "remove_plugin") # pylint: disable=too-few-public-methods class PluginDescription: def __init__(self): self.text_sources: list[TextSource] = [] self.action_decorators: list[Action] = [] self.content_decorators: list[ty.Type[Source]] = [] self.action_generators: list[ActionGenerator] = [] self.sources: list[Source] = [] def load_plugin(plugin_id: str) -> PluginDescription: """Load plugin by `plugin_id`. @S_sources are to be included directly in the catalog, @s_sources as just as subitems """ sources: list[Source] = [] text_sources: list[TextSource] = [] action_decorators: list[Action] = [] content_decorators: list[ty.Type[Source]] = [] action_generators: list[ActionGenerator] = [] initialize_plugin(plugin_id) if not plugins.is_plugin_loaded(plugin_id): return PluginDescription() text_sources.extend( load_plugin_objects(plugin_id, PluginAttr.TEXT_SOURCES) ) action_decorators.extend( load_plugin_objects(plugin_id, PluginAttr.ACTION_DECORATORS) ) action_generators.extend( load_plugin_objects(plugin_id, PluginAttr.ACTION_GENERATORS) ) # Register all Sources as (potential) content decorators content_decorators.extend( load_plugin_objects(plugin_id, PluginAttr.SOURCES, instantiate=False) ) content_decorators.extend( load_plugin_objects( plugin_id, PluginAttr.CONTENT_DECORATORS, instantiate=False ) ) sources.extend(load_plugin_objects(plugin_id, PluginAttr.SOURCES)) desc = PluginDescription() desc.text_sources = text_sources desc.action_decorators = action_decorators desc.content_decorators = content_decorators desc.sources = sources desc.action_generators = action_generators return desc @contextlib.contextmanager def exception_guard(name, *args, callback=None, **kwargs): "Guard for exceptions, print traceback and call @callback if any is raised" try: yield except Exception: pretty.print_error(__name__, f"Loading {name} raised an exception:") traceback.print_exc() pretty.print_error(__name__, "This error is probably a bug in", name) pretty.print_error(__name__, "Please file a bug report") if callback is not None: callback(*args, **kwargs) def remove_plugin(plugin_id: str) -> None: plugins.unimport_plugin(plugin_id) kupfer-328/kupfer/core/plugins.py000066400000000000000000000365351500175051100171520ustar00rootroot00000000000000from __future__ import annotations import importlib.util import pkgutil import sys import textwrap import traceback import types import typing as ty from enum import Enum from kupfer import icons from kupfer import plugin as kplugin from kupfer.core import settings from kupfer.support import pretty if ty.TYPE_CHECKING: from gettext import gettext as _ from kupfer.support.types import ExecInfo # import kupfer.icons on demand later __all__ = ( "LoadingError", "NotEnabledError", "PluginAttr", "get_plugin_attribute", "get_plugin_attributes", "get_plugin_desc", "get_plugin_error", "get_plugin_ids", "get_plugin_info", "get_plugin_name", "initialize_plugin", "is_plugin_loaded", "load_plugin_objects", "register_plugin_unimport_hook", "unimport_plugin", ) class PluginAttr(Enum): SOURCES = "__kupfer_sources__" TEXT_SOURCES = "__kupfer_text_sources__" CONTENT_DECORATORS = "__kupfer_contents__" ACTION_DECORATORS = "__kupfer_actions__" ACTION_GENERATORS = "__kupfer_action_generators__" SETTINGS = "__kupfer_settings__" INITIALIZE = "initialize_plugin" FINALIZE = "finalize_plugin" # info attributes KUPFER_NAME = "__kupfer_name__" VERSION = "__version__" DESCRIPTION = "__description__" AUTHOR = "__author__" # other NAME = "__name__" FILE = "__file__" _INFO_ATTRIBUTES = tuple( pa.value for pa in ( PluginAttr.KUPFER_NAME, PluginAttr.VERSION, PluginAttr.DESCRIPTION, PluginAttr.AUTHOR, ) ) _PLUGIN_ICON_FILE = "icon-list" _PLUGIN_HOOKS: dict[str, list[tuple[ty.Callable[..., None], ty.Any]]] = {} class NotEnabledError(Exception): """Plugin may not be imported since it is not enabled""" def get_plugin_ids() -> ty.Iterator[str]: """Enumerate possible plugin ids. Return a sequence of possible plugin ids, not guaranteed to be plugins.""" for _importer, modname, _ispkg in pkgutil.iter_modules(kplugin.__path__): if ( modname != "__init__" and not modname.endswith("_support") and not modname.startswith("_") ): yield modname # pylint: disable=too-few-public-methods class _FakePlugin: def __init__( self, plugin_id: str, attributes: dict[str, ty.Any], exc_info: ExecInfo | None, ) -> None: self.is_fake_plugin = True self.exc_info = exc_info self.__name__ = plugin_id vars(self).update(attributes) def __repr__(self) -> str: return f"<{type(self).__name__} {self.__name__}>" PluginModule = ty.Union[types.ModuleType, _FakePlugin] # imported plugins, none=not existing _IMPORTED_PLUGINS: dict[str, PluginModule | None] = {} def get_plugin_info() -> ty.Iterator[dict[str, ty.Any]]: """Generator, yields dictionaries of plugin descriptions with at least the fields: name, localized_name, version, description, author.""" for plugin_name in sorted(get_plugin_ids()): try: plugin = _import_plugin_any(plugin_name) if not plugin: continue plugin = vars(plugin) except ImportError as exc: pretty.print_error( __name__, f"import plugin '{plugin_name}':", exc ) continue except Exception: pretty.print_error(__name__, f"Could not load '{plugin_name}'") pretty.print_exc(__name__) continue localized_name = plugin.get("__kupfer_name__", None) desc = plugin.get("__description__", "") vers = plugin.get("__version__", "") author = plugin.get("__author__", "") # skip false matches; # all plugins have to have @localized_name if localized_name is None: continue yield { "name": plugin_name, "localized_name": localized_name, "version": vers, "description": desc or "", "author": author, "provides": (), } def get_plugin_desc() -> str: """Return a formatted list of plugins suitable for printing to terminal""" infos = list(get_plugin_info()) verlen = max(len(r["version"]) for r in infos) idlen = max(len(r["name"]) for r in infos) maxlen = 78 left_margin = 2 + idlen + 1 + verlen + 1 def format_desc(rec: dict[str, ty.Any]) -> str: # Wrap the description and align continued lines wrapped = textwrap.wrap(rec["description"], maxlen - left_margin) description = ("\n" + " " * left_margin).join(wrapped) name = rec["name"].ljust(idlen) ver = rec["version"].ljust(verlen) return f" {name} {ver} {description}" return "\n".join(map(format_desc, infos)) class LoadingError(ImportError): pass def _truncate_source( text: str, find_attributes: ty.Iterable[str] ) -> ty.Iterator[str]: found_info_attributes = set(find_attributes) for line in text.splitlines(): # skip import from __future__ that must be in first line if line.startswith("from __future__ import "): continue # keep empty lines if not line.strip(): yield line continue first_word = line.split(None, 1)[0] if first_word in found_info_attributes: found_info_attributes.discard(first_word) elif first_word in ("from", "import", "class", "def", "if"): break yield line if found_info_attributes: raise LoadingError( "Could not pre-load plugin: Fields missing: " f"{list(found_info_attributes)}. " "These fields need to be defined before any other code, " "including imports." ) def _import_plugin_fake( modpath: str, error: ExecInfo | None = None ) -> _FakePlugin | None: """Return an object that has the plugin info attributes we can rescue from a plugin raising on import. @error: If applicable, a tuple of exception info """ try: spec = importlib.util.find_spec(modpath) except (ImportError, AttributeError, TypeError, ValueError): return None loader = spec.loader if spec is not None else None if not loader: return None code = loader.get_source(modpath) # type: ignore if not code: return None try: filename = loader.get_filename(modpath) # type: ignore except AttributeError: try: filename = loader.archive + loader.prefix # type: ignore except AttributeError: filename = f"<{modpath}>" env = {"__name__": modpath, "__file__": filename, "__builtins__": {"_": _}} code = "\n".join(_truncate_source(code, _INFO_ATTRIBUTES)) try: # pylint: disable=eval-used eval(compile(code, filename, "exec"), env) except Exception: pretty.print_error(__name__, "When loading", modpath) pretty.print_exc(__name__) attributes = {k: env.get(k) for k in _INFO_ATTRIBUTES} attributes.update( (k.value, env.get(k.value)) for k in (PluginAttr.NAME, PluginAttr.FILE) ) return _FakePlugin(modpath, attributes, error) def _import_hook_fake(pathcomps: ty.Iterable[str]) -> PluginModule | None: modpath = ".".join(pathcomps) return _import_plugin_fake(modpath) def _import_hook_true(pathcomps: tuple[str, ...]) -> PluginModule: """@pathcomps path components to the import""" path = ".".join(pathcomps) fromlist = pathcomps[-1:] try: setctl = settings.get_settings_controller() if not setctl.get_plugin_enabled(pathcomps[-1]): raise NotEnabledError(f"{pathcomps[-1]} is not enabled") plugin = __import__(path, fromlist=fromlist) pretty.print_debug(__name__, f"Loading {plugin.__name__}") pretty.print_debug(__name__, f" from {plugin.__file__}") return plugin except ImportError as exc: # Try to find a fake plugin if it exists fake_plugin = _import_plugin_fake(path, error=sys.exc_info()) if not fake_plugin: raise pretty.print_error( __name__, f"Could not import plugin '{fake_plugin.__name__}': {exc}", ) return fake_plugin def _import_plugin_true(name: str) -> PluginModule | None: """Try to import the plugin from the package, and then from our plugin directories in $.""" plugin = None try: plugin = _staged_import(name, _import_hook_true) except (ImportError, NotEnabledError): # Reraise to send this up raise except Exception: # catch any other error for plugins and write traceback traceback.print_exc() pretty.print_error(__name__, f"Could not import plugin '{name}'") return plugin def _staged_import( name: str, import_hook: ty.Callable[[tuple[str, ...]], PluginModule | None], ) -> PluginModule | None | ty.Any: """Import plugin @name using @import_hook""" # FIXME: ty.Any because typeguard try: return import_hook(_plugin_path(name)) except ImportError as exc: if name not in exc.args[0]: raise return None def _import_plugin(name: str) -> PluginModule | None: if is_plugin_loaded(name): return _IMPORTED_PLUGINS[name] plugin = None try: plugin = _import_plugin_true(name) except NotEnabledError: plugin = _staged_import(name, _import_hook_fake) finally: # store non-existing plugins as None here _IMPORTED_PLUGINS[name] = plugin return plugin def _import_plugin_any(name: str) -> ty.Any: if name in _IMPORTED_PLUGINS: return _IMPORTED_PLUGINS[name] return _staged_import(name, _import_hook_fake) def _plugin_path(name: str) -> tuple[str, ...]: return ("kupfer", "plugin", name) # Plugin Attributes def get_plugin_attributes( plugin_name: str, attrs: tuple[str | PluginAttr, ...], warn: bool = False, ) -> ty.Iterator[ty.Any]: """Generator of the attributes named @attrs to be found in plugin @plugin_name. If the plugin is not found, we write an error and yield nothing. If @warn, we print a warning if a plugin does not have a requested attribute.""" try: plugin = _import_plugin(plugin_name) except ImportError as exc: pretty.print_info(__name__, f"Skipping plugin {plugin_name}: {exc}") return for attr in attrs: if isinstance(attr, PluginAttr): attr = attr.value # noqa: PLW2901 try: yield getattr(plugin, attr) except AttributeError as exc: if warn: pretty.print_info(__name__, f"Plugin {plugin_name}: {exc}") yield None def get_plugin_attribute( plugin_name: str, attr: PluginAttr | str ) -> ty.Any | None: """Get single plugin attribute""" for value in get_plugin_attributes(plugin_name, (attr,)): return value or None return None def load_plugin_objects( plugin_name: str, attr: PluginAttr = PluginAttr.SOURCES, instantiate: bool = True, ) -> ty.Iterable[ty.Any]: """Load plugin sources or actions or other type objects (selected by @attr).""" objects = get_plugin_attribute(plugin_name, attr) if not objects: return for obj in get_plugin_attributes(plugin_name, objects, warn=True): if obj: if instantiate: yield obj() else: yield obj else: pretty.print_info( __name__, f"Object not found for {plugin_name} in {attr}" ) # Plugin Initialization & Error def is_plugin_loaded(plugin_name: str) -> bool: if plg := _IMPORTED_PLUGINS.get(plugin_name): return not getattr(plg, "is_fake_plugin", None) return False def _loader_hook(modpath: tuple[str, ...]) -> ty.Any: modname = ".".join(modpath) try: spec = importlib.util.find_spec(modname) except (ImportError, AttributeError, TypeError, ValueError) as ex: raise ImportError(f"No loader found for {modname}") from ex loader = spec.loader if spec is not None else None if not loader: raise ImportError(f"No loader found for {modname}") if not loader.is_package(modname): # type: ignore raise ImportError("Is not a package") return loader def _load_icons(plugin_name: str) -> None: try: _loader = _staged_import(plugin_name, _loader_hook) except ImportError: return modname = ".".join(_plugin_path(plugin_name)) try: icon_file = pkgutil.get_data(modname, _PLUGIN_ICON_FILE) except OSError: # icon-list file just missing, let is pass silently return def get_icon_data(basename): return pkgutil.get_data(modname, basename) if icon_file: icons.parse_load_icon_list(icon_file, get_icon_data, plugin_name) def initialize_plugin(plugin_name: str) -> None: """Initialize plugin. Find settings attribute if defined, and initialize it.""" _load_icons(plugin_name) if settings_dict := get_plugin_attribute(plugin_name, PluginAttr.SETTINGS): settings_dict.initialize(plugin_name) if initialize := get_plugin_attribute(plugin_name, PluginAttr.INITIALIZE): initialize(plugin_name) if finalize := get_plugin_attribute(plugin_name, PluginAttr.FINALIZE): register_plugin_unimport_hook(plugin_name, finalize, plugin_name) def unimport_plugin(plugin_name: str) -> None: """Remove @plugin_name from the plugin list and dereference its python modules.""" # Run unimport hooks if plugin_name in _PLUGIN_HOOKS: try: for callback, args in reversed(_PLUGIN_HOOKS[plugin_name]): callback(*args) except Exception: pretty.print_error(__name__, "Error finalizing", plugin_name) pretty.print_exc(__name__) _PLUGIN_HOOKS.pop(plugin_name) _IMPORTED_PLUGINS.pop(plugin_name) plugin_module_name = ".".join(_plugin_path(plugin_name)) pretty.print_debug(__name__, "Dereferencing module", plugin_module_name) if plugin_module_name in sys.modules: sys.modules.pop(plugin_module_name) for mod in list(sys.modules): if mod.startswith(plugin_module_name + "."): pretty.print_debug(__name__, "Dereferencing module", mod) sys.modules.pop(mod) def register_plugin_unimport_hook( plugin_name: str, callback: ty.Callable[..., None], *args: ty.Any ) -> None: if plugin_name not in _IMPORTED_PLUGINS: raise ValueError(f"No such plugin {plugin_name}") _PLUGIN_HOOKS.setdefault(plugin_name, []).append((callback, args)) def get_plugin_error(plugin_name: str) -> ty.Any: """Return None if plugin is loaded without error, else return a tuple of exception information.""" try: if (plugin := _import_plugin(plugin_name)) and getattr( plugin, "is_fake_plugin", None ): return plugin.exc_info except ImportError: return sys.exc_info() return None def get_plugin_name(modulename: str) -> str: """Get plugin name according to @modulename. (return __kupfer_name__ in @modulename module). """ name: str | None = None for module in _IMPORTED_PLUGINS.values(): if not module or isinstance(module, _FakePlugin): continue if module.__name__ == modulename: name = module.__kupfer_name__ break if name: return name return modulename.split(".")[-1] kupfer-328/kupfer/core/qfurl.py000066400000000000000000000077761500175051100166270ustar00rootroot00000000000000from __future__ import annotations import typing as ty import urllib.parse from contextlib import suppress from urllib.parse import urlparse as _urlparse from urllib.parse import urlunparse as _urlunparse from kupfer.support import pretty if ty.TYPE_CHECKING: from kupfer.obj.base import Leaf, Source __all__ = ("QFURL_SCHEME", "Qfurl", "QfurlError") QFURL_SCHEME = "qpfer" # One would hope that there was a better way to do this urllib.parse.uses_netloc.append(QFURL_SCHEME) with suppress(AttributeError): urllib.parse.uses_fragment.append(QFURL_SCHEME) class QfurlError(Exception): pass class Qfurl: """A Qfurl is a URI to locate unique objects in kupfer's catalog. The Qfurl is built up as follows: ``qpfer://mother/qfid#module_and_type_hint`` The mother part is a mother source identifier and is optional. The module_and_type_hint is optional. A short url looks like the following: ``qpfer:identifier`` This class provides methods to get the Qfurl for an object, and resolve the object in a catalog. >>> class Object (object): ... qf_id = "token" ... >>> q = Qfurl(Object()) >>> Qfurl.reduce_url(q.url) 'qpfer:token' >>> class Source (object): ... def get_leaves(self): ... yield Object() ... def provides(self): ... yield Object ... >>> q.resolve_in_catalog((Source(), )) # doctest: +ELLIPSIS <__main__.Object object at 0x...> """ def __init__(self, obj=None, url=None): """Create a new Qfurl for object @obj""" if obj: typname = f"{type(obj).__module__}.{type(obj).__name__}" try: qfid = obj.qf_id except AttributeError as exe: raise QfurlError(f"{obj} has no Qfurl") from exe self.url = _urlunparse((QFURL_SCHEME, "", qfid, "", "", typname)) else: self.url = url def __str__(self) -> str: return self.url def __hash__(self) -> int: return hash(self.url) def __eq__(self, other: object) -> bool: return self.reduce_url(self.url) == self.reduce_url(other.url) # type: ignore @classmethod def reduce_url(cls, url: str) -> str: """ >>> url = "qpfer://mother/qfid#module_and_type_hint" >>> Qfurl.reduce_url(url) 'qpfer://mother/qfid' """ return urllib.parse.urldefrag(url)[0].replace("///", "", 1) @classmethod def _parts_mother_id_typename(cls, url: str) -> tuple[str, str, str]: """ >>> murl = "qpfer://mother/qfid#module_and_type_hint" >>> Qfurl._parts_mother_id_typename(murl) ('mother', 'qfid', 'module_and_type_hint') """ scheme, mother, qfid, _ign, _ore, typname = _urlparse(url) if scheme != QFURL_SCHEME: raise QfurlError(f"Wrong scheme: {scheme}") qfid = qfid.lstrip("/") return mother, qfid, typname def resolve_in_catalog( self, catalog: ty.Collection[Source] ) -> Leaf | None: """Resolve self in a catalog of sources. Return *immediately* on match found""" _mother, _qfid, typname = self._parts_mother_id_typename(self.url) _module, name = typname.rsplit(".", 1) if typname else (None, None) for src in catalog: if ( name and name not in (pt.__name__ for pt in src.provides()) and name not in ( t.__name__ for pt in src.provides() for t in pt.__subclasses__() ) ): continue for obj in src.get_leaves() or []: if not hasattr(obj, "qf_id"): continue with suppress(QfurlError): if self == Qfurl(obj): return obj pretty.print_debug(__name__, "No match found for", self) return None if __name__ == "__main__": import doctest doctest.testmod() kupfer-328/kupfer/core/relevance.py000066400000000000000000000174701500175051100174320ustar00rootroot00000000000000# Copyright (C) 2009 Ulrik Sverdrup # 2008 Christian Hergert # 2007 Chris Halse Rogers, DR Colkitt # David Siegel, James Walker # Jason Smith, Miguel de Icaza # Rick Harding, Thomsen Anders # Volker Braun, Jonathon Anderson # # 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 . """ This module provides relevance matching and formatting of related strings based on the relevance. It originates in Gnome-Do. * Python port by Christian Hergert * Module updated by Ulrik Sverdrup to clean up and dramatically speed up the code, by using more pythonic constructs as well as doing less work. Compatibility: Python 3 """ from __future__ import annotations import typing as ty __all__ = ("format_common_substrings", "score", "score_single") FormatCleanCB = ty.Callable[[str], str] FormatMatchCB = ty.Callable[[str], str] def _default_formatter(x: str) -> str: return x def format_common_substrings( string: str, query: str, format_clean: FormatCleanCB | None = None, format_match: FormatMatchCB | None = None, ) -> str: """Creates a new string highlighting matching substrings. Returns: a formatted string >>> format_common_substrings('hi there dude', 'hidude', ... format_match=lambda m: "%s" % m) 'hi there dude' >>> format_common_substrings('parallelism', 'lsm', format_match=str.upper) 'paralleLiSM' """ format_clean = format_clean or _default_formatter def _format(x: str) -> str: return x and format_clean(x) if not query: return _format(string) lowerstr = string.lower() # find overall range of match first, last = _find_best_match(lowerstr, query) if first == -1: return _format(string) # find longest perfect match, put in slc for slc in range(len(query), 0, -1): if query[:slc] == lowerstr[first : first + slc]: break nextkey = query[slc:] head = string[:first] match = string[first : first + slc] matchtail = string[first + slc : last] tail = string[last:] format_match = format_match or _default_formatter return "".join( ( _format(head), format_match(match), format_common_substrings( matchtail, nextkey, format_clean, format_match ), _format(tail), ) ) def score_single(string: str, query: str) -> float: """Find the shortest possible substring that matches the query and get the ration of their lengths for a base score. string: text body to score query: A single character This is a single character approximation to `score`. >>> round(score_single('terminal', 't'), 6) 0.973125 >>> round(score_single('terminal', 'e'), 6) 0.903125 >>> round(score_single('terminal', 'a'), 6) 0.903125 >>> round(score_single('t', 't'), 6) 0.995 """ string = string.lower() first = string.find(query) if first == -1: return 0.0 if first == 0: return 0.97 + 0.025 / len(string) return 0.9 + 0.025 / len(string) def score(string: str, query: str) -> float: """A relevancy score for the string ranging from 0 to 1. @string: a string to be scored @query: a string query to score against `string' is treated case-insensitively while `query' is interpreted literally, including case and whitespace. Returns: a float between 0 and 1 >>> round(score('terminal', 'trml'), 6) 0.735099 >>> round(score('terminal', 'term'), 6) 0.992303 >>> print(score('terminal', 'try')) 0.0 >>> print(score('terminal', '')) 1.0 >>> round(score('terminal', 't'), 6) 0.98949 >>> round(score('terminal', 'e'), 6) 0.918438 """ if not query: return 1.0 string = string.lower() # Find the shortest possible substring that matches the query # and get the ration of their lengths for a base score first, last = _find_best_match(string, query) if first == -1: return 0.0 query_len = len(query) strscore: float = query_len / (last - first) # Now we weight by string length so shorter strings are better strscore *= 0.7 + query_len / len(string) * 0.3 # Bonus points if the characters start words bad = 1 first_count = 0 for i in range(first, last - 1): if string[i] in " -.([_": if string[i + 1] in query: first_count += 1 else: bad += 1 # A first character match counts extra if query[0] == string[0]: first_count += 2 # The longer the acronym, the better it scores good = first_count * first_count * 4 # Better yet if the match itself started there if first == 0: good += 2 # Super duper bonus if it is a perfect match if query == string: good += last * 2 + 4 strscore = (strscore + 3 * good / (good + bad)) / 4 # This fix makes sure that perfect matches always rank higher # than split matches. Perfect matches get the .9 - 1.0 range # everything else lower if last - first == query_len: return 0.9 + 0.1 * strscore return 0.9 * strscore def _find_best_match(string: str, query: str) -> tuple[int, int]: """Finds the shortest substring of @s that contains all characters of query in order. @string: a string to search @query: a string query to search for Returns: a two-item tuple containing the start and end indices of the match. No match returns (-1,-1). >>> _find_best_match('terminal', 'trml') (0, 8) >>> _find_best_match('total told', 'tl') (2, 5) >>> _find_best_match('terminal', 'yl') (-1, -1) """ # Find the last instance of the last character of the query # since we never need to search beyond that last_char = string.rfind(query[-1]) # No instance of the character? if last_char == -1: return -1, -1 # Loop through each instance of the first character in query index = string.find(query[0]) best_match_start = -1 best_match_end = -1 query_len = len(query) last_index = last_char - query_len + 1 while 0 <= index <= last_index: # See if we can fit the whole query in the tail # We know the first char matches, so we dont check it. cur = index + 1 qcur = 1 while qcur < query_len: # find where in the string the next query character is # if not found, we are done cur = string.find(query[qcur], cur, last_char + 1) if cur == -1: return best_match_start, best_match_end cur += 1 qcur += 1 # take match if it is shorter # if perfect match, we are done if best_match_start == -1 or (cur - index) < ( best_match_end - best_match_start ): best_match_start = index best_match_end = cur if cur - index == query_len: break index = string.find(query[0], index + 1) return best_match_start, best_match_end if __name__ == "__main__": import doctest doctest.testmod() kupfer-328/kupfer/core/search.py000066400000000000000000000114311500175051100167220ustar00rootroot00000000000000from __future__ import annotations import operator import typing as ty from kupfer.core import learn, relevance from kupfer.obj.base import Action, Leaf __all__ = ( "Rankable", "add_rank_objects", "bonus_actions", "bonus_objects", "find_best_sort", "make_rankables", "score_actions", "score_objects", "wrap_rankable", ) # RankableObject is type of object that can be put in Rankable. RankableObject = ty.Union[Leaf, Action] def make_rankables( itr: ty.Iterable[RankableObject], rank: int = 0 ) -> ty.Iterable[Rankable]: """Create Rankable from some KupferObject:w""" return (Rankable(str(obj), obj, rank) for obj in itr) def wrap_rankable(obj: Leaf, rank: int = 0) -> Rankable: return Rankable(str(obj), obj, rank) class Rankable: """Rankable has an object (represented item), value (determines rank) and an associated rank.""" # To save memory with (really) many Rankables __slots__ = ("aliases", "object", "rank", "value") def __init__(self, value: str, obj: RankableObject, rank: int = 0) -> None: self.rank: int = rank self.value: str = value self.object: RankableObject = obj self.aliases: ty.Collection[str] = getattr(obj, "name_aliases", ()) def __str__(self): return f"{self.rank:.2f}: {self.value!r}, {self.object!r}" def __repr__(self): return f"" def bonus_objects( rankables: ty.Iterable[Rankable], key: str, extra_bonus: int = 0 ) -> ty.Iterator[Rankable]: """ Increment rank of each item in `rankables` for mnemonic score for key and `extra_bonus`. """ get_record_score = learn.get_record_score for obj in rankables: obj.rank += get_record_score(obj.object, key) + extra_bonus yield obj def bonus_actions( rankables: ty.Iterable[Rankable], key: str ) -> ty.Iterator[Rankable]: """ generator of @rankables that have mnemonics for @key Add bonus for mnemonics and rank_adjust rank is added to prev rank, all items are yielded""" get_record_score = learn.get_record_score for obj in rankables: obj.rank += get_record_score(obj.object, key) + obj.object.rank_adjust yield obj def add_rank_objects( rankables: ty.Iterable[Rankable], rank: int ) -> ty.Iterator[Rankable]: """ Add @rank to rank of all @rankables. rankables: Iterable[Rankable] - updated rank: Fixed rank """ for obj in rankables: obj.rank += rank yield obj def score_objects( rankables: ty.Iterable[Rankable], key: str ) -> ty.Iterator[Rankable]: """ rankables: List[Rankable] Prune rankables that score low for the key. """ key = key.lower() _score = relevance.score_single if len(key) == 1 else relevance.score for rankable in rankables: # Rank object rank = int(_score(rankable.value, key) * 100) if rank < 90: # noqa:PLR2004 # consider aliases and change rb.value if alias is better # aliases rank lower so that value is chosen when close arank_value = max( ((_score(alias, key), alias) for alias in rankable.aliases), default=None, ) if arank_value: arank, value = arank_value arank *= 95 if arank > rank: rankable.value = value rank = int(arank) rankable.rank = rank if rankable.rank > 10: # noqa:PLR2004 yield rankable def score_actions( rankables: ty.Iterable[Rankable], for_leaf: Leaf | None ) -> ty.Iterator[Rankable]: """Alternative (rigid) scoring mechanism for objects, putting much more weight in rank_adjust.""" get_record_score = learn.get_record_score for obj in rankables: obj_object = ty.cast("Action", obj.object) rank_adj = obj_object.rank_adjust + learn.get_correlation_bonus( obj_object, for_leaf ) if rank_adj > 0: obj.rank = 50 + rank_adj + get_record_score(obj_object) // 2 elif rank_adj == 0: obj.rank = get_record_score(obj_object) else: obj.rank = -50 + rank_adj + get_record_score(obj_object) yield obj _rank_key = operator.attrgetter("rank") def find_best_sort( rankables: list[Rankable], ) -> ty.Iterable[Rankable]: """Yield rankables in best rank first order. A special kind of lazy sort: simply find the best ranked item and yield it first, then if needed continue by sorting the rest. Note: this will duplicate the best item.""" maxval = max(rankables, default=None, key=_rank_key) if maxval is None: return yield maxval rankables.sort(key=_rank_key, reverse=True) yield from rankables kupfer-328/kupfer/core/searcher.py000066400000000000000000000131551500175051100172560ustar00rootroot00000000000000from __future__ import annotations import operator import typing as ty from kupfer.core import search from kupfer.core.search import Rankable from kupfer.support import pretty from kupfer.support.itertools import peekfirst, unique_iterator if ty.TYPE_CHECKING: from kupfer.obj.base import Action, Leaf, Source, TextSource __all__ = ("Searcher",) T = ty.TypeVar("T") # function that validate leaves before search ItemCheckFunc = ty.Callable[[ty.Iterable[T]], ty.Iterable[T]] # function that decorate leaves before access DecoratorFunc = ty.Callable[[ty.Iterable[Rankable]], ty.Iterable[Rankable]] def _identity(x: ty.Any) -> ty.Any: return x def _as_set_iter(seq: ty.Iterable[Rankable]) -> ty.Iterable[Rankable]: key = operator.attrgetter("object") return unique_iterator(seq, key=key) def _valid_check(seq: ty.Iterable[Rankable]) -> ty.Iterable[Rankable]: """yield items of @seq that are valid""" for itm in seq: obj = itm.object if (not hasattr(obj, "is_valid")) or obj.is_valid(): yield itm class Searcher: """This class searches KupferObjects efficiently, and stores searches in a cache for a very limited time (*). (*) As of this writing, the cache is used when the old key is a prefix of the search key. """ __slots__ = ("_old_key", "_source_cache") def __init__(self): self._source_cache = {} self._old_key: str | None = None def reset(self): self._source_cache.clear() self._old_key = None # pylint: disable=too-many-locals,too-many-branches def search( self, sources_: ty.Iterable[Source | TextSource], key: str, score: bool = True, item_check: ItemCheckFunc[Leaf | Action] | None = None, decorator: DecoratorFunc | None = None, ) -> tuple[Rankable | None, ty.Iterable[Rankable]]: """ @sources is a sequence listing the inputs, which should be Sources, TextSources. If @score, sort by rank. filters (with _identity() as default): @item_check: Check items before adding to search pool @decorator: Decorate items before access Return (first, match_iter), where first is the first match, and match_iter an iterator to all matches, including the first match. """ # use lowercase for search, but for text sources keep original case. keyl = key.lower() if not self._old_key or not keyl.startswith(self._old_key): self._source_cache.clear() self._old_key = keyl # General strategy: Extract a `list` from each source, # and perform ranking as in place operations on lists item_check = item_check or _identity decorator = decorator or _identity start_time = pretty.timing_start() match_lists: list[Rankable] = [] for src in sources_: fixedrank = 0 can_cache = True src_hash = hash(src) # Look in source cache for stored rankables rankables = self._source_cache.get(src_hash) if not rankables: if hasattr(src, "get_text_items"): # TextSources items = src.get_text_items(key) fixedrank = src.get_rank() # type: ignore can_cache = False else: # Source items = src.get_leaves() rankables = search.make_rankables(item_check(items)) if not rankables: continue if score: if fixedrank: rankables = search.add_rank_objects(rankables, fixedrank) elif keyl: rankables = search.bonus_objects( search.score_objects(rankables, keyl), keyl, src.rank_adjust, ) if can_cache: rankables = tuple(rankables) self._source_cache[src_hash] = rankables match_lists.extend(rankables) matches = search.find_best_sort(match_lists) if score else match_lists # Check if the items are valid as the search # results are accessed through the iterators unique_matches = _as_set_iter(matches) match, match_iter = peekfirst(decorator(_valid_check(unique_matches))) pretty.timing_step(__name__, start_time, "ranked") return match, match_iter def rank_actions( self, objects: ty.Iterable[Action], key: str, leaf: Leaf | None, item_check: ItemCheckFunc[Action] | None = None, decorator: DecoratorFunc | None = None, ) -> tuple[Rankable | None, ty.Iterable[Rankable]]: """Rank actions by `key` for `leaf`. rank @objects, which should be a sequence of KupferObjects, for @key, with the action ranker algorithm. @leaf is the Leaf the action is going to be invoked on Filters and return value like .score(). """ item_check = item_check or _identity decorator = decorator or _identity rankables = search.make_rankables(item_check(objects)) if key: key = key.lower() rankables = search.score_objects(rankables, key) matches = search.bonus_actions(rankables, key) else: matches = search.score_actions(rankables, leaf) sorted_matches = sorted( matches, key=operator.attrgetter("rank"), reverse=True ) match, match_iter = peekfirst(decorator(sorted_matches)) return match, match_iter kupfer-328/kupfer/core/settings.py000066400000000000000000000623011500175051100173170ustar00rootroot00000000000000from __future__ import annotations import ast import configparser import copy import locale import os import typing as ty from gi.repository import GLib, GObject, Pango from kupfer import config from kupfer.support import pretty, scheduler __all__ = ( "SettingsController", "get_configured_terminal", "get_settings_controller", "is_known_terminal_executable", ) AltValidator = ty.Callable[[dict[str, ty.Any]], bool] Config = dict[str, dict[str, ty.Any]] @ty.runtime_checkable class ExtendedSetting(ty.Protocol): """Protocol that define non-simple configuration option""" def load( self, plugin_id: str, key: str, config_value: str | float | None ) -> None: """load value for @plugin_id and @key, @config_value is value stored in regular Kupfer config for plugin/key""" def save(self, plugin_id: str, key: str) -> str: """Save value for @plugin_id and @key. @Return value that should be stored in Kupfer config for plugin/key (string)""" PlugConfigValue = ty.Union[ str, bool, int, float, list[ty.Any], ExtendedSetting ] # pylint: disable=too-few-public-methods @ty.runtime_checkable class ValueConverter(ty.Protocol): """Protocol that represent callable used to convert value stored in config file (as str) into required value (int, float, etc). """ def __call__(self, value: str, default: ty.Any) -> PlugConfigValue: ... # PlugConfigValueType = ty.Union[type[PlugConfigValue], ValueConverter] PlugConfigValueType = ty.Union[ty.Any, ValueConverter] def _strbool(value: ty.Any, default: bool = False) -> bool: """Coerce bool from string value or bool""" if isinstance(value, bool): return value value = str(value).lower() if value in ("no", "false"): return False if value in ("yes", "true"): return True return default def _strint(value: ty.Any, default: int = 0) -> int: """Coerce bool from string value or bool""" try: return int(value) except ValueError: return default def _strlist(value: str, default: list[ty.Any] | None = None) -> list[ty.Any]: """Parse string into list using ast literal_eval. literal_eval handle only 'safe' data, so should work fine. """ try: val = ast.literal_eval(value) if isinstance(val, list): return val raise ValueError(f"invalid type: {val!r}") except (TypeError, SyntaxError, MemoryError, RecursionError) as err: raise ValueError(f"evaluate {value!r} error") from err def _override_encoding(name: str) -> str | None: """Return a new encoding name if we want to override it, else return None. This is used to “upgrade” ascii to UTF-8 since the latter is a superset. """ if name.lower() in ("ascii", "ANSI_X3.4-1968".lower()): return "UTF-8" return None def _fill_parser_read( parser: configparser.RawConfigParser, defaults: Config, ) -> None: """Add values from `defaults` to `parser`.""" for secname, section in defaults.items(): if not parser.has_section(secname): parser.add_section(secname) for key, default in section.items(): if isinstance(default, (tuple, list)): default = SettingsController.sep.join(default) # noqa:PLW2901 elif isinstance(default, int): default = str(default) # noqa:PLW2901 parser.set(secname, key, default) # pylint: disable=too-many-return-statements def _parse_value(defval: ty.Any, value: str) -> ty.Any: # noqa:PLR0911 if isinstance(defval, tuple): if not value: return () return tuple( filter(None, map(str.strip, value.split(SettingsController.sep))) ) if isinstance(defval, list): if not value: return [] return list( filter(None, map(str.strip, value.split(SettingsController.sep))) ) if isinstance(defval, bool): return _strbool(value) if isinstance(defval, int): return type(defval)(value) return value def _fill_confmap_from_parser( parser: configparser.RawConfigParser, confmap: Config, defaults: Config, ) -> None: """Put values from `parser` to `confmap` using `defaults` as schema.""" for secname in parser.sections(): if secname not in confmap: confmap[secname] = {} for key in parser.options(secname): value = parser.get(secname, key) if ((sec := defaults.get(secname)) is not None) and ( (defval := sec.get(key)) is not None ): value = _parse_value(defval, value) confmap[secname][key] = value def _confmap_difference(conf: Config, defaults: Config) -> Config: """Extract the non-default keys to write out""" difference = {} for secname, section in conf.items(): if secname not in defaults: difference[secname] = section.copy() continue difference[secname] = {} for key, config_val in section.items(): if ( secname in defaults and key in defaults[secname] and defaults[secname][key] == config_val ): continue difference[secname][key] = config_val if not difference[secname]: difference.pop(secname) return difference def _fill_parser_from_config( parser: configparser.RawConfigParser, defaults: Config ) -> None: """Put content of `defaults` into `parser`.""" for secname in sorted(defaults): section = defaults[secname] if not parser.has_section(secname): parser.add_section(secname) for key in sorted(section): value = section[key] if isinstance(value, (tuple, list)): value = SettingsController.sep.join(value) elif isinstance(value, int): value = str(value) parser.set(secname, key, value) # pylint: disable=too-many-public-methods class SettingsController(GObject.GObject, pretty.OutputMixin): # type: ignore __gtype_name__ = "SettingsController" config_filename = "kupfer.cfg" defaults_filename = "defaults.cfg" sep = ";" default_directories = ( "~/", "~/Desktop", ) # Minimal "defaults" to define all fields # Read defaults defined in a defaults.cfg file _defaults: ty.Final[dict[str, ty.Any]] = { "Kupfer": { "keybinding": "", "magickeybinding": "", "showstatusicon": True, "showstatusicon_ai": False, "usecommandkeys": True, }, "Appearance": { "icon_large_size": 128, "icon_small_size": 24, "list_height": 200, }, "Directories": { "direct": default_directories, "catalog": (), }, "DeepDirectories": { "direct": (), "catalog": (), "depth": 1, }, "Keybindings": {}, "Tools": {}, } _inst: SettingsController | None = None @classmethod def instance(cls) -> SettingsController: """SettingsController is singleton; instance return one, global instance.""" if cls._inst is None: cls._inst = SettingsController() assert cls._inst return cls._inst def __init__(self) -> None: GObject.GObject.__init__(self) self._defaults_path: str | None = None self.encoding = _override_encoding(locale.getpreferredencoding()) self.output_debug("Using", self.encoding) self._config = self._read_config() self._save_timer = scheduler.Timer(True) self._alternatives: dict[str, ty.Any] = {} self._alternative_validators: dict[str, AltValidator | None] = {} def _update_config_save_timer(self) -> None: self._save_timer.set(60, self._save_config) def _read_config(self, read_config: bool = True) -> Config: """Read cascading config files: default -> then config (in all XDG_CONFIG_DIRS).""" parser = configparser.RawConfigParser() # Set up defaults confmap = copy.deepcopy(self._defaults) _fill_parser_read(parser, confmap) # Read all config files config_files: list[str] = [] try: defaults_path = config.get_data_file(self.defaults_filename) except config.ResourceLookupError: self.output_error( f"Error: no default config file {self.defaults_filename} " "found!" ) else: self._defaults_path = defaults_path config_files.append(defaults_path) if read_config and ( config_path := config.get_config_file(self.config_filename) ): config_files.append(config_path) for config_file in config_files: try: parser.read(config_file, encoding=self.encoding) except OSError as exc: # noqa:PERF203 self.output_error( f"Error reading configuration file {config_file}: {exc}" ) except UnicodeDecodeError as exc: self.output_error( f"Error reading configuration file {config_file}: {exc}" ) # Read parsed file into the dictionary again _fill_confmap_from_parser(parser, confmap, self._defaults) return confmap def _save_config(self, _scheduler: ty.Any = None) -> None: self.output_debug("Saving config") config_path = config.save_config_file(self.config_filename) if not config_path: self.output_info("Unable to save settings, can't find config dir") return # read in just the default values default_confmap = self._read_config(read_config=False) parser = configparser.RawConfigParser() confmap = _confmap_difference(self._config, default_confmap) _fill_parser_from_config(parser, confmap) ## Write to tmp then rename over for it to be atomic temp_config_path = f"{config_path}.{os.getpid()}" with open(temp_config_path, "w", encoding="UTF_8") as out: parser.write(out) os.rename(temp_config_path, config_path) def get_config(self, section: str, key: str) -> ty.Any: """General interface, but section must exist""" if section in self._defaults: key = key.lower() return self._config[section].get(key) raise KeyError(f"Invalid settings section: {section}") def set_config(self, section: str, key: str, value: ty.Any) -> bool: """General interface, but section must exist""" self.output_debug("Set", section, key, "to", value) key = key.lower() oldvalue = self._config[section].get(key) if section in self._defaults: if oldvalue is None: self._config[section][key] = str(value) else: self._config[section][key] = type(oldvalue)(value) self._emit_value_changed(section, key, value) self._update_config_save_timer() return True raise KeyError(f"Invalid settings section: {section}") def _emit_value_changed( self, section: str, key: str, value: ty.Any ) -> None: signal = f"value-changed::{section.lower()}.{key.lower()}" self.emit(signal, section, key, value) def _get_raw_config( self, section: str, key: str ) -> str | bool | int | float | None: """General interface, but section must exist""" key = key.lower() return self._config[section].get(key) def _set_raw_config( self, section: str, key: str, value: str | bool | float | None ) -> bool: """General interface, but will create section""" self.output_debug("Set", section, key, "to", value) if section not in self._config: self._config[section] = {} key = key.lower() self._config[section][key] = value self._update_config_save_timer() return False def _get_from_defaults( self, section: str, option: str ) -> str | bool | int | float | None: """Load values from default configuration file.""" if self._defaults_path is None: self.output_error("Defaults not found") return None parser = configparser.RawConfigParser() parser.read(self._defaults_path) return parser.get(section, option.lower()) def _get_from_defaults_section( self, section: str ) -> list[tuple[str, str]] | None: """Load values from default configuration file, return all section items as (key, value).""" if self._defaults_path is None: self.output_error("Defaults not found") return None parser = configparser.RawConfigParser() parser.read(self._defaults_path) return parser.items(section) def get_config_int(self, section: str, key: str) -> int: """section must exist""" if section not in self._defaults: raise KeyError(f"Invalid settings section: {section}") key = key.lower() value = self._config[section].get(key) return _strint(value) def get_plugin_enabled(self, plugin_id: str) -> bool: """Convenience: if @plugin_id is enabled""" return self.get_plugin_config_bool(plugin_id, "kupfer_enabled", False) def set_plugin_enabled(self, plugin_id: str, enabled: bool) -> bool: """Convenience: set if @plugin_id is enabled""" ret = self.set_plugin_config( plugin_id, "kupfer_enabled", enabled, value_type=_strbool ) self.emit("plugin-enabled-changed", plugin_id, enabled) return ret def get_plugin_is_hidden(self, plugin_id: str) -> bool: """Convenience: if @plugin_id is hidden""" return self.get_plugin_config_bool(plugin_id, "kupfer_hidden", False) @classmethod def _source_config_repr(cls, obj: ty.Any) -> str: name = type(obj).__name__ return "".join((c if c.isalnum() else "_") for c in name) def get_source_is_toplevel(self, plugin_id: str, src: ty.Any) -> bool: key = "kupfer_toplevel_" + self._source_config_repr(src) default = not getattr(src, "source_prefer_sublevel", False) return self.get_plugin_config_bool(plugin_id, key, default) def set_source_is_toplevel( self, plugin_id: str, src: ty.Any, value: bool ) -> bool: key = "kupfer_toplevel_" + self._source_config_repr(src) self.emit("plugin-toplevel-changed", plugin_id, value) return self.set_plugin_config( plugin_id, key, value, value_type=_strbool ) def get_keybinding(self) -> str: """Convenience: Kupfer keybinding as string""" return str(self.get_config("Kupfer", "keybinding")) def set_keybinding(self, keystr: str) -> bool: """Convenience: Set Kupfer keybinding as string""" return self.set_config("Kupfer", "keybinding", keystr) def get_magic_keybinding(self) -> str: """Convenience: Kupfer alternate keybinding as string""" return str(self.get_config("Kupfer", "magickeybinding")) def set_magic_keybinding(self, keystr: str) -> bool: """Convenience: Set alternate keybinding as string""" return self.set_config("Kupfer", "magickeybinding", keystr) def get_global_keybinding(self, key: str) -> str: if key == "keybinding": return self.get_keybinding() if key == "magickeybinding": return self.get_magic_keybinding() raise ValueError("invalid key {key}") def set_global_keybinding(self, key: str, val: str) -> bool: if key == "keybinding": return self.set_keybinding(val) if key == "magickeybinding": return self.set_magic_keybinding(val) return False def get_use_command_keys(self) -> bool: return _strbool(self.get_config("Kupfer", "usecommandkeys")) def set_use_command_keys(self, enabled: bool) -> bool: return self.set_config("Kupfer", "usecommandkeys", enabled) def get_action_accelerator_modifer(self) -> str: return str(self.get_config("Kupfer", "action_accelerator_modifer")) def set_action_accelerator_modifier(self, value: str) -> bool: """ Valid values are: 'alt', 'ctrl' """ return self.set_config("Kupfer", "action_accelerator_modifer", value) def set_large_icon_size(self, size: str) -> bool: return self.set_config("Appearance", "icon_large_size", size) def set_small_icon_size(self, size: str) -> bool: return self.set_config("Appearance", "icon_small_size", size) def get_show_status_icon(self) -> bool: """Convenience: Show icon in notification area as bool (GTK).""" return _strbool(self.get_config("Kupfer", "showstatusicon")) def set_show_status_icon(self, enabled: bool) -> bool: """Set config value and return success""" return self.set_config("Kupfer", "showstatusicon", enabled) def get_show_status_icon_ai(self) -> bool: """Convenience: Show icon in notification area as bool (AyatanaAppIndicator3)""" return _strbool(self.get_config("Kupfer", "showstatusicon_ai")) def set_show_status_icon_ai(self, enabled: bool) -> bool: """Set config value and return success""" return self.set_config("Kupfer", "showstatusicon_ai", enabled) def get_directories(self, direct: bool = True) -> ty.Iterator[str]: """Yield directories to use as directory sources""" specialdirs = { k: getattr(GLib.UserDirectory, k) for k in dir(GLib.UserDirectory) if k.startswith("DIRECTORY_") } def get_special_dir(opt): if opt.startswith("USER_"): opt = opt[5:] if opt in specialdirs: return GLib.get_user_special_dir(specialdirs[opt]) return None level = "Direct" if direct else "Catalog" for direc in self.get_config("Directories", level): dpath = get_special_dir(direc) yield dpath or os.path.abspath(os.path.expanduser(direc)) def set_directories(self, dirs: list[str]) -> bool: return self.set_config("Directories", "direct", dirs) def get_plugin_config( self, plugin: str, key: str, value_type: PlugConfigValueType = str, default: PlugConfigValue | None = None, ) -> PlugConfigValue | None: """Return setting @key for plugin names @plugin, try to coerce to type @value_type. Else return @default if does not exist, or can't be coerced """ plug_section = f"plugin_{plugin}" if plug_section not in self._config: return default val = self._get_raw_config(plug_section, key) if val is None: return default if isinstance(value_type, type) and issubclass( value_type, ExtendedSetting ): val_obj: ExtendedSetting = value_type() val_obj.load(plugin, key, val) return val_obj value = default try: if value_type is bool: value = _strbool(val) elif value_type is list: assert isinstance(val, str) value = _strlist(val) elif isinstance(value_type, type): value = value_type(val) elif isinstance(value_type, ValueConverter): value = value_type(val, default=default) # type: ignore except (ValueError, TypeError) as err: self.output_info(f"Error for load value {plug_section}.{key}", err) return value def get_plugin_config_bool( self, plugin: str, key: str, default: bool ) -> bool: res = self.get_plugin_config(plugin, key, _strbool, default) assert isinstance(res, bool) return res def set_plugin_config( self, plugin: str, key: str, value: PlugConfigValue, value_type: PlugConfigValueType = str, ) -> bool: """Try set @key for plugin names @plugin, coerce to @value_type first.""" plug_section = f"plugin_{plugin}" self._emit_value_changed(plug_section, key, value) value_repr: int | str | float | None if isinstance(value, ExtendedSetting): value_repr = value.save(plugin, key) elif value_type is list: value_repr = str(value) elif value is None or isinstance(value, (str, float, int)): value_repr = value return self._set_raw_config(plug_section, key, value_repr) def get_accelerator(self, name: str) -> str | None: res = self.get_config("Keybindings", name) assert res is None or isinstance(res, str) return res def set_accelerator(self, name: str, key: str) -> bool: return self.set_config("Keybindings", name, key) def get_accelerators(self) -> dict[str, ty.Any]: return self._config["Keybindings"] def reset_keybindings(self) -> None: if key := self._get_from_defaults("Kupfer", "keybinding"): self.set_keybinding(str(key)) if key := self._get_from_defaults("Kupfer", "magickeybinding"): self.set_magic_keybinding(str(key)) def reset_accelerators(self) -> None: for key, value in self._get_from_defaults_section("Keybindings") or (): self.set_config("Keybindings", key, value) def get_preferred_tool(self, tool_id: str) -> str | None: """Get preferred ID for a @tool_id. Supported: 'terminal', 'editor' """ res = self.get_config("Tools", tool_id) assert res is None or isinstance(res, str) return res def set_preferred_tool(self, tool_id: str, value: ty.Any) -> bool: return self.set_config("Tools", tool_id, value) ## Alternatives section ## Provide alternatives for each category ## for example the category "terminal" def get_valid_alternative_ids( self, category_key: str ) -> ty.Iterator[tuple[str, str]]: """Get a list of (id_, name) tuples for the given @category_key.""" if category_key not in self._alternative_validators: return validator = self._alternative_validators[category_key] for id_, alternative in self._alternatives[category_key].items(): if not validator or validator(alternative): name = alternative["name"] yield (id_, name) def get_all_alternatives(self, category_key: str) -> ty.Any: return self._alternatives[category_key] def get_preferred_alternative( self, category_key: str ) -> dict[str, ty.Any] | None: """Get preferred alternative dict for @category_key.""" tool_id = self.get_preferred_tool(category_key) alternatives = self._alternatives[category_key] if alt := alternatives.get(tool_id): assert not alt or isinstance(alt, dict) return alt self.output_debug("Warning, no configuration for", category_key) return next(iter(alternatives.values()), None) def update_alternatives( self, category_key: str, alternatives: dict[str, ty.Any], validator: AltValidator | None, ) -> None: self._alternatives[category_key] = alternatives self._alternative_validators[category_key] = validator self.emit("alternatives-changed::" + category_key, category_key) def get_ellipsize_mode(self) -> Pango.EllipsizeMode: if self.get_config("Appearance", "ellipsize_mode") == "1": return Pango.EllipsizeMode.END return Pango.EllipsizeMode.MIDDLE # Arguments: Section, Key, Value # Detailed by 'section.key' in lowercase GObject.signal_new( "value-changed", SettingsController, GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.DETAILED, GObject.TYPE_BOOLEAN, (GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_PYOBJECT), ) # Arguments: Plugin ID, Value GObject.signal_new( "plugin-enabled-changed", SettingsController, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_STRING, GObject.TYPE_INT), ) # Arguments: Plugin ID, Value GObject.signal_new( "plugin-toplevel-changed", SettingsController, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_STRING, GObject.TYPE_INT), ) # Arguments: Alternative-category # Detailed by: category key, in lowercase GObject.signal_new( "alternatives-changed", SettingsController, GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.DETAILED, GObject.TYPE_BOOLEAN, (GObject.TYPE_STRING,), ) # Get SettingsController instance get_settings_controller = SettingsController.instance def is_known_terminal_executable(exearg: str) -> bool: """Check is `exearg` is know terminal executable""" setctl = get_settings_controller() for term in setctl.get_all_alternatives("terminal").values(): if exearg == term["argv"][0]: return True return False def get_configured_terminal() -> dict[str, ty.Any] | None: """Return the configured Terminal object""" setctl = get_settings_controller() return setctl.get_preferred_alternative("terminal") kupfer-328/kupfer/core/sources.py000066400000000000000000000645261500175051100171550ustar00rootroot00000000000000from __future__ import annotations import gzip import hashlib import itertools import os import pickle import threading import time import traceback import typing as ty import weakref from collections import defaultdict from pathlib import Path from kupfer import config from kupfer.core import pluginload, plugins from kupfer.obj import Action, AnySource, Leaf, Source, TextSource from kupfer.obj.sources import MultiSource, SourcesSource from kupfer.support import conspickle, pretty, scheduler if ty.TYPE_CHECKING: from kupfer.obj.base import ActionGenerator __all__ = ( "InternalError", "PeriodicRescanner", "SourceController", "SourceDataPickler", "SourcePickler", "get_source_controller", ) class InternalError(Exception): pass class PeriodicRescanner(pretty.OutputMixin): """Periodically rescan a @catalog of sources. Do first rescan after @startup seconds, then followup with rescans in @period. Each campaign of rescans is separarated by @campaign seconds. Source may define own min rescan interval, so can be rescanned less frequently. Last rescan is hold in source last_scan property, so when zeroed - force load on next rescan. """ def __init__( self, period: int = 5, startup: int = 10, campaign: int = 60, min_rescan_interval: int = 900, ) -> None: self._startup = startup self._period = period self._campaign = campaign self._timer = scheduler.Timer() self._min_rescan_interval = min_rescan_interval self._catalog: ty.Iterable[Source] = [] self._catalog_cur: ty.Iterator[Source] | None = None def set_catalog(self, catalog: ty.Iterable[Source]) -> None: self._catalog = catalog self._catalog_cur = iter(self._catalog) self.output_debug(f"Registering new campaign, in {self._startup} s") self._timer.set(self._startup, self._new_campaign) def _new_campaign(self) -> None: self.output_info(f"Starting new campaign, interval {self._period} s") self._catalog_cur = iter(self._catalog) self._timer.set(self._period, self._periodic_rescan_helper) def _periodic_rescan_helper(self) -> None: # Advance until we find a source that was not recently rescanned for source in self._catalog_cur or (): # skip dynamic sources if source.is_dynamic(): continue # for old objects that may not have this attribute last_scan = getattr(source, "last_scan", 0) interval = max( getattr(source, "source_scan_interval", 0), self._min_rescan_interval, ) next_scan = last_scan + interval - time.time() if next_scan <= 0: self.output_debug(f"scanning {source}") self._start_source_rescan(source) return self.output_debug( f"source {source} up to date, next scan in {int(next_scan)}s" ) # No source to scan found self.output_info(f"Campaign finished, pausing {self._campaign} s") self._timer.set(self._campaign, self._new_campaign) def rescan_now(self, source: Source, force_update: bool = False) -> None: "Rescan @source immediately" if source.is_dynamic(): return # on initial rescan force update also "cached" source when there is no # items in cache. force_update |= ( isinstance(source.cached_items, (list, tuple)) and len(source.cached_items) == 0 ) self._rescan_source(source, force_update=force_update, campaign=False) def _start_source_rescan(self, source: Source) -> None: thread = threading.Thread( target=self._rescan_source, args=(source, True, True) ) thread.daemon = True thread.start() def _rescan_source( self, source: Source, force_update: bool = True, campaign: bool = False ) -> None: start = time.monotonic() try: leaves = source.get_leaves(force_update=force_update) or () cnt = sum(1 for leaf in leaves) duration = time.monotonic() - start self.output_info( f"scan {source}: {cnt} leaves in {duration:0.5f} s" ) except Exception as exc: self.output_error(f"Scanning {source}: {exc}") self.output_exc() if campaign: # try to process next source self._timer.set(self._period, self._periodic_rescan_helper) class SourcePickler(pretty.OutputMixin): """Takes care of pickling and unpickling Kupfer Sources.""" format_version = 5 name_template = "k%s-v%d.pickle.gz" def __init__(self) -> None: # TODO: check self.open = lambda f, mode: gzip.open(f, mode, compresslevel=3) # noqa:SIM115 @classmethod def should_use_cache(cls) -> bool: return config.has_capability("CACHE") @classmethod def should_use_cache_for_source(cls, source: Source) -> bool: return cls.should_use_cache() and source.source_use_cache def rm_old_cachefiles(self) -> None: """Checks if there are old cachefiles from last version, and deletes those""" home = config.get_cache_home() assert home for dpath, _dirs, files in os.walk(home): # Look for files matching beginning and end of # name_template, with the previous file version chead, ctail = self.name_template.split("%s") ctail = ctail % ((self.format_version - 1),) obsolete_files = [] for cfile in files: if cfile.startswith(chead) and cfile.endswith(ctail): cfullpath = os.path.join(dpath, cfile) obsolete_files.append(cfullpath) if obsolete_files: self.output_info( "Removing obsolete cache files:", *obsolete_files, sep="\n", ) for fpath in obsolete_files: # be overly careful assert fpath.startswith(home) assert "kupfer" in fpath Path(fpath).unlink() def get_filename(self, source: Source) -> str: """Return cache filename for @source""" # make sure we take the source name into account # so that we get a "break" when locale changes source_id = f"{source!r}{source}{source.version}" hash_str = hashlib.md5(source_id.encode("utf-8")).hexdigest() filename = self.name_template % (hash_str, self.format_version) home = config.get_cache_home() assert home return os.path.join(home, filename) def unpickle_source(self, source: Source) -> ty.Any: if not self.should_use_cache_for_source(source): return None if cached := self._unpickle_source(self.get_filename(source)): # check consistency if source == cached: return cached self.output_debug("Cached version mismatches", source) return None def _unpickle_source(self, pickle_file: str) -> ty.Any: try: pfile = Path(pickle_file).read_bytes() source = pickle.loads(pfile) assert isinstance(source, Source), "Stored object not a Source" sname = os.path.basename self.output_debug("Loading", source, "from", sname(pickle_file)) return source except OSError: return None except (pickle.PickleError, Exception) as exc: self.output_info(f"Error loading {pickle_file}: {exc}") return None def pickle_source(self, source: Source) -> bool: if self.should_use_cache_for_source(source): return self._pickle_source(self.get_filename(source), source) return False def _pickle_source(self, pickle_file: str, source: Source) -> bool: """When writing to a file, use pickle.dumps() and then write the file in one go. If the file is a gzip file, pickler's thousands of small writes are very slow.""" sname = os.path.basename self.output_debug("Storing", source, "as", sname(pickle_file)) Path(pickle_file).write_bytes( pickle.dumps(source, pickle.HIGHEST_PROTOCOL) ) return True class SourceDataPickler(pretty.OutputMixin): """Takes care of pickling and unpickling Kupfer Sources' configuration or data. The SourceDataPickler requires a protocol of three methods: config_save_name() Return an ascii name to be used as a token/key for the configuration config_save() Return an object to be saved as configuration config_restore(obj) Receive the configuration object `obj' to load """ format_version = 2 name_template = "config-%s-v%d.pickle" def __init__(self) -> None: self.open = open @classmethod def get_filename(cls, source: Source) -> str: """Return filename for @source""" assert hasattr(source, "config_save_name") name = source.config_save_name() filename = cls.name_template % (name, cls.format_version) filepath = config.save_config_file(filename) assert filepath return filepath @classmethod def source_has_config(cls, source: Source) -> ty.Any: return getattr(source, "config_save_name", None) def load_source(self, source: Source) -> None: if data := self._load_data(self.get_filename(source)): assert hasattr(source, "config_restore") source.config_restore(data) def _load_data(self, pickle_file: str) -> ty.Any: try: pfile = Path(pickle_file).read_bytes() data = conspickle.BasicUnpickler.loads(pfile) sname = os.path.basename(pickle_file) self.output_debug("Loaded configuration from", sname) return data # self.output_debug(data) except OSError: return None except (pickle.PickleError, Exception) as exc: self.output_error(f"Loading {pickle_file}: {exc}") return None def save_source(self, source: Source) -> bool: return self._save_data(self.get_filename(source), source) def _save_data(self, pickle_file: str, source: Source) -> bool: sname = os.path.basename(pickle_file) assert hasattr(source, "config_save") obj = source.config_save() try: data = pickle.dumps(obj, pickle.HIGHEST_PROTOCOL) except pickle.PickleError: self.output_error("Unable to save configuration for", source) self.output_error("Saving configuration raised an exception:") traceback.print_exc() self.output_error("Please file a bug report") data = None if data: self.output_debug("Storing configuration for", source, "as", sname) ## Write to temporary and rename into place tmp_pickle_file = f"{pickle_file}.{os.getpid()}" Path(tmp_pickle_file).write_bytes(data) os.rename(tmp_pickle_file, pickle_file) return True ## define type for Source subclass to prevent problems with mixins SourceSubclass = ty.TypeVar("SourceSubclass", bound=Source) # pylint: disable=too-many-instance-attributes,too-many-public-methods class SourceController(pretty.OutputMixin): """Control sources; loading, pickling, rescanning Call .add() to add sources. Call .initialize() before use commences. """ _instance: SourceController | None = None @classmethod def instance(cls) -> SourceController: """Get instance of SourceController (singleton)""" if cls._instance is None: cls._instance = SourceController() assert cls._instance return cls._instance def __init__(self): self._sources: set[Source] = set() self.action_decorators: dict[ty.Type[Leaf], set[Action]] = defaultdict( set ) self._rescanner = PeriodicRescanner(period=1) self._toplevel_sources: set[Source] = set() self._text_sources: set[TextSource] = set() self._content_decorators: dict[ty.Type[Leaf], set[ty.Type[Source]]] = ( defaultdict(set) ) self._action_generators: list[ActionGenerator] = [] # map any object defined in plugin to plugin id self._plugin_object_map: weakref.WeakKeyDictionary[ty.Any, str] = ( weakref.WeakKeyDictionary() ) self._loaded_successfully = False self._did_finalize_sources = False # _pre_root cache root sources self._pre_root: list[Source] | None = None def add( self, plugin_id: str | None, srcs: ty.Iterable[Source], toplevel: bool = False, initialize: bool = False, ) -> None: self._invalidate_root() new_srcs = set(self._try_restore(srcs)) new_srcs.update(srcs) self._sources.update(new_srcs) if toplevel: self._toplevel_sources.update(new_srcs) if initialize: self._initialize_sources(new_srcs) self._cache_sources(new_srcs) self._rescanner.set_catalog(self._sources) if plugin_id: self._register_plugin_objects(plugin_id, *new_srcs) def set_toplevel(self, src: Source, toplevel: bool) -> None: assert src in self._sources, ( "Source is not tracked in SourceController" ) self._invalidate_root() if toplevel: self._toplevel_sources.add(src) else: self._toplevel_sources.discard(src) def _register_plugin_objects( self, plugin_id: str, *objects: ty.Any ) -> None: """Register a plugin id mapping for @objects""" for obj in objects: self._plugin_object_map[obj] = plugin_id pretty.print_debug(__name__, "Add", obj) def _remove(self, src: Source) -> None: self._invalidate_root() self._toplevel_sources.discard(src) self._sources.discard(src) self._rescanner.set_catalog(self._sources) self._finalize_source(src) pretty.print_debug(__name__, "Remove", src) def get_plugin_id_for_object(self, obj: ty.Any) -> str | None: return self._plugin_object_map.get(obj) def remove_objects_for_plugin_id(self, plugin_id: str) -> bool: """Remove all objects for @plugin_id Return True if the catalog configuration changed """ removed_source = False self.output_debug("Removing objects for plugin:", plugin_id) # sources for src in list(self._sources): if self.get_plugin_id_for_object(src) == plugin_id: self._remove(src) removed_source = True # all other objects def remove_matching_objects(collection, plugin_id): for obj in list(collection): if self.get_plugin_id_for_object(obj) == plugin_id: collection.remove(obj) pretty.print_debug(__name__, "Remove", obj) remove_matching_objects(self._text_sources, plugin_id) for typ_v in self._content_decorators.values(): remove_matching_objects(typ_v, plugin_id) for a_typ_v in self.action_decorators.values(): remove_matching_objects(a_typ_v, plugin_id) remove_matching_objects(self._action_generators, plugin_id) return removed_source def get_sources(self) -> set[Source]: return self._sources def add_text_sources(self, plugin_id, srcs): self._text_sources.update(srcs) self._register_plugin_objects(plugin_id, *srcs) def get_text_sources(self) -> set[TextSource]: return self._text_sources def add_content_decorators( self, plugin_id: str, decos: dict[ty.Type[Leaf], set[ty.Type[Source]]], ) -> None: for typ, val in decos.items(): self._content_decorators[typ].update(val) self._register_plugin_objects(plugin_id, *val) def add_action_decorators( self, plugin_id: str, decos: dict[ty.Type[Leaf], list[Action]] ) -> None: for typ, val in decos.items(): self.action_decorators[typ].update(val) self._register_plugin_objects(plugin_id, *val) for typ_v in self.action_decorators.values(): self._disambiguate_actions(typ_v) def add_action_generator( self, plugin_id: str, agenerator: ActionGenerator ) -> None: self._action_generators.append(agenerator) self._register_plugin_objects(plugin_id, agenerator) def _disambiguate_actions(self, actions: ty.Iterable[Action]) -> None: """Rename actions by the same name (adding a suffix)""" names: dict[str, Action] = {} renames = set() for action in actions: name = str(action) if name in names: renames.add(names[name]) renames.add(action) else: names[name] = action for action in renames: self.output_debug(f"Disambiguate Action {action}") plugin_name = plugins.get_plugin_name(type(action).__module__) plugin_suffix = f" ({plugin_name})" if not action.name.endswith(plugin_suffix): action.name += plugin_suffix def __contains__(self, src: Source) -> bool: return src in self._sources def __getitem__(self, src: Source) -> Source: for source in self._sources: if source == src: return source raise KeyError @property def root(self) -> Source | None: """Get the root source of catalog""" if len(self._sources) == 1: (root_catalog,) = self._sources # pylint: disable=unbalanced-tuple-unpacking elif len(self._sources) > 1: root_catalog = MultiSource(self.firstlevel) else: root_catalog = None return root_catalog def _invalidate_root(self) -> None: "The source root needs to be recalculated" self._pre_root = None @property def firstlevel(self) -> list[Source]: if self._pre_root: return self._pre_root sourceindex = self._sources.copy() kupfer_sources = SourcesSource(self._sources) sourceindex.add(kupfer_sources) # Make sure firstlevel is ordered # So that it keeps the ordering.. SourcesSource first firstlevel: list[Source] = [SourcesSource(sourceindex)] firstlevel.extend(self._toplevel_sources) self._pre_root = firstlevel return firstlevel @classmethod def good_source_for_types( cls, source: AnySource, types: tuple[ty.Any, ...] ) -> bool: """return whether @s provides good leaves for @types""" if provides := list(source.provides()): return any(issubclass(t, types) for t in provides) return True def root_for_types( self, types: ty.Iterable[ty.Any], extra_sources: ty.Iterable[Source] | None = None, ) -> MultiSource: """Get root for a flat catalog of all catalogs providing at least Leaves of @types. types: Iterable of classes extra_sources: Sources to include Take all sources which: Provide a type T so that it is a subclass to one in the set of types we want """ ttypes: tuple[ty.Any, ...] = tuple(types) firstlevel = set(extra_sources or []) # include the Catalog index since we want to include # the top of the catalogs (like $HOME) catalog_index = (SourcesSource(self._sources),) firstlevel.update( s for s in itertools.chain(self._sources, catalog_index) if self.good_source_for_types(s, ttypes) ) return MultiSource(firstlevel) def get_canonical_source(self, src: AnySource) -> AnySource: """Return the canonical instance for @source""" # check if we already have source, then return that if not isinstance(src, Source): return src try: return self[src] except KeyError: src.initialize() return src def get_contents_for_leaf( self, leaf: Leaf, types: tuple[ty.Any, ...] | None = None ) -> ty.Iterator[AnySource]: """Iterator of content sources for @leaf, providing @types (or None for all)""" for typ, val in self._content_decorators.items(): if not isinstance(leaf, typ): continue for content in val: with pluginload.exception_guard( content, self._remove_source, content, is_decorator=True ): dsrc = content.decorate_item(leaf) # type: ignore if not dsrc: continue if types and not self.good_source_for_types(dsrc, types): continue yield self.get_canonical_source(dsrc) def get_actions_for_leaf(self, leaf: Leaf) -> ty.Iterator[Action]: for typ, val in self.action_decorators.items(): if isinstance(leaf, typ): yield from val for agenerator in self._action_generators: yield from agenerator.get_actions_for_leaf(leaf) def decorate_object(self, obj: Leaf, action: Action | None = None) -> None: """If `obj` may have content (Source) and currently there is no assigned content - get sources for `obj` and optional `action` and add it into obj. Multiple sources are packed into SourcesSource. WARN: obj is updated in packet """ if hasattr(obj, "has_content") and not obj.has_content(): types = tuple(action.object_types()) if action else () contents = tuple(self.get_contents_for_leaf(obj, types)) if not contents: obj.add_content(None) elif len(contents) == 1: assert isinstance(contents[0], Source) obj.add_content(contents[0]) else: assert isinstance(contents[0], Source) sources = ty.cast("ty.Collection[Source]", contents) obj.add_content( SourcesSource(sources, name=str(obj), use_reprs=False) ) def finalize(self) -> None: """Finalize all sources, equivalent to deactivating all sources""" for src in self._sources: src.finalize() self._did_finalize_sources = True def save_cache(self) -> None: """Save all caches (non-important data)""" if not self._did_finalize_sources: raise InternalError("Called save_cache without finalize!") if self._loaded_successfully: self._pickle_sources(self._sources) else: self.output_debug("Not writing cache on failed load") def save_data(self) -> None: """Save (important) user data/configuration""" if not self._loaded_successfully: self.output_info("Not writing configuration on failed load") return configsaver = SourceDataPickler() for source in self._sources: if configsaver.source_has_config(source): self._save_source(source, pickler=configsaver) @classmethod def _save_source(cls, source: Source, pickler: ty.Any = None) -> None: configsaver = pickler or SourceDataPickler() configsaver.save_source(source) def _finalize_source(self, source: Source) -> None: """Either save config, or save cache for @source""" source.finalize() if SourceDataPickler.source_has_config(source): self._save_source(source) elif not source.is_dynamic(): self._pickle_source(source) def _pickle_sources(self, sources: ty.Iterable[Source]) -> None: sourcepickler = SourcePickler() sourcepickler.rm_old_cachefiles() for source in sources: if source.is_dynamic() or SourceDataPickler.source_has_config( source ): continue self._pickle_source(source, pickler=sourcepickler) @classmethod def _pickle_source(cls, source: Source, pickler: ty.Any = None) -> None: sourcepickler = pickler or SourcePickler() sourcepickler.pickle_source(source) def _try_restore(self, srcs: ty.Iterable[Source]) -> ty.Iterator[Source]: """Try to restore the source that is equivalent to the "dummy" instance @source, from cache, or from saved configuration. yield the instances that succeed. """ sourcepickler = SourcePickler() configsaver = SourceDataPickler() for source in srcs: if configsaver.source_has_config(source): configsaver.load_source(source) else: source = sourcepickler.unpickle_source(source) # noqa:PLW2901 if source: yield source def _remove_source( self, source: Source, is_decorator: bool = False ) -> None: """Oust @source from catalog if any exception is raised""" if not is_decorator: self._sources.discard(source) self._toplevel_sources.discard(source) source_type = type(source) else: source_type = ty.cast("ty.Type[Source]", source) for cdv in self._content_decorators.values(): cdv.discard(source_type) def initialize(self) -> None: """Initialize all sources and cache toplevel sources""" self._initialize_sources(self._sources) self._rescanner.set_catalog(self._sources) self._cache_sources(self._toplevel_sources) self._loaded_successfully = True def _initialize_sources(self, srcs: ty.Iterable[Source]) -> None: for src in srcs: with pluginload.exception_guard(src, self._remove_source, src): src.initialize() def _cache_sources(self, srcs: ty.Iterable[Source]) -> None: # Make sure that the toplevel sources are cached # either newly rescanned or the cache is fully loaded self.output_info("Initial sources load") for src in srcs: with pluginload.exception_guard(src, self._remove_source, src): self._rescanner.rescan_now(src, force_update=False) get_source_controller = SourceController.instance kupfer-328/kupfer/desktop_launch.py000066400000000000000000000344111500175051100175330ustar00rootroot00000000000000from __future__ import annotations import os import typing as ty from contextlib import suppress from dataclasses import dataclass from pathlib import Path import xdg.DesktopEntry import xdg.Exceptions from gi.repository import Gdk, Gio, GLib, Gtk from kupfer.core import settings from kupfer.support import desktop_parse, pretty from kupfer.support import itertools as kitertools __all__ = ["launch_app_info", "spawn_app", "spawn_app_id"] STARTUP_ENV = "DESKTOP_STARTUP_ID" # TODO: Broadcast Gio's launched message on dbus # NOTE: GDK's startup notification things that we use # are really only sending xmessages. (roughly). class SpawnError(Exception): """Error starting application""" class ResourceLookupError(Exception): """Unable to find resource""" class ResourceReadError(Exception): """Unable to open resource""" def _find_desktop_file(desk_id: str) -> str: """Find file for @desk_id or raise ResourceLookupError Desktop files are found by appending /applications/ to $XDG_DATA_DIRS, but if they are located in subdirs of that, then additional 'subdirectory-' prefixes are used. """ if not desk_id: raise ResourceLookupError("Empty id") try: return next(xdg.BaseDirectory.load_data_paths("applications", desk_id)) # type: ignore except StopIteration: ## it was not found as an immediate child of the data paths, ## so we split by the hyphens and search deeper file_id = desk_id directories = ["applications"] def lookup(path: list[str]) -> str | None: """Return location for @path if exists, else none""" return next(xdg.BaseDirectory.load_data_paths(*path), None) def get_dir_id_depth(desk_id: str, depth: int) -> tuple[str, str]: "split 'hyph-example-id' at the nth hyphen" parts = desk_id.split("-", depth) return "-".join(parts[:depth]), "-".join(parts[depth:]) while True: ## try the first parts of the id to see if it matches a directory for x in range(1, 4): dirname, rest_id = get_dir_id_depth(file_id, x) if rest_id and lookup([*directories, dirname]): file_id = rest_id directories.append(dirname) break else: ## we did not reach break break if desktop_file_path := lookup([*directories, file_id]): return desktop_file_path raise ResourceLookupError(f"Cannot locate '{desk_id}'") def _read_desktop_info(desktop_file: str) -> dict[str, str | bool]: """Get the keys StartupNotify, Terminal, Exec, Path, Icon. Return dict with bool and unicode values.""" # Return values in unicode try: entry = xdg.DesktopEntry.DesktopEntry(desktop_file) except xdg.Exceptions.Error as exc: raise ResourceReadError from exc if not entry.getExec(): raise ResourceReadError("Invalid data: empty Exec key") return { "Terminal": entry.getTerminal(), "StartupNotify": entry.getStartupNotify(), "Exec": entry.getExec(), "Path": entry.getPath(), "Icon": entry.getIcon(), "Name": entry.getName(), } def _app_to_desktop_info(app_info: Gio.AppInfo) -> dict[str, str | bool]: return { "Exec": app_info.get_commandline() or "", "Name": app_info.get_name(), "Icon": "", "Path": "", "Terminal": False, "StartupNotify": False, } def _get_file_path(gfile: Gio.File) -> str: if gfile: return ty.cast("str", gfile.get_path() or gfile.get_uri()) return "" @dataclass class _Flags: did_see_small_f: bool = False did_see_large_f: bool = False # pylint: disable=too-many-locals def _replace_format_specs( argv: list[str], location: str, desktop_info: dict[str, ty.Any], gfilelist: list[Gio.File], ) -> tuple[bool, bool, list[str]]: """ http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s06.html Replace format specifiers %% literal % %f file %F list of files %u URL %U list of URLs %i --icon %c Translated name %k location of .desktop file deprecated are removed: %d %D %n %N %v %m apart from those, all other.. stay and are ignored Like other implementations, we do actually insert a local path for %u and %U if it exists. Return (supports_single, added_at_end, argv) supports_single: Launcher only supports a single file caller has to re-call for each file added_at_end: No format found for the file, it was added at the end """ supports_single_file = False files_added_at_end = False flags = _Flags() fileiter = iter(gfilelist) def get_next_file_path() -> str: with suppress(StopIteration): file = next(fileiter) return _get_file_path(file) return "" # pylint: disable=too-many-return-statements def replace_single_code(key: str) -> str | None: # noqa: PLR0911 "Handle all embedded format codes, including those to be removed" if key in ("%d", "%D", "%n", "%N", "%v", "%m"): # deprecated keys return "" if key == "%%": return "%" if key in ("%f", "%u"): if flags.did_see_large_f or flags.did_see_small_f: pretty.print_debug( __name__, "Warning, multiple file format specs!" ) return "" flags.did_see_small_f = True return get_next_file_path() if key == "%c": return desktop_info["Name"] or location if key == "%k": return location return None def replace_array_format(elem: str) -> tuple[bool, str | list[str]]: """Handle array format codes -- only recognized as single arguments Return flag, arglist where flag is true if something was replaced """ if elem in ("%U", "%F"): if flags.did_see_large_f or flags.did_see_small_f: pretty.print_debug( __name__, "Warning, multiple file format specs!" ) return True, [] flags.did_see_large_f = True return True, list(filter(bool, map(_get_file_path, gfilelist))) if elem == "%i": if desktop_info["Icon"]: return True, ["--icon", desktop_info["Icon"]] return True, [] return False, elem new_argv: list[str] = [] for x in argv: if not x: # the arg is an empty string, we don't need extra processing new_argv.append(x) continue succ, newargs = replace_array_format(x) if succ: new_argv.extend(newargs) elif arg := kitertools.two_part_mapper(x, replace_single_code): # Handle embedded format codes new_argv.append(arg) if len(gfilelist) > 1 and not flags.did_see_large_f: supports_single_file = True if not flags.did_see_small_f and not flags.did_see_large_f and gfilelist: files_added_at_end = True new_argv.append(get_next_file_path()) return supports_single_file, files_added_at_end, new_argv def _file_for_app_info(app_info: Gio.AppInfo) -> str | None: try: return _find_desktop_file(app_info.get_id()) except ResourceLookupError: pretty.print_exc(__name__) return None def _info_for_desktop_file( desktop_file: str | None, ) -> dict[str, ty.Any] | None: if desktop_file: try: return _read_desktop_info(desktop_file) except ResourceReadError: pretty.print_exc(__name__) return None # pylint: disable=too-few-public-methods @ty.runtime_checkable class LaunchCallback(ty.Protocol): def __call__( self, argv: list[str], pid: int, notify_id: int | None, filelist: list[str], timestamp: int | None, /, ) -> None: ... # pylint: disable=too-many-locals def launch_app_info( # noqa:PLR0912 app_info: Gio.AppInfo, gfiles: ty.Iterable[Gio.File] | None = None, in_terminal: bool | None = None, timestamp: int | None = None, desktop_file: str | None = None, launch_cb: LaunchCallback | None = None, screen: Gdk.Screen | None = None, work_dir: str | None = None, ) -> bool: """Launch @app_info, opening @gfiles. @in_terminal: override Terminal flag @timestamp: override timestamp @desktop_file: specify location of desktop file @launch_cb: Called once per launched process, like ``spawn_app`` @work_dir: overwrite work dir of application. By default it's "Path" parameter in desktop file. Will pass on exceptions from spawn_app """ gfiles = list(gfiles or []) desktop_file = desktop_file or _file_for_app_info(app_info) desktop_info = _info_for_desktop_file(desktop_file) if not desktop_file or not desktop_info: # Allow in-memory app_info creations (without id or desktop file) desktop_file = "" desktop_info = _app_to_desktop_info(app_info) # in this case, the command line is already primarily escaped desktop_exe = desktop_info["Exec"] assert desktop_exe and isinstance(desktop_exe, str) argv = desktop_parse.parse_argv(desktop_exe) else: # In the normal case, we must first escape one round argv = desktop_parse.parse_unesc_argv(desktop_info["Exec"]) assert argv and argv[0] # Now Resolve the %f etc format codes multiple_needed, _missing_format, launch_argv = _replace_format_specs( argv, desktop_file, desktop_info, gfiles ) if not multiple_needed: # Launch 1 process launch_records = [(launch_argv, gfiles)] else: # Launch one process per file launch_records = [(launch_argv, [gfiles[0]])] for file in gfiles[1:]: *_ignore, launch_argv = _replace_format_specs( argv, desktop_file, desktop_info, [file] ) launch_records.append((launch_argv, [file])) notify = bool(desktop_info["StartupNotify"]) if not work_dir: work_dir = ty.cast("ty.Optional[str]", desktop_info["Path"]) if in_terminal is None: in_terminal = bool(desktop_info["Terminal"]) if in_terminal: term = settings.get_configured_terminal() if term: notify = notify or bool(term["startup_notify"]) for argv, files in launch_records: if in_terminal and term: targv = list(term["argv"]) if exearg := term["exearg"]: targv.append(exearg) argv = targv + argv # noqa: PLW2901 if not spawn_app( app_info, argv, files, work_dir, notify, timestamp=timestamp, launch_cb=launch_cb, screen=screen, ): return False return True def spawn_app_id( app_id: str, argv: list[str], workdir: str | None = None, startup_notify: bool = True, screen: Gdk.Screen | None = None, ) -> bool: """Spawn @argv trying to notify it as if it is app_id.""" try: app_info = _get_info_for_id(app_id) except (TypeError, RuntimeError): app_info = None startup_notify = False return bool( spawn_app(app_info, argv, [], workdir, startup_notify, screen=screen) ) def spawn_app( app_info: Gio.AppInfo | None, argv: list[str], filelist: list[ty.Any], workdir: str | None = None, startup_notify: bool = True, timestamp: int | None = None, launch_cb: LaunchCallback | None = None, screen: Gdk.Screen | None = None, ) -> int: """Spawn app. @argv: argument list including files @workdir: where to set workdir if not cwd @app_info: Used for startup notification, if @startup_notify is True @filelist: Used for startup notification @startup_notify: Use startup notification @timestamp: Event timestamp @launch_cb: Called if successful with (argv, pid, notify_id, filelist, timestamp) @screen: GdkScreen on which to put the application return pid if successful raise SpawnError on error """ notify_id = None if startup_notify: display = Gdk.Display.get_default() ctx = display.get_app_launch_context() ctx.set_timestamp(timestamp or Gtk.get_current_event_time()) if screen: ctx.set_screen(screen) # This not only returns the string ID but # it actually starts the startup notification! notify_id = ctx.get_startup_notify_id(app_info, filelist) child_env_add = {STARTUP_ENV: notify_id} else: child_env_add = {} if not workdir or not Path(workdir).exists(): workdir = "." argv_ = list(_locale_encode_argv(argv)) pid: int try: pid, *_ig = GLib.spawn_async( argv_, flags=GLib.SpawnFlags.SEARCH_PATH, working_directory=workdir, child_setup=child_setup, user_data=child_env_add, ) pretty.print_debug(__name__, "Launched", argv_, notify_id, "pid:", pid) except GLib.GError as exc: pretty.print_error(__name__, "Error Launching ", argv_, str(exc)) if notify_id: Gdk.notify_startup_complete_with_id(notify_id) raise SpawnError(exc.message) from exc # pylint: disable=no-member if launch_cb: launch_cb(argv, pid, notify_id, filelist, timestamp) return pid def child_setup(add_environ: dict[str, str]) -> None: """Called to setup the child process before exec() @add_environ is a dict for extra env variables """ for key, val in add_environ.items(): os.putenv(key, val) def _locale_encode_argv(argv: list[str] | list[bytes]) -> ty.Iterator[str]: for x in argv: if isinstance(x, str): yield x else: yield x.decode("UTF-8", "replace") def _get_info_for_id(app_id: str) -> Gio.DesktopAppInfo: return Gio.DesktopAppInfo.new(app_id) if __name__ == "__main__": while True: id_ = input("Give me an App ID > ") launch_app_info(_get_info_for_id(id_ + ".desktop"), []) # launch_app_info(Gio.AppInfo("gvim"), [Gio.File(".")]) kupfer-328/kupfer/environment.py000066400000000000000000000022551500175051100170750ustar00rootroot00000000000000from __future__ import annotations import os try: from gi.repository import Wnck except ImportError: Wnck = None from kupfer import config from kupfer.support import datatools, pretty __all__ = ("allows_keybinder", "is_kwin", "is_wayland") @datatools.evaluate_once def is_kwin() -> bool: """Try to figure out if KWin is the current window manager. If Wnck unavailable try guess from environment variables. """ if Wnck and (screen := Wnck.Screen.get_default()) is not None: winmgr: str | None = screen.get_window_manager_name() pretty.print_debug(__name__, "window manager is", winmgr) if winmgr: return winmgr.lower() == "kwin" return _desktop_environment_guess().lower() == "kde" def _desktop_environment_guess() -> str: ret = os.getenv("XDG_CURRENT_DESKTOP") or "" pretty.print_debug(__name__, "desktop environment is", ret) return ret def is_wayland() -> bool: """Check is Wayland is current graphics environment""" return bool(os.getenv("WAYLAND_DISPLAY")) def allows_keybinder() -> bool: """Check is keybinder available.""" return config.has_capability("KEYBINDER") and not is_wayland() kupfer-328/kupfer/icons.py000066400000000000000000000431441500175051100156460ustar00rootroot00000000000000from __future__ import annotations import typing as ty from contextlib import suppress from gi.repository import GdkPixbuf, Gio, Gtk from gi.repository.Gio import ( FILE_ATTRIBUTE_STANDARD_ICON, FILE_ATTRIBUTE_THUMBNAIL_PATH, File, FileIcon, Icon, ThemedIcon, ) from gi.repository.GLib import GError from kupfer.core import settings from kupfer.support import datatools, pretty, scheduler __all__ = ( "ComposedIcon", "ComposedIconSmall", "IconRenderer", "get_gicon_for_file", "get_gicon_for_names", "get_gicon_from_file", "get_gicon_with_fallbacks", "get_good_name_for_icon_names", "get_icon_for_gicon", "get_icon_for_name", "get_icon_from_file", "get_pixbuf_from_data", "get_pixbuf_from_file", "get_thumbnail_for_gfile", "is_good_gicon", "parse_load_icon_list", ) _ICON_CACHE: ty.Final[ datatools.LruCache[tuple[int, str], GdkPixbuf.Pixbuf] ] = datatools.LruCache(128, name="_ICON_CACHE") _LARGE_SZ = 128 _SMALL_SZ = 24 ## default fallbacks for our themable icons _KUPFER_ICON_FALLBACKS: ty.Final = { "kupfer-execute": "system-run", "kupfer-object": "text-x-generic", "kupfer-object-multiple": "folder", "kupfer-catalog": "system-search", "kupfer-search": "system-search", } _KUPFER_LOCALLY_INSTALLED_NAMES: ty.Final[set[str]] = set() def _on_icon_theme_changed(theme): pretty.print_info(__name__, "Icon theme changed, clearing cache") _ICON_CACHE.clear() _default_theme = Gtk.IconTheme.get_default() # pylint: disable=no-member _default_theme.connect("changed", _on_icon_theme_changed) _local_theme = Gtk.IconTheme.new() _local_theme.set_search_path([]) def parse_load_icon_list( icon_list_data: bytes, get_data_func: ty.Callable[[str], bytes], plugin_name: str | None = None, ) -> None: """ @icon_list_data: A bytestring whose lines identify icons @get_data_func: A function to return the data for a relative filename @plugin_name: plugin id, if applicable """ try: icon_list_string = icon_list_data.decode("utf-8") except UnicodeDecodeError as exc: pretty.print_error( __name__, f"Malformed icon-list in plugin {plugin_name!r}: {exc!r}", ) raise for line in icon_list_string.splitlines(): # ignore '#'-comments if line.startswith("#") or not line.strip(): continue fields = tuple(map(str.strip, line.split("\t", 2))) if len(fields) <= 1: pretty.print_error( __name__, "Malformed icon-list line {line!r} from {plugin_name!r}", ) continue icon_name, basename, *_tail = fields override = "!override" in fields _load_icon_from_func( plugin_name, icon_name, get_data_func, override, func_args=basename ) def _load_icon_from_func( plugin_name: str | None, icon_name: str, get_data_func: ty.Callable[[str], bytes], override: bool, func_args: str, ) -> None: """ Load icon from @icon_data into the name @icon_name @get_data_func: function to retrieve the data if needed @override: override the icon theme """ if not override and icon_name in _KUPFER_LOCALLY_INSTALLED_NAMES: pretty.print_debug(__name__, "Skipping existing", icon_name) return if not override and _default_theme.has_icon(icon_name): pretty.print_debug(__name__, "Skipping themed icon", icon_name) return try: icon_data = get_data_func(func_args) except Exception: pretty.print_error( __name__, f"Error loading icon {icon_name!r} for {plugin_name!r}" ) pretty.print_exc(__name__) return for size in (_SMALL_SZ, _LARGE_SZ): pixbuf = get_pixbuf_from_data(icon_data, size, size) Gtk.IconTheme.add_builtin_icon( # pylint: disable=no-member icon_name, size, pixbuf ) pretty.print_debug( __name__, "Loading icon", icon_name, "at", size, "for", plugin_name ) _KUPFER_LOCALLY_INSTALLED_NAMES.add(icon_name) def _get_icon(key: str, icon_size: int) -> ty.Iterator[GdkPixbuf.Pixbuf]: """ try retrieve icon in cache is a generator so it can be concisely called with a for loop FIXME: not used (?) """ with suppress(KeyError): yield _ICON_CACHE[(icon_size, key)] def _store_icon(key: str, icon_size: int, icon: GdkPixbuf.Pixbuf) -> None: """ Store an icon in cache. It must not have been stored before """ assert icon, f"icon {key} may not be {icon}" _ICON_CACHE[(icon_size, key)] = icon def _get_icon_dwim( icon: ty.Union[Icon, str], icon_size: int ) -> GdkPixbuf.Pixbuf | None: """Make an icon at @icon_size where @icon can be either an icon name, or a gicon """ if isinstance(icon, Icon): return get_icon_for_gicon(icon, icon_size) if icon: return get_icon_for_name(icon, icon_size) pretty.print_debug(__name__, "_get_icon_dwim failed for", icon, icon_size) return None # pylint: disable=too-few-public-methods class ComposedIcon: """ A composed icon, which kupfer will render to pixbuf as background icon with the decorating icon as emblem If `emblem_is_fallback` is True, use emblem if rendered icon is smaller than `minimum_icon_size`. ComposedIcon is cached, i.e. when ComposedIcon is created first cache is checked if there is already object with the same parameters. If yes - its returned, otherwise new object is created. Icon itself is rendered only once. """ _cache: datatools.LruCache[tuple[ty.Any, ...], GdkPixbuf.Pixbuf | None] = ( datatools.LruCache(32, name="ComposedIcon cache") ) __slots__ = ( "_rendered", "_rendered_size", "baseicon", "emblem_is_fallback", "emblemicon", "minimum_icon_size", ) def __init__( self, baseicon: GIcon | str, emblem: GIcon | str, emblem_is_fallback: bool = False, minimum_icon_size: int = 48, ) -> None: self.minimum_icon_size = minimum_icon_size self.baseicon = baseicon self.emblemicon = emblem self.emblem_is_fallback = emblem_is_fallback @classmethod def new(cls, *args, **kwargs): """Construct a composed icon from @baseicon and @emblem, which may be GIcons or icon names (strings) """ return cls(*args, **kwargs) def render_composed_icon(self, icon_size: int) -> GdkPixbuf.Pixbuf | None: key = ( self.baseicon, self.emblemicon, self.emblem_is_fallback, self.minimum_icon_size, icon_size, ) with suppress(KeyError): return ComposedIcon._cache[key] # If it's too small, render as fallback icon if icon_size < self.minimum_icon_size: if self.emblem_is_fallback: icon = _get_icon_for_standard_gicon(self.emblemicon, icon_size) else: icon = _get_icon_for_standard_gicon(self.baseicon, icon_size) ComposedIcon._cache[key] = icon return icon toppbuf = _get_icon_dwim(self.emblemicon, icon_size) bottompbuf = _get_icon_dwim(self.baseicon, icon_size) if not toppbuf or not bottompbuf: ComposedIcon._cache[key] = None return None dest = bottompbuf.copy() # @frac is the scale frac = 0.6 dcoord = int((1 - frac) * icon_size) dsize = int(frac * icon_size) # http://library.gnome.org/devel/gdk-pixbuf/unstable//gdk-pixbuf-scaling.html toppbuf.composite( dest, dcoord, dcoord, dsize, dsize, dcoord, dcoord, frac, frac, GdkPixbuf.InterpType.BILINEAR, 255, ) ComposedIcon._cache[key] = dest return dest # pylint: disable=invalid-name def ComposedIconSmall( # noqa:N802 baseicon: GIcon | str, emblem: GIcon | str, **kwargs: ty.Any ) -> ComposedIcon: """Create composed icon for leaves with emblem visible on browser list""" return ComposedIcon( baseicon, emblem, minimum_icon_size=_SMALL_SZ, **kwargs ) GIcon = ty.Union[ComposedIcon, ThemedIcon, FileIcon] def get_thumbnail_for_gfile( gfile: Gio.File, width: int = -1, height: int = -1 ) -> GdkPixbuf.Pixbuf | None: """ Return a Pixbuf thumbnail for the file at gfile: Gio.File size is @width x @height return None if not found """ if not gfile.query_exists(): return None finfo = gfile.query_info( FILE_ATTRIBUTE_THUMBNAIL_PATH, Gio.FileQueryInfoFlags.NONE, None ) thumb_path = finfo.get_attribute_byte_string(FILE_ATTRIBUTE_THUMBNAIL_PATH) return get_pixbuf_from_file(thumb_path, width, height) def get_pixbuf_from_file( thumb_path: str | None, width: int = -1, height: int = -1 ) -> GdkPixbuf.Pixbuf | None: """ Return a Pixbuf thumbnail for the file at @thumb_path sized @width x @height For non-icon pixbufs: We might cache these, but on different terms than the icon cache if @thumb_path is None, return None """ if not thumb_path: return None try: return GdkPixbuf.Pixbuf.new_from_file_at_size( thumb_path, width, height ) except GError as exc: # this error is not important, the program continues on fine, # so we put it in debug output. pretty.print_debug( __name__, "get_pixbuf_from_file file:", thumb_path, "error:", exc ) return None _GICON_CACHE: datatools.LruCache[str, GIcon | None] = datatools.LruCache( 128, name="_GICON_CACHE" ) def get_gicon_for_file(uri: str) -> GIcon | None: """ Return a GIcon representing the file at the @uri, which can be *either* and uri or a path return None if not found """ with suppress(KeyError): return _GICON_CACHE[uri] gfile = File.new_for_path(uri) if not gfile.query_exists(): gfile = File.new_for_uri(uri) if not gfile.query_exists(): pretty.print_debug(__name__, "get_gicon_for_file", uri, "failed") _GICON_CACHE[uri] = None return None finfo = gfile.query_info( FILE_ATTRIBUTE_STANDARD_ICON, Gio.FileQueryInfoFlags.NONE, None ) gicon = finfo.get_attribute_object(FILE_ATTRIBUTE_STANDARD_ICON) _GICON_CACHE[uri] = gicon return gicon def get_gicon_from_file(path: str) -> FileIcon | None: """Load GIcon from @path; return None if failed.""" with suppress(KeyError): return _GICON_CACHE[path] icon = None file = File.new_for_path(path) if file.query_exists(): icon = FileIcon.new(file) else: pretty.print_debug(__name__, "get_gicon_from_file", path, "failed") _GICON_CACHE[path] = icon return icon def get_icon_for_gicon( gicon: GIcon, icon_size: int ) -> GdkPixbuf.Pixbuf | None: """ Return a pixbuf of @icon_size for the @gicon NOTE: Currently only the following can be rendered: Gio.ThemedIcon Gio.FileIcon kupfer.icons.ComposedIcon """ # FIXME: We can't load any general GIcon if not gicon: return None if isinstance(gicon, ComposedIcon): return gicon.render_composed_icon(icon_size) return _get_icon_for_standard_gicon(gicon, icon_size) def _get_icon_for_standard_gicon( gicon: ty.Any, icon_size: int ) -> GdkPixbuf.Pixbuf | None: """Render ThemedIcon and FileIcon""" if isinstance(gicon, FileIcon): ifile = gicon.get_file() return get_icon_from_file(ifile.get_path(), icon_size) if isinstance(gicon, ThemedIcon): names = gicon.get_names() return get_icon_for_name(names[0], icon_size, names) pretty.print_debug( __name__, "_get_icon_for_standard_gicon, could not load", gicon ) return None class IconRenderer: """ Default GTK+ implementation """ @classmethod def pixbuf_for_name( cls, icon_name: str, icon_size: int ) -> GdkPixbuf.Pixbuf | None: if icon_name in _KUPFER_LOCALLY_INSTALLED_NAMES: with suppress(GError): return _local_theme.load_icon( icon_name, icon_size, Gtk.IconLookupFlags.USE_BUILTIN # pylint: disable=no-member | Gtk.IconLookupFlags.FORCE_SIZE, # pylint: disable=no-member ) with suppress(GError): return _default_theme.load_icon( icon_name, icon_size, Gtk.IconLookupFlags.USE_BUILTIN # pylint: disable=no-member | Gtk.IconLookupFlags.FORCE_SIZE, # pylint: disable=no-member ) return None @classmethod def pixbuf_for_file( cls, file_path: str, icon_size: int ) -> GdkPixbuf.Pixbuf | None: with suppress(GError): return GdkPixbuf.Pixbuf.new_from_file_at_size( file_path, icon_size, icon_size ) return None _ICON_RENDERER = IconRenderer # pylint: disable=invalid-name def _setup_icon_renderer(_sched: ty.Any) -> None: setctl = settings.get_settings_controller() setctl.connect( "alternatives-changed::icon_renderer", _on_icon_render_change ) setctl.connect( "value-changed::tools.icon_renderer", _on_icon_render_change ) _on_icon_render_change(setctl) def _on_icon_render_change(setctl, *_arguments): global _ICON_RENDERER # pylint: disable=global-statement # noqa: PLW0603 renderer_dict = setctl.get_preferred_alternative("icon_renderer") assert renderer_dict renderer = renderer_dict.get("renderer") if not renderer or renderer is _ICON_RENDERER: return pretty.print_debug(__name__, "Using", renderer) _on_icon_theme_changed(None) _ICON_RENDERER = renderer scheduler.get_scheduler().connect("loaded", _setup_icon_renderer) def get_icon_for_name( icon_name: str, icon_size: int, icon_names: ty.Iterable[str] | None = None, ) -> GdkPixbuf.Pixbuf | None: if icon_name: with suppress(KeyError): return _ICON_CACHE[(icon_size, icon_name)] # Try the whole list of given names for load_name in icon_names or (icon_name,): try: if icon := _ICON_RENDERER.pixbuf_for_name(load_name, icon_size): break if (fallback_name := _KUPFER_ICON_FALLBACKS.get(icon_name)) and ( icon := _ICON_RENDERER.pixbuf_for_name( fallback_name, icon_size ) ): break except Exception: pretty.print_exc(__name__) icon = None else: # if we did not reach 'break' in the loop pretty.print_debug( __name__, "get_gicon_for_name name", icon_name, "size", icon_size, "names", icon_names, "failed", ) return None # We store the first icon in the list, even if the match # found was later in the chain _store_icon(icon_name, icon_size, icon) return icon def get_icon_from_file( icon_file: str, icon_size: int ) -> GdkPixbuf.Pixbuf | None: # try to load from cache with suppress(KeyError): return _ICON_CACHE[(icon_size, icon_file)] if icon := _ICON_RENDERER.pixbuf_for_file(icon_file, icon_size): _store_icon(icon_file, icon_size, icon) return icon return None def is_good_gicon(gicon: GIcon | None) -> bool: """Return True if it is likely that @gicon will load a visible icon (icon name exists in theme, or icon references existing file) """ if not gicon: return False if isinstance(gicon, ThemedIcon): return bool(get_good_name_for_icon_names(gicon.get_names())) if isinstance(gicon, FileIcon): ifile = gicon.get_file() return ifile.query_exists() # type: ignore # Since we can't load it otherwise (right now, see above) return False def get_gicon_with_fallbacks( gicon: GIcon | None, names: ty.Iterable[str] ) -> GIcon | None: if is_good_gicon(gicon): return gicon name = None for name in names: gicon = ThemedIcon.new(name) if is_good_gicon(gicon): return gicon return ThemedIcon.new(name) if name else None def get_good_name_for_icon_names(names: ty.Iterable[str]) -> str | None: """Return first name in @names that exists in current icon theme, or None """ for name in names: if _default_theme.has_icon(name): return name return None def get_gicon_for_names(*names: str) -> ThemedIcon: return ThemedIcon.new_from_names(names) def get_pixbuf_from_data( data: bytes, width: int | None = None, height: int | None = None, ) -> GdkPixbuf.Pixbuf: """Create pixbuf object from data with optional scaling @data: picture as raw data @width, @height: optional destination size """ ploader = GdkPixbuf.PixbufLoader.new() if width and height: def set_size( img: GdkPixbuf.PixbufLoader, img_width: int, img_height: int ) -> None: assert width and height scale = min(width / float(img_width), height / float(img_height)) new_width, new_height = ( int(img_width * scale), int(img_height * scale), ) img.set_size(new_width, new_height) ploader.connect("size-prepared", set_size) ploader.write(data) ploader.close() return ploader.get_pixbuf() kupfer-328/kupfer/interface.py000066400000000000000000000057601500175051100164750ustar00rootroot00000000000000from __future__ import annotations import typing as ty # NOTE: TextRepresentation moved into obj.representation # pylint: disable=unused-import from kupfer.obj.representation import ( TextRepresentation, UriListRepresentation, ) if ty.TYPE_CHECKING: from gi.repository import Gtk from kupfer.obj.base import KupferObject __all__ = ( "TextRepresentation", "UriListRepresentation", "copy_to_clipboard", "get_text_representation", ) def get_text_representation(obj: ty.Any) -> str | None: """Get text representation from any @obj.""" try: return obj.get_text_representation() # type: ignore except AttributeError: return None def copy_to_clipboard(obj: KupferObject, clipboard: Gtk.Clipboard) -> bool: """Copy @obj to @clipboard, a Gtk.Clipboard. Support only text representation. TODO: support images (maybe) Return True if successful """ try: text = obj.get_text_representation() # type: ignore except AttributeError: pass else: clipboard.set_text(text, -1) # -1 for computed string length return True return False # bellow part is legacy code that don't work anyway. # ## support copying text to clipboard # ## as well as files in both the general uri-list representation # ## and in nautilus' file copy clipboard type # (uri_id, text_id, nautilus_id) = (80, 81, 82) # nautilus_target = Gdk.Atom.intern("x-special/gnome-copied-files", False) # # udata is the data dict # # def store(clipboard, sdata, info, udata): # # if info == uri_id: # # sdata.set_uris(udata[uri_id]) # # if info == text_id: # # sdata.set_text(udata[text_id]) # # if info == nautilus_id: # # str_data_format = 8 # # sdata.set(nautilus_target, str_data_format, udata[nautilus_id]) # # def clear(clipboard, udata): # # pass # data: dict[int, ty.Any] = {} # try: # urilist = obj.get_urilist_representation() # type: ignore # except AttributeError: # pass # else: # if urilist: # targets = Gtk.TargetList.new(None) # targets.add_uri_targets(uri_id) # # targets = Gtk.target_list_add_uri_targets(targets, uri_id) # targets.add(nautilus_target, 0, nautilus_id) # data[uri_id] = urilist # data[nautilus_id] = "copy\n" + "\n".join(urilist) # try: # text = obj.get_text_representation() # type: ignore # except AttributeError: # pass # else: # targets = Gtk.TargetList.new(None) # targets.add_text_targets(text_id) # clipboard.set_text(text, -1) # -1 for computed string length # data[text_id] = text # if data: # # F I X M E: How to set URIs on clipboard? # # clipboard.set_with_data(targets, store, clear, data) # # store all targets # # clipboard.set_can_store(targets) # return True # return False kupfer-328/kupfer/keyrelay.py000066400000000000000000000040131500175051100163500ustar00rootroot00000000000000""" This is a program of its own, that does not integrate with the Kupfer process. """ import os import typing as ty import dbus import gi from dbus.mainloop.glib import DBusGMainLoop gi.require_version("Gtk", "3.0") gi.require_version("Keybinder", "3.0") # pylint: disable=wrong-import-position from gi.repository import Gtk, Keybinder # noqa:E402 if ty.TYPE_CHECKING: from gettext import gettext as _ __all__ = ("main",) SERV = "se.kaizer.kupfer" OBJ = "/interface" IFACE = "se.kaizer.kupfer.Listener" def _get_all_keys() -> list[str]: try: bus = dbus.Bus() obj = bus.get_object(SERV, OBJ) iface = dbus.Interface(obj, IFACE) return iface.GetBoundKeys(byte_arrays=True) # type: ignore except dbus.DBusException as exc: print(exc) print("Waiting for Kupfer to start..") return [] def _rebind_key(keystring: str, is_bound: bool) -> None: if is_bound: print("binding", keystring) Keybinder.bind(keystring, _relay_key, keystring) else: print("unbinding", keystring) Keybinder.unbind(keystring) def _relay_key(key: str) -> None: print("Relaying", key) time = Keybinder.get_current_event_time() s_id = f"kupfer-{os.getpid()}_TIME{time}" bus = dbus.Bus() obj = bus.get_object(SERV, OBJ, introspect=False) iface = dbus.Interface(obj, IFACE) iface.RelayKeysFromDisplay(key, os.getenv("DISPLAY", ":0"), s_id) def main() -> None: DBusGMainLoop(set_as_default=True) for key in _get_all_keys(): _rebind_key(key, True) bus = dbus.Bus() bus.add_signal_receiver( _rebind_key, "BoundKeyChanged", dbus_interface=IFACE ) sicon = Gtk.StatusIcon.new_from_icon_name("kupfer") display = os.getenv("DISPLAY", ":0") sicon.set_tooltip_text( _("Keyboard relay is active for display %s") % display ) sicon.set_visible(True) try: Gtk.main() except KeyboardInterrupt as exc: raise SystemExit(0) from exc if __name__ == "__main__": main() kupfer-328/kupfer/launch.py000066400000000000000000000601331500175051100160020ustar00rootroot00000000000000from __future__ import annotations import os import pickle import signal import sys import typing as ty import urllib.parse from collections import defaultdict from contextlib import suppress from pathlib import Path from time import time from gi.repository import Gdk, Gio, GLib, Gtk try: from gi.repository import Wnck Wnck.set_client_type(Wnck.ClientType.PAGER) if "WAYLAND_DISPLAY" in os.environ: Wnck.Screen.get_default = lambda *_x: None except ImportError as e: from kupfer.support import pretty pretty.print_info(__name__, "Disabling window tracking:", e) Wnck = None from kupfer import config, desktop_launch from kupfer.core import settings ## NOTE: SpawnError *should* be imported from this module TODO: check # pylint: disable=unused-import from kupfer.desktop_launch import SpawnError from kupfer.support import fileutils, pretty, scheduler, system from kupfer.ui import uievents __all__ = ( "AsyncCommand", "SpawnError", "application_close_all", "application_id", "application_is_running", "get_applications_matcher_service", "get_display_path_for_bytestring", "launch_application", "show_help_url", "show_url", "spawn_async", "spawn_async_notify_as", "spawn_async_raise", "spawn_in_terminal", "spawn_terminal", ) _DEFAULT_ASSOCIATIONS = { "evince": "Document Viewer", "file-roller": "File Roller", # "gedit" : "Text Editor", "gnome-keyring-manager": "Keyring Manager", "nautilus-browser": "File Manager", "rhythmbox": "Rhythmbox Music Player", } def application_id( app_info: Gio.AppInfo, desktop_file: str | None = None ) -> str: """Return an application id (string) for GAppInfo @app_info""" app_id = app_info.get_id() or desktop_file or "" return app_id.removesuffix(".desktop") # pylint: disable=too-many-arguments def launch_application( app_info: Gio.AppInfo, files: ty.Iterable[Gio.File] = (), uris: ty.Iterable[str] = (), paths: ty.Iterable[str] = (), track: bool = True, activate: bool = True, desktop_file: str | None = None, screen: Gdk.Screen | None = None, work_dir: str | None = None, ) -> bool: """Launch `app_rec` correctly, using a startup notification. You may pass inlist of `Gio.Files` in `files` and/or a list of `uris` and/or list of `paths`. This lists are combined together. if `track`, it is a user-level application. if `activate`, activate rather than start a new version. `app_rec` is either an `GAppInfo` or (`GAppInfo`, desktop_file_path) tuple. `work_dir`: overwrite work directory of application. Raises `SpawnError` on failed program start. """ assert app_info assert not (bool(paths) and bool(uris)), ( "either paths or uris must be given: " + repr((paths, uris)) ) svc = get_applications_matcher_service() app_id = application_id(app_info, desktop_file) if activate and svc.application_is_running(app_id): svc.application_to_front(app_id) return True launch_callback = None if track: # An launch callback closure for the @app_id def app_launch_callback(argv, pid, _notify_id, _files, _timestamp): if not settings.is_known_terminal_executable(argv[0]): svc.launched_application(app_id, pid) launch_callback = app_launch_callback files = list(files) if paths: files.extend(map(Gio.File.new_for_path, paths)) if uris: files.extend(map(Gio.File.new_for_uri, uris)) desktop_launch.launch_app_info( app_info, files, timestamp=uievents.current_event_time(), desktop_file=desktop_file, launch_cb=launch_callback, screen=screen, work_dir=work_dir, ) return True def application_is_running(app_id: str) -> bool: svc = get_applications_matcher_service() return svc.application_is_running(app_id) def application_close_all(app_id: str) -> None: svc = get_applications_matcher_service() svc.application_close_all(app_id) class ApplicationsMatcherService(pretty.OutputMixin): """Handle launching applications and see if they still run. This is a learning service, since we have no first-class application object on the Linux desktop """ _instance: ApplicationsMatcherService | None = None @classmethod def instance(cls) -> ApplicationsMatcherService: if cls._instance is None: cls._instance = ApplicationsMatcherService() return cls._instance def __init__(self): self.register: dict[str, str] = {} self._get_wnck_screen_windows_stacked() scheduler.get_scheduler().connect("finish", self._on_finish) self._load() @classmethod def _get_wnck_screen_windows_stacked(cls) -> ty.Iterable["Wnck.Window"]: if Wnck and (screen := Wnck.Screen.get_default()): return screen.get_windows_stacked() # type: ignore return () def _get_filename(self) -> str: # Version 1: Up to incl v203 # Version 2: Do not track terminals version = 2 return os.path.join( config.get_cache_home() or "", f"application_identification_v{version}.pickle", ) def _load(self) -> None: reg = self._unpickle_register(self._get_filename()) self.register = reg or _DEFAULT_ASSOCIATIONS # pretty-print register to debug if self.register: self.output_debug("Learned the following applications") items = "\n".join( f" {k:<30} : {v}" for k, v in self.register.items() ) self.output_debug(f"\n{{\n{items}\n}}") def _on_finish(self, _sched: ty.Any) -> None: self._pickle_register(self.register, self._get_filename()) def _unpickle_register(self, pickle_file: str) -> dict[str, str] | None: try: source = pickle.loads(Path(pickle_file).read_bytes()) assert isinstance(source, dict), "Stored object not a dict" self.output_debug(f"Reading from {pickle_file}") return source except OSError: pass except (pickle.PickleError, Exception) as exc: self.output_info(f"Error loading {pickle_file}: {exc}") return None def _pickle_register(self, reg: ty.Any, pickle_file: str) -> bool: self.output_debug(f"Saving to {pickle_file}") Path(pickle_file).write_bytes( pickle.dumps(reg, pickle.HIGHEST_PROTOCOL) ) return True def _store(self, app_id: str, window: "Wnck.Window") -> None: # FIXME: Store the 'res_class' name? application = window.get_application() res_class = window.get_class_group().get_res_class() store_name = application.get_name() self.register[app_id] = res_class self.output_debug( "storing application", app_id, "as", store_name, "res_class", res_class, ) def _has_match(self, app_id: str | None) -> bool: if not app_id: return False return app_id in self.register def _is_match(self, app_id: str, window: "Wnck.Window") -> bool: application = window.get_application() res_class = window.get_class_group().get_res_class() reg_name = self.register.get(app_id) if reg_name and reg_name in (application.get_name(), res_class): return True return app_id in (application.get_name().lower(), res_class.lower()) def launched_application(self, app_id: str, pid: int) -> None: if self._has_match(app_id): return timeout = time() + 15 GLib.timeout_add_seconds( 2, self._find_application, app_id, pid, timeout ) # and once later GLib.timeout_add_seconds( 30, self._find_application, app_id, pid, timeout ) def _find_application(self, app_id: str, pid: int, timeout: float) -> bool: if self._has_match(app_id): return False # self.output_debug("Looking for window for application", app_id) for win in self._get_wnck_screen_windows_stacked(): app = win.get_application() app_pid = app.get_pid() or win.get_pid() if app_pid == pid: self._store(app_id, win) return False return time() <= timeout def application_name(self, app_id: str | None) -> str | None: if not app_id: return None return self.register.get(app_id) def application_is_running(self, app_id: str) -> bool: for win in self._get_wnck_screen_windows_stacked(): if ( win.get_application() and self._is_match(app_id, win) and win.get_window_type() == Wnck.WindowType.NORMAL ): return True return False def _get_application_windows( self, app_id: str ) -> ty.Iterator["Wnck.Window"]: if not Wnck: return for win in self._get_wnck_screen_windows_stacked(): if ( win.get_application() and self._is_match(app_id, win) and win.get_window_type() == Wnck.WindowType.NORMAL ): yield win def application_to_front(self, app_id: str) -> None: application_windows = list(self._get_application_windows(app_id)) if not application_windows: return etime = uievents.current_event_time() # if True, focus app's all windows on the same workspace # if False, focus only one window (in cyclical manner) focus_all = True if focus_all: self._to_front_application_style(application_windows, etime) return self._to_front_single(application_windows, etime) def _to_front_application_style( self, application_windows: list["Wnck.Window"], evttime: int ) -> None: workspaces: dict[Wnck.Workspace, list[Wnck.Window]] = defaultdict(list) cur_screen = application_windows[0].get_screen() cur_workspace = cur_screen.get_active_workspace() ## get all visible windows in stacking order vis_windows = [ win for win in self._get_wnck_screen_windows_stacked() if ( win.get_window_type() == Wnck.WindowType.NORMAL and win.is_visible_on_workspace(cur_workspace) ) ] ## sort windows into "bins" by workspace for win in application_windows: if win.get_window_type() == Wnck.WindowType.NORMAL: wspc = win.get_workspace() or cur_workspace workspaces[wspc].append(win) cur_wspc_windows = workspaces[cur_workspace] # make a rotated workspace list, with current workspace first all_workspaces = cur_screen.get_workspaces() all_workspaces.pop(cur_workspace.get_number()) # check if the application's window on current workspace # are the topmost focus_windows = [] if cur_wspc_windows and set( vis_windows[-len(cur_wspc_windows) :] ) != set(cur_wspc_windows): focus_windows = cur_wspc_windows ## if the topmost window is already active, take another if focus_windows[-1] == vis_windows[-1]: focus_windows.pop() else: # all windows are focused, find on next workspace for wspc in all_workspaces[1:]: if focus_windows := workspaces[wspc]: break else: # no windows on other workspaces, so we rotate among # the local ones focus_windows = cur_wspc_windows[:1] self._focus_windows(focus_windows, evttime) def _to_front_single( self, application_windows: list["Wnck.Window"], evttime: int ) -> None: # bring the first window to front for window in application_windows: self._focus_windows([window], evttime) return def _focus_windows( self, windows: list["Wnck.Window"], evttime: int ) -> None: for window in windows: # we special-case the desktop # only show desktop if it's the only window if window.get_name() == "x-nautilus-desktop": if len(windows) == 1: if screen := Wnck.Screen.get_default(): screen.toggle_showing_desktop(True) else: continue if wspc := window.get_workspace(): wspc.activate(evttime) window.activate_transient(evttime) def application_close_all(self, app_id: str) -> None: application_windows = self._get_application_windows(app_id) evttime = uievents.current_event_time() for win in application_windows: if not win.is_skip_tasklist(): win.close(evttime) # Get the (singleton) ApplicationsMatcherService" get_applications_matcher_service = ApplicationsMatcherService.instance def _split_string(inp: bytes, length: int) -> ty.Iterator[bytes]: """Split @inp in pieces of @length >>> list(_split_string(b"abcdefghijk", 3)) [b"abc", b"def", b"ghi", b"jk"] """ while inp: yield inp[:length] inp = inp[length:] class AsyncCommand(pretty.OutputMixin): """Run a command asynchronously (using the GLib mainloop). call @finish_callback when command terminates, or when command is killed after @timeout_s seconds, whichever comes first. If @timeout_s is None, no timeout is used If stdin is a byte string, it is supplied on the command's stdin. If env is None, command will inherit the parent's environment. finish_callback -> (AsyncCommand, stdout_output, stderr_output) Attributes: self.exit_status Set after process exited self.finished bool """ # the maximum input (bytes) we'll read in one shot (one io_callback) max_input_buf = 512 * 1024 def __init__( self, argv: list[str], finish_callback: ty.Callable[[AsyncCommand, bytes, bytes], None], timeout_s: int | None, stdin: bytes | None = None, env: ty.Any = None, ) -> None: self.stdout: list[bytes] = [] self.stderr: list[bytes] = [] self.stdin: list[bytes] = [] self.timeout = False self.killed = False self.finished = False self.finish_callback = finish_callback self.exit_status: int | None = None self.output_debug("AsyncCommand:", argv) flags = GLib.SPAWN_SEARCH_PATH | GLib.SPAWN_DO_NOT_REAP_CHILD kwargs = {} if env is not None: kwargs["envp"] = env pid, stdin_fd, stdout_fd, stderr_fd = GLib.spawn_async( argv, standard_output=True, standard_input=True, standard_error=True, flags=flags, **kwargs, ) if stdin: self.stdin = list(_split_string(stdin, self.max_input_buf)) in_io_flags = ( GLib.IO_OUT | GLib.IO_ERR | GLib.IO_HUP | GLib.IO_NVAL ) GLib.io_add_watch( stdin_fd, in_io_flags, self._in_io_callback, self.stdin ) else: os.close(stdin_fd) io_flags = GLib.IO_IN | GLib.IO_ERR | GLib.IO_HUP | GLib.IO_NVAL GLib.io_add_watch(stdout_fd, io_flags, self._io_callback, self.stdout) GLib.io_add_watch(stderr_fd, io_flags, self._io_callback, self.stderr) self.pid = pid GLib.child_watch_add(pid, self._child_callback) if timeout_s is not None: GLib.timeout_add_seconds(timeout_s, self._timeout_callback) def _io_callback( self, sourcefd: int, condition: int, databuf: list[bytes] ) -> bool: if condition & GLib.IO_IN: databuf.append(os.read(sourcefd, self.max_input_buf)) return True return False def _in_io_callback( self, sourcefd: int, condition: int, databuf: list[bytes] ) -> bool: """write to child's stdin""" if condition & GLib.IO_OUT: if not databuf: os.close(sourcefd) return False data = databuf.pop(0) written = os.write(sourcefd, data) if written < len(data): databuf.insert(0, data[written:]) return True return False def _child_callback(self, pid: int, condition: int) -> None: # @condition is the &status field of waitpid(2) (C library) self.exit_status = os.WEXITSTATUS(condition) self.finished = True self.finish_callback( self, b"".join(self.stdout), b"".join(self.stderr) ) def _timeout_callback(self) -> None: "send term signal on timeout" if not self.finished: self.timeout = True os.kill(self.pid, signal.SIGTERM) GLib.timeout_add_seconds(2, self._kill_callback) def _kill_callback(self) -> None: "Last resort, send kill signal" if not self.finished: self.killed = True os.kill(self.pid, signal.SIGKILL) def spawn_terminal( workdir: str | None = None, screen: str | None = None ) -> bool: "Raises SpawnError" term = settings.get_configured_terminal() if not term: return False notify = term["startup_notify"] app_id = term["desktopid"] argv = term["argv"] return desktop_launch.spawn_app_id(app_id, argv, workdir, notify, screen) def spawn_in_terminal(argv: list[str], workdir: str | None = None) -> bool: "Raises SpawnError" term = settings.get_configured_terminal() if not term: return False notify = term["startup_notify"] _argv = list(term["argv"]) if term["exearg"]: _argv.append(term["exearg"]) _argv.extend(argv) return desktop_launch.spawn_app_id( term["desktopid"], _argv, workdir, notify ) def spawn_async_notify_as(app_id: str, argv: list[str]) -> bool: """ Spawn argument list @argv and startup-notify as if application @app_id is starting (if possible) raises SpawnError """ return desktop_launch.spawn_app_id(app_id, argv, None, True) def spawn_async( argv: ty.Collection[str], in_dir: str = ".", *, finish_callback: ty.Callable[[int], None] | None = None, ) -> bool: """ Silently spawn @argv in the background Returns False on failure """ try: return spawn_async_raise(argv, in_dir, finish_callback=finish_callback) except SpawnError as exc: pretty.print_debug(__name__, "spawn_async", argv, exc) return False def spawn_async_raise( argv: ty.Collection[str], workdir: str = ".", *, finish_callback: ty.Callable[[int], None] | None = None, ) -> bool: """ A version of spawn_async that raises on error. raises SpawnError """ pretty.print_debug(__name__, "spawn_async", argv, workdir) try: res = GLib.spawn_async( argv, working_directory=workdir, flags=GLib.SPAWN_SEARCH_PATH ) if finish_callback and res: def _callback(pid: int, condition: int) -> None: finish_callback(os.WEXITSTATUS(condition)) GLib.child_watch_add(res[0], _callback) return bool(res) except GLib.GError as exc: raise SpawnError(exc.message) from exc # pylint: disable=no-member return False def _try_register_pr_pdeathsig() -> None: """ Register pr_set_pdeathsig (linux-only) for the calling process which is a signal delivered when its parent dies. This should ensure child processes die with the parent. """ pr_set_pdeathsig = 1 sighup = 1 if sys.platform != "linux2": return with suppress(ImportError): # pylint: disable=import-outside-toplevel import ctypes with suppress(AttributeError, OSError): libc = ctypes.CDLL("libc.so.6") libc.prctl(pr_set_pdeathsig, sighup) def _on_child_exit( pid: int, condition: int, user_data: tuple[ty.Any, bool] ) -> None: # @condition is the &status field of waitpid(2) (C library) argv, respawn = user_data if respawn: is_signal = os.WIFSIGNALED(condition) if is_signal and respawn: def callback(*args): _spawn_child(*args) return False GLib.timeout_add_seconds(10, callback, argv, respawn) def _spawn_child( argv: list[str], respawn: bool = True, display: str | None = None ) -> int: """ Spawn argv in the mainloop and keeping it as a child process (it will be made sure to exit with the parent). @respawn: If True, respawn if child dies abnormally raises launch.SpawnError returns pid """ flags = GLib.SPAWN_SEARCH_PATH | GLib.SPAWN_DO_NOT_REAP_CHILD envp: list[str] = [] if display: # environment is passed as a sequence of strings envd = os.environ.copy() envd["DISPLAY"] = display envp = ["=".join((k, v)) for k, v in envd.items()] try: pid: int pid, *_fds = GLib.spawn_async( argv, envp, flags=flags, child_setup=_try_register_pr_pdeathsig, ) except GLib.GError as exc: raise SpawnError(str(exc)) from exc if pid: GLib.child_watch_add(pid, _on_child_exit, (argv, respawn)) return pid def start_plugin_helper( name: str, respawn: bool, display: str | None = None ) -> int: """ @respawn: If True, respawn if child dies abnormally raises SpawnError UNUSED """ argv = [sys.executable] argv.extend(sys.argv) argv.append(f"--exec-helper={name}") pretty.print_debug(__name__, "Spawning", argv) return _spawn_child(argv, respawn, display=display) def show_path(path: str) -> None: """Open local @path with default viewer""" # Implemented using Gtk.show_uri gfile = Gio.File.new_for_path(path) if not gfile: return url = gfile.get_uri() show_url(url) def show_url(url: str) -> bool: """Open any @url with default viewer""" # if there is no schema w url add default http:// # this allow open urls like 'www.foobar.com'. url = url.strip() purl = urllib.parse.urlparse(url) if not purl.scheme: url = f"http://{url}" try: pretty.print_debug(__name__, "show_url", url) return ty.cast( "bool", Gtk.show_uri( Gdk.Screen.get_default(), url, Gtk.get_current_event_time() ), ) except GLib.GError as exc: pretty.print_error(__name__, "Gtk.show_uri:", exc) return False def show_help_url(url: str) -> bool: """Try at length to display a startup notification for the help browser. Return False if there is no handler for the help URL """ ## Check that the system help viewer is Yelp, ## and if it is, launch its startup notification. scheme = Gio.File.new_for_uri(url).get_uri_scheme() default = Gio.app_info_get_default_for_uri_scheme(scheme) if not default: return False help_viewer_id = "yelp.desktop" try: yelp = Gio.DesktopAppInfo.new(help_viewer_id) except (TypeError, RuntimeError): return show_url(url) cmd_path = fileutils.lookup_exec_path(default.get_executable()) yelp_path = fileutils.lookup_exec_path(yelp.get_executable()) if cmd_path and yelp_path and os.path.samefile(cmd_path, yelp_path): with suppress(SpawnError): spawn_async_notify_as(help_viewer_id, [cmd_path, url]) return True return show_url(url) def get_display_path_for_bytestring(filepath: str | bytes) -> str: """Return a unicode path for display for string or bytestring @filepath Will use glib's filename decoding functions, and will format nicely (denote home by ~/ etc) """ desc: str = GLib.filename_display_name(filepath) homedir = system.get_homedir() if desc.startswith(homedir) and homedir != desc: desc = f"~{desc[len(homedir) :]}" return desc if __name__ == "__main__": import doctest doctest.testmod() kupfer-328/kupfer/main.py000066400000000000000000000136211500175051100154540ustar00rootroot00000000000000import argparse import gettext import locale import runpy import sys import typing as ty from contextlib import suppress from pathlib import Path if ty.TYPE_CHECKING: from gettext import gettext as _ try: from kupfer import version_subst # type:ignore except ImportError: version_subst = None __all__ = ("main",) def _setup_locale_and_gettext() -> None: """Set up localization with gettext""" package_name = "kupfer" localedir = "./locale" for ldir in ("./locale", "/usr/local/share/locale/"): if Path(ldir).is_dir(): localedir = ldir break if version_subst: package_name = version_subst.PACKAGE_NAME localedir = version_subst.LOCALEDIR # Install _() builtin for gettext; always returning unicode objects # also install ngettext() gettext.install(package_name, localedir=localedir, names=("ngettext",)) # For Gtk.Builder, we need to call the C library gettext functions # As well as set the codeset to avoid locale-dependent translation # of the message catalog locale.bindtextdomain(package_name, localedir) locale.bind_textdomain_codeset(package_name, "UTF-8") # to load in current locale properly for sorting etc with suppress(locale.Error): locale.setlocale(locale.LC_ALL, "") _setup_locale_and_gettext() def _print(*args: ty.Any) -> None: enc = locale.getpreferredencoding(do_setlocale=False) sys.stdout.buffer.write(" ".join(args).encode(enc, "replace")) sys.stdout.buffer.write(b"\n") def _make_help_text( program_options: list[tuple[str, str]], misc_options: list[tuple[str, str]] ) -> str: usage_string = _("Usage: kupfer [ OPTIONS | FILE ... ]") def format_options(opts): return "\n".join(f" --{o:<15} {h}" for o, h in opts) popts = format_options(program_options) mopts = format_options(misc_options) return f"{usage_string}\n\n{popts}\n\n{mopts}\n" def _make_plugin_list() -> str: # require setup path and locales from kupfer.core import plugins # pylint: disable=import-outside-toplevel plugin_header = _("Available plugins:") plugin_list = plugins.get_plugin_desc() return "\n".join((plugin_header, plugin_list)) def _get_options() -> argparse.Namespace: """Return a list of other application flags with --* prefix included.""" from kupfer import version # pylint: disable=import-outside-toplevel parser = argparse.ArgumentParser( prog=version.PROGRAM_NAME, description=version.SHORT_DESCRIPTION, ) parser.add_argument( "--no-splash", action="store_true", help=_("do not present main interface on launch"), ) parser.add_argument( "--list-plugins", action="store_true", help=_("list available plugins") ) parser.add_argument( "--debug", action="store_true", help=_("enable debug info") ) # TRANS: --exec-helper=HELPER is an internal command # TRANS: that executes a helper program that is part of kupfer parser.add_argument("--exec-helper", nargs=1, help=_("run plugin helper")) parser.add_argument( "--no-colors", action="store_true", help=_("do not use colored text in terminal"), ) parser.add_argument( "--version", action="version", version=f"{version.PACKAGE_NAME} {version.VERSION}", ) # Fix sys.argv that can be None in exceptional cases if sys.argv[0] is None: sys.argv[0] = "kupfer" args = parser.parse_args() if args.list_plugins: _print(_gtkmain(_make_plugin_list)) raise SystemExit if args.exec_helper: _exec_helper(args.exec_helper[0]) raise SystemExit(1) return args def _print_banner() -> None: # require setup path and locales from kupfer import version # pylint: disable=import-outside-toplevel if not sys.stdout or not sys.stdout.isatty(): return banner = _( "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" ) % vars(version) _print(banner) def _set_process_title() -> None: try: import setproctitle # pylint: disable=import-outside-toplevel except ImportError: pass else: setproctitle.setproctitle("kupfer") def _exec_helper(helpername: str) -> None: runpy.run_module(helpername, run_name="__main__", alter_sys=True) raise SystemExit def _gtkmain( run_function: ty.Callable[..., ty.Any], *args: ty.Any, **kwargs: ty.Any, ) -> ty.Any: import gi # pylint: disable=import-outside-toplevel gi.require_version("Gtk", "3.0") gi.require_version("Gdk", "3.0") with suppress(ValueError): gi.require_version("Wnck", "3.0") with suppress(ValueError): gi.require_version("AyatanaAppIndicator3", "0.1") return run_function(*args, **kwargs) def _browser_start(quiet: bool) -> None: from gi.repository import Gdk # pylint: disable=import-outside-toplevel if not Gdk.Screen.get_default(): print("No Screen Found, Exiting...", file=sys.stderr) sys.exit(1) from kupfer.ui import browser # pylint: disable=import-outside-toplevel wctrl = browser.WindowController() wctrl.main(quiet=quiet) def main() -> None: # parse commandline before importing UI cli_opts = _get_options() _print_banner() # pylint: disable=import-outside-toplevel from kupfer import version from kupfer.support import pretty if cli_opts.debug: pretty.DEBUG = True pretty.print_debug( __name__, "Version:", version.PACKAGE_NAME, version.VERSION ) with suppress(ImportError): import debug debug.install() # enable colors only on terminal pretty.COLORS = sys.stdout.isatty() and not cli_opts.no_colors sys.excepthook = sys.__excepthook__ _set_process_title() quiet = cli_opts.no_splash _gtkmain(_browser_start, quiet) kupfer-328/kupfer/obj/000077500000000000000000000000001500175051100147255ustar00rootroot00000000000000kupfer-328/kupfer/obj/__init__.py000066400000000000000000000016711500175051100170430ustar00rootroot00000000000000""" This file import most common objects, so can they can be imported directly from kupfer.obj """ from kupfer.obj import fileactions from kupfer.obj.actions import Execute, OpenTerminal, OpenUrl, Perform from kupfer.obj.apps import AppLeaf from kupfer.obj.base import ( Action, AnySource, KupferObject, Leaf, Source, TextSource, ) from kupfer.obj.exceptions import NotAvailableError, OperationError from kupfer.obj.files import FileLeaf from kupfer.obj.objects import RunnableLeaf, SourceLeaf, TextLeaf, UrlLeaf # importint fileactions here prevent circular imports __dummy = fileactions __all__ = ( "Action", "AnySource", "AppLeaf", "Execute", "FileLeaf", "FileLeaf", "KupferObject", "Leaf", "NotAvailableError", "OpenTerminal", "OpenUrl", "OperationError", "Perform", "RunnableLeaf", "Source", "SourceLeaf", "TextLeaf", "TextSource", "UrlLeaf", ) kupfer-328/kupfer/obj/actions.py000066400000000000000000000101751500175051100167430ustar00rootroot00000000000000""" Global actions. This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ from __future__ import annotations import typing as ty from kupfer import launch, support from kupfer.desktop_launch import SpawnError from kupfer.obj.base import Action, Leaf from kupfer.obj.exceptions import OperationError from kupfer.obj.objects import RunnableLeaf if ty.TYPE_CHECKING: from gettext import gettext as _ from kupfer.core import commandexec __all__ = ("Execute", "OpenTerminal", "OpenUrl", "Perform") class OpenTerminal(Action): action_accelerator = "t" def __init__(self, name: str = _("Open Terminal Here")) -> None: super().__init__(name) def wants_context(self) -> bool: return True def activate( self, leaf: Leaf, iobj: Leaf | None = None, ctx: commandexec.ExecutionToken | None = None, ) -> Leaf | None: assert ctx try: launch.spawn_terminal(leaf.object, ctx.environment.get_screen()) return None except SpawnError as exc: raise OperationError(exc) from exc def get_description(self) -> str | None: return _("Open this location in a terminal") def get_icon_name(self) -> str: return "utilities-terminal" class Execute(Action): """Execute executable file (FileLeaf)""" rank_adjust = 10 def __init__(self, in_terminal=False, quoted=True): name = _("Run in Terminal") if in_terminal else _("Run (Execute)") super().__init__(name) self.in_terminal = in_terminal self.quoted = quoted def repr_key(self): return (self.in_terminal, self.quoted) def activate( self, leaf: Leaf, iobj: Leaf | None = None, ctx: commandexec.ExecutionToken | None = None, ) -> Leaf | None: if self.quoted: argv = [leaf.object] else: argv = support.argv_for_commandline(leaf.object) if self.in_terminal: launch.spawn_in_terminal(argv) else: launch.spawn_async(argv) return None def get_description(self) -> str | None: if self.in_terminal: return _("Run this program in a Terminal") return _("Run this program") class OpenUrl(Action): action_accelerator: str | None = "o" rank_adjust: int = 5 def __init__(self, name: str = _("Open URL")) -> None: super().__init__(name) def activate( self, leaf: Leaf, iobj: Leaf | None = None, ctx: commandexec.ExecutionToken | None = None, ) -> Leaf | None: url = leaf.object self.open_url(url) return None def open_url(self, url: str) -> None: launch.show_url(url) def get_description(self) -> str: return _("Open URL with default viewer") def get_icon_name(self) -> str: return "forward" class Perform(Action): """Perform the action in a RunnableLeaf. RunnableLeaf can return result. In this case `has_result` and `item_types` must be specified. """ action_accelerator: str | None = "o" rank_adjust = 5 def __init__( self, name: str = _("Run"), has_result: bool = False, item_types: ty.Collection[Leaf] = (), ): # TRANS: 'Run' as in Perform a (saved) command super().__init__(name=name) self._has_result = has_result self._item_types = item_types def has_result(self): return self._has_result def wants_context(self) -> bool: return True def activate( self, leaf: Leaf, iobj: Leaf | None = None, ctx: commandexec.ExecutionToken | None = None, ) -> Leaf | None: assert isinstance(leaf, RunnableLeaf) if leaf.wants_context(): return ty.cast("ty.Optional[Leaf]", leaf.run(ctx=ctx)) return ty.cast("ty.Optional[Leaf]", leaf.run()) def get_description(self) -> str: return _("Perform command") def item_types(self): return self._item_types kupfer-328/kupfer/obj/apps.py000066400000000000000000000265721500175051100162560ustar00rootroot00000000000000""" Application - related objects (leaves, sources) This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ from __future__ import annotations import os import typing as ty from contextlib import suppress from gi.repository import Gio, GLib from kupfer import icons, launch from kupfer.obj.base import Action, Leaf, Source from kupfer.obj.exceptions import InvalidDataError, OperationError from kupfer.obj.helplib import FilesystemWatchMixin, PicklingHelperMixin from kupfer.support import pretty from kupfer.version import DESKTOP_ID if ty.TYPE_CHECKING: from gettext import gettext as _ from kupfer.core import commandexec __all__ = ( "AppLeaf", "AppLeafContentMixin", "ApplicationSource", "CloseAll", "Launch", "LaunchAgain", ) class AppLeafContentMixin: """Mixin for Source that correspond one-to-one with a AppLeaf. This Mixin sees to that the Source is set as content for the application with id 'cls.appleaf_content_id', which may also be a sequence of ids. Source has to define the attribute appleaf_content_id and must inherit this mixin BEFORE the Source This Mixin defines: get_leaf_repr decorates_type, decorates_item """ _cached_leaf_repr: AppLeaf | None @classmethod def get_leaf_repr(cls) -> AppLeaf | None: if not hasattr(cls, "_cached_leaf_repr"): cls._cached_leaf_repr = cls.__get_leaf_repr() return cls._cached_leaf_repr @classmethod def __get_appleaf_id_iter(cls) -> ty.Iterator[str]: assert hasattr(cls, "appleaf_content_id") if isinstance(cls.appleaf_content_id, str): yield cls.appleaf_content_id else: yield from cls.appleaf_content_id @classmethod def __get_leaf_repr(cls) -> AppLeaf | None: for appleaf_id in cls.__get_appleaf_id_iter(): with suppress(InvalidDataError): return AppLeaf(app_id=appleaf_id) return None @classmethod def decorates_type(cls) -> ty.Type[Leaf]: return AppLeaf @classmethod def decorate_item(cls, leaf: Leaf) -> AppLeafContentMixin | None: if leaf == cls.get_leaf_repr(): return cls() return None class ApplicationSource( AppLeafContentMixin, Source, PicklingHelperMixin, FilesystemWatchMixin ): """Abstract, helper class that include parent object to create source that is bound to application leaf with file/folders monitoring.""" class AppLeaf(Leaf): LOAD_EXTRA_ALIASES: bool = False def __init__( self, item: ty.Any = None, init_path: str | None = None, app_id: str | None = None, require_x: bool = True, app_actions: list[tuple[str, str]] | None = None, ) -> None: """Try constructing an Application for GAppInfo @item, for file @path or for package name @app_id. @require_x: require executable file @app_actions: additional application actions defined in desktop file as list of (action name, action display name) Represented object is Gio.DesktopAppInfo. """ self._init_path = init_path self._init_item_id = app_id and app_id + ".desktop" # finish will raise InvalidDataError on invalid item self._finish(require_x, item) self.app_actions = app_actions super().__init__(self.object, self.object.get_name()) self._add_aliases() def _add_aliases(self) -> None: # find suitable alias # use package name: non-extension part of ID package_name = GLib.filename_display_basename(self.get_id()) if package_name and package_name not in str(self).lower(): self.kupfer_add_alias(package_name) # add executable as alias if cmdl := self.object.get_executable(): self.kupfer_add_alias(cmdl) # do not continue when application setting "load extra aliases" if off if not AppLeaf.LOAD_EXTRA_ALIASES: return # add non-localized name if (en_name := self.object.get_string("Name")) != self.name: self.kupfer_add_alias(en_name) # add generic name if ( name := ( self.object.get_string("GenericName") or self.object.get_string("GenericName") ) ) and name != self.name: self.kupfer_add_alias(name) # add keywords if keywords := self.object.get_string_list("Keywords"): for keyword in keywords: self.kupfer_add_alias(keyword) # add Comment if comment := ( self.object.get_locale_string("Comment") or self.object.get_string("Comment") ): self.kupfer_add_alias(comment) def __hash__(self) -> int: return hash(str(self)) def __eq__(self, other: object) -> bool: return ( isinstance(other, type(self)) and self.get_id() == other.get_id() ) def __getstate__(self) -> dict[str, ty.Any]: self._init_item_id = self.object and self.object.get_id() state = dict(vars(self)) state["object"] = None return state def __setstate__(self, state: dict[str, ty.Any]) -> None: vars(self).update(state) self._finish() def _finish( self, require_x: bool = False, item: Gio.DesktopAppInfo | None = None, ) -> None: """Try to set self.object from init's parameters""" if not item: # Construct an AppInfo item from either path or item_id try: if self._init_path and ( not require_x or os.access(self._init_path, os.X_OK) ): # serilizable if created from a "loose file" self.serializable = 1 item = Gio.DesktopAppInfo.new_from_filename( self._init_path ) elif self._init_item_id: item = Gio.DesktopAppInfo.new(self._init_item_id) except TypeError as exc: pretty.print_debug( __name__, "Application not found:", self._init_item_id, self._init_path, ) raise InvalidDataError from exc self.object = item if not self.object: raise InvalidDataError def repr_key(self) -> ty.Any: return self.get_id() def launch( self, files: ty.Iterable[Gio.File] = (), paths: ty.Iterable[str] = (), activate: bool = False, ctx: commandexec.ExecutionToken | None = None, work_dir: str | None = None, uris: ty.Iterable[str] = (), ) -> bool: """Launch the represented applications. `files` is a sequence of GFiles (Gio.File), `paths` is a sequence of paths (str), `uris` is list of uri. All three lists are combined together. In most cases only one list should be passed to this method. When `activate` is True - activate running instance instead of start new. `work_dir` can overwrite work directory of application. """ try: return launch.launch_application( self.object, files=files, paths=paths, uris=uris, activate=activate, desktop_file=self._init_path, screen=ctx and ctx.environment.get_screen(), work_dir=work_dir, ) except launch.SpawnError as exc: raise OperationError(exc) from exc def get_id(self) -> str: """Return the unique ID for this app. This is the GIO id "gedit.desktop" minus the .desktop part for system-installed applications. """ return launch.application_id(self.object, self._init_path) def get_actions(self) -> ty.Iterable[Action]: id_ = self.get_id() if id_ == DESKTOP_ID: return if launch.application_is_running(id_): yield Launch(_("Go To"), is_running=True) yield CloseAll() else: yield Launch() yield LaunchAgain() def get_description(self) -> str | None: # Use Application's description, else use executable # for "file-based" applications we show the path app_desc = self.object.get_description() ret: str = app_desc or self.object.get_executable() if self._init_path: app_path = launch.get_display_path_for_bytestring(self._init_path) return f"({app_path}) {ret}" return ret def get_gicon(self) -> icons.GIcon | None: return self.object.get_icon() def get_icon_name(self) -> str: return "exec" class Launch(Action): """Launches an application (AppLeaf)""" action_accelerator: str | None = "o" rank_adjust = 5 def __init__( self, name: str | None = _("Launch"), is_running: bool = False, open_new: bool = False, ) -> None: """ If @is_running, style as if the app is running (Show application) If @open_new, always start a new instance. """ Action.__init__(self, name) self.is_running = is_running self.open_new = open_new def wants_context(self) -> bool: return True def activate( self, leaf: Leaf, iobj: Leaf | None = None, ctx: commandexec.ExecutionToken | None = None, ) -> Leaf | None: assert isinstance(leaf, AppLeaf) leaf.launch(activate=not self.open_new, ctx=ctx) return None def get_description(self) -> str: if self.is_running: return _("Show application window") return _("Launch application") def get_icon_name(self) -> str: if self.is_running: return "go-jump" return "kupfer-launch" class LaunchAgain(Launch): action_accelerator: str | None = None rank_adjust = 0 def __init__(self, name: str | None = _("Launch Again")): Launch.__init__(self, name, open_new=True) def item_types(self) -> ty.Iterator[ty.Type[Leaf]]: yield AppLeaf def valid_for_item(self, leaf: Leaf) -> bool: assert isinstance(leaf, AppLeaf) return launch.application_is_running(leaf.get_id()) def get_description(self) -> str: return _("Launch another instance of this application") class CloseAll(Action): """Attempt to close all application windows""" rank_adjust = -10 def __init__(self, name: str | None = _("Close")) -> None: Action.__init__(self, name) def activate( self, leaf: Leaf, iobj: Leaf | None = None, ctx: commandexec.ExecutionToken | None = None, ) -> Leaf | None: assert isinstance(leaf, AppLeaf) launch.application_close_all(leaf.get_id()) return None def item_types(self) -> ty.Iterator[ty.Type[Leaf]]: yield AppLeaf def valid_for_item(self, leaf: Leaf) -> bool: assert isinstance(leaf, AppLeaf) return launch.application_is_running(leaf.get_id()) def get_description(self) -> str: return _("Attempt to close all application windows") def get_icon_name(self) -> str: return "window-close" kupfer-328/kupfer/obj/base.py000066400000000000000000000447321500175051100162230ustar00rootroot00000000000000""" Base kupfer objects definitions. This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ from __future__ import annotations import time import typing as ty from kupfer import icons from kupfer.support import itertools, kupferstring, pretty if ty.TYPE_CHECKING: from gettext import gettext as _ from gi.repository import GdkPixbuf from kupfer.core import commandexec __all__ = [ "Action", "ActionGenerator", "AnySource", "KupferObject", "Leaf", "Source", "TextSource", "_NonpersistentToken", ] class KupferObject: """Base class for kupfer data model This class provides a way to get at an object's: * icon with get_thumbnail, get_pixbuf and get_icon * name with unicode() or str() * description with get_description @rank_adjust should be used _very_ sparingly: Default actions should have +5 or +1 Destructive (dangerous) actions should have -5 or -10 @fallback_icon_name is a class attribute for the last fallback icon; it must always be accessible. """ rank_adjust: int = 0 fallback_icon_name: str = "kupfer-object" # _is_builtin: bool = False def __init__(self, name: str | None = None) -> None: """Init kupfer object with.""" self.name: str = name or self.__class__.__name__ folded_name = kupferstring.tofolded(self.name) self.kupfer_add_alias(folded_name) def kupfer_add_alias(self, alias: str) -> None: """Add alias to object. This create name_aliases set if not exist for this leaf.""" if alias != str(self): if not hasattr(self, "name_aliases"): self.name_aliases = set() self.name_aliases.add(alias) def __str__(self) -> str: return self.name def __repr__(self) -> str: if cached := getattr(self, "_cached_repr", None): return ty.cast("str", cached) if key := self.repr_key(): rep = f"<{self.__module__}.{self.__class__.__name__} {key}>" else: rep = f"<{self.__module__}.{self.__class__.__name__}>" self._cached_repr = rep return rep def repr_key(self) -> ty.Any: """Return an object whose str() will be used in the __repr__, self is returned by default. This value is used to recognize objects, for example learning commonly used objects.""" return self def get_description(self) -> str | None: """Return a description of the specific item.""" return None def get_thumbnail( self, width: int, height: int ) -> GdkPixbuf.Pixbuf | None: """Return pixbuf of size @width x @height if available. Most objects will not implement this.""" return None def get_pixbuf(self, icon_size: int) -> GdkPixbuf.Pixbuf | None: """Returns an icon in pixbuf format with dimension @icon_size. Subclasses should implement: get_gicon and get_icon_name, if they make sense. The methods are tried in that order.""" if (gicon := self.get_gicon()) and ( pbuf := icons.get_icon_for_gicon(gicon, icon_size) ): return pbuf if (icon_name := self.get_icon_name()) and ( icon := icons.get_icon_for_name(icon_name, icon_size) ): return icon return icons.get_icon_for_name(self.fallback_icon_name, icon_size) def get_icon(self) -> icons.GIcon | None: """Returns an icon in GIcon format. Subclasses should implement: get_gicon and get_icon_name, if they make sense. The methods are tried in that order.""" if (gicon := self.get_gicon()) and icons.is_good_gicon(gicon): return gicon if ( icon_name := self.get_icon_name() ) and icons.get_good_name_for_icon_names((icon_name,)): return icons.get_gicon_for_names(icon_name) return icons.get_gicon_for_names(self.fallback_icon_name) def get_gicon(self) -> icons.GIcon | None: """Return GIcon, if there is one""" return None def get_icon_name(self) -> str: """Return icon name. All items should have at least a generic icon name to return.""" return self.fallback_icon_name T = ty.TypeVar("T") class _NonpersistentToken(ty.Generic[T]): """Hold data that goes None when pickled.""" __slots__ = ("object",) def __init__(self, object_: T) -> None: self.object: T = object_ def __bool__(self) -> bool: return bool(self.object) def __reduce__(self): return (sum, ((), None)) class Leaf(KupferObject): """Base class for objects Leaf.object is the represented object (data) All Leaves should be hashable (__hash__ and __eq__) """ def __init__(self, obj: ty.Any, name: str) -> None: """Represented object @obj and its @name""" super().__init__(name) self.object = obj self._content_source: _NonpersistentToken[Source] | None = None def __hash__(self) -> int: return hash(str(self)) def __eq__(self, other: object) -> bool: return type(self) is type(other) and self.object == other.object # type: ignore def add_content(self, content: Source | None) -> None: """Register content source @content with Leaf""" if content: self._content_source = _NonpersistentToken(content) def has_content(self) -> bool: return bool(self._content_source) def content_source(self, alternate: bool = False) -> Source | None: """Content of leaf. it MAY alter behavior with @alternate, as easter egg/extra mode""" if self._content_source: return self._content_source.object return None def get_actions(self) -> ty.Iterable[Action]: """Default (builtin) actions for this Leaf""" return () class Action(KupferObject): '''Base class for all actions. Implicit interface: valid_object will be called once for each (secondary) object to see if it applies. If it is not defined, all objects are assumed ok (within the other type/source constraints) def valid_object(self, obj, for_item): """Whether @obj is good for secondary obj, where @for_item is passed in as a hint for which it should be applied to """ return True @action_accelerator: str or None Default single lowercase letter key to use for selecting the action quickly ''' fallback_icon_name: str = "kupfer-execute" action_accelerator: str | None = None def __hash__(self) -> int: return hash(repr(self)) def __eq__(self, other: object) -> bool: return ( type(self) is type(other) and repr(self) == repr(other) and str(self) == str(other) ) def repr_key(self) -> ty.Any: """by default, actions of one type are all the same""" return None def activate( self, leaf: Leaf, iobj: Leaf | None = None, ctx: commandexec.ExecutionToken | None = None, ) -> Leaf | None: """Use this action with @obj and @iobj leaf: the direct object (Leaf) iobj: the indirect object (Leaf), if ``self.requires_object`` returns ``False`` ctx: optional ExecutionToken if ``self.wants_context`` returns ``True``, then the action also receives an execution context object as ``ctx``. Also, ``activate_multiple(self, objects, iobjects=None, ctx=None)`` is called if it is defined and the action gets either multiple objects or iobjects. """ raise NotImplementedError def wants_context(self) -> bool: """Return ``True`` if ``activate`` should receive the ActionExecutionContext as the keyword argument context Defaults to ``False`` in accordance with the old protocol """ return False def is_factory(self) -> bool: """Return whether action may return a result collection as a Source""" return False def has_result(self) -> bool: """Return whether action may return a result item as a Leaf""" return False def is_async(self) -> bool: """If this action runs asynchronously, return True. Then activate(..) must return an object from the kupfer.task module, which will be queued to run by Kupfer's task scheduler. """ return False def item_types(self) -> ty.Iterable[ty.Type[Leaf]]: """Yield types this action may apply to. This is used only when this action is specified in __kupfer_actions__ to "decorate" """ return () def valid_for_item(self, leaf: Leaf) -> bool: """Whether action can be used with exactly @item""" return True def requires_object(self) -> bool: """If this action requires a secondary object to complete is action, return True.""" return False def object_source(self, for_item: Leaf | None = None) -> Source | None: """Source to use for object or None, to use the catalog (flat and filtered for @object_types).""" return None def object_source_and_catalog(self, for_item: Leaf) -> bool: return False def object_types(self) -> ty.Iterable[ty.Type[Leaf]]: """Yield types this action may use as indirect objects, if the action requrires it.""" return () class Source(KupferObject, pretty.OutputMixin): """Source: Data provider for a kupfer browser. All Sources should be hashable and treated as equal if their @repr are equal! *source_user_reloadable* if True source get "Reload" action without debug mode. *source_prefer_sublevel* if True, the source by default exports its contents in a subcatalog, not to the toplevel. NOTE: *Almost never* use this: let the user decide, default to toplevel. *source_use_cache* if True, the source can be pickled to disk to save its cached items until the next time the launcher is started. *source_scan_interval* set typical rescan interval (not guaranteed) in seconds. Set 0 to use default. values lower than min_rescan_interval in PeriodicRescanner are ignored. Warning: last scan time is pickled, so after restart - source may be immediately rescanned. *rank_adjust* change all leaves rank by given value. This only apply to search with key when given leaf already pass minimum rank level. """ fallback_icon_name = "kupfer-object-multiple" source_user_reloadable = False source_prefer_sublevel = False source_use_cache = True source_scan_interval: int = 0 def __init__(self, name): KupferObject.__init__(self, name) self.cached_items: ty.Iterable[Leaf] | None = None self._version: int = 1 # last source rescan timestamp self.last_scan: int = 0 @property def version(self) -> int: """Version is for pickling (save and restore from cache), subclasses should increase self._version when changing.""" return self._version def __eq__(self, other): return ( type(self) is type(other) and repr(self) == repr(other) and self.version == other.version ) def __hash__(self) -> int: return hash(repr(self)) def toplevel_source(self) -> Source: return self def initialize(self) -> None: """Called when a Source enters Kupfer's system for real. This method is called at least once for any "real" Source. A Source must be able to return an icon name for get_icon_name as well as a description for get_description, even if this method was never called. """ def finalize(self) -> None: """Called before a source is deactivated.""" def repr_key(self) -> ty.Any: return None def get_items(self) -> ty.Iterable[Leaf]: """Internal method to compute and return the needed items. Subclasses should use this method to return a sequence or iterator to the leaves it contains """ return [] def get_items_forced(self) -> ty.Iterable[Leaf]: """Force compute and return items for source. Default - call get_items method.""" return self.get_items() def is_dynamic(self) -> bool: """Whether to recompute contents each time it is accessed.""" return False def mark_for_update(self, postpone: bool = False) -> None: """Mark source as changed. When postpone is True, cached items are not cleaned so be available to use and refreshed on next PeriodicRescanner run. If there is no cached_items source load items on next use. """ self.last_scan = 0 if not postpone: self.cached_items = None def should_sort_lexically(self) -> bool: """Sources should return items by most relevant order (most relevant first). If this is True, Source will sort items from get_item() in locale lexical order.""" return False def get_leaves(self, force_update: bool = False) -> ty.Iterable[Leaf]: """Return a list of leaves. Subclasses should implement ``get_items()``, so that ``Source`` can handle sorting and caching. If *force_update*, ignore cache, load *all* leaves from source and store it into cache. Print number of items loaded. If source ``get_items()`` return list or tuple - also all leaves are loaded and stored in cache. Otherwise (when ``get_items()`` is generator) leaves are loaded on request and cached in ``SavedIterable``. If ``should_sort_lexically()`` is True - all leaves are loaded, sorted and cached. """ if self.is_dynamic(): items = ( self.get_items_forced() if force_update else self.get_items() ) if self.should_sort_lexically(): items = kupferstring.locale_sort(items) return items if self.cached_items is None or force_update: items = ( self.get_items_forced() if force_update else self.get_items() ) if self.should_sort_lexically(): # sorting make list items = kupferstring.locale_sort(items) if force_update: # make list when needed self.cached_items = itertools.as_list(items) self.output_debug(f"Loaded {len(self.cached_items)} items") elif isinstance(items, (list, tuple)): self.cached_items = items self.output_debug(f"Loaded {len(items)} items (l)") else: # use savediterable only for iterators self.cached_items = itertools.SavedIterable(items) self.output_debug("Loaded items") self.last_scan = int(time.time()) return self.cached_items or () def has_parent(self) -> bool: """Return True when source has other, parent Source.""" return False def get_parent(self) -> Source | None: """Return parent Source for given source if exists or None.""" return None def get_leaf_repr(self) -> Leaf | None: """Return, if applicable, another object to take the source's place as Leaf""" return None def get_valid_leaf_repr(self) -> tuple[bool, Leaf | None]: """Return, if applicable, another object to take the source's place as Leaf. Return tuple (leaf representation is valid, leaf). Valid representation may be None, so first element of tuple must be checked.""" if ( (leaf_repr := self.get_leaf_repr()) and (hasattr(leaf_repr, "is_valid")) and not leaf_repr.is_valid() ): return False, None return True, leaf_repr def provides(self) -> ty.Iterable[ty.Type[Leaf]]: """A seq of the types of items it provides; empty is taken as anything -- however most sources should set this to exactly the type they yield. """ return () def get_search_text(self) -> str: """Message displayed on gui when no item is selected.""" return _("Type to search") def get_empty_text(self) -> str: """Text displayed when no leaves found in source.""" return _("%s is empty") % str(self) class TextSource(KupferObject): """TextSource base class implementation, this is a pseudo Source.""" def __init__( self, name: str | None = None, placeholder: str | None = None, ) -> None: """ *name*: Localized name *placeholder*: Localized placeholder when it has no input """ if not name: name = _("Text") KupferObject.__init__(self, name) self.placeholder = placeholder def __eq__(self, other: object) -> bool: return type(self) is type(other) and repr(self).__eq__(repr(other)) def __hash__(self) -> int: return hash(repr(self)) def initialize(self) -> None: pass def repr_key(self) -> ty.Any: return None def get_rank(self) -> int: """All items are given this rank.""" return 20 def get_items(self, text: str) -> ty.Iterable[Leaf]: return () def get_text_items(self, text: str) -> ty.Iterable[Leaf]: """Get leaves for string `text`.""" return self.get_items(text) def has_parent(self) -> bool: return False def provides(self) -> ty.Iterable[ty.Type[Leaf]]: """A seq of the types of items it provides""" yield Leaf def get_icon_name(self) -> str: return "edit-select-all" def get_search_text(self) -> str: return self.placeholder or _("Text") def get_empty_text(self) -> str: return self.placeholder or _("Text") # pylint: disable=too-few-public-methods class ActionGenerator: """A "source" for actions. NOTE: The ActionGenerator should not perform any expensive computation, and not access any slow media (files, network) when returning actions. Such expensive checks must be performed in each Action's valid_for_item method. """ def get_actions_for_leaf(self, leaf: Leaf) -> ty.Iterable[Action]: """Return actions appropriate for given leaf.""" return () AnySource = ty.Union[Source, TextSource] kupfer-328/kupfer/obj/compose.py000066400000000000000000000130071500175051100167450ustar00rootroot00000000000000""" Object related to composited objects. This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ from __future__ import annotations import typing as ty from kupfer import icons, puid from kupfer.obj import actions, exceptions, objects from kupfer.obj.base import Action, Leaf, Source from kupfer.support import itertools, pretty, scheduler, textutils if ty.TYPE_CHECKING: from gettext import gettext as _ from gettext import ngettext from kupfer.core import commandexec __all__ = ( "ComposedLeaf", "MultipleLeaf", "TimedPerform", ) class TimedPerform(actions.Perform): """A timed (delayed) version of Run (Perform)""" action_accelerator: str | None = None def __init__(self, name: str = _("Run after Delay...")) -> None: super().__init__(name) def activate( self, leaf: Leaf, iobj: Leaf | None = None, ctx: commandexec.ExecutionToken | None = None, ) -> Leaf | None: assert isinstance(leaf, objects.RunnableLeaf) assert isinstance(iobj, objects.TextLeaf) # make a timer that will fire when Kupfer exits interval = textutils.parse_time_interval(iobj.object) pretty.print_debug(__name__, f"Run {leaf} in {interval} seconds") timer = scheduler.Timer(True) if leaf.wants_context(): timer.set(interval, leaf.run, ctx) else: timer.set(interval, leaf.run) return None def requires_object(self) -> bool: return True def object_types(self) -> ty.Iterator[ty.Type[Leaf]]: yield objects.TextLeaf def valid_object(self, iobj: Leaf, for_item: Leaf | None = None) -> bool: return textutils.parse_time_interval(iobj.object) > 0 def get_description(self) -> str: return _("Perform command after a specified time interval") class ComposedLeaf(objects.RunnableLeaf): """Leaf that contains many other leaves, created by compose action. Represented object is tuple (object, action, action object). """ serializable = 1 def __init__( self, obj: Leaf, action: Action, iobj: Leaf | None = None ) -> None: object_ = (obj, action, iobj) # A slight hack: We remove trailing ellipsis and whitespace name = " → ".join( str(o).strip(".… ") for o in object_ if o is not None ) objects.RunnableLeaf.__init__(self, object_, name) def __getstate__(self) -> dict[str, ty.Any]: state = dict(vars(self)) state["object"] = [puid.get_unique_id(o) for o in self.object] return state def __setstate__(self, state: dict[str, ty.Any]) -> None: vars(self).update(state) objid, actid, iobjid = state["object"] obj = puid.resolve_unique_id(objid) assert isinstance(obj, Leaf) act = puid.resolve_action_id(actid, obj) iobj = puid.resolve_unique_id(iobjid) if (not obj or not act) or (iobj is None) != (iobjid is None): raise exceptions.InvalidDataError(f"Parts of {self} not restored") self.object[::] = [obj, act, iobj] def get_actions(self) -> ty.Iterator[Action]: yield actions.Perform() yield TimedPerform() def repr_key(self) -> ty.Any: return self def wants_context(self) -> bool: return True def run(self, ctx: commandexec.ExecutionToken | None = None) -> None: obj, action, iobj = self.object assert ctx and hasattr(ctx, "delegated_run") ctx.delegated_run(obj, action, iobj) def get_gicon(self) -> icons.GIcon | None: obj, action, _iobj = self.object return icons.ComposedIcon(obj.get_icon(), action.get_icon()) class _MultipleLeafContentSource(Source): def __init__(self, leaf: Leaf) -> None: Source.__init__(self, str(leaf)) self.leaf = leaf def get_items(self) -> ty.Any: return self.leaf.object class MultipleLeaf(Leaf): """A Leaf for the direct representation of many leaves. It is not a container or "source", it *is* the many leaves itself. The represented object is a sequence of Leaves.""" serializable = 1 def __init__(self, obj: ty.Any, name: str = _("Multiple Objects")) -> None: # modifying the list of objects is strictly forbidden robj = list(itertools.unique_iterator(obj)) Leaf.__init__(self, robj, name) def get_multiple_leaf_representation(self) -> ty.Sequence[Leaf]: return ty.cast("ty.Sequence[Leaf]", self.object) def __getstate__(self) -> dict[str, ty.Any]: state = dict(vars(self)) state["object"] = [puid.get_unique_id(o) for o in self.object] return state def __setstate__(self, state: dict[str, ty.Any]) -> None: vars(self).update(state) objs = [] for id_ in state["object"]: if (obj := puid.resolve_unique_id(id_)) is not None: objs.append(obj) else: raise exceptions.InvalidDataError( f"{id_} could not be restored!" ) self.object[::] = objs def has_content(self) -> bool: return True def content_source(self, alternate: bool = False) -> Source: return _MultipleLeafContentSource(self) def get_description(self) -> str: num = len(self.object) return ngettext("%s object", "%s objects", num) % (num,) def get_icon_name(self) -> str: return "kupfer-object-multiple" kupfer-328/kupfer/obj/contacts.py000066400000000000000000000177371500175051100171340ustar00rootroot00000000000000""" Kupfer's Contacts API Main definition and *constructor* classes. Constructor classes such as EmailContact are used to conveniently construct contacts with common traits. To *use* contacts, always use ContactLeaf, asking for specific slots to be filled. """ from __future__ import annotations import typing as ty from kupfer import icons from kupfer.obj.grouping import GroupingLeaf, Slots from kupfer.support import validators if ty.TYPE_CHECKING: from gettext import gettext as _ from gi.repository import GdkPixbuf from kupfer.obj.base import Leaf __author__ = ( "Ulrik Sverdrup , " "Karol Będkowski , " "Adi Sieker " ) __all__ = ( "AIMContact", "AddressContact", "ContactLeaf", "EmailContact", "GoogleTalkContact", "ICQContact", "IMContact", "JabberContact", "MSNContact", "PhoneContact", "QQContact", "SkypeContact", "YahooContact", "email_from_leaf", ) EMAIL_KEY = "EMAIL" NAME_KEY = "NAME" PHONE_KEY = "PHONE" ADDRESS_KEY = "ADDRESS" LABEL_KEY = "LABEL" JABBER_JID_KEY = "JID" JABBER_STATUS_KEY = "JABBER_STATUS" JABBER_RESOURCE_KEY = "JABBER_RESOURCE" AIM_KEY = "AIM" GOOGLE_TALK_KEY = "GOOGLE_TALK" ICQ_KEY = "ICQ" MSN_KEY = "MSN" QQ_KEY = "QQ" SKYPE_KEY = "SKYPE" YAHOO_KEY = "YAHOO" class ContactLeaf(GroupingLeaf): """Represent "human" contact leaf, like email, im address and so.""" grouping_slots: tuple[str, ...] = () def __init__(self, obj: ty.Any, name: str, image: ty.Any = None) -> None: self.image = image GroupingLeaf.__init__(self, obj, name) def get_icon_name(self) -> str: return "stock_person" def get_text_representation(self) -> str | None: return self.get_description() def get_thumbnail( self, width: int, height: int ) -> GdkPixbuf.Pixbuf | None: if self.image: return icons.get_pixbuf_from_data(self.image, width, height) return GroupingLeaf.get_thumbnail(self, width, height) ## E-mail convenience and constructors def _get_email_from_url(url: str) -> str: """convert http://foo@bar.pl -> foo@bar.pl""" *_dummy, email = url.partition("://") return email or url def email_from_leaf(leaf: Leaf) -> str | None: """Return an email address string if @leaf has a valid email address. @leaf may also be a TextLeaf or UrlLeaf. Return a false value if no valid email is found. """ if isinstance(leaf, ContactLeaf): return leaf.get(EMAIL_KEY) # type: ignore email = _get_email_from_url(str(leaf.object)) return email if validators.is_valid_email(email) else None class EmailContact(ContactLeaf): grouping_slots = (*ContactLeaf.grouping_slots, EMAIL_KEY) def __init__(self, email: str, name: str, image: ty.Any = None) -> None: slots = {EMAIL_KEY: email, NAME_KEY: name} ContactLeaf.__init__(self, slots, name, image) def repr_key(self) -> ty.Any: return self.object[EMAIL_KEY] def get_description(self) -> str: return self.object[EMAIL_KEY] # type:ignore def get_gicon(self) -> icons.GIcon: return icons.ComposedIconSmall(self.get_icon_name(), "stock_mail") class IMContact(ContactLeaf): grouping_slots = (*ContactLeaf.grouping_slots, EMAIL_KEY) def __init__( self, im_id_kind: str, im_id: str, name: str, label: str | None = None, other_slots: Slots = None, image: ty.Any = None, ) -> None: self.im_id_kind = im_id_kind slots = {im_id_kind: im_id, NAME_KEY: name, LABEL_KEY: label} if other_slots: slots.update(other_slots) ContactLeaf.__init__(self, slots, name, image) self.kupfer_add_alias(im_id) def repr_key(self) -> ty.Any: return self.object[self.im_id_kind] def get_description(self) -> str: return ( # type:ignore self.object[LABEL_KEY] or self.object[self.im_id_kind] ) class JabberContact(IMContact): """Minimal class for all Jabber contacts.""" grouping_slots = (*IMContact.grouping_slots, JABBER_JID_KEY) def __init__( self, jid: str, name: str, status: str | None = None, resource: str | None = None, slots: Slots = None, image: ty.Any = None, ) -> None: IMContact.__init__( self, JABBER_JID_KEY, jid, name or jid, other_slots=slots, image=image, ) self._description: str = _("[%(status)s] %(userid)s/%(service)s") % { # TRANS: unknown user status "status": status or _("unknown"), "userid": jid, "service": resource or "", } def get_description(self) -> str: return self._description class AIMContact(IMContact): grouping_slots = (*IMContact.grouping_slots, AIM_KEY) def __init__( self, id_: str, name: str, slots: Slots = None, image: ty.Any = None, ) -> None: IMContact.__init__(self, AIM_KEY, id_, name, _("Aim"), slots, image) class GoogleTalkContact(IMContact): grouping_slots = (*IMContact.grouping_slots, GOOGLE_TALK_KEY) def __init__( self, id_: str, name: str, slots: Slots = None, image: ty.Any = None ) -> None: IMContact.__init__( self, GOOGLE_TALK_KEY, id_, name, _("Google Talk"), slots, image ) class ICQContact(IMContact): grouping_slots = (*IMContact.grouping_slots, ICQ_KEY) def __init__( self, id_: str, name: str, slots: Slots = None, image: ty.Any = None ) -> None: IMContact.__init__(self, ICQ_KEY, id_, name, _("ICQ"), slots, image) class MSNContact(IMContact): grouping_slots = (*IMContact.grouping_slots, MSN_KEY) def __init__( self, id_: str, name: str, slots: Slots = None, image: ty.Any = None ) -> None: IMContact.__init__(self, MSN_KEY, id_, name, _("MSN"), slots, image) class QQContact(IMContact): grouping_slots = (*IMContact.grouping_slots, QQ_KEY) def __init__( self, id_: str, name: str, slots: Slots = None, image: ty.Any = None ) -> None: IMContact.__init__(self, QQ_KEY, id_, name, _("QQ"), slots, image) class YahooContact(IMContact): grouping_slots = (*IMContact.grouping_slots, YAHOO_KEY) def __init__( self, id_: str, name: str, slots: Slots = None, image: ty.Any = None ) -> None: IMContact.__init__( self, YAHOO_KEY, id_, name, _("Yahoo"), slots, image ) class SkypeContact(IMContact): grouping_slots = (*IMContact.grouping_slots, SKYPE_KEY) def __init__( self, id_: str, name: str, slots: Slots = None, image: ty.Any = None ) -> None: IMContact.__init__( self, SKYPE_KEY, id_, name, _("Skype"), slots, image ) class PhoneContact(ContactLeaf): grouping_slots = (*ContactLeaf.grouping_slots, EMAIL_KEY) def __init__( self, number: str, name: str, label: str, slots: Slots = None, image: ty.Any = None, ) -> None: pslots = {PHONE_KEY: number, NAME_KEY: name, LABEL_KEY: label} if slots: pslots.update(slots) ContactLeaf.__init__(self, pslots, name, image) def repr_key(self) -> ty.Any: return self.object[PHONE_KEY] def get_description(self) -> str: return f"{self.object[LABEL_KEY]}: {self.object[PHONE_KEY]}" class AddressContact(ContactLeaf): grouping_slots = (*ContactLeaf.grouping_slots, EMAIL_KEY) def __init__( self, address: str, name: str, label: str, slots: Slots = None, image: ty.Any = None, ) -> None: aslots = {ADDRESS_KEY: address, NAME_KEY: name, LABEL_KEY: label} if slots: aslots.update(slots) ContactLeaf.__init__(self, aslots, name, image) def repr_key(self) -> ty.Any: return self.object[ADDRESS_KEY] kupfer-328/kupfer/obj/exceptions.py000066400000000000000000000023511500175051100174610ustar00rootroot00000000000000""" Common exceptions definition. This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ import typing as ty if ty.TYPE_CHECKING: from gettext import gettext as _ __all__ = ( "Error", "InvalidDataError", "InvalidLeafError", "NoDefaultApplicationError", "NoMultiError", "NotAvailableError", "OperationError", ) class Error(Exception): pass class InvalidDataError(Error): """The data is wrong for the given Leaf""" class OperationError(Error): """Command execution experienced an error""" class InvalidLeafError(OperationError): """The Leaf passed to an Action is invalid""" class NotAvailableError(OperationError): """User-visible error message when an external tool is the wrong version.""" def __init__(self, toolname: str): OperationError.__init__( self, _("%s does not support this operation") % toolname ) class NoMultiError(OperationError): def __init__(self): OperationError.__init__( self, _("Can not be used with multiple objects") ) class NoDefaultApplicationError(OperationError): pass kupfer-328/kupfer/obj/fileactions.py000066400000000000000000000073001500175051100175770ustar00rootroot00000000000000""" Actions for file leaves. This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ from __future__ import annotations import os import typing as ty from collections import defaultdict from gi.repository import Gio, GLib from kupfer import launch from kupfer.obj import files from kupfer.obj.base import Action, Leaf from kupfer.obj.exceptions import NoDefaultApplicationError from kupfer.support import pretty if ty.TYPE_CHECKING: from gettext import gettext as _ from kupfer.core import commandexec __all__ = ( "GetParent", "Open", ) class Open(Action): """Open with default application.""" action_accelerator = "o" rank_adjust = 5 def __init__(self, name: str = _("Open")) -> None: Action.__init__(self, name) @classmethod def default_application_for_leaf( cls, leaf: files.FileLeaf ) -> Gio.AppInfo | None: content_attr = Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE gfile = leaf.get_gfile() try: info = gfile.query_info( content_attr, Gio.FileQueryInfoFlags.NONE, None ) except GLib.GError as err: pretty.print_error("get appinfo for leaf", leaf, "error", err) return None content_type = info.get_attribute_string(content_attr) def_app = Gio.app_info_get_default_for_type(content_type, False) if not def_app: raise NoDefaultApplicationError( ( _("No default application for %(file)s (%(type)s)") % {"file": str(leaf), "type": content_type} ) + "\n" + _('Please use "%s"') % _("Set Default Application...") ) return def_app def wants_context(self) -> bool: return True def activate( self, leaf: Leaf, iobj: Leaf | None = None, ctx: commandexec.ExecutionToken | None = None, ) -> None: assert ctx self.activate_multiple((leaf,), ctx) def activate_multiple( self, objects: ty.Iterable[Leaf], ctx: commandexec.ExecutionToken | None = None, ) -> None: appmap: dict[str, Gio.AppInfo] = {} leafmap: dict[str, list[files.FileLeaf]] = defaultdict(list) for obj in objects: assert isinstance(obj, files.FileLeaf) if app := self.default_application_for_leaf(obj): id_ = app.get_id() appmap[id_] = app leafmap[id_].append(obj) for id_, leaves in leafmap.items(): app = appmap[id_] launch.launch_application( app, paths=[L.object for L in leaves], activate=False, screen=ctx and ctx.environment.get_screen(), ) def get_description(self) -> str | None: return _("Open with default application") class GetParent(Action): action_accelerator = "p" rank_adjust = -5 def __init__(self, name: str = _("Get Parent Folder")) -> None: super().__init__(name) def has_result(self) -> bool: return True def activate( self, leaf: Leaf, iobj: Leaf | None = None, ctx: commandexec.ExecutionToken | None = None, ) -> files.FileLeaf: assert isinstance(leaf, files.FileLeaf) fileloc = leaf.object parent = os.path.normpath(os.path.join(fileloc, os.path.pardir)) return files.FileLeaf(parent) def get_description(self) -> str | None: return None def get_icon_name(self) -> str: return "folder-open" kupfer-328/kupfer/obj/files.py000066400000000000000000000141531500175051100164050ustar00rootroot00000000000000""" File-related objects This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ from __future__ import annotations import os import typing as ty from os import path from pathlib import Path from gi.repository import GdkPixbuf, Gio, GLib from kupfer import icons, launch from kupfer.obj import actions, fileactions, filesrc from kupfer.obj.base import Action, Leaf, Source from kupfer.obj.exceptions import InvalidDataError from kupfer.obj.representation import TextRepresentation from kupfer.support import pretty __all__ = ("FileLeaf",) class FileLeaf(Leaf, TextRepresentation): """Represents one file: the represented object is a string.""" serializable: int | None = 1 def __init__( self, obj: str | Path, name: str | None = None, alias: str | None = None, ) -> None: """Construct a FileLeaf The display name of the file is normally derived from the full path, and @name should normally be left unspecified. @obj: string (path) or Path object @name: file name or None for using basename """ if obj is None: raise InvalidDataError(f"File path for {name} may not be None") if isinstance(obj, Path): obj = str(obj) # Use glib filename reading to make display name out of filenames # this function returns a `unicode` object if not name: name = GLib.filename_display_basename(obj) assert name super().__init__(obj, name) if alias: self.kupfer_add_alias(alias) @classmethod def from_uri(cls, uri: str) -> FileLeaf | None: """Construct a FileLeaf from local `uri`. Return FileLeaf if it is supported, else None. """ gfile = Gio.File.new_for_uri(uri) fpath = gfile.get_path() if fpath: return cls(fpath) return None def __hash__(self) -> int: return hash(str(self)) def __eq__(self, other: object) -> bool: try: return ( type(self) is type(other) and str(self) == str(other) and path.samefile(self.object, other.object) # type: ignore ) except OSError as exc: pretty.print_debug(__name__, exc) return False def repr_key(self) -> ty.Any: return self.object def canonical_path(self) -> str: """Return the true path of the File (without symlinks)""" assert isinstance(self.object, str) return path.realpath(self.object) def is_valid(self) -> bool: return os.access(self.object, os.R_OK) def is_writable(self) -> bool: return os.access(self.object, os.W_OK) def is_executable(self) -> bool: return not path.isdir(self.object) and os.access( self.object, os.R_OK | os.X_OK ) def is_dir(self) -> bool: return path.isdir(self.object) def get_text_representation(self) -> str: return GLib.filename_display_name(self.object) # type: ignore def get_urilist_representation(self) -> list[str]: return [self.get_gfile().get_uri()] def get_gfile(self) -> Gio.File: """Return a Gio.File of self.""" return Gio.File.new_for_path(self.object) def get_description(self) -> str | None: return launch.get_display_path_for_bytestring(self.canonical_path()) def get_actions(self) -> ty.Iterable[Action]: yield fileactions.Open() yield fileactions.GetParent() if self.is_dir(): yield actions.OpenTerminal() elif self.is_valid() and self._is_good_executable(): yield actions.Execute() yield actions.Execute(in_terminal=True) def has_content(self) -> bool: return self.is_dir() or Leaf.has_content(self) def content_source(self, alternate: bool = False) -> Source | None: if self.is_dir(): return filesrc.DirectorySource(self.object, show_hidden=alternate) return Leaf.content_source(self) def get_thumbnail( self, width: int, height: int ) -> GdkPixbuf.Pixbuf | None: if self.is_dir(): return None return icons.get_thumbnail_for_gfile(self.get_gfile(), width, height) def get_gicon(self) -> icons.GIcon | None: return icons.get_gicon_for_file(self.object) def get_icon_name(self) -> str: if self.is_dir(): return "folder" return "text-x-generic" def get_content_type(self) -> str | None: ret: str uncertain: bool ret, uncertain = Gio.content_type_guess(self.object, None) if not uncertain: return ret content_attr = Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE gfile = self.get_gfile() if not gfile.query_exists(None): return None info = gfile.query_info( content_attr, Gio.FileQueryInfoFlags.NONE, None ) content_type: str = info.get_attribute_string(content_attr) return content_type def is_content_type(self, ctype: str) -> bool: """Return True if this file is of the type `ctype` mime type, can have wildcards like 'image/*'.""" predicate = Gio.content_type_is_a ctype_guess, uncertain = Gio.content_type_guess(self.object, None) ret: bool = predicate(ctype_guess, ctype) if ret or not uncertain: return ret content_attr = Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE gfile = self.get_gfile() if not gfile.query_exists(None): return False info = gfile.query_info( content_attr, Gio.FileQueryInfoFlags.NONE, None ) content_type = info.get_attribute_string(content_attr) return predicate(content_type, ctype) # type: ignore def _is_good_executable(self): if not self.is_executable(): return False ctype, uncertain = Gio.content_type_guess(self.object, None) return uncertain or Gio.content_type_can_be_executable(ctype) kupfer-328/kupfer/obj/filesrc.py000066400000000000000000000126421500175051100167330ustar00rootroot00000000000000""" File - related sources This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ from __future__ import annotations import os import typing as ty from contextlib import suppress from os import path from gi.repository import Gio, GLib from kupfer import icons from kupfer.obj import apps, files from kupfer.obj.base import Leaf, Source from kupfer.obj.exceptions import InvalidDataError from kupfer.obj.helplib import FilesystemWatchMixin from kupfer.support import fileutils if ty.TYPE_CHECKING: from gettext import gettext as _ __all__ = ( "DirectorySource", "FileSource", "construct_file_leaf", ) def construct_file_leaf(obj: str) -> Leaf: """If the path in @obj points to a Desktop Item file, return an AppLeaf, otherwise return a FileLeaf """ if obj.endswith(".desktop"): with suppress(InvalidDataError): return apps.AppLeaf(init_path=obj) return files.FileLeaf(obj) class DirectorySource(Source, FilesystemWatchMixin): source_use_cache = False def __init__( self, directory: str, show_hidden: bool = False, *, toplevel: bool = False, ) -> None: # Use glib filename reading to make display name out of filenames # this function returns a `unicode` object name = GLib.filename_display_basename(directory) super().__init__(name) self._directory = directory self._show_hidden = show_hidden self._toplevel = toplevel self.monitor: ty.Any = None self._user_home = os.path.expanduser("~") def __repr__(self) -> str: return ( f"{self.__class__.__module__}.{self.__class__.__name__}" f'("{self._directory}", show_hidden={self._show_hidden})' ) def initialize(self) -> None: # only toplevel directories are active monitored if self._toplevel: self.monitor = self.monitor_directories(self._directory) def finalize(self) -> None: if self.monitor: self.stop_monitor_fs_changes(self.monitor) self.monitor = None def monitor_include_file(self, gfile: Gio.File) -> bool: return self._show_hidden or not gfile.get_basename().startswith(".") def get_items(self) -> ty.Iterator[Leaf]: dirfiles: ty.Iterable[os.DirEntry[str]] try: with os.scandir(self._directory) as dirfiles: if self._show_hidden: yield from ( construct_file_leaf(entry.path) for entry in dirfiles ) else: yield from ( construct_file_leaf(entry.path) for entry in dirfiles if entry.name[0] != "." ) except OSError as exc: self.output_error(exc) def should_sort_lexically(self) -> bool: return True def _parent_path(self) -> str: return path.normpath(path.join(self._directory, path.pardir)) def has_parent(self) -> bool: return not path.samefile(self._directory, self._parent_path()) def get_parent(self) -> DirectorySource | None: if not self.has_parent(): return None return DirectorySource(self._parent_path()) def get_description(self) -> str: return _("Directory source %s") % self._directory def get_gicon(self) -> icons.GIcon | None: return icons.get_gicon_for_file(self._directory) def get_icon_name(self) -> str: return "folder" def get_leaf_repr(self) -> Leaf | None: alias = None directory = self._directory if os.path.samefile(directory, self._user_home): alias = _("Home Folder") return files.FileLeaf(directory, alias=alias) def provides(self) -> ty.Iterable[ty.Type[Leaf]]: yield files.FileLeaf yield apps.AppLeaf class FileSource(Source): source_use_cache = False def __init__(self, dirlist: list[str], depth: int = 0) -> None: """ @dirlist: Directories as byte strings """ name = GLib.filename_display_basename(dirlist[0]) if len(dirlist) > 1: name = _("%s et. al.") % name super().__init__(name) self.dirlist = dirlist self.depth = depth def __repr__(self) -> str: mod = self.__class__.__module__ cname = self.__class__.__name__ dirs = ", ".join(f'"{d}"' for d in sorted(self.dirlist)) return f"{mod}.{cname}(({dirs}, ), depth={self.depth})" def get_items(self) -> ty.Iterable[Leaf]: for directory in self.dirlist: dirfiles = fileutils.get_dirlist( directory, max_depth=self.depth, exclude=self._exclude_file ) yield from map(construct_file_leaf, dirfiles) def should_sort_lexically(self) -> bool: return True def _exclude_file(self, filename: str) -> bool: return filename.startswith(".") def get_description(self) -> str: return _("Recursive source of %(dir)s, (%(levels)d levels)") % { "dir": self.name, "levels": self.depth, } def get_icon_name(self) -> str: return "folder-saved-search" def provides(self) -> ty.Iterator[ty.Type[Leaf]]: yield files.FileLeaf yield apps.AppLeaf kupfer-328/kupfer/obj/grouping.py000066400000000000000000000212421500175051100171320ustar00rootroot00000000000000""" Classes used to provide grouping leaves mechanism. This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ from __future__ import annotations import copy import itertools import time import typing as ty import weakref from collections import defaultdict from gi.repository import Gdk, Gtk from kupfer.obj.base import Action, Leaf, Source from kupfer.support import itertools as kitertools from kupfer.support import kupferstring if ty.TYPE_CHECKING: from gettext import gettext as _ from kupfer.core import commandexec __author__ = ( "Karol Będkowski , " "Ulrik Sverdrup " ) __all__ = ["GroupingLeaf", "GroupingSource", "ToplevelGroupingSource"] Slots = ty.Optional[dict[str, ty.Any]] class GroupingLeaf(Leaf): """A Leaf that groups with other leaves inside Grouping Sources. The represented object of a GroupedLeaf is a dictionary of (slot, value) pairs, where slot identifies the slot, and the value is something that must be equal to be grouped. The GroupingLeaf must have a value for all @grouping_slots, but values of None will not be grouped with others. """ grouping_slots: tuple[str, ...] = () def __init__(self, obj: ty.Any, name: str) -> None: Leaf.__init__(self, obj, name) self.links = [self] def slots(self) -> Slots: return ty.cast("Slots", self.object) def has_content(self) -> bool: return len(self.links) > 1 def content_source(self, alternate: bool = False) -> Source: return _GroupedItemsSource(self) def get(self, key: ty.Any, default: ty.Any = None) -> ty.Any: try: return next(self.all(key)) except StopIteration: return default def __len__(self) -> int: return len(self.links) def __contains__(self, key: ty.Any) -> bool: "Return True if GroupedLeaf has value for @key" return any(key in leaf.object for leaf in self.links) def __getitem__(self, key: ty.Any) -> ty.Any: "Get first (canonical) value for key" try: return next(self.all(key)) except StopIteration as exc: raise KeyError(f"{self} has no slot {key}") from exc def all(self, key: ty.Any) -> ty.Iterator[ty.Any]: "Return iterator of all values for @key" return (leaf.object[key] for leaf in self.links if key in leaf.object) def check_key(self, key: ty.Any) -> bool: """check if GroupedLeaf has non empty value for @key""" return any(bool(leaf.object.get(key)) for leaf in self.links) def get_actions(self) -> ty.Iterable[Action]: for key, val in kitertools.unique_iterator( keyval for leaf in self.links for keyval in leaf.object.items() ): yield CopySlotAction(key, val) _Groups = dict[tuple[str, ty.Any], set[GroupingLeaf]] _NonGroupLeaves = list[Leaf] class GroupingSource(Source): def __init__(self, name: str, sources: list[Source]) -> None: Source.__init__(self, name) self.sources = sources def _get_groups( self, force_update: bool ) -> tuple[_Groups, _NonGroupLeaves]: groups: _Groups = defaultdict(set) non_group_leaves: list[Leaf] = [] for src in self.sources: leaves = Source.get_leaves(src, force_update) for leaf in leaves or (): try: slots = leaf.slots() # type: ignore except AttributeError: # noqa:PERF203 # Let through Non-grouping leaves non_group_leaves.append(leaf) else: assert isinstance(leaf, GroupingLeaf) if not leaf.grouping_slots: self.output_error( "GroupingLeaf has no grouping slots", repr(leaf) ) continue for slot in leaf.grouping_slots: if value := slots.get(slot): groups[(slot, value)].add(leaf) return groups, non_group_leaves def _merge_groups(self, groups: _Groups) -> set[tuple[str, ty.Any]]: redundant_keys = set() def merge_groups(key1, key2): if groups[key1] is not groups[key2]: groups[key1].update(groups[key2]) groups[key2] = groups[key1] redundant_keys.add(key2) # Find all (slot, value) combinations that have more than one leaf # and merge those groups for (slot, value), gleaves in groups.items(): if len(gleaves) <= 1: continue for leaf in list(gleaves): for slot2 in leaf.grouping_slots: for value2 in leaf.all(slot2): if value2: merge_groups((slot, value), (slot2, value2)) return redundant_keys def get_leaves(self, force_update: bool = False) -> ty.Iterable[Leaf]: starttime = time.time() # map (slot, value) -> group groups, non_group_leaves = self._get_groups(force_update) # Keep track of keys that are only duplicate references redundant_keys = self._merge_groups(groups) keys = set(groups) keys.difference_update(redundant_keys) leaves: ty.Iterable[Leaf] = ( self._make_group_leader(groups[K]) for K in keys ) if self.should_sort_lexically(): leaves = kupferstring.locale_sort(leaves) if (mergetime := time.time() - starttime) > 0.05: # noqa: PLR2004 self.output_debug(f"Warning(?): merged in {mergetime} seconds") return itertools.chain(non_group_leaves, leaves) def repr_key(self) -> ty.Any: # Distinguish when used as GroupingSource if isinstance(self, GroupingSource): return str(self) return Source.repr_key(self) @classmethod def _make_group_leader(cls, leaves: set[GroupingLeaf]) -> Leaf: if len(leaves) == 1: (leaf,) = leaves return leaf obj = copy.copy(next(iter(leaves))) obj.links = list(leaves) for other in leaves: obj.kupfer_add_alias(str(other)) # adding the other's aliases can be misleading # since the matched email address might not be # what we are e-mailing # obj.name_aliases.update(other.name_aliases) return obj class ToplevelGroupingSource(GroupingSource): """Sources of this type group their leaves with others in the toplevel of the catalog.""" _sources: ty.ClassVar[ dict[str, weakref.WeakKeyDictionary[Source, int]] ] = {} def __init__(self, name: str, category: str) -> None: GroupingSource.__init__(self, name, [self]) self.category = category def toplevel_source(self) -> Source: if self.category not in self._sources: return self sources = list(self._sources[self.category].keys()) return GroupingSource(self.category, sources) def initialize(self) -> None: if self.category not in self._sources: self._sources[self.category] = weakref.WeakKeyDictionary() self._sources[self.category][self] = 1 self.output_debug(f"Register {self.category} source {self}") def finalize(self) -> None: del self._sources[self.category][self] self.output_debug(f"Unregister {self.category} source {self}") class _GroupedItemsSource(Source): def __init__(self, leaf: GroupingLeaf) -> None: Source.__init__(self, str(leaf)) self._leaf = leaf def get_items(self) -> ty.Iterator[Leaf]: yield from self._leaf.links def repr_key(self) -> ty.Any: return repr(self._leaf) class CopySlotAction(Action): rank_adjust = -5 """Action for GroupingLeaf - copy given slot value to clipboard.""" def __init__(self, slot_name: str, value: str) -> None: name = slot_name.replace("_", " ").lower() super().__init__(_("Copy %s") % name) self.value = value def wants_context(self): return True def activate( self, leaf: Leaf, iobj: Leaf | None = None, ctx: commandexec.ExecutionToken | None = None, ) -> Leaf | None: assert ctx clip = Gtk.Clipboard.get_for_display( ctx.environment.get_screen().get_display(), Gdk.SELECTION_CLIPBOARD ) clip.set_text(self.value, -1) return None def get_description(self) -> str: return _("Copy '%s' to clipboard") % self.value kupfer-328/kupfer/obj/helplib.py000066400000000000000000000173761500175051100167340ustar00rootroot00000000000000""" This module contains Helper constructs This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ from __future__ import annotations import typing as ty from pathlib import Path from gi.repository import Gio, GLib from kupfer.support import pretty if ty.TYPE_CHECKING: from kupfer.core import commandexec from kupfer.obj import base __all__ = ( "NonpersistentToken", "PicklingHelperMixin", "reverse_action", ) class PicklingHelperMixin: """This pickling helper will define __getstate__/__setstate__ acting simply on the class dictionary; it is up to the inheriting class to set up: pickle_prepare: Modify the instance dict to remove any unpickleable attributes, the resulting dict will be pickled unpickle_finish: Finish unpickling by restoring nonpickled attributes from the saved class dict, or setting up change callbacks or similar """ def pickle_prepare(self) -> None: pass def unpickle_finish(self) -> None: pass def __getstate__(self) -> dict[str, ty.Any]: """On pickle, getstate will call self.pickle_prepare(), then it will return the class' current __dict__.""" self.pickle_prepare() return self.__dict__ def __setstate__(self, state: dict[str, ty.Any]) -> None: """On unpickle, setstate will restore the class' __dict__, then call self.unpickle_finish().""" self.__dict__.update(state) self.unpickle_finish() TokenDataT = ty.TypeVar("TokenDataT") class NonpersistentToken(PicklingHelperMixin, ty.Generic[TokenDataT]): """A token will keep a reference until pickling, when it is deleted""" data: TokenDataT | None def __init__(self, data: TokenDataT): self.data = data def __bool__(self) -> bool: return bool(self.data) def pickle_prepare(self) -> None: self.data = None FileMonitorToken = NonpersistentToken[list[Gio.FileMonitor]] class FilesystemWatchMixin: """A mixin for Sources watching directories""" def monitor_files(self, *files: str | Path) -> FileMonitorToken: """Start monitoring `files` for changes. Similar `monitor_directories`, but monitor also not existing files.""" tokens = [] for file in files: if isinstance(file, Path): file = str(file) # noqa: PLW2901 gfile = Gio.File.new_for_path(file) try: monitor = gfile.monitor_file(Gio.FileMonitorFlags.NONE, None) except GLib.GError as exc: pretty.print_debug(__name__, "FilesystemWatchMixin", exc) continue if monitor: monitor.connect("changed", self._on_file_changed) tokens.append(monitor) return NonpersistentToken(tokens) def monitor_directories( self, *directories: str | Path, force: bool = False ) -> FileMonitorToken: """Register @directories for monitoring; On changes, the Source will be marked for update. This method returns a monitor token that has to be stored for the monitor to be active. The token will be a false value if nothing could be monitored. Nonexisting directories are skipped, if not passing `force` True. """ tokens = [] for directory in directories: if isinstance(directory, Path): directory = str(directory) # noqa: PLW2901 gfile = Gio.File.new_for_path(directory) if not force and not gfile.query_exists(): continue try: monitor = gfile.monitor_directory( Gio.FileMonitorFlags.WATCH_MOUNTS, None ) except GLib.GError as exc: pretty.print_debug(__name__, "FilesystemWatchMixin", exc) continue if monitor: monitor.connect("changed", self._on_directory_changed) tokens.append(monitor) return NonpersistentToken(tokens) def monitor_include_file(self, gfile: Gio.File) -> bool: """Return whether @gfile should trigger an update event by default, files beginning with "." are ignored. This method is used for monitoring both files and directories. """ return not (gfile and gfile.get_basename().startswith(".")) def stop_monitor_fs_changes( self, nptoken: FileMonitorToken | None ) -> None: """Stop monitoring for files or directories changes""" if nptoken and nptoken.data: for token in nptoken.data: assert isinstance(token, Gio.FileMonitor) token.cancel() def _on_directory_changed( self, _monitor: ty.Any, file1: Gio.File, _file2: ty.Any, evt_type: Gio.FileMonitorEvent, ) -> None: if evt_type in ( Gio.FileMonitorEvent.CREATED, Gio.FileMonitorEvent.DELETED, ) and self.monitor_include_file(file1): pretty.print_debug( __name__, "_on_directory_changed", file1.get_path() ) assert hasattr(self, "mark_for_update") self.mark_for_update() def _on_file_changed( self, _monitor: ty.Any, file1: Gio.File, _file2: ty.Any, evt_type: Gio.FileMonitorEvent, ) -> None: if evt_type in ( Gio.FileMonitorEvent.CREATED, Gio.FileMonitorEvent.DELETED, Gio.FileMonitorEvent.CHANGED, ) and self.monitor_include_file(file1): pretty.print_debug(__name__, "_on_file_changed", file1.get_path()) assert hasattr(self, "mark_for_update") self.mark_for_update() def reverse_action( action: ty.Type[base.Action], rank: int = 0 ) -> ty.Type[base.Action]: """Return a reversed version a three-part action. @action: the action class @rank: the rank_adjust to give the reversed action A three-part action requires a direct object (item) and an indirect object (iobj). In general, the item must be from the Catalog, while the iobj can be from one, specified special Source. If this is used, and the action will be reversed, the base action must be the one specifying a source for the iobj. The reversed action will always take both item and iobj from the Catalog, filtered by type. If valid_object(iobj, for_leaf=None) is used, it will always be called with only the new item as the first parameter when reversed. """ class ReverseAction(action): # type: ignore rank_adjust = rank def activate( self, leaf: base.Leaf, iobj: base.Leaf | None = None, ctx: commandexec.ExecutionToken | None = None, ) -> ty.Any: assert iobj return action.activate(self, iobj, leaf, ctx) def item_types(self) -> ty.Iterable[ty.Type[base.Leaf]]: return action.object_types(self) def valid_for_item(self, leaf: base.Leaf) -> bool: try: return action.valid_object(self, leaf) # type: ignore except AttributeError: return True def object_types(self) -> ty.Iterable[ty.Type[base.Leaf]]: return action.item_types(self) def valid_object( self, obj: base.Leaf, for_item: base.Leaf | None = None ) -> bool: return action.valid_for_item(self, obj) def object_source( self, for_item: base.Leaf | None = None ) -> base.Source | None: return None ReverseAction.__name__ = "Reverse" + action.__name__ return ReverseAction kupfer-328/kupfer/obj/hosts.py000066400000000000000000000050771500175051100164500ustar00rootroot00000000000000""" Kupfer's Hosts API Main definition and *constructor* classes. This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ from __future__ import annotations import typing as ty from kupfer.obj.grouping import GroupingLeaf, Slots __author__ = ( "Ulrik Sverdrup , " "Karol Będkowski " ) __all__ = ( "HostLeaf", "HostServiceLeaf", ) HOST_NAME_KEY = "HOST_NAME" HOST_ADDRESS_KEY = "HOST_ADDRESS" HOST_SERVICE_NAME_KEY = "HOST_SERVICE_NAME" HOST_SERVICE_PORT_KEY = "HOST_SERVICE_PORT" HOST_SERVICE_USER_KEY = "HOST_SERVICE_USER" HOST_SERVICE_PASS_KEY = "HOST_SERVICE_PASS" HOST_SERVICE_REMOTE_PATH_KEY = "HOST_SERVICE_REMOTE_PATH" class HostLeaf(GroupingLeaf): grouping_slots = (HOST_NAME_KEY, HOST_ADDRESS_KEY) def __init__(self, obj: dict[str, ty.Any], name: str) -> None: super().__init__(obj, name) if service := obj.get(HOST_SERVICE_NAME_KEY): if hostname := obj.get(HOST_NAME_KEY): self.kupfer_add_alias(f"{service}://{hostname}") if address := obj.get(HOST_ADDRESS_KEY): self.kupfer_add_alias(f"{service}://{address}") def get_icon_name(self) -> str: return "computer" def get_text_representation(self): obj = self.object if service := obj.get(HOST_SERVICE_NAME_KEY): if hostname := obj.get(HOST_NAME_KEY): return f"{service}://{hostname}" if address := obj.get(HOST_ADDRESS_KEY): return f"{service}://{address}" return self.name class HostServiceLeaf(HostLeaf): """Leaf dedicated for well known services like ftp, ssh, vnc""" # pylint: disable=too-many-arguments def __init__( self, name: str, address: str, service: str, description: str, port: str | None = None, user: str | None = None, password: str | None = None, slots: Slots = None, ) -> None: _slots = { HOST_NAME_KEY: name, HOST_ADDRESS_KEY: address, HOST_SERVICE_NAME_KEY: service, HOST_SERVICE_PORT_KEY: port, HOST_SERVICE_USER_KEY: user, HOST_SERVICE_PASS_KEY: password, } if slots: _slots.update(slots) HostLeaf.__init__(self, _slots, name or address) self._description = description def get_description(self) -> str: return self._description kupfer-328/kupfer/obj/objects.py000066400000000000000000000144531500175051100167370ustar00rootroot00000000000000""" Copyright 2007--2009 Ulrik Sverdrup This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ from __future__ import annotations import typing as ty import zlib from kupfer import icons from kupfer.obj import actions from kupfer.obj.base import Action, Leaf, Source from kupfer.obj.representation import TextRepresentation if ty.TYPE_CHECKING: from gettext import gettext as _ from gettext import ngettext from kupfer.core import commandexec __all__ = ( "RunnableLeaf", "SourceLeaf", "TextLeaf", "UrlLeaf", ) class SourceLeaf(Leaf): def __init__(self, obj: Source, name: str | None = None) -> None: """Create SourceLeaf for source @obj. Represented object is source.""" Leaf.__init__(self, obj, name or str(obj)) def has_content(self) -> bool: return True def repr_key(self) -> str: return repr(self.object) def content_source(self, alternate: bool = False) -> Source: assert isinstance(self.object, Source) return self.object def get_description(self) -> str | None: assert isinstance(self.object, Source) return self.object.get_description() @property def fallback_icon_name(self) -> str: # type: ignore assert isinstance(self.object, Source) return self.object.fallback_icon_name def get_gicon(self) -> icons.GIcon | None: return self.object.get_gicon() def get_icon_name(self) -> str: assert isinstance(self.object, Source) return self.object.get_icon_name() class UrlLeaf(Leaf, TextRepresentation): serializable = 1 def __init__(self, obj: str, name: str | None) -> None: super().__init__(obj, name or obj) if obj != name: self.kupfer_add_alias(obj) def get_actions(self) -> ty.Iterator[Action]: yield actions.OpenUrl() def get_description(self) -> str: return self.object # type:ignore def get_icon_name(self) -> str: return "text-html" class RunnableLeaf(Leaf): """Leaf where the Leaf is basically the action itself, for items such as Quit, Log out etc.""" def __init__(self, obj: ty.Any = None, name: str = "") -> None: Leaf.__init__(self, obj, name) def get_actions(self) -> ty.Iterator[Action]: yield actions.Perform( has_result=self.has_result(), item_types=tuple(self.item_types()) ) def has_result(self) -> bool: return False def item_types(self) -> ty.Iterable[Leaf]: return () def run(self, ctx: commandexec.ExecutionToken | None = None) -> ty.Any: raise NotImplementedError def wants_context(self) -> bool: """Return ``True`` if you want the actions' execution context passed as ctx= in RunnableLeaf.run.""" return False def repr_key(self) -> ty.Any: return None def get_gicon(self) -> icons.GIcon | None: if iname := self.get_icon_name(): return icons.get_gicon_with_fallbacks(None, (iname,)) return icons.ComposedIcon("kupfer-object", "kupfer-execute") def get_icon_name(self) -> str: return "" class TextLeaf(Leaf, TextRepresentation): """Represent a text query. The represented object is a string""" serializable = 1 def __init__(self, text: str, name: str | None = None) -> None: """@text *must* be unicode or UTF-8 str""" if not name: name = self.get_first_text_line(text) if not text or not name: name = _("(Empty Text)") assert name Leaf.__init__(self, text, name) def repr_key(self) -> ty.Any: return zlib.crc32(self.object.encode("utf-8", "surrogateescape")) @classmethod def get_first_text_line(cls, text: str) -> str: if not text: return text firstline, *_dummy = text.lstrip().partition("\n") return firstline def get_description(self) -> str: numlines = self.object.count("\n") + 1 desc = self.get_first_text_line(self.object) # TRANS: This is description for a TextLeaf, a free-text search # TRANS: The plural parameter is the number of lines %(num)d return ngettext( '"%(text)s"', '(%(num)d lines) "%(text)s"', numlines ) % {"num": numlines, "text": desc} def get_icon_name(self) -> str: return "edit-select-all" class _ExecuteAction(Action): """Execute action selected as leaf on iobj. This is special action used in "action -> object" mode. For most this action copy properties from real action; only replace leaves with indirect objects. """ rank_adjust = 99999 def __init__(self, action: Action) -> None: super().__init__(name=_("Run On...")) self.action = action def wants_context(self) -> bool: return self.action.wants_context() def has_result(self): return self.action.has_result() def is_factory(self): return self.action.is_factory() def is_async(self): return self.action.is_async() def activate(self, leaf, iobj=None, ctx=None): """For this action leaf is Action type, iobj is leaf of type accepted by action.""" assert iobj return self.action.activate(iobj, ctx=ctx) def requires_object(self): return True def object_types(self): yield from self.action.item_types() def valid_object(self, iobj, for_item=None): return self.action.valid_for_item(iobj) def repr_key(self) -> ty.Any: return self.action class ActionLeaf(Leaf): """ActionLeaf is special leaf that carry real "action". Is used in two-panes mode (Action -> object) and allow user to select action in first panel. """ object: Action serializable = None def __init__(self, action: Action): Leaf.__init__(self, action, action.name) def get_actions(self): return (_ExecuteAction(self.object),) def get_gicon(self): return self.object.get_gicon() def get_icon_name(self): return self.object.get_icon_name() def repr_key(self) -> ty.Any: return self.object def get_description(self): return self.object.get_description() kupfer-328/kupfer/obj/representation.py000066400000000000000000000023201500175051100203360ustar00rootroot00000000000000""" Interfaces that may implements objects. This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ # TODO: use interfaces (?) # ruff: import abc __all__ = ("TextRepresentation", "UriListRepresentation") # pylint: disable=too-few-public-methods class TextRepresentation(abc.ABC): # noqa: B024 """Kupfer Objects that implement this interface have a plain text representation that can be used for Copy & Paste etc.""" def get_text_representation(self) -> str: """The default implementation returns the represented object""" # pylint: disable=no-member assert hasattr(self, "object") return str(self.object) # pylint: disable=too-few-public-methods class UriListRepresentation(abc.ABC): # noqa: B024 """Kupfer Objects that implement this interface have a uri-list representation that can be used for Copy & Paste etc get_urilist_representation should return a sequence of string URIs.""" def get_urilist_representation(self) -> list[str]: """The default implementation raises notimplementederror""" raise NotImplementedError kupfer-328/kupfer/obj/sources.py000066400000000000000000000041121500175051100167600ustar00rootroot00000000000000""" Sources definition. This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ from __future__ import annotations import typing as ty from kupfer.obj.base import Leaf, Source from kupfer.obj.objects import SourceLeaf from kupfer.support import itertools if ty.TYPE_CHECKING: from gettext import gettext as _ __all__ = ( "MultiSource", "SourcesSource", ) class SourcesSource(Source): """A source whose items are SourceLeaves for @source""" def __init__( self, sources: ty.Collection[Source], name: str | None = None, use_reprs: bool = True, ) -> None: super().__init__(name or _("Catalog Index")) self.sources = sources self.use_reprs = use_reprs def get_items(self) -> ty.Iterable[Leaf]: """Ask each Source for a Leaf substitute, else yield a SourceLeaf""" if self.use_reprs: for src in self.sources: yield src.get_leaf_repr() or SourceLeaf(src) return yield from map(SourceLeaf, self.sources) def should_sort_lexically(self) -> bool: return True def get_description(self) -> str: return _("An index of all available sources") def get_icon_name(self) -> str: return "kupfer-catalog" class MultiSource(Source): """A source whose items are the combined items of all @sources""" fallback_icon_name = "kupfer-catalog" def __init__(self, sources: ty.Collection[Source]) -> None: super().__init__(_("Catalog")) self.sources = sources def is_dynamic(self) -> bool: """MultiSource should be dynamic so some of its content also can be.""" return True def get_items(self) -> ty.Iterable[Leaf]: uniq_srcs = itertools.unique_iterator( S.toplevel_source() for S in self.sources ) for src in uniq_srcs: yield from src.get_leaves() or () def get_description(self) -> str: return _("Root catalog") kupfer-328/kupfer/obj/special.py000066400000000000000000000044421500175051100167230ustar00rootroot00000000000000""" Special objects. This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ from __future__ import annotations import typing as ty from kupfer.obj.objects import RunnableLeaf from kupfer.ui import preferences if ty.TYPE_CHECKING: from gettext import gettext as _ from kupfer.core import commandexec __version__ = "2023-09-09" __all__ = ( "CommandNotAvailableLeaf", "InvalidCredentialsLeaf", "NonfunctionalLeaf", "PleaseConfigureLeaf", ) class PleaseConfigureLeaf(RunnableLeaf): """Show information and allow to open preferences for given plugin""" message = _("Please Configure Plugin") description = _("Plugin %s is not configured") def __init__(self, plugin_id: str, plugin_name: str) -> None: plugin_id = plugin_id.split(".")[-1] RunnableLeaf.__init__(self, plugin_id, self.message) self.plugin_name = plugin_name def wants_context(self) -> bool: return True def run(self, ctx: commandexec.ExecutionToken | None = None) -> None: assert ctx preferences.show_plugin_info(self.object, ctx.environment) def get_icon_name(self) -> str: return "preferences-desktop" def get_description(self) -> str: return self.description % self.plugin_name class InvalidCredentialsLeaf(PleaseConfigureLeaf): description = _("Invalid user credentials for %s") class NonfunctionalLeaf(PleaseConfigureLeaf): """Leaf with custom error message that open plugin preferences dialog.""" def __init__( self, plugin_id: str, plugin_name: str, description: str ) -> None: super().__init__(plugin_id, plugin_name) self.description = description def get_description(self) -> str: return self.description class CommandNotAvailableLeaf(PleaseConfigureLeaf): """Leaf with message "command ... not available" that open plugin preferences dialog.""" description = _("Command '%s' not available") def __init__(self, plugin_id: str, plugin_name: str, command: str) -> None: super().__init__(plugin_id, plugin_name) self.command = command def get_description(self) -> str: return self.description % self.command kupfer-328/kupfer/plugin/000077500000000000000000000000001500175051100154515ustar00rootroot00000000000000kupfer-328/kupfer/plugin/__init__.py000066400000000000000000000014701500175051100175640ustar00rootroot00000000000000import os from kupfer import config from kupfer.support import pretty def _extend_path(): # Inside a function to not leak variables to module namespace if not config.has_capability("CUSTOM_PLUGINS"): return # Add plugins in data directories __path__.extend(config.get_data_dirs("plugins")) # Add .zip files in plugins directories for directory in __path__.copy(): try: with os.scandir(directory) as entries: if zipnames := [f for f in entries if f.name.endswith(".zip")]: pretty.print_debug(__name__, "Adding", directory, zipnames) __path__.extend(z.path for z in zipnames) except OSError as error: # noqa: PERF203 pretty.print_error(__name__, error) continue _extend_path() kupfer-328/kupfer/plugin/_firefox_support.py000066400000000000000000000141701500175051100214230ustar00rootroot00000000000000"""Firefox common functions.""" from __future__ import annotations import itertools import sqlite3 import time import typing as ty from configparser import RawConfigParser from contextlib import closing from pathlib import Path from kupfer.obj import UrlLeaf from kupfer.support import pretty MAX_ITEMS = 10000 _BOOKMARKS_SQL = """ SELECT moz_places.url, moz_bookmarks.title FROM moz_places, moz_bookmarks WHERE moz_places.id = moz_bookmarks.fk AND moz_bookmarks.keyword_id IS NULL ORDER BY visit_count DESC LIMIT ?""" def make_absolute_and_check(firefox_dir: Path, path: str) -> Path | None: """Helper, make path absolute and check is exist.""" dpath = firefox_dir.joinpath(path) if dpath.is_dir(): return dpath return None def _find_default_profile(firefox_dir: Path) -> Path | None: """Try to find default/useful profile in firefox located in `firefox_dir`""" config = RawConfigParser({"Default": "0"}) config.read(firefox_dir.joinpath("profiles.ini")) path = None # find Instal.* section and default profile for section in config.sections(): if section.startswith("Install"): if not config.has_option(section, "Default"): continue # found default profile if path := make_absolute_and_check( firefox_dir, config.get(section, "Default") ): pretty.print_debug( __name__, "Found install default profile", path ) return path break pretty.print_debug(__name__, "Install* default profile not found") # not found default profile, iterate profiles, try to find default for section in config.sections(): if not section.startswith("Profile"): continue if ( config.has_option(section, "Default") and config.get(section, "Default") == "1" and ( path := make_absolute_and_check( firefox_dir, config.get(section, "Path") ) ) ): pretty.print_debug( __name__, "Found profile with default=1", section, path ) return path # if section has path - remember it and use if default is not found if not path and config.has_option(section, "Path"): path = make_absolute_and_check( firefox_dir, config.get(section, "Path") ) # not found default profile, return any found path (if any) return path def _get_home_file( needed_file: str, profile_dir: str | Path | None, firefox_dir: Path, ) -> Path | None: """Get path to `needed_file` in `profile_dir`. When no `profile_dir` is not given try to find default profile in profiles.ini. `profile_dir` may be only profile name and is relative to ~/.mozilla/firefox or may be full path to profile dir. """ if profile_dir: # user define profile name or dir, check it and if valid use id profile_dir = Path(profile_dir).expanduser() if not profile_dir.is_absolute(): profile_dir = firefox_dir.joinpath(profile_dir) if not profile_dir.is_dir(): # fail; given profile not exists pretty.print_debug( __name__, "Firefox custom profile_dir not exists", profile_dir ) return None return profile_dir.joinpath(needed_file) if not firefox_dir.exists(): pretty.print_debug(__name__, "Firefox dir not exists", firefox_dir) return None if not firefox_dir.joinpath("profiles.ini").is_file(): pretty.print_debug( __name__, "Firefox profiles.ini not exists", firefox_dir ) return None pretty.print_debug(__name__, "Firefox dir", firefox_dir) path = _find_default_profile(firefox_dir) pretty.print_debug(__name__, "Profile path", path) return path.joinpath(needed_file) if path else None def get_firefox_home_file( needed_file: str, profile_dir: str | Path | None = None ) -> Path | None: """Get path to `needed_file` in `profile_dir`. When no `profile_dir` is not given try to find default profile in profiles.ini. `profile_dir` may be only profile name and is relative to ~/.mozilla/firefox or may be full path to profile dir. """ firefox_dir = Path("~/.mozilla/firefox").expanduser() return _get_home_file(needed_file, profile_dir, firefox_dir) def get_librewolf_home_file( needed_file: str, profile_dir: str | Path | None = None ) -> Path | None: """Get path to `needed_file` in `profile_dir`. When no `profile_dir` is not given try to find default profile in profiles.ini. `profile_dir` may be only profile name and is relative to ~/.librewolf or may be full path to profile dir. """ firefox_dir = Path("~/.librewolf").expanduser() return _get_home_file(needed_file, profile_dir, firefox_dir) def query_database( db_file_path: Path | str, sql: str, args: tuple[ty.Any, ...] = () ) -> ty.Iterable[tuple[ty.Any, ...]]: """Query firefox database. Iterator must be exhausted to prevent hanging connection.""" fpath = str(db_file_path).replace("?", "%3f").replace("#", "%23") fpath = "file:" + fpath + "?immutable=1&mode=ro" for _ in range(2): try: pretty.print_debug(__name__, "Query Firefox db", db_file_path, sql) with closing(sqlite3.connect(fpath, uri=True, timeout=1)) as conn: cur = conn.cursor() cur.execute(sql, args) yield from cur return except sqlite3.Error as err: # noqa: PERF203 # Something is wrong with the database # wait short time and try again pretty.print_error(__name__, "Query Firefox db error:", str(err)) time.sleep(1) def get_bookmarks( path: Path | None, max_items: int = MAX_ITEMS ) -> list[UrlLeaf]: """Load bookmarks from given `path` database.""" if not path: return [] return list( itertools.starmap( UrlLeaf, query_database(path, _BOOKMARKS_SQL, (max_items,)), ) ) kupfer-328/kupfer/plugin/applications.py000066400000000000000000000305031500175051100205120ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("Applications") __kupfer_sources__ = ("AppSource",) __kupfer_actions__ = ( "OpenWith", "OpenWithByMime", "SetDefaultApplication", "ResetAssociations", "LaunchHere", "AppAdditionalAction", ) __description__ = _("All applications and preferences") __version__ = "2023.1" __author__ = "" import typing as ty from pathlib import Path from gi.repository import Gio from kupfer import config, plugin_support from kupfer.obj import Action, AppLeaf, FileLeaf, Leaf, Source, UrlLeaf from kupfer.obj.helplib import FilesystemWatchMixin from kupfer.support import weaklib if ty.TYPE_CHECKING: from gettext import gettext as _ _ALTERNATIVES = ( "", "Cinnamon", "EDE", "GNOME", "KDE", "LXDE", "LXQt", "MATE", "Pantheon", "ROX", "Razor", "TDE", "Unity", "XFCE", ) __kupfer_settings__ = plugin_support.PluginSettings( { "key": "desktop_type", "label": _("Applications for Desktop Environment"), "type": str, "value": "", "alternatives": _ALTERNATIVES, }, { "key": "desktop_filter", "label": _("Use Desktop Filter"), "type": bool, "value": True, }, { "key": "load_extra_aliases", "label": _("Load extra aliases"), "type": bool, "value": False, "tooltip": _( "Load additional aliases like keywords or " "other names. This may slowdown searching. " "Change this setting may require reload." ), }, ) # Gio.AppInfo / Desktop Item nodisplay vs hidden: # NoDisplay: Don't show this in program menus # Hidden: Disable/never use at all WHITELIST_IDS: ty.Final = ( # we think that these are useful to show "eog.desktop", "evince.desktop", "gnome-about.desktop", "gstreamer-properties.desktop", "notification-properties.desktop", "shotwell-viewer.desktop", ) BLACKLIST_IDS: ty.Final = ("nautilus-home.desktop",) def initialize_plugin(name: str) -> None: def on_change_settings(*args: ty.Any) -> None: AppLeaf.LOAD_EXTRA_ALIASES = __kupfer_settings__["load_extra_aliases"] __kupfer_settings__.connect_settings_changed_cb(on_change_settings) def _should_show( app_info: Gio.AppInfo, desktop_type: str, use_filter: bool ) -> bool: if app_info.get_nodisplay(): return False if not use_filter: return True if desktop_type == "": return app_info.should_show() # type: ignore return app_info.get_show_in(desktop_type) # type:ignore class AppSource(Source, FilesystemWatchMixin): """Applications source This Source contains all user-visible applications (as given by the desktop files). """ source_scan_interval: int = 3600 def __init__(self, name=None): super().__init__(name or _("Applications")) self.monitor_token = None def initialize(self): application_dirs = config.get_data_dirs("", "applications") self.monitor_token = self.monitor_directories(*application_dirs) weaklib.gobject_connect_weakly( __kupfer_settings__, "plugin-setting-changed", self._on_setting_change, ) def _on_setting_change(self, *_args): self.mark_for_update() def get_items(self): use_filter = __kupfer_settings__["desktop_filter"] desktop_type = __kupfer_settings__["desktop_type"] # Add this to the default for item in Gio.app_info_get_all(): id_ = item.get_id() if id_ in WHITELIST_IDS or ( _should_show(item, desktop_type, use_filter) and id_ not in BLACKLIST_IDS ): # load extra app action defined in desktop file app_actions = [ (action, item.get_action_name(action)) for action in item.list_actions() ] yield AppLeaf(item, app_actions=app_actions) def should_sort_lexically(self): return True def get_description(self): return _("All applications and preferences") def get_icon_name(self): return "applications-office" def provides(self): yield AppLeaf class OpenWith(Action): action_accelerator = "w" def __init__(self): super().__init__(_("Open With Any Application...")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx assert iobj self.activate_multiple((leaf,), (iobj,), ctx) def activate_multiple( self, objects: ty.Iterable[Leaf], iobjects: ty.Iterable[Leaf], ctx: ty.Any, ) -> None: # for each application, launch all the files paths = [L.object for L in objects] for iobj_app in iobjects: assert isinstance(iobj_app, AppLeaf) iobj_app.launch(paths=paths, ctx=ctx) def item_types(self): yield FileLeaf def requires_object(self): return True def object_types(self): yield AppLeaf def object_source(self, for_item=None): return AppsAll() def object_source_and_catalog(self, for_item): return True def valid_object(self, iobj, for_item): return iobj.object.supports_files() or iobj.object.supports_uris() def get_description(self): return _("Open with any application") class OpenWithByMime(Action): rank_adjust = 5 action_accelerator = "w" def __init__(self): super().__init__(_("Open With...")) def wants_context(self): return True def activate( self, leaf: Leaf, iobj: Leaf | None = None, ctx: ty.Any = None ) -> None: assert ctx assert iobj self.activate_multiple((leaf,), (iobj,), ctx) def activate_multiple( self, objects: ty.Iterable[Leaf], iobjects: ty.Iterable[Leaf], ctx: ty.Any, ) -> None: # for each application, launch all the files files: list[Gio.File] = [] files.extend( Gio.File.new_for_path(p.object) for p in objects if not isinstance(p, UrlLeaf) ) files.extend( Gio.File.new_for_uri(p.object) for p in objects if isinstance(p, UrlLeaf) ) for iobj_app in iobjects: assert isinstance(iobj_app, AppLeaf) iobj_app.launch(files=files, ctx=ctx) def item_types(self): yield FileLeaf yield UrlLeaf def object_types(self): yield AppLeaf def requires_object(self): return True def object_source(self, for_item=None): if isinstance(for_item, FileLeaf) and ( mime := for_item.get_content_type() ): return AppsForMime(mime) return None def valid_object(self, iobj, for_item): return iobj.object.supports_files() or iobj.object.supports_uris() def get_description(self): return _("Open with application supporting this file type") class SetDefaultApplication(Action): def __init__(self): super().__init__(_("Set Default Application...")) def activate(self, leaf, iobj=None, ctx=None): assert iobj desktop_item = iobj.object desktop_item.set_as_default_for_type(leaf.get_content_type()) def item_types(self): yield FileLeaf def requires_object(self): return True def object_types(self): yield AppLeaf def object_source(self, for_item=None): return AppsAll() def object_source_and_catalog(self, for_item): return True def valid_object(self, iobj, for_item): return iobj.object.supports_files() or iobj.object.supports_uris() def get_description(self): return _("Set default application to open this file type") class AppsAll(Source): def __init__(self): super().__init__(_("Applications")) def initialize(self): weaklib.gobject_connect_weakly( __kupfer_settings__, "plugin-setting-changed", self._on_setting_change, ) def _on_setting_change(self, *_args): self.mark_for_update() def get_items(self): use_filter = __kupfer_settings__["desktop_filter"] desktop_type = __kupfer_settings__["desktop_type"] # Get all apps; this includes those only configured for # opening files with. for item in Gio.AppInfo.get_all(): if _should_show(item, desktop_type, use_filter): continue if not item.supports_uris() and not item.supports_files(): continue yield AppLeaf(item) def should_sort_lexically(self): return False def get_description(self): return None def get_icon_name(self): return "applications-office" def provides(self): yield AppLeaf class AppsForMime(Source): source_use_cache = False def __init__(self, mimetype: str) -> None: super().__init__(_("Applications supporting %s") % mimetype) self._mimetype = mimetype def get_items(self) -> ty.Iterator[AppLeaf]: for item in Gio.app_info_get_all_for_type(self._mimetype): if not item.supports_uris() and not item.supports_files(): continue yield AppLeaf(item) def should_sort_lexically(self): return False def provides(self): yield AppLeaf class ResetAssociations(Action): rank_adjust = -10 def __init__(self): super().__init__(_("Reset Associations")) def activate(self, leaf, iobj=None, ctx=None): content_type = leaf.get_content_type() Gio.AppInfo.reset_type_associations(content_type) def item_types(self): yield FileLeaf def get_description(self): return _("Reset program associations for files of this type.") class LaunchHere(Action): def __init__(self, name=_("Start Application Here...")): super().__init__(name) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx assert iobj if leaf.is_dir(): work_dir = leaf.object else: work_dir = str(Path(leaf.object).parent) iobj.launch(activate=False, ctx=ctx, work_dir=work_dir) def get_description(self) -> str: return _("Launch application in this location") def get_icon_name(self) -> str: return "kupfer-launch" def item_types(self): yield FileLeaf # def valid_for_item(self, leaf): # # leaf is FileLeaf # return leaf.is_dir() def requires_object(self): return True def object_types(self): yield AppLeaf def object_source(self, for_item=None): return AppsAll() def object_source_and_catalog(self, for_item): return True class _AppAction(Leaf): def __init__(self, action: str, name: str) -> None: super().__init__(action, name) def get_icon_name(self) -> str: return "kupfer-launch" class _AppActionsSource(Source): source_use_cache = False def __init__(self, appleaf: AppLeaf) -> None: super().__init__("application actions") self.appleaf = appleaf def get_items(self): if self.appleaf.app_actions: for action, name in self.appleaf.app_actions: yield _AppAction(action, name) def provides(self): yield _AppAction class AppAdditionalAction(Action): def __init__(self, name=_("Application actions...")): super().__init__(name) def activate(self, leaf, iobj=None, ctx=None): assert iobj assert isinstance(leaf, AppLeaf) assert leaf.app_actions appinfo = leaf.object appinfo.launch_action(iobj.object) def item_types(self): yield AppLeaf def requires_object(self): return True def object_types(self): yield _AppAction def object_source(self, for_item=None): return _AppActionsSource(for_item) def valid_for_item(self, leaf: Leaf) -> bool: # application must have any actions assert isinstance(leaf, AppLeaf) return bool(leaf.app_actions) def get_description(self): return _("Extra actions for application") def get_icon_name(self) -> str: return "gtk-execute" kupfer-328/kupfer/plugin/apt_tools.py000066400000000000000000000157271500175051100200430ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("APT") __kupfer_sources__ = () __kupfer_text_sources__ = () __kupfer_actions__ = ( "ShowPackageInfo", "SearchPackageName", "InstallPackage", "OpenPackageWebsite", "SearchForFile", ) __description__ = _("Interface with the package manager APT") __version__ = "" __author__ = ( "Martin Koelewijn , " "Ulrik Sverdrup " ) import subprocess import typing as ty import urllib.parse from kupfer import icons, launch, plugin_support, support from kupfer.obj import Action, Leaf, Source, TextLeaf from kupfer.support import kupferstring, task from kupfer.ui import uiutils if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_settings__ = plugin_support.PluginSettings( { "key": "installation_method", "label": _("Installation method"), "type": str, "value": "gksu -- apt-get install --yes", }, ) plugin_support.check_command_available("apt", "apt-cache") # pylint: disable=too-few-public-methods class InfoTask(task.Task): def __init__(self, text: str): super().__init__() self.text = text self.aptitude: bytes | None = None self.apt_cache: bytes | None = None self._finish_callback = None def start(self, finish_callback): self._finish_callback = finish_callback timeout = 60 launch.AsyncCommand( ["apt", "show", self.text], self._aptitude_finished, timeout ) launch.AsyncCommand( ["apt-cache", "policy", self.text], self._aptcache_finished, timeout, ) def _aptitude_finished( self, acommand: launch.AsyncCommand, stdout: bytes, stderr: bytes ) -> None: self.aptitude = stderr + stdout self._check_end() def _aptcache_finished( self, acommand: launch.AsyncCommand, stdout: bytes, stderr: bytes ) -> None: self.apt_cache = stderr + stdout self._check_end() def _check_end(self): if self.aptitude is None or self.apt_cache is None: return assert self._finish_callback text = kupferstring.fromlocale( self.aptitude ) + kupferstring.fromlocale(self.apt_cache) uiutils.show_text_result(text, title=_("Show Package Information")) self._finish_callback(self) class ShowPackageInfo(Action): def __init__(self): Action.__init__(self, _("Show Package Information")) self.kupfer_add_alias("apt show") def is_async(self): return True def activate(self, leaf, iobj=None, ctx=None): return InfoTask(leaf.object.strip()) def item_types(self): yield TextLeaf yield Package def valid_for_item(self, leaf): # check if it is a single word text = leaf.object return len(text.split(None, 1)) == 1 def get_gicon(self): return icons.ComposedIcon("dialog-information", "package-x-generic") class OpenPackageWebsite(Action): def __init__(self): Action.__init__(self, _("Browse packages.debian.org")) def activate(self, leaf, iobj=None, ctx=None): name = leaf.object.strip() url = f"https://packages.debian.org/{name}" launch.show_url(url) def get_description(self): return _("Open packages.debian.org page for package") def item_types(self): yield TextLeaf yield Package def valid_for_item(self, leaf): # check if it is a single word text = leaf.object return len(text.split(None, 1)) == 1 def get_gicon(self): return icons.ComposedIcon("edit-find", "package-x-generic") class InstallPackage(Action): def __init__(self): Action.__init__(self, _("Install")) self.kupfer_add_alias("apt install") def activate(self, leaf, iobj=None, ctx=None): self.activate_multiple((leaf,)) def activate_multiple(self, objs): program = __kupfer_settings__["installation_method"] pkgs = [o.object.strip() for o in objs] prog_argv = support.argv_for_commandline(program) launch.spawn_in_terminal(prog_argv + pkgs) def item_types(self): yield Package yield TextLeaf def get_description(self): return _("Install package using the configured method") def get_icon_name(self): return "document-save" class Package(Leaf): def __init__(self, package: str, desc: str): Leaf.__init__(self, package, package) self.desc = desc def get_text_representation(self): return self.object def get_description(self): return self.desc def get_icon_name(self): return "package-x-generic" class PackageSearchSource(Source): def __init__(self, query): self.query = query Source.__init__(self, _('Packages matching "%s"') % query) def repr_key(self): return self.query def get_items(self): proc = subprocess.run( ["apt-cache", "search", "--names-only", self.query], capture_output=True, check=True, ) for line in kupferstring.fromlocale(proc.stdout).splitlines(): line = line.strip() # noqa: PLW2901 if not line: continue package, sep, desc = line.partition(" - ") if not sep: self.output_error("apt-cache: ", line) continue yield Package(package, desc) def should_sort_lexically(self): return True def provides(self): yield TextLeaf def get_icon_name(self): return "system-software-install" class SearchPackageName(Action): def __init__(self): Action.__init__(self, _("Search Package Name...")) self.kupfer_add_alias("apt search") def is_factory(self): return True def activate(self, leaf, iobj=None, ctx=None): package = leaf.object.strip() return PackageSearchSource(package) def item_types(self): yield TextLeaf def valid_for_item(self, leaf): # check if it is a single word text = leaf.object return len(text.split(None, 1)) == 1 def get_icon_name(self): return "system-software-install" class SearchForFile(Action): def __init__(self): Action.__init__(self, _("Search for file in packages...")) self.kupfer_add_alias("apt file") def activate(self, leaf, iobj=None, ctx=None): name = urllib.parse.quote(leaf.object.strip()) url = f"https://packages.debian.org/file:{name}" launch.show_url(url) def get_description(self): return _( "Search the contents of Debian distributions for any files (online)" ) def item_types(self): yield TextLeaf def valid_for_item(self, leaf): text = leaf.object return len(text) > 2 # noqa: PLR2004 def get_gicon(self): return icons.ComposedIcon("edit-find", "package-x-generic") kupfer-328/kupfer/plugin/archiveinside.py000066400000000000000000000137171500175051100206510ustar00rootroot00000000000000""" A test project to see if we can make a plugin that allows us to drill down into compressed archives. So far we only support .zip and .tar, .tar.gz, .tar.bz2, using Python's standard library. """ from __future__ import annotations __kupfer_name__ = _("Deep Archives") __kupfer_contents__ = ("ArchiveContent",) __description__ = _("Allow browsing inside compressed archive files") __version__ = "" __author__ = "Ulrik Sverdrup " import hashlib import os import shutil import tarfile import typing as ty import zipfile from pathlib import Path from kupfer.obj import FileLeaf, Leaf, Source from kupfer.obj.filesrc import DirectorySource from kupfer.support import pretty, scheduler, types if ty.TYPE_CHECKING: from gettext import gettext as _ # Limit this to archives of a couple of megabytes MAX_ARCHIVE_BYTE_SIZE = 15 * 1024**2 # Wait a year, or until program shutdown for cleaning up # archive files VERY_LONG_TIME_S = 3600 * 24 * 365 class UnsafeArchiveError(Exception): def __init__(self, path: str): Exception.__init__(self, f"Refusing to extract unsafe path: {path}") def _is_safe_to_unarchive(path: str) -> bool: "return whether @path is likely a safe path to unarchive" npth = os.path.normpath(path) return not os.path.isabs(npth) and not npth.startswith(os.path.pardir) @ty.runtime_checkable class _Extractor(ty.Protocol): extensions: ty.Collection[str] predicate: ty.Callable[[str], bool] | None def __call__(self, src: str, dst: str) -> None: ... class ArchiveContent(Source): extractors: ty.ClassVar[list[_Extractor]] = [] unarchived_files: ty.ClassVar[list[str]] = [] end_timer = scheduler.Timer(True) def __init__(self, fileleaf: FileLeaf, unarchive_func: _Extractor) -> None: Source.__init__(self, _("Content of %s") % fileleaf) self.path = fileleaf.object self.unarchiver = unarchive_func def repr_key(self): return self.path def get_items(self) -> ty.Iterable[Leaf]: # always use the same destination for the same file and mtime basename = os.path.basename(os.path.normpath(self.path)) root, _ext = os.path.splitext(basename) mtime = os.stat(self.path).st_mtime fileid = hashlib.sha1((f"{self.path}{mtime}").encode()).hexdigest() pth = os.path.join("/tmp", f"kupfer-{root}-{fileid}") if not Path(pth).exists(): self.output_debug(f"Extracting with {self.unarchiver}") self.unarchiver(self.path, pth) self.unarchived_files.append(pth) self.end_timer.set( VERY_LONG_TIME_S, self.clean_up_unarchived_files ) files = list(DirectorySource(pth, show_hidden=True).get_leaves()) if len(files) == 1 and files[0].has_content(): csrc = files[0].content_source() return (csrc.get_leaves() or []) if csrc else [] return files def get_description(self) -> str | None: return None @classmethod def decorates_type(cls): return FileLeaf @classmethod def decorate_item(cls, leaf: FileLeaf) -> ArchiveContent | None: basename = os.path.basename(leaf.object).lower() for extractor in cls.extractors: if any(basename.endswith(ext) for ext in extractor.extensions): assert extractor.predicate if Path(leaf.object).is_file() and extractor.predicate( leaf.object ): return cls._source_for_path(leaf, extractor) return None @classmethod def _source_for_path( cls, leaf: FileLeaf, extractor: _Extractor ) -> ArchiveContent | None: byte_size = os.stat(leaf.object).st_size if byte_size < MAX_ARCHIVE_BYTE_SIZE: return cls(leaf, extractor) return None @classmethod def clean_up_unarchived_files(cls) -> None: if not cls.unarchived_files: return def clean_up_error_handler( func: ty.Callable[..., object], path: str, exc_info: types.ExecInfo ) -> object: pretty.print_error(__name__, f"Error in {func} deleting {path}:") pretty.print_error(__name__, exc_info) return None pretty.print_info(__name__, "Removing extracted archives..") for filetree in set(cls.unarchived_files): pretty.print_debug( __name__, "Removing", os.path.basename(filetree) ) # TODO: deprecated: onerror since 3.12 shutil.rmtree(filetree, onerror=clean_up_error_handler) cls.unarchived_files = [] @classmethod def extractor( cls, extensions: ty.Collection[str], predicate: ty.Callable[[str], bool], ) -> ty.Callable[[ty.Callable[[str, str], None]], _Extractor]: def decorator(func: ty.Callable[[str, str], None]) -> _Extractor: extr = ty.cast("_Extractor", func) extr.extensions = extensions extr.predicate = predicate cls.extractors.append(extr) return extr return decorator @ArchiveContent.extractor( (".tar", ".tar.gz", ".tgz", ".tar.bz2"), tarfile.is_tarfile ) def extract_tarfile(filepath: str, destpath: str) -> None: with tarfile.TarFile.open(filepath, "r") as zfile: try: for member in zfile.getnames(): if not _is_safe_to_unarchive(member): raise UnsafeArchiveError(member) zfile.extractall(path=destpath) finally: pass # ZipFile only supports extractall since Python 2.6 @ArchiveContent.extractor((".zip",), zipfile.is_zipfile) def extract_zipfile(filepath: str, destpath: str) -> None: with zipfile.ZipFile(filepath, "r") as zfile: try: for member in zfile.namelist(): if not _is_safe_to_unarchive(member): raise UnsafeArchiveError(member) zfile.extractall(path=destpath) finally: pass kupfer-328/kupfer/plugin/archivemanager.py000066400000000000000000000147451500175051100210120ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("Archive Manager") __kupfer_sources__ = () __kupfer_text_sources__ = () __kupfer_actions__ = ("UnpackHere", "CreateArchive", "CreateArchiveIn") __description__ = _("Use Archive Manager actions") __version__ = "2023-05-15" __author__ = "Ulrik, KB" import os import re import shutil import typing as ty # since "path" is a very generic name, you often forget.. from os import path as os_path from pathlib import Path from kupfer import launch, plugin_support, runtimehelper from kupfer.obj import Action, FileLeaf, Leaf, OperationError from kupfer.obj.special import CommandNotAvailableLeaf from kupfer.support import fileutils if ty.TYPE_CHECKING: from gettext import gettext as _ from kupfer.core import commandexec __kupfer_settings__ = plugin_support.PluginSettings( { "key": "archive_type", "label": _("Compressed archive type for 'Create Archive In'"), "type": str, "value": ".tar.gz", "alternatives": ( ".7z", ".tar", ".tar.gz", ".tar.bz2", ".tar.xz", ".zip", ), }, { "key": "tool", "label": _("Tool used for operations:"), "type": str, "value": "file-roller", "alternatives": ( "File-roller", "7-zip", "7za", ), }, ) _EXTENSIONS_SET = ( ".7z", ".Z", ".ace", ".alz", ".ar", ".arj", ".bz", ".bz2", ".cab", ".cbr", ".cbz", ".cpio", ".deb", ".dmg", ".ear", ".gz", ".iso", ".jar", ".lha", ".lz", ".lzh", ".lzma", ".lzo", ".rar", ".rpm", ".sit", ".snap", ".sqsh", ".tar", ".taz", ".tbz", ".tbz2", ".tgz", ".tlrz", ".tlz", ".tzo", ".tzst", ".war", ".xz", ".zip", ".zoo", ".zst", ) def _tool_cmd_path(tool: str) -> str | None: if tool == "7-zip": return shutil.which("7z") if tool == "7za": return shutil.which("7za") return shutil.which("file-roller") class UnpackHere(Action): def __init__(self) -> None: Action.__init__(self, _("Extract Here")) def activate( self, leaf: Leaf, iobj: Leaf | None = None, ctx: commandexec.ExecutionToken | None = None, ) -> Leaf | None: tool = __kupfer_settings__["tool"] if not _tool_cmd_path(tool): return CommandNotAvailableLeaf(__name__, __kupfer_name__, tool) filedir = str(Path(leaf.object).parent) if tool == "7-zip": launch.spawn_in_terminal(["7z", "x", leaf.object], filedir) return None if tool == "7za": launch.spawn_in_terminal(["7za", "x", leaf.object], filedir) return None launch.spawn_async_notify_as( "file-roller.desktop", ["file-roller", "--extract-here", leaf.object], ) return None def valid_for_item(self, leaf): fname, ext = os.path.splitext(leaf.object) # check for standard extension or a multi-part rar extension ext = ext.lower() if ext in _EXTENSIONS_SET: return True # for multi-part archives must exists also file without number, ie: # Filename.rar Filename.r00 Filename.r01 etc # not sure we can allow decompress no-first archive if re.search(r".r\d+$", ext) is not None: return os_path.isfile(f"{fname}.rar") return False def item_types(self): yield FileLeaf def get_description(self): return _("Extract compressed archive") def get_icon_name(self): return "extract-archive" def _make_archive(filepaths: ty.Iterable[str]) -> None: cmd = ["file-roller", "--add"] cmd.extend(filepaths) launch.spawn_async_notify_as("file-roller.desktop", cmd) class CreateArchive(Action): def __init__(self): Action.__init__(self, _("Create Archive")) def activate(self, leaf, iobj=None, ctx=None): _make_archive((leaf.object,)) def activate_multiple(self, objs): _make_archive(L.object for L in objs) def item_types(self): yield FileLeaf def get_description(self): return _("Create a compressed archive from folder") def get_icon_name(self): return "add-files-to-archive" def valid_for_item(self, leaf: Leaf) -> bool: """Allow to launch this action only with file-roller""" tool = __kupfer_settings__["tool"] return tool not in ("7-zip", "7za") def _make_archive_in( ctx: commandexec.ExecutionToken, basename: str, dirpath: str, filepaths: ty.Iterable[str], ) -> str: archive_type = __kupfer_settings__["archive_type"] archive_path = fileutils.get_destpath_in_directory( dirpath, basename, archive_type ) tool = __kupfer_settings__["tool"] if not _tool_cmd_path(tool): raise OperationError(f"Command {tool} not available") if tool in ("7-zip", "7za"): cmd = ["7za" if tool == "7za" else "7z", "a", archive_path] cmd.extend(filepaths) launch.spawn_in_terminal(cmd) else: cmd = ["file-roller", f"--add-to={archive_path}"] cmd.extend(filepaths) launch.spawn_async_notify_as("file-roller.desktop", cmd) runtimehelper.register_async_file_result(ctx, archive_path) return archive_path class CreateArchiveIn(Action): def __init__(self): Action.__init__(self, _("Create Archive In...")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert iobj assert ctx dirpath = iobj.object basename = os_path.basename(leaf.object) _make_archive_in(ctx, basename, dirpath, (leaf.object,)) def activate_multiple(self, objs, iobjs, ctx): # TRANS: Default filename (no extension) for 'Create Archive In...' basename = _("Archive") for iobj in iobjs: _make_archive_in( ctx, basename, iobj.object, (L.object for L in objs) ) def item_types(self): yield FileLeaf def requires_object(self): return True def object_types(self): yield FileLeaf def valid_object(self, obj, for_item=None): return fileutils.is_directory_writable(obj.object) def get_description(self): return _("Create a compressed archive from folder") def get_icon_name(self): return "add-files-to-archive" kupfer-328/kupfer/plugin/aria2.py000066400000000000000000000044621500175051100170270ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("Aria2") __kupfer_sources__ = () __kupfer_text_sources__ = () __kupfer_actions__ = ("Download",) __description__ = _("Download files using remote instance of Aria2") __version__ = "2023-05-14" __author__ = "KB" import json import time import typing as ty import urllib.request from kupfer import plugin_support from kupfer.obj import Action, OperationError, UrlLeaf from kupfer.ui import uiutils if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_settings__ = plugin_support.PluginSettings( { "key": "aria2_url", "label": _("Aria2 URL"), "type": str, "value": "", "tooltip": _( "Base URL for remote Aria2 instance ie. http://localhost:6800/" ), }, { "key": "aria2_token", "label": _("Secret token"), "type": str, "value": "", "tooltip": _( "Enter the Aria2 RPC secret token (leave empty if " "authentication is not enabled) " ), }, ) class Download(Action): """Action to download file""" def __init__(self): Action.__init__(self, _("Remote Download")) def activate(self, leaf, iobj=None, ctx=None): aria2url = __kupfer_settings__["aria2_url"] if not aria2url: return params: list[str | list[str]] = [] if token := __kupfer_settings__["aria2_token"]: params.append(f"token:{token}") params.append([str(leaf.object)]) jsonreq = json.dumps( { "jsonrpc": "2.0", "id": f"kupfer-{time.time()}", "method": "aria2.addUri", "params": params, } ) data = jsonreq.encode("ascii") with urllib.request.urlopen(aria2url, data) as response: if response.status == 200: # noqa:PLR2004 uiutils.show_notification("Kupfer", _("Download started")) return if res := response.read(): err = res.decode() else: err = str(response.status) raise OperationError(f"Request failed: {err}") def item_types(self): yield UrlLeaf def get_description(self): return _("Download using remote instance of Aria2") kupfer-328/kupfer/plugin/audacious.py000066400000000000000000000277261500175051100200160ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("Audacious") __kupfer_sources__ = ("AudaciousSource",) __description__ = _("Control Audacious playback and playlist") __version__ = "2023.1" __author__ = "Horia V. Corcalciuc , US, KB" # TODO: support many playlists (?); for now we load only active playlist import subprocess import time import typing as ty import dbus from kupfer import icons, launch, plugin_support from kupfer.obj import ( Action, Leaf, NotAvailableError, RunnableLeaf, Source, SourceLeaf, ) from kupfer.obj.apps import AppLeafContentMixin from kupfer.support import kupferstring, pretty, weaklib from kupfer.ui import uiutils if ty.TYPE_CHECKING: from gettext import gettext as _ plugin_support.check_dbus_connection() __kupfer_settings__ = plugin_support.PluginSettings( { "key": "playlist_toplevel", "label": _("Include songs in top level"), "type": bool, "value": True, }, ) _AUDTOOL = "audtool" _AUDACIOUS = "audacious" _BUS_NAME = "org.atheme.audacious" _OBJ_NAME = "/org/atheme/audacious" _IFACE_NAME = "org.atheme.audacious" plugin_support.check_command_available(_AUDTOOL) def _create_dbus_connection( iface: str, obj: str, service: str ) -> dbus.Interface: """Create dbus connection to NetworkManager""" sbus = dbus.SessionBus() try: if dobj := sbus.get_object(service, obj): return dbus.Interface(dobj, iface) except dbus.exceptions.DBusException as err: pretty.print_debug(__name__, err) raise NotAvailableError(service) from err raise NotAvailableError(service) def get_playlist_songs_dbus() -> ty.Iterator[SongLeaf]: conn = _create_dbus_connection(_IFACE_NAME, _OBJ_NAME, _BUS_NAME) total = conn.Length() for pos in range(1, total + 1): title = " ".join( (conn.SongTuple(pos, "title"), conn.SongTuple(pos, "artist")) ).strip() if not title: title = conn.SongTitle(pos) yield SongLeaf(pos, title) def get_playlist_songs() -> ty.Iterator[SongLeaf]: """Yield tuples of (position, name) for playlist songs""" with subprocess.Popen( [_AUDTOOL, "playlist-display"], stdout=subprocess.PIPE ) as proc: stdout, _stderr = proc.communicate() for line in stdout.splitlines(): if not line.count(b"|") >= 2: # noqa:PLR2004 continue position, rest = line.split(b"|", 1) songname, rest = rest.rsplit(b"|", 1) pos = int(position.strip()) name = kupferstring.fromlocale(songname.strip()) yield SongLeaf(pos, name) def get_current_song() -> str | None: try: conn = _create_dbus_connection(_IFACE_NAME, _OBJ_NAME, _BUS_NAME) pos = conn.Position() total = conn.Length() return "\n".join( filter( None, ( conn.SongTuple(pos, "title"), conn.SongTuple(pos, "artist"), conn.SongTitle(pos), _("Position: %(pos)d / %(total)d") % {"pos": pos, "total": total}, ), ) ) except Exception: pretty.print_exc(__name__) with subprocess.Popen( [_AUDTOOL, "current-song"], stdout=subprocess.PIPE ) as proc: stdout, _stderr = proc.communicate() for line in stdout.splitlines(): return kupferstring.fromlocale(line) return None def _audtool_command(args: tuple[str, ...], activate: bool = True) -> None: def _cb(res: int) -> None: if res == 0: return # audacious not running launch.spawn_async(("audacious",)) time.sleep(1) launch.spawn_async(args) launch.spawn_async(args, finish_callback=_cb) class Enqueue(Action): action_accelerator = "e" def __init__(self): Action.__init__(self, _("Enqueue")) def activate(self, leaf, iobj=None, ctx=None): pos = leaf.object try: conn = _create_dbus_connection(_IFACE_NAME, _OBJ_NAME, _BUS_NAME) conn.PlayqueneAdd(pos) except Exception: pretty.print_exc(__name__) launch.spawn_async((_AUDTOOL, "playqueue-add", str(pos))) def get_description(self): return _("Add track to the Audacious play queue") def get_gicon(self): return icons.ComposedIcon("gtk-execute", "media-playback-start") def get_icon_name(self): return "media-playback-start" class Dequeue(Action): def __init__(self): Action.__init__(self, _("Dequeue")) def activate(self, leaf, iobj=None, ctx=None): pos = leaf.object try: conn = _create_dbus_connection(_IFACE_NAME, _OBJ_NAME, _BUS_NAME) conn.PlayqueneRemove(pos) except Exception: launch.spawn_async((_AUDTOOL, "playqueue-remove", str(pos))) def get_description(self): return _("Remove track from the Audacious play queue") def get_gicon(self): return icons.ComposedIcon("gtk-execute", "media-playback-stop") def get_icon_name(self): return "media-playback-stop" class JumpToSong(Action): action_accelerator = "o" def __init__(self): Action.__init__(self, _("Play")) def activate(self, leaf, iobj=None, ctx=None): pos = leaf.object try: conn = _create_dbus_connection(_IFACE_NAME, _OBJ_NAME, _BUS_NAME) conn.Jump(pos) conn.Play() except Exception: _audtool_command((_AUDTOOL, "playlist-jump", str(pos))) time.sleep(1) launch.spawn_async((_AUDTOOL, "playback-play")) def get_description(self): return _("Jump to track in Audacious") def get_icon_name(self): return "media-playback-start" class Play(RunnableLeaf): def __init__(self): RunnableLeaf.__init__(self, name=_("Play")) def run(self, ctx=None): try: conn = _create_dbus_connection(_IFACE_NAME, _OBJ_NAME, _BUS_NAME) conn.Play() except Exception: _audtool_command((_AUDTOOL, "playback-play")) def get_description(self): return _("Resume playback in Audacious") def get_icon_name(self): return "media-playback-start" class Stop(RunnableLeaf): def __init__(self): RunnableLeaf.__init__(self, name=_("Stop")) def run(self, ctx=None): try: conn = _create_dbus_connection(_IFACE_NAME, _OBJ_NAME, _BUS_NAME) conn.Stop() except Exception: launch.spawn_async((_AUDTOOL, "playback-play")) def get_description(self): return _("Stop playback in Audacious") def get_icon_name(self): return "media-playback-stop" class Pause(RunnableLeaf): def __init__(self): RunnableLeaf.__init__(self, name=_("Pause")) def run(self, ctx=None): try: conn = _create_dbus_connection(_IFACE_NAME, _OBJ_NAME, _BUS_NAME) conn.Pause() except Exception: launch.spawn_async((_AUDTOOL, "playback-pause")) def get_description(self): return _("Pause playback in Audacious") def get_icon_name(self): return "media-playback-pause" class Next(RunnableLeaf): def __init__(self): RunnableLeaf.__init__(self, name=_("Next")) def run(self, ctx=None): try: conn = _create_dbus_connection(_IFACE_NAME, _OBJ_NAME, _BUS_NAME) conn.Advance() except Exception: _audtool_command((_AUDTOOL, "playlist-advance")) def get_description(self): return _("Jump to next track in Audacious") def get_icon_name(self): return "media-skip-forward" class Previous(RunnableLeaf): def __init__(self): RunnableLeaf.__init__(self, name=_("Previous")) def run(self, ctx=None): try: conn = _create_dbus_connection(_IFACE_NAME, _OBJ_NAME, _BUS_NAME) conn.Reverse() except Exception: _audtool_command((_AUDTOOL, "playlist-reverse")) def get_description(self): return _("Jump to previous track in Audacious") def get_icon_name(self): return "media-skip-backward" class ClearQueue(RunnableLeaf): def __init__(self): RunnableLeaf.__init__(self, name=_("Clear Queue")) def run(self, ctx=None): try: conn = _create_dbus_connection(_IFACE_NAME, _OBJ_NAME, _BUS_NAME) conn.PlayqueneClear() except Exception: launch.spawn_async((_AUDTOOL, "playqueue-clear")) def get_description(self): return _("Clear the Audacious play queue") def get_icon_name(self): return "edit-clear" class Shuffle(RunnableLeaf): def __init__(self): RunnableLeaf.__init__(self, name=_("Shuffle")) def run(self, ctx=None): launch.spawn_async((_AUDTOOL, "playlist-shuffle-toggle")) def get_description(self): return _("Toggle shuffle in Audacious") def get_icon_name(self): return "media-playlist-shuffle" class Repeat(RunnableLeaf): def __init__(self): RunnableLeaf.__init__(self, name=_("Repeat")) def run(self, ctx=None): launch.spawn_async((_AUDTOOL, "playlist-repeat-toggle")) def get_description(self): return _("Toggle repeat in Audacious") def get_icon_name(self): return "media-playlist-repeat" class ShowPlaying(RunnableLeaf): def __init__(self): RunnableLeaf.__init__(self, name=_("Show Playing")) def run(self, ctx=None): song = get_current_song() if song is not None: uiutils.show_notification(song, icon_name="audio-x-generic") def get_description(self): return _("Tell which song is currently playing") def get_gicon(self): return icons.ComposedIcon("dialog-information", "audio-x-generic") def get_icon_name(self): return "dialog-information" class SongLeaf(Leaf): """The SongLeaf's represented object is the Playlist index""" def get_actions(self): yield JumpToSong() yield Enqueue() yield Dequeue() def get_icon_name(self): return "audio-x-generic" def get_text_representation(self): return self.name class AudaciousSongsSource(Source): def __init__(self): Source.__init__(self, _("Playlist")) def get_items(self): try: return list(get_playlist_songs_dbus()) except Exception: pretty.print_exc(__name__) return list(get_playlist_songs()) def get_gicon(self): return icons.ComposedIcon( _AUDACIOUS, "audio-x-generic", emblem_is_fallback=True ) def provides(self): yield SongLeaf class AudaciousSource(AppLeafContentMixin, Source): appleaf_content_id = _AUDACIOUS source_user_reloadable = True source_scan_interval: int = 3600 def __init__(self): Source.__init__(self, _("Audacious")) def initialize(self): bus = dbus.SessionBus() weaklib.dbus_signal_connect_weakly( bus, "NameOwnerChanged", self._name_owner_changed, dbus_interface="org.freedesktop.DBus", arg0=_BUS_NAME, ) def _name_owner_changed(self, name, old, new): if new: self.mark_for_update(postpone=True) def get_items(self): yield Play() yield Stop() yield Pause() yield Next() yield Previous() yield ClearQueue() yield ShowPlaying() # Commented as these seem to have no effect # yield Shuffle() # yield Repeat() songs_source = AudaciousSongsSource() yield SourceLeaf(songs_source) if __kupfer_settings__["playlist_toplevel"]: yield from songs_source.get_leaves() def get_description(self): return __description__ def get_icon_name(self): return _AUDACIOUS def provides(self): yield RunnableLeaf kupfer-328/kupfer/plugin/brotab.py000066400000000000000000000054531500175051100173030ustar00rootroot00000000000000__kupfer_name__ = _("Brotab") __kupfer_sources__ = ("TabSource",) __kupfer_actions__ = ("TabActivate", "TabClose", "TabGetUrl") __description__ = _("Firefox Tabs") __version__ = "2020.1" __author__ = "Peter Stuifzand " import typing as ty from brotab.api import MultipleMediatorsAPI # pylint: disable=import-error from brotab.main import create_clients # pylint: disable=import-error from kupfer.obj import Action, Leaf, Source, UrlLeaf if ty.TYPE_CHECKING: from gettext import gettext as _ def get_api(): clients = create_clients() return MultipleMediatorsAPI(clients) def get_active_tab(): api = get_api() tabs = api.get_active_tabs(None) return tabs[0] def get_tabs(): api = get_api() tabs = api.list_tabs([]) for tab in tabs: yield tab.split("\t") class TabLeaf(Leaf): """ Tab leaf This Leaf represents a tab from Brotab in Firefox """ def __init__(self, tab_id, title, url): self.title = title self.url = url super().__init__(tab_id, title) def get_description(self): return self.url def get_icon_name(self): return "web-browser" class TabSource(Source): """ Tab source This Source contains all Tabs from Firefox (as given by Brotab) """ source_use_cache = False task_update_interval_sec = 5 def __init__(self, name=None): super().__init__(name or _("Firefox Tabs")) def get_items(self): cache = {} for tab in get_tabs(): cache[tab[0]] = tab yield TabLeaf(tab[0], tab[1], tab[2]) active_tabs = get_api().get_active_tabs([]) for active_tab in active_tabs[0]: tab = cache[active_tab] yield TabLeaf(tab[0], tab[1], tab[2]) def get_description(self): return _("Firefox browser tabs") def provides(self): yield TabLeaf def get_icon_name(self): return "web-browser" class TabActivate(Action): def __init__(self): super().__init__(_("Activate Tab")) def activate(self, leaf, iobj=None, ctx=None): get_api().activate_tab([leaf.object], True) def item_types(self): yield TabLeaf def get_icon_name(self): return "go-jump" class TabClose(Action): def __init__(self): super().__init__(_("Close Tab")) def activate(self, leaf, iobj=None, ctx=None): get_api().close_tabs([leaf.object]) def item_types(self): yield TabLeaf def get_icon_name(self): return "window-close" class TabGetUrl(Action): def __init__(self): super().__init__(_("Get URL")) def has_result(self): return True def activate(self, leaf, iobj=None, ctx=None): return UrlLeaf(leaf.url, leaf.title) def item_types(self): yield TabLeaf kupfer-328/kupfer/plugin/calculator.py000066400000000000000000000111561500175051100201600ustar00rootroot00000000000000__kupfer_name__ = _("Calculator") __kupfer_actions__ = ("Calculate",) __description__ = _("Calculate mathematical expressions") __version__ = "2017.1" __author__ = "Ulrik Sverdrup " import cmath import inspect import math import textwrap import typing as ty from contextlib import suppress from kupfer import launch, version from kupfer.obj import Action, TextLeaf from kupfer.support import pretty from kupfer.ui import uiutils if ty.TYPE_CHECKING: from gettext import gettext as _ class IgnoreResultError(Exception): pass class KupferSurprise(float): """kupfer cleverness to the inf**inf """ def __call__(self, *args): launch.show_url(version.WEBSITE) raise IgnoreResultError # pylint: disable=too-few-public-methods class DummyResult: def __str__(self): return "" class Help: """help() Show help about the calculator """ def __call__(self): environment = make_environment(last_result=DummyResult()) docstrings = [] for attr in sorted(environment): if attr != "_" and attr.startswith("_"): continue val = environment[attr] if not callable(val): docstrings.append(f"{attr} = {val}") continue with suppress(AttributeError): try: # use .replace() to remove unimportant '/' marker in signature sig = str(inspect.signature(val)).replace(", /)", ")") doc = f"{attr}{sig}\n{val.__doc__}" except ValueError: doc = val.__doc__ docstrings.append(doc) formatted = [] maxlen = 72 left_margin = 4 for docstr in docstrings: # Wrap the description and align continued lines docsplit = docstr.split("\n", 1) if len(docsplit) <= 1: formatted.append(docstr) continue wrapped_lines = textwrap.wrap( docsplit[1].strip(), maxlen - left_margin ) wrapped = ("\n" + " " * left_margin).join(wrapped_lines) formatted.append(f"{docsplit[0]}\n {wrapped}") uiutils.show_text_result("\n\n".join(formatted), _("Calculator")) raise IgnoreResultError def __complex__(self): return self() def make_environment(last_result=None): "Return a namespace for the calculator's expressions to be executed in." environment = dict(vars(math)) environment.update(vars(cmath)) # define some constants missing if last_result is not None: environment["_"] = last_result environment["help"] = Help() environment["kupfer"] = KupferSurprise("inf") # make the builtins inaccessible environment["__builtins__"] = {} return environment def format_result(res): cres = complex(res) parts = [] if cres.real: # pylint: disable=using-constant-test parts.append(str(cres.real)) if cres.imag: # pylint: disable=using-constant-test parts.append(str(complex(0, cres.imag))) return "+".join(parts) or str(res) class Calculate(Action): # since it applies only to special queries, we can up the rank rank_adjust = 10 # global last_result last_result: ty.ClassVar[dict[str, ty.Any]] = {"last": None} def __init__(self): Action.__init__(self, _("Calculate")) def has_result(self): return True def activate(self, leaf, iobj=None, ctx=None): expr = leaf.object.lstrip("= ") # try to add missing parentheses brackets_missing = expr.count("(") - expr.count(")") if brackets_missing > 0: expr += ")" * brackets_missing # hack: change all decimal points (according to current locale) to '.' # expr = expr.replace(locale.localeconv()['decimal_point'], '.') environment = make_environment(self.last_result["last"]) pretty.print_debug(__name__, "Evaluating", expr) try: result = eval(expr, environment) # pylint: disable=eval-used resultstr = format_result(result) self.last_result["last"] = result except IgnoreResultError: return None except Exception as exc: pretty.print_error(__name__, type(exc).__name__, exc) resultstr = str(exc) return TextLeaf(resultstr) def item_types(self): yield TextLeaf def valid_for_item(self, leaf): text = leaf.object return bool(text) and text.startswith("=") def get_description(self): return None kupfer-328/kupfer/plugin/chromium.py000066400000000000000000000046551500175051100176600ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("Chromium Bookmarks") __kupfer_sources__ = ("BookmarksSource",) __description__ = _("Index of Chromium bookmarks") __version__ = "" __author__ = "Francesco Marella " import typing as ty from kupfer import config, plugin_support from kupfer.obj import Source, UrlLeaf from kupfer.obj.apps import AppLeafContentMixin from kupfer.obj.helplib import FileMonitorToken, FilesystemWatchMixin from kupfer.plugin import chromium_support if ty.TYPE_CHECKING: from gettext import gettext as _ plugin_support.check_any_command_available("chromium", "chromium-browser") def _get_chrome_conf_filepath() -> str | None: fpath = config.get_config_file("Bookmarks", package="chromium/Default") # If there is no chromium bookmarks file, look for a google-chrome one if not fpath: fpath = config.get_config_file( "Bookmarks", package="google-chrome/Default" ) return fpath class BookmarksSource(AppLeafContentMixin, Source, FilesystemWatchMixin): appleaf_content_id = ("chromium-browser", "chromium") source_scan_interval: int = 3600 def __init__(self) -> None: self.monitor_token: FileMonitorToken | None = None super().__init__(_("Chromium Bookmarks")) def initialize(self) -> None: if fpath := _get_chrome_conf_filepath(): self.monitor_token = self.monitor_directories(fpath) def monitor_include_file(self, gfile): return gfile and gfile.get_basename() == "lock" def mark_for_update(self, postpone=False): super().mark_for_update(postpone=True) def _get_chromium_items(self, fpath: str) -> ty.Iterator[UrlLeaf]: """Parse Chromium' bookmarks backups""" self.output_debug("Parsing", fpath) bookmarks = chromium_support.get_bookmarks(fpath) for book in bookmarks: yield UrlLeaf(book["url"], book["name"]) def get_items(self) -> ty.Iterable[UrlLeaf]: if fpath := _get_chrome_conf_filepath(): try: return self._get_chromium_items(fpath) except Exception as exc: self.output_error(exc) self.output_error("No Chromium bookmarks file found") return () def get_description(self): return _("Index of Chromium bookmarks") def get_icon_name(self): return "chromium-browser" def provides(self): yield UrlLeaf kupfer-328/kupfer/plugin/chromium_support.py000066400000000000000000000023701500175051100214440ustar00rootroot00000000000000import json import os import typing as ty _CONTAINER = "folder" _UNWANTED_SCHEME = ("data", "place", "javascript") def _is_container(item: dict[str, ty.Any]) -> bool: return item["type"] == _CONTAINER # type:ignore def _is_good_bookmark(item: dict[str, ty.Any]) -> bool: if url := item.get("url"): return url.split(":", 1)[0] not in _UNWANTED_SCHEME return False def get_bookmarks(bookmarks_file: str) -> ty.Iterable[dict[str, ty.Any]]: # construct and configure the parser if not bookmarks_file: return with open(bookmarks_file, encoding="UTF-8") as fin: content = fin.read() root = json.loads(content) folders = [] # add some folders folders.extend(root["roots"]["bookmark_bar"]["children"]) folders.extend(root["roots"]["other"]["children"]) # make a dictionary of unique bookmarks bmap = set() for item in folders: if _is_good_bookmark(item) and (iid := item["id"]) not in bmap: bmap.add(iid) yield item if _is_container(item): folders.extend(item["children"]) if __name__ == "__main__": fpath = os.path.expanduser("~/.config/chromium/Default/") print("Parsed # bookmarks:", len(list(get_bookmarks(fpath)))) kupfer-328/kupfer/plugin/clawsmail.py000066400000000000000000000145071500175051100200060ustar00rootroot00000000000000__kupfer_name__ = _("Claws Mail") __kupfer_sources__ = ("ClawsContactsSource",) __kupfer_actions__ = ("NewMailAction", "SendFileByMail") __description__ = _("Claws Mail Contacts and Actions") __version__ = "2018-10-07" __author__ = "Karol Będkowski " import typing as ty import xml import xml.parsers from pathlib import Path from xml.dom import minidom from kupfer import launch, plugin_support from kupfer.obj import Action, FileLeaf, RunnableLeaf, TextLeaf, UrlLeaf from kupfer.obj.apps import AppLeafContentMixin from kupfer.obj.contacts import ContactLeaf, EmailContact, email_from_leaf from kupfer.obj.grouping import ToplevelGroupingSource from kupfer.obj.helplib import FilesystemWatchMixin if ty.TYPE_CHECKING: from gettext import gettext as _ plugin_support.check_command_available("claws-mail") class ComposeMail(RunnableLeaf): """Create new mail without recipient""" def __init__(self): RunnableLeaf.__init__(self, name=_("Compose New Email")) def run(self, ctx=None): launch.spawn_async(["claws-mail", "--compose"]) def get_description(self): return _("Compose a new message in Claws Mail") def get_icon_name(self): return "mail-message-new" class ReceiveMail(RunnableLeaf): """Receive all new mail from all accounts""" def __init__(self): RunnableLeaf.__init__(self, name=_("Receive All Email")) def run(self, ctx=None): launch.spawn_async(["claws-mail", "--receive-all"]) def get_description(self): return _("Receive new messages from all accounts in ClawsMail") def get_icon_name(self): return "mail-send-receive" class NewMailAction(Action): """Create new mail to selected leaf""" def __init__(self): Action.__init__(self, _("Compose Email")) def activate(self, leaf, iobj=None, ctx=None): self.activate_multiple((leaf,)) def activate_multiple(self, objects): recipients = ",".join(filter(None, map(email_from_leaf, objects))) launch.spawn_async(["claws-mail", "--compose", recipients]) def get_icon_name(self): return "mail-message-new" def item_types(self): yield ContactLeaf # we can enter email yield TextLeaf yield UrlLeaf def valid_for_item(self, leaf): return bool(email_from_leaf(leaf)) class SendFileByMail(Action): """Create new e-mail and attach selected file""" def __init__(self): Action.__init__(self, _("Send in Email To...")) def activate(self, leaf, iobj=None, ctx=None): assert iobj self.activate_multiple((leaf,), (iobj,)) def activate_multiple(self, objects, iobjects): recipients = ",".join(filter(None, map(email_from_leaf, iobjects))) attachlist = ["--attach"] + [L.object for L in objects] launch.spawn_async( ["claws-mail", "--compose", recipients, *attachlist] ) def item_types(self): yield FileLeaf def valid_for_item(self, leaf): return not leaf.is_dir() def requires_object(self): return True def object_types(self): yield ContactLeaf # we can enter email yield TextLeaf yield UrlLeaf def valid_object(self, iobj, for_item=None): return bool(email_from_leaf(iobj)) def get_description(self): return _("Compose new message in Claws Mail and attach file") def get_icon_name(self): return "document-send" class ClawsContactsSource( AppLeafContentMixin, ToplevelGroupingSource, FilesystemWatchMixin ): appleaf_content_id = "claws-mail" source_scan_interval: int = 3600 def __init__(self, name=_("Claws Mail Address Book")): super().__init__(name, "Contacts") self._claws_addrbook_dir = Path("~/.claws-mail/addrbook").expanduser() self._claws_addrbook_index = self._claws_addrbook_dir.joinpath( "addrbook--index.xml" ) self._version = 5 self.monitor_token = None def initialize(self): ToplevelGroupingSource.initialize(self) if not self._claws_addrbook_dir.is_dir(): return self.monitor_token = self.monitor_directories( str(self._claws_addrbook_dir) ) def monitor_include_file(self, gfile): # monitor only addrbook-*.xml files return ( gfile and gfile.get_basename().endswith(".xml") and gfile.get_basename().startswith("addrbook-") ) def mark_for_update(self, postpone=False): super().mark_for_update(postpone=True) def get_items(self): if self._claws_addrbook_index.is_file(): for addrbook_file in self._load_address_books(): addrbook_filepath = self._claws_addrbook_dir.joinpath( addrbook_file ) if not addrbook_filepath.exists(): continue try: dtree = minidom.parse(str(addrbook_filepath)) persons = dtree.getElementsByTagName("person") for person in persons: commonname = person.getAttribute("cn") addresses = person.getElementsByTagName("address") for address in addresses: email = address.getAttribute("email") yield EmailContact(email, commonname) except (Exception, xml.parsers.expat.ExpatError) as err: self.output_error(err) yield ComposeMail() yield ReceiveMail() def should_sort_lexically(self): # since it is a grouping source, grouping and non-grouping will be # separate and only grouping leaves will be sorted return True def get_description(self): return _("Contacts from Claws Mail Address Book") def get_icon_name(self): return "claws-mail" def provides(self): yield RunnableLeaf yield ContactLeaf def _load_address_books(self): """load list of address-book files""" try: dtree = minidom.parse(str(self._claws_addrbook_index)) for book in dtree.getElementsByTagName("book"): yield book.getAttribute("file") except (Exception, xml.parsers.expat.ExpatError) as err: self.output_error(err) kupfer-328/kupfer/plugin/clipboard.py000066400000000000000000000224021500175051100177620ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("Clipboards") __kupfer_sources__ = ("ClipboardSource",) __kupfer_actions__ = ("ClearClipboards",) __description__ = _("Recent clipboards and clipboard proxy objects") __version__ = "2023-03-22" __author__ = "Ulrik Sverdrup " import typing as ty from collections import deque from contextlib import suppress from pathlib import Path from gi.repository import Gdk, Gio, Gtk from kupfer import plugin_support from kupfer.obj import ( Action, FileLeaf, Leaf, Source, SourceLeaf, TextLeaf, UrlLeaf, ) from kupfer.obj.compose import MultipleLeaf from kupfer.support import validators if ty.TYPE_CHECKING: from gettext import gettext as _ from gettext import ngettext __kupfer_settings__ = plugin_support.PluginSettings( { "key": "max", "label": _("Number of recent clipboards to remember"), "type": int, "value": 10, }, { "key": "use_selection", "label": _("Include selected text in clipboard history"), "type": bool, "value": False, }, { "key": "sync_selection", "label": _("Copy selected text to primary clipboard"), "type": bool, "value": False, }, ) class SelectedText(TextLeaf): qf_id = "selectedtext" def __init__(self, text): TextLeaf.__init__(self, text, _("Selected Text")) def __repr__(self): return f"<{__name__} {self.qf_id}>" class SelectedFile(FileLeaf): qf_id = "selectedfile" def __init__(self, text): super().__init__(text, _("Selected File")) def __repr__(self): return f"<{__name__} {self.qf_id}>" class SelectedUrl(UrlLeaf): qf_id = "selectedtext" def __init__(self, text): super().__init__(text, _("Selected URL")) def __repr__(self): return f"<{__name__} {self.qf_id}>" def _new_selected_leaf(text: str | None) -> Leaf | None: if not text: return None if validators.is_url(text): return SelectedUrl(text) if validators.is_valid_file_path(text): path = Path(text).expanduser() if path.exists(): return SelectedFile(path) return SelectedText(text) class ClipboardText(TextLeaf): def get_description(self): numlines = self.object.count("\n") + 1 desc = self.get_first_text_line(self.object) return ngettext( 'Clipboard "%(desc)s"', 'Clipboard with %(num)d lines "%(desc)s"', numlines, ) % {"num": numlines, "desc": desc} class CurrentClipboardText(ClipboardText): qf_id = "clipboardtext" def __init__(self, text): ClipboardText.__init__(self, text, _("Clipboard Text")) def __repr__(self): return f"<{__name__} {self.qf_id}>" class ClipboardUrl(UrlLeaf): def get_description(self): return _('Clipboard "%(desc)s"') % {"desc": self.object, "num": 1} class ClipboardFile(FileLeaf): def get_description(self): return _('Clipboard "%(desc)s"') % {"desc": self.object, "num": 1} class CurrentClipboardUrl(ClipboardUrl): qf_id = "clipboardtext" def __init__(self, text): super().__init__(text, _("Clipboard URL")) def __repr__(self): return f"<{__name__} {self.qf_id}>" class CurrentClipboardFile(FileLeaf): "represents the *unique* current clipboard file" qf_id = "clipboardfile" def __init__(self, filepath): """@filepath is a filesystem byte string `str`""" FileLeaf.__init__(self, filepath, _("Clipboard File")) def __repr__(self): return f"<{__name__} {self.qf_id}>" class CurrentClipboardFiles(MultipleLeaf): "represents the *unique* current clipboard if there are many files" qf_id = "clipboardfile" def __init__(self, paths): files = [FileLeaf(path) for path in paths] MultipleLeaf.__init__(self, files, _("Clipboard Files")) def __repr__(self): return f"<{__name__} {self.qf_id}>" def _new_current_leaf(text: str | None) -> Leaf | None: if not text: return None if validators.is_url(text): return CurrentClipboardUrl(text) if validators.is_valid_file_path(text): path = Path(text).expanduser() with suppress(OSError): if path.exists(): return CurrentClipboardFile(path) return CurrentClipboardText(text) def _new_clipboard_leaf(text: str) -> Leaf: if validators.is_url(text): return ClipboardUrl(text, None) if validators.is_valid_file_path(text): with suppress(OSError, RuntimeError): path = Path(text).expanduser() if path.exists(): return ClipboardFile(path) return ClipboardText(text) class ClearClipboards(Action): def __init__(self): Action.__init__(self, _("Clear")) def activate(self, leaf, iobj=None, ctx=None): leaf.object.clear() def item_types(self): yield SourceLeaf def valid_for_item(self, leaf): return isinstance(leaf.object, ClipboardSource) def get_description(self): return _("Remove all recent clipboards") def get_icon_name(self): return "edit-clear" class ClipboardSource(Source): source_scan_interval: int = 3600 selected_text: str | None clipboard_uris: list[str] clipboard_text: str | None def __init__(self): Source.__init__(self, _("Clipboards")) self.clipboards: deque[str] = deque() # pylint: disable=attribute-defined-outside-init def initialize(self): clip = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) self._sig_id1 = clip.connect( "owner-change", self._on_clipboard_changed ) clip = Gtk.Clipboard.get(Gdk.SELECTION_PRIMARY) self._sig_id2 = clip.connect( "owner-change", self._on_clipboard_changed ) self.clipboard_uris = [] self.clipboard_text = None self.selected_text = None def finalize(self): clip = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) clip.disconnect(self._sig_id1) clip = Gtk.Clipboard.get(Gdk.SELECTION_PRIMARY) clip.disconnect(self._sig_id2) self._sig_id1 = None self._sig_id2 = None self.clipboard_uris = [] self.clipboard_text = None self.selected_text = None self.mark_for_update() def _on_clipboard_changed(self, clip, event, *args): is_selection = event.selection == Gdk.SELECTION_PRIMARY clip.request_text(self._on_text_for_change, is_selection) if not is_selection: clip.request_uris(self._on_uris_for_change) def _on_text_for_change(self, clip, text, is_selection): if text is None: return max_len = __kupfer_settings__["max"] is_valid = bool(text and text.strip()) is_sync_selection = ( is_selection and __kupfer_settings__["sync_selection"] ) if ( not is_selection or __kupfer_settings__["use_selection"] ) and is_valid: self._add_to_history(text, is_selection) if is_sync_selection and is_valid: Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD).set_text(text, -1) if is_selection: self.selected_text = text if not is_selection or is_sync_selection: self.clipboard_text = text self._prune_to_length(max_len) self.mark_for_update() def _on_uris_for_change(self, clip, uris): self.clipboard_uris = uris if uris is not None else [] self.mark_for_update() def _add_to_history(self, cliptext, is_selection): if cliptext in self.clipboards: self.clipboards.remove(cliptext) # if the previous text is a prefix of the new selection, supersede it if ( is_selection and self.clipboards and ( cliptext.startswith(self.clipboards[-1]) or cliptext.endswith(self.clipboards[-1]) ) ): self.clipboards.pop() self.clipboards.append(cliptext) def _prune_to_length(self, max_len): while len(self.clipboards) > max_len: self.clipboards.popleft() def get_items(self): # selected text if leaf := _new_selected_leaf(self.selected_text): yield leaf # produce the current clipboard files if any paths: list[str] = list( filter( None, ( Gio.File.new_for_uri(uri).get_path() for uri in self.clipboard_uris ), ) ) if len(paths) == 1: yield CurrentClipboardFile(paths[0]) elif len(paths) > 1: yield CurrentClipboardFiles(paths) # put out the current clipboard text if leaf := _new_current_leaf(self.clipboard_text): yield leaf # put out the clipboard history yield from map(_new_clipboard_leaf, reversed(self.clipboards)) def get_description(self): return __description__ def get_icon_name(self): return "edit-paste" def provides(self): yield TextLeaf yield FileLeaf yield MultipleLeaf def clear(self): self.clipboards.clear() self.mark_for_update() kupfer-328/kupfer/plugin/commands.py000066400000000000000000000156321500175051100176330ustar00rootroot00000000000000__kupfer_name__ = _("Shell Commands") __kupfer_sources__ = () __kupfer_actions__ = ( "PassToCommand", "FilterThroughCommand", "WriteToCommand", ) __kupfer_text_sources__ = ("CommandTextSource",) __description__ = ( _( "Run command-line programs. Actions marked with" " the symbol %s run in a subshell." ) % "\N{GEAR}" ) __version__ = "" __author__ = "Ulrik Sverdrup " import os import typing as ty from kupfer import icons, launch from kupfer.obj import ( Action, Execute, FileLeaf, OperationError, TextLeaf, TextSource, ) from kupfer.support import kupferstring, pretty if ty.TYPE_CHECKING: from gettext import gettext as _ def finish_command(ctx, acommand, stdout, stderr, post_result=True): """Show async error if @acommand returns error output & error status. Else post async result if @post_result. """ max_error_msg = 512 pretty.print_debug(__name__, "Exited:", acommand) if acommand.exit_status != 0 and not stdout and stderr: errstr = kupferstring.fromlocale(stderr)[:max_error_msg] ctx.register_late_error(OperationError(errstr)) elif post_result: leaf = TextLeaf(kupferstring.fromlocale(stdout)) ctx.register_late_result(leaf) class GetOutput(Action): def __init__(self): Action.__init__(self, _("Run (Get Output)")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx if isinstance(leaf, Command): argv = ["sh", "-c", leaf.object, "--"] else: argv = [leaf.object] def finish_callback(acommand, stdout, stderr): finish_command(ctx, acommand, stdout, stderr) pretty.print_debug(__name__, "Spawning with timeout 15 seconds") launch.AsyncCommand(argv, finish_callback, 15) def get_description(self): return _("Run program and return its output") + " \N{GEAR}" class PassToCommand(Action): def __init__(self): # TRANS: The user starts a program (command) and the text # TRANS: is an argument to the command Action.__init__(self, _("Pass to Command...")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert iobj assert ctx self.activate_multiple((leaf,), (iobj,), ctx) def _run_command(self, objs, iobj, ctx): if isinstance(iobj, Command): argv = ["sh", "-c", iobj.object + ' "$@"', "--"] else: argv = [iobj.object] def finish_callback(acommand, stdout, stderr): finish_command(ctx, acommand, stdout, stderr, False) argv.extend([o.object for o in objs]) pretty.print_debug(__name__, "Spawning without timeout") launch.AsyncCommand(argv, finish_callback, None) def activate_multiple(self, objs, iobjs, ctx): for iobj in iobjs: self._run_command(objs, iobj, ctx) def item_types(self): yield TextLeaf yield FileLeaf def requires_object(self): return True def object_types(self): yield FileLeaf yield Command def valid_object(self, iobj, for_item=None): if isinstance(iobj, Command): return True return iobj.is_executable() def get_description(self): return ( _("Run program with object as an additional parameter") + " \N{GEAR}" ) class WriteToCommand(Action): def __init__(self, name=None): # TRANS: The user starts a program (command) and # TRANS: the text is written on stdin Action.__init__(self, name or _("Write to Command...")) self.post_result = False def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert iobj assert ctx if isinstance(iobj, Command): argv = ["sh", "-c", iobj.object] else: argv = [iobj.object] def finish_callback(acommand, stdout, stderr): finish_command(ctx, acommand, stdout, stderr, self.post_result) pretty.print_debug(__name__, "Spawning without timeout") output = leaf.object.encode("utf-8") launch.AsyncCommand(argv, finish_callback, None, stdin=output) def item_types(self): yield TextLeaf def requires_object(self): return True def object_types(self): yield FileLeaf yield Command def valid_object(self, iobj, for_item=None): if isinstance(iobj, Command): return True return iobj.is_executable() def get_description(self): return ( _("Run program and supply text on the standard input") + " \N{GEAR}" ) class FilterThroughCommand(WriteToCommand): def __init__(self): # TRANS: The user starts a program (command) and # TRANS: the text is written on stdin, and we # TRANS: present the output (stdout) to the user. super().__init__(_("Filter through Command...")) self.post_result = True def get_description(self): return ( _("Run program and supply text on the standard input") + " \N{GEAR}" ) class Command(TextLeaf): def __init__(self, exepath, name): TextLeaf.__init__(self, name, name) self.exepath = exepath def repr_key(self): return self.name def get_actions(self): yield Execute(quoted=False) yield Execute(in_terminal=True, quoted=False) yield GetOutput() def get_description(self): args = " ".join(str(self).split(None, 1)[1:]) return f"{self.exepath} {args}" def get_gicon(self): return icons.get_gicon_for_file(self.exepath) def get_icon_name(self): return "application-x-executable" class CommandTextSource(TextSource): """Yield path and command text items""" def __init__(self): TextSource.__init__(self, name=_("Shell Commands")) def get_rank(self): return 80 def get_text_items(self, text): if not text.strip(): return if "\n" in text: return ## check for absolute path with arguments firstword, *rest = text.split(None, 1) ## files are handled elsewhere if firstword.startswith("/") and not rest: return ## absolute paths come out here since ## os.path.join with two abspaths returns the latter # iterate over $PATH directories env_path = os.environ.get("PATH", os.defpath) for execdir in env_path.split(os.pathsep): exepath = os.path.join(execdir, firstword) if os.access(exepath, os.R_OK | os.X_OK) and os.path.isfile( exepath ): yield Command(exepath, text) break def get_description(self): return _("Run command-line programs") kupfer-328/kupfer/plugin/core/000077500000000000000000000000001500175051100164015ustar00rootroot00000000000000kupfer-328/kupfer/plugin/core/COPYING000066400000000000000000000022541500175051100174370ustar00rootroot00000000000000object.svg: Derived from insert-object.svg in gnome's default icon theme. window.svg: Derived from window-new.svg in gnome's Adwaita icon theme. The whole package's copyright file is as follows: ---- It was downloaded from Copyright: This work is licenced under the terms of either the GNU LGPL v3 or Creative Commons Attribution-Share Alike 3.0 United States License. To view a copy of the CC-BY-SA licence, visit http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA. When attributing the artwork, using "GNOME Project" is enough. Please link to http://www.gnome.org where available. On Debian GNU/Linux systems, the complete text of the GNU General Public License can be found in `/usr/share/common-licenses/GPL-2'. ---- stock_person.svg: https://commons.wikimedia.org/wiki/File:Gnome-stock_person.svg (Creative Commons Attribution-Share Alike 3.0 United States license) stock_mail.svg: https://commons.wikimedia.org/wiki/File:Gnome-emblem-mail.svg (Creative Commons Attribution-Share Alike 3.0 United States license) kupfer-328/kupfer/plugin/core/__init__.py000066400000000000000000000112461500175051100205160ustar00rootroot00000000000000__kupfer_name__ = "Core" # The following attributes are updated later __kupfer_sources__ = () __kupfer_text_sources__ = () __kupfer_contents__ = () __kupfer_actions__ = ("SearchInside", "CopyToClipboard", "Rescan") __description__ = "Core actions and items" __version__ = "" __author__ = "Ulrik Sverdrup " import typing as ty from contextlib import suppress from gi.repository import Gdk, Gtk from kupfer import interface from kupfer.core import commandexec from kupfer.obj import Action, Leaf, Source, SourceLeaf from kupfer.obj.apps import AppLeaf from kupfer.obj.exceptions import InvalidLeafError from kupfer.obj.sources import MultiSource from kupfer.plugin.core import commands, contents, internal, text from kupfer.support import pretty, task if ty.TYPE_CHECKING: from gettext import gettext as _ def _is_debug(): # Return True if Kupfer is in debug mode return pretty.DEBUG def register_subplugin(module): attrs = ( "__kupfer_sources__", "__kupfer_actions__", "__kupfer_text_sources__", "__kupfer_contents__", ) for attr in attrs: object_names = getattr(module, attr, ()) globals()[attr] += object_names globals().update((sym, getattr(module, sym)) for sym in object_names) register_subplugin(contents) register_subplugin(text) register_subplugin(internal) register_subplugin(commands) if _is_debug(): from kupfer.plugin.core import debug register_subplugin(debug) def initialize_plugin(x): # pylint: disable=import-outside-toplevel from kupfer.plugin.core import alternatives alternatives.initialize_alternatives(__name__) class _MultiSource(MultiSource): def is_dynamic(self): return False class SearchInside(Action): """Return the content source for a Leaf""" def __init__(self): super().__init__(_("Search Contents")) def is_factory(self): return True def activate(self, leaf, iobj=None, ctx=None): if not leaf.has_content(): raise InvalidLeafError("Must have content") return leaf.content_source() def activate_multiple(self, objs): return _MultiSource([L.content_source() for L in objs]) def item_types(self): yield Leaf def valid_for_item(self, leaf): return leaf.has_content() def get_description(self): return _("Search inside this catalog") def get_icon_name(self): return "kupfer-search" class CopyToClipboard(Action): # rank down since it applies everywhere rank_adjust = -2 action_accelerator = "c" def __init__(self): Action.__init__(self, _("Copy")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx clip = Gtk.Clipboard.get_for_display( ctx.environment.get_screen().get_display(), Gdk.SELECTION_CLIPBOARD ) interface.copy_to_clipboard(leaf, clip) def item_types(self): yield Leaf def valid_for_item(self, leaf): with suppress(AttributeError): return bool(interface.get_text_representation(leaf)) def get_description(self): return _("Copy to clipboard") def get_icon_name(self): return "edit-copy" class RescanActionTask(task.ThreadTask): def __init__( self, source: Source, async_token: commandexec.ExecutionToken, retval: Leaf, ) -> None: task.ThreadTask.__init__(self) self.source = source self.async_token = async_token self.retval = retval def thread_do(self) -> None: self.source.get_leaves(force_update=True) def thread_finish(self) -> None: self.async_token.register_late_result(self.retval) class Rescan(Action): """A source action: Rescan a source!""" rank_adjust = -5 def __init__(self): Action.__init__(self, _("Rescan")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx if not leaf.has_content(): raise InvalidLeafError("Must have content") source = leaf.content_source() return RescanActionTask(source, ctx, leaf) def is_async(self): return True def get_description(self): return _("Force reindex of this source") def get_icon_name(self): return "view-refresh" def item_types(self): yield AppLeaf yield SourceLeaf def valid_for_item(self, leaf): if not leaf.has_content(): return False if leaf.content_source().is_dynamic(): return False return _is_debug() or leaf.content_source().source_user_reloadable kupfer-328/kupfer/plugin/core/alternatives.py000066400000000000000000000100771500175051100214610ustar00rootroot00000000000000import typing as ty from gi.repository import Gio from kupfer import icons, plugin_support from kupfer.support import desktop_parse if ty.TYPE_CHECKING: from gettext import gettext as _ def initialize_alternatives(name): plugin_support.register_alternative( name, "icon_renderer", "gtk", name=_("GTK+"), renderer=icons.IconRenderer, ) plugin_support.register_alternative( name, "terminal", "gnome-terminal", name=_("GNOME Terminal"), argv=["gnome-terminal"], exearg="-x", desktopid="gnome-terminal.desktop", startup_notify=True, ) plugin_support.register_alternative( name, "terminal", "xfce4-terminal", name=_("XFCE Terminal"), argv=["xfce4-terminal"], exearg="-x", desktopid="xfce4-terminal.desktop", startup_notify=True, ) plugin_support.register_alternative( name, "terminal", "exo-open", name="exo-open", argv=["exo-open", "--launch", "TerminalEmulator"], exearg="", desktopid="", startup_notify=False, ) plugin_support.register_alternative( name, "terminal", "lxterminal", name=_("LXTerminal"), argv=["lxterminal"], exearg="-e", desktopid="lxterminal.desktop", startup_notify=False, ) plugin_support.register_alternative( name, "terminal", "xterm", name=_("X Terminal"), argv=["xterm"], exearg="-e", desktopid="xterm.desktop", startup_notify=False, ) plugin_support.register_alternative( name, "terminal", "x-terminal-emulator", name="x-terminal-emulator", argv=["x-terminal-emulator"], exearg="-e", desktopid="", startup_notify=False, ) plugin_support.register_alternative( name, "terminal", "urxvt", name=_("Urxvt"), argv=["urxvt"], exearg="-e", desktopid="urxvt.desktop", startup_notify=False, ) plugin_support.register_alternative( name, "terminal", "konsole", name=_("Konsole"), argv=["konsole"], exearg="-e", desktopid="konsole.desktop", # Not sure here, so setting to false startup_notify=False, ) _register_terminal_emulators(name) _register_text_editors(name) def _register_text_editors(name): plugin_support.register_alternative( name, "editor", "sys-editor", name=_("System `editor`"), argv=["editor"], terminal=True, ) # find all applications that support text/plain and register it # as text editors for app in Gio.app_info_get_all_for_type("text/plain"): app_id = app.get_id() cmd = app.get_commandline() args = desktop_parse.parse_argv(cmd) plugin_support.register_alternative( name, "editor", app_id.removesuffix(".desktop"), name=app.get_display_name(), argv=args, terminal=app.get_boolean("Terminal"), ) def _register_terminal_emulators(name): """Find all applications with category 'TerminalEmulator' and register it as terminal alternative.""" # hard coded skip-list for already defined above terminals but with # different id skip = ("debian-uxterm.desktop", "debian-xterm.desktop") for app in Gio.app_info_get_all(): app_id = app.get_id() if app_id in skip: continue if "TerminalEmulator" not in (app.get_categories() or ""): continue cmd = app.get_commandline() args = desktop_parse.parse_argv(cmd) plugin_support.register_alternative( name, "terminal", app_id.removesuffix(".desktop"), name=app.get_display_name(), argv=args, exearg="", desktopid=app_id, startup_notify=False, ) kupfer-328/kupfer/plugin/core/commands.py000066400000000000000000000033151500175051100205560ustar00rootroot00000000000000__kupfer_actions__ = ("SaveToFile",) import os import typing as ty from kupfer.core import execfile from kupfer.obj import Action, FileLeaf, TextLeaf, TextSource from kupfer.obj.compose import ComposedLeaf if ty.TYPE_CHECKING: from gettext import gettext as _ class SaveToFile(Action): def __init__(self): Action.__init__(self, _("Save As...")) def has_result(self): return True def activate(self, leaf, iobj=None, ctx=None): assert iobj filepath = iobj.object execfile.save_to_file(leaf, filepath) execfile.update_icon(leaf, iobj.object) return FileLeaf(os.path.abspath(filepath)) def item_types(self): yield ComposedLeaf def requires_object(self): return True def object_types(self): yield TextLeaf def object_source(self, for_item=None): return NameSource(_("Save As..."), ".kfcom") class NameSource(TextSource): """A source for new names for a file; here we "autopropose" the source file's extension, but allow overriding it as well as renaming to without extension (selecting the normal TextSource-returned string). """ def __init__(self, name, extension, sourcefile=None): TextSource.__init__(self, name) self.sourcefile = sourcefile self.extension = extension def get_rank(self): return 100 def get_items(self, text): if not text: return t_root, t_ext = os.path.splitext(text) yield TextLeaf(text) if t_ext else TextLeaf(t_root + self.extension) def get_gicon(self): return self.sourcefile and self.sourcefile.get_gicon() def get_icon_name(self): return "text-x-generic" kupfer-328/kupfer/plugin/core/contents.py000066400000000000000000000062461500175051100206200ustar00rootroot00000000000000import atexit import os import sys import typing as ty from gi.repository import Gtk from kupfer.obj import RunnableLeaf, Source from kupfer.obj.apps import AppLeafContentMixin from kupfer.support import pretty from kupfer.ui import about, kupferhelp, preferences from kupfer.version import DESKTOP_ID if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_sources__ = ("KupferSource",) __kupfer_actions__ = () __author__ = "Ulrik Sverdrup " __all__ = list(__kupfer_sources__) def _is_debug(): # Return True if Kupfer is in debug mode return pretty.DEBUG class DebugRestart(RunnableLeaf): def __init__(self): RunnableLeaf.__init__(self, None, _("Restart Kupfer")) @classmethod def _exec_new_kupfer(cls, executable, argv): os.execvp(executable, [executable, *argv]) def run(self, ctx=None): Gtk.main_quit() atexit.register(self._exec_new_kupfer, sys.executable, sys.argv) def get_description(self): return str(self) def get_icon_name(self): return "view-refresh" class Quit(RunnableLeaf): qf_id = "quit" def __init__(self, name=None): super().__init__(name=name or _("Quit")) def run(self, ctx=None): Gtk.main_quit() def get_description(self): return _("Quit Kupfer") def get_icon_name(self): return "application-exit" class About(RunnableLeaf): def __init__(self, name=None): if not name: name = _("About Kupfer") super().__init__(name=name) def wants_context(self): return True def run(self, ctx=None): assert ctx about.show_about_dialog(ctx.environment) def get_description(self): return _("Show information about Kupfer authors and license") def get_icon_name(self): return "help-about" class Help(RunnableLeaf): def __init__(self, name=None): super().__init__(name=name or _("Kupfer Help")) def wants_context(self): return True def run(self, ctx=None): assert ctx kupferhelp.show_help(ctx.environment) def get_description(self): return _("Get help with Kupfer") def get_icon_name(self): return "help-contents" class Preferences(RunnableLeaf): def __init__(self, name=None): super().__init__(name=name or _("Kupfer Preferences")) def wants_context(self): return True def run(self, ctx=None): assert ctx preferences.show_preferences(ctx.environment) def get_description(self): return _("Show preferences window for Kupfer") def get_icon_name(self): return "preferences-desktop" class KupferSource(AppLeafContentMixin, Source): appleaf_content_id = DESKTOP_ID def __init__(self, name=None): Source.__init__(self, name or _("Kupfer")) def is_dynamic(self): return True def get_items(self): yield Preferences() yield Help() yield About() yield Quit() yield DebugRestart() def get_description(self): return None def get_icon_name(self): return "search" def provides(self): yield RunnableLeaf kupfer-328/kupfer/plugin/core/debug.py000066400000000000000000000142411500175051100200430ustar00rootroot00000000000000""" This module contains internal and / or experimental Kupfer features. These are not meant to be useful to "normal" users of Kupfer -- if they are, they can be tested here before they migrate to a fitting plugin. """ import io from kupfer import puid # NOTE: Core imports from kupfer.core import learn, qfurl from kupfer.obj import Action, Leaf, Source from kupfer.obj.compose import ComposedLeaf from kupfer.support import pretty from kupfer.ui import uiutils __kupfer_sources__ = () __kupfer_contents__ = ("ComposedSource",) __kupfer_actions__ = ("DebugInfo", "Forget") __description__ = __doc__ __author__ = "Ulrik Sverdrup " class DebugInfo(Action): """Print debug info to terminal""" rank_adjust = -50 def __init__(self): Action.__init__(self, "Debug Info") def activate(self, leaf, iobj=None, ctx=None): output = io.StringIO() def print_func(*args): print(" ".join(str(a) for a in args), file=output) pretty.print_debug("debug", *args) print_func("Debug info about", leaf) print_func(leaf, repr(leaf)) def get_qfurl(leaf): try: return qfurl.Qfurl(leaf) except qfurl.QfurlError: pass return None def get_object_fields(leaf): return { "repr": leaf, "description": leaf.get_description(), "thumb": leaf.get_thumbnail(32, 32), "gicon": leaf.get_gicon(), "icon": leaf.get_icon(), "icon-name": leaf.get_icon_name(), "type": type(leaf), "module": leaf.__module__, "aliases": getattr(leaf, "name_aliases", None), "qfurl": get_qfurl(leaf), "puid": puid.get_unique_id(leaf), } def get_leaf_fields(leaf): base = get_object_fields(leaf) base.update( { "object": leaf.object, "object-type": type(leaf.object), "content": leaf.content_source(), "content-alt": leaf.content_source(alternate=True), "builtin-actions": list(leaf.get_actions()), } ) return base def get_source_fields(src): base = get_object_fields(src) base.update( { "dynamic": src.is_dynamic(), "sort": src.should_sort_lexically(), "parent": src.get_parent(), "leaf": src.get_leaf_repr(), "provides": list(src.provides()), "cached_items": type(src.cached_items), "len": isinstance(src.cached_items, list) and len(src.cached_items), } ) return base def print_fields(fields): for field in sorted(fields): val = fields[field] rep = repr(val) print_func(f"{field:<15}:", rep) if str(val) not in rep: print_func(f"{field:<15}:", val) leafinfo = get_leaf_fields(leaf) print_fields(leafinfo) if leafinfo["content"]: print_func("Content ============") print_fields(get_source_fields(leafinfo["content"])) if leafinfo["content"] != leafinfo["content-alt"]: print_func("Content-Alt ========") print_fields(get_source_fields(leafinfo["content-alt"])) uiutils.show_text_result(output.getvalue()) def get_description(self): return "Print debug output (for internal kupfer use)" def get_icon_name(self): return "emblem-system" def item_types(self): yield Leaf class Forget(Action): rank_adjust = -10 def __init__(self): Action.__init__(self, "Forget") def activate(self, leaf, iobj=None, ctx=None): # FIXME: This is a large, total, utter HACK if isinstance(leaf, ComposedLeaf): for obj in leaf.object: learn.unregister(repr(obj)) if isinstance(leaf, ActionLeaf): learn.unregister(repr(leaf.object)) else: learn.unregister(repr(leaf)) def item_types(self): yield Leaf def get_description(self): return "Let Kupfer forget about this object" class ActionLeaf(Leaf): def __init__(self, action): Leaf.__init__(self, action, str(action)) def get_actions(self): act = self.object if not (hasattr(act, "requires_object") and act.requires_object()): yield Apply(act) def get_description(self): return self.object.get_description() def get_icon_name(self): return self.object.get_icon_name() class Apply(Action): rank_adjust = 5 def __init__(self, action): Action.__init__(self, "Apply To...") self.action = action def is_factory(self): return self.action.is_factory() def has_result(self): return self.action.has_result() def is_async(self): return self.action.is_async() def requires_object(self): return True def object_types(self): return self.action.item_types() def valid_object(self, obj, for_item=None): return self.action.valid_for_item(obj) def wants_context(self): return self.action.wants_context() def activate(self, leaf, iobj=None, ctx=None): return self.action.activate(iobj, ctx=ctx) class ComposedSource(Source): """Decorated ComposedLeaf with a Source that shows the contents of Composed Commands""" def __init__(self, leaf): Source.__init__(self, "Composed Command") self.leaf = leaf def get_items(self): obj = self.leaf.object yield self.leaf.object[0] yield ActionLeaf(obj[1]) if self.leaf.object[2] is not None: yield self.leaf.object[2] def repr_key(self): return self.leaf.repr_key() @classmethod def decorates_type(cls): return ComposedLeaf @classmethod def decorate_item(cls, leaf): return cls(leaf) kupfer-328/kupfer/plugin/core/icon-list000066400000000000000000000003631500175051100202270ustar00rootroot00000000000000# IconName File # the fields must be tab-separated # icons are used if not existing in the icon theme kupfer-object object.svg kupfer-object-multiple objects.svg kupfer-window window.svg stock_person stock_person.svg stock_mail stock_mail.svg kupfer-328/kupfer/plugin/core/internal.py000066400000000000000000000046211500175051100205720ustar00rootroot00000000000000import typing as ty from kupfer.core import commandexec from kupfer.obj import Leaf, RunnableLeaf, Source if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_sources__ = ("KupferInterals", "CommandResults") __author__ = "Ulrik Sverdrup " class LastCommand(RunnableLeaf): """Represented object is the command tuple to run""" qf_id = "lastcommand" def __init__(self, obj): RunnableLeaf.__init__(self, obj, _("Last Command")) def wants_context(self): return True def run(self, ctx=None): assert ctx obj, action, iobj = self.object return ctx.delegated_run(obj, action, iobj) class KupferInterals(Source): def __init__(self): Source.__init__(self, _("Internal Kupfer Objects")) def is_dynamic(self): return True def get_items(self): ctx = commandexec.default_action_execution_context() if ctx.last_command is not None: yield LastCommand(ctx.last_command) def provides(self): yield LastCommand class LastResultObject(Leaf): "dummy superclass" def __init__(self, leaf): super().__init__(leaf.object, _("Last Result")) def _make_first_result_object(leaf): # global LastResultObject class _LastResultObject(LastResultObject): qf_id = "lastresult" def __init__(self, leaf): super().__init__(leaf) vars(self).update(vars(leaf)) self.name = _("Last Result") self.__original_leaf = leaf self.__class__.__bases__ = (leaf.__class__, Leaf) def get_gicon(self): return None def get_icon_name(self): return Leaf.get_icon_name(self) def get_thumbnail(self, width, height): return None def get_description(self): return str(self.__original_leaf) return _LastResultObject(leaf) class CommandResults(Source): def __init__(self): Source.__init__(self, _("Command Results")) def is_dynamic(self): return True def get_items(self): ctx = commandexec.default_action_execution_context() yield from reversed(ctx.last_results) try: leaf = ctx.last_results[-1] except IndexError: return yield _make_first_result_object(leaf) def provides(self): yield Leaf yield LastResultObject kupfer-328/kupfer/plugin/core/object.svg000066400000000000000000000173541500175051100204020ustar00rootroot00000000000000 image/svg+xml insert-object 04-07-07 Lapo Calamandrei stock insert object kupfer-328/kupfer/plugin/core/objects.svg000066400000000000000000000205231500175051100205550ustar00rootroot00000000000000 image/svg+xml 04-07-07 Lapo Calamandrei stock insert object kupfer-328/kupfer/plugin/core/stock_mail.svg000066400000000000000000000501221500175051100212470ustar00rootroot00000000000000 image/svg+xml Mail Emblem 2005-02-19 Lapo Calamandrei Mail emblem Jakub Steiner Andreas Nilsson mail message e-mail Lapo Calamandrei, Andreas Nilsson, Novell Inc. kupfer-328/kupfer/plugin/core/stock_person.svg000066400000000000000000000100171500175051100216320ustar00rootroot00000000000000 kupfer-328/kupfer/plugin/core/system-run.svg000066400000000000000000000424071500175051100212570ustar00rootroot00000000000000 image/svg+xml Lapo Calamandrei System Run run launch exec kupfer-328/kupfer/plugin/core/text.py000066400000000000000000000077471500175051100177560ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = "Free-text Queries" __kupfer_sources__ = () __kupfer_text_sources__ = ( "BasicTextSource", "PathTextSource", "URLTextSource", ) __kupfer_actions__ = ("OpenTextUrl",) __description__ = "Basic support for free-text queries" __version__ = "2021.1" __author__ = "Ulrik Sverdrup " import os import typing as ty import urllib.error import urllib.parse import urllib.request from contextlib import suppress from pathlib import Path from kupfer import launch from kupfer.obj import FileLeaf, Leaf, OpenUrl, TextLeaf, TextSource, UrlLeaf from kupfer.support import pretty, system from kupfer.support.validators import is_url if ty.TYPE_CHECKING: from gettext import gettext as _ class BasicTextSource(TextSource): """The most basic TextSource yields one TextLeaf""" def __init__(self): TextSource.__init__(self, name=_("Text")) def get_text_items(self, text): if text: yield TextLeaf(text) def provides(self): yield TextLeaf class PathTextSource(TextSource, pretty.OutputMixin): """Return existing full paths if typed""" def __init__(self): TextSource.__init__(self, name="Filesystem Text Matches") def get_rank(self): return 80 def _is_local_file_url(self, url: str) -> bool: # Recognize file:/// or file://localhost/ or file:/// URLs hostname = system.get_hostname() return url.startswith( ("file:///", "file://localhost/", f"file://{hostname}/") ) def get_text_items(self, text: str) -> ty.Iterator[Leaf]: # Find directories or files if self._is_local_file_url(text): leaf = FileLeaf.from_uri(text) if leaf and leaf.is_valid(): yield leaf return urlpath = Path(text) if not urlpath.is_absolute(): urlpath = Path(system.get_homedir()).joinpath(urlpath) with suppress(OSError): filepath = urlpath.resolve(strict=True) if os.access(filepath, os.R_OK): yield FileLeaf(filepath) def provides(self): yield FileLeaf class OpenTextUrl(OpenUrl): rank_adjust = 1 def activate(self, leaf, iobj=None, ctx=None): if url := self._get_leaf_valid_url(leaf): launch.show_url(url) def item_types(self): yield Leaf def valid_for_item(self, leaf: Leaf) -> bool: return bool(self._get_leaf_valid_url(leaf)) def _get_leaf_valid_url(self, leaf: Leaf) -> str | None: if isinstance(leaf, TextLeaf) and (url := is_url(leaf.object)): return url with suppress(AttributeError): if (trepr := leaf.get_text_representation()) and ( # type: ignore url := is_url(trepr) ): return url with suppress(AttributeError, NotImplementedError): for url in leaf.get_urilist_representation() or []: # type: ignore if url and (url := is_url(url)): return url return None class URLTextSource(TextSource): """detect URLs and webpages""" def __init__(self): TextSource.__init__(self, name="URL Text Matches") def get_rank(self): return 75 def get_text_items(self, text: str) -> ty.Iterator[Leaf]: # Only detect "perfect" URLs text = text.strip() if not text: return components = urllib.parse.urlparse(text) # scheme and netloc are required if not components.scheme or not components.netloc: return # check for any whitespaces; quick and dirty if len(text.split(None, 1)) != 1: return name = f"{components.netloc}{components.path}".strip("/") # Try to turn an URL-escaped string into a Unicode string name = urllib.parse.unquote(name) or text yield UrlLeaf(text, name=name) def provides(self): yield UrlLeaf kupfer-328/kupfer/plugin/core/view-refresh.svg000066400000000000000000000407441500175051100215410ustar00rootroot00000000000000 image/svg+xml Jakub Steiner http://jimmac.musichall.cz View Refresh reload refresh view kupfer-328/kupfer/plugin/core/window.svg000066400000000000000000000167631500175051100204460ustar00rootroot00000000000000 image/svg+xml kupfer-328/kupfer/plugin/custom_terminal.py000066400000000000000000000026411500175051100212330ustar00rootroot00000000000000__kupfer_name__ = _("Custom Terminal") __description__ = _( """Configure a custom terminal emulator. The plugin adds another terminal alternative (select it on the main page).""" ) __version__ = "" __author__ = "Ulrik Sverdrup" import typing as ty from kupfer import plugin_support, support from kupfer.support import fileutils if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_settings__ = plugin_support.PluginSettings( { "key": "command", "label": _("Command"), "type": str, "value": "", }, { "key": "exearg", "label": _("Execute flag"), "type": str, "value": "-e", "tooltip": ( "The flag which makes the terminal execute" " everything following it in the argument string. " ), }, ) def initialize_plugin(name): __kupfer_settings__.connect_settings_changed_cb(_update_alternative) _update_alternative() def _update_alternative(*args): command = __kupfer_settings__["command"] exearg = __kupfer_settings__["exearg"] argv = support.argv_for_commandline(command) if not argv or not fileutils.lookup_exec_path(argv[0]): return plugin_support.register_alternative( __name__, "terminal", "custom1", name=_("Custom Terminal"), argv=argv, exearg=exearg, desktopid="", startup_notify=True, ) kupfer-328/kupfer/plugin/darktheme.py000066400000000000000000000020131500175051100177630ustar00rootroot00000000000000__kupfer_name__ = _("Prefer Dark Theme") __description__ = "" __version__ = "2017.1" __author__ = "" import typing as ty from gi.repository import Gtk from kupfer import plugin_support from kupfer.support import pretty if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_settings__ = plugin_support.PluginSettings( { "key": "prefer_dark", "label": _("Prefer Dark Theme"), "type": bool, "value": True, }, ) def initialize_plugin(name): use_theme(__kupfer_settings__["prefer_dark"]) __kupfer_settings__.connect_settings_changed_cb(_on_change_theme) def finalize_plugin(name): use_theme(None) def _on_change_theme(sender, key, value): use_theme(value) PREFER_DARK = "gtk-application-prefer-dark-theme" def use_theme(enabled): pretty.print_debug(__name__, "updating setting to", enabled) sett = Gtk.Settings.get_default() if enabled is None: sett.reset_property(PREFER_DARK) else: sett.set_property(PREFER_DARK, enabled) kupfer-328/kupfer/plugin/deepdirectories.py000066400000000000000000000036151500175051100212020ustar00rootroot00000000000000""" Changes: 2018-09-04 * fix: Python 3 compatibility 2012-10-08 * fix: errors when no one configured directories exists 2012-06-09 + max depth; fix source name 2012-06-08 - init """ __kupfer_name__ = _("Deep Directories") __kupfer_sources__ = ("DeepDirSource",) __description__ = _("Recursive index directories") __version__ = "2018-09-04" __author__ = "Karol Będkowski " import os import typing as ty from kupfer import plugin_support from kupfer.obj.filesrc import FileSource if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_settings__ = plugin_support.PluginSettings( { "key": "dirs", "label": _("Directories:"), "type": list, "helper": "choose_directory", "value": ["~/Documents/"], }, { "key": "depth", "label": _("Depth (max 10):"), "type": int, "value": 2, "max": 10, "min": 1, }, ) _MAX_DEPTH = 10 class DeepDirSource(FileSource): def __init__(self, name=_("Deep Directories")): FileSource.__init__( self, [""], min(__kupfer_settings__["depth"], _MAX_DEPTH), ) self.name = name def initialize(self): __kupfer_settings__.connect( "plugin-setting-changed", self._on_setting_changed ) def get_items(self): self.dirlist = list(self._get_dirs()) self.depth = min(__kupfer_settings__["depth"], _MAX_DEPTH) yield from FileSource.get_items(self) @staticmethod def _get_dirs(): dirs = __kupfer_settings__["dirs"] for path in dirs or (): if (path := os.path.expanduser(path.strip())) and os.path.isdir( path ): yield path def _on_setting_changed(self, settings, key, value): if key in ("dirs", "depth"): self.mark_for_update() kupfer-328/kupfer/plugin/defaultmail.py000066400000000000000000000021761500175051100203200ustar00rootroot00000000000000__kupfer_name__ = _("Default Email Client") __kupfer_actions__ = ("NewMailAction",) __description__ = _("Compose email using the system's default mailto: handler") __version__ = "2017.1" __author__ = "" import typing as ty from kupfer import launch from kupfer.obj import Action, TextLeaf, UrlLeaf from kupfer.obj.contacts import ContactLeaf, email_from_leaf if ty.TYPE_CHECKING: from gettext import gettext as _ class NewMailAction(Action): def __init__(self): Action.__init__(self, _("Compose Email To")) def activate(self, leaf, iobj=None, ctx=None): email = email_from_leaf(leaf) launch.show_url(f"mailto:{email}") def activate_multiple(self, objects): recipients = ",".join(filter(None, map(email_from_leaf, objects))) url = "mailto:" + recipients launch.show_url(url) def item_types(self): yield ContactLeaf yield TextLeaf yield UrlLeaf def valid_for_item(self, leaf): return bool(email_from_leaf(leaf)) def get_description(self): return __description__ def get_icon_name(self): return "mail-message-new" kupfer-328/kupfer/plugin/devhelp.py000066400000000000000000000020371500175051100174540ustar00rootroot00000000000000__kupfer_name__ = _("Devhelp") __kupfer_actions__ = ("LookUp",) __description__ = _("Search in Devhelp") __version__ = "2017.1" __author__ = "" import typing as ty from kupfer import icons, launch, plugin_support from kupfer.obj import Action, OperationError, TextLeaf if ty.TYPE_CHECKING: from gettext import gettext as _ plugin_support.check_command_available("devhelp") class LookUp(Action): fallback_icon_name = "edit-find" def __init__(self): Action.__init__(self, _("Search in Devhelp")) def activate(self, leaf, iobj=None, ctx=None): text = leaf.object try: launch.spawn_async_raise(["devhelp", f"--search={text}"]) except launch.SpawnError as exc: raise OperationError(exc) from exc def item_types(self): yield TextLeaf def valid_for_item(self, leaf): text = leaf.object return "\n" not in text def get_icon_name(self): return "devhelp" def get_gicon(self): return icons.ComposedIcon("devhelp", "edit-find") kupfer-328/kupfer/plugin/dictionary.py000066400000000000000000000042761500175051100202010ustar00rootroot00000000000000__kupfer_name__ = _("Dictionary") __kupfer_actions__ = ("LookUp",) __description__ = _("Look up word in dictionary") __version__ = "2023-04-14" __author__ = "Ulrik, KB" import shutil import typing as ty from dataclasses import dataclass from kupfer import launch, plugin_support from kupfer.desktop_launch import SpawnError from kupfer.obj import Action, OperationError, TextLeaf if ty.TYPE_CHECKING: from gettext import gettext as _ @dataclass class Dict: title: str args: list[str] dictionaries = { "gnome-dictionary": Dict( _("Gnome Dictionary"), ["gnome-dictionary", "--look-up=%s"] ), "mate-dictionary": Dict( _("Mate Dictionary"), ["mate-dictionary", "--look-up=%s"] ), "purple": Dict(_("Purple"), ["purple", "--define=%s"]), "xfce4-dict": Dict(_("Xfce4 Dict"), ["xfce4-dict", "--dict", "%s"]), "org.goldendict.GoldenDict": Dict(_("GoldenDict"), ["goldendict", "%s"]), } __kupfer_settings__ = plugin_support.PluginSettings( { "key": "dictionary", "label": _("Dictionary"), "type": str, "alternatives": [ (key, dic.title) for key, dic in dictionaries.items() ], "value": "gnome-dictionary", } ) class LookUp(Action): def __init__(self): Action.__init__(self, _("Look Up")) def activate(self, leaf, iobj=None, ctx=None): text = leaf.object dict_id = __kupfer_settings__["dictionary"] dict_def = dictionaries[dict_id] if not shutil.which(dict_def.args[0]): raise OperationError(f"{dict_def.title} not available") dict_argv = [arg.replace("%s", text) for arg in dict_def.args] try: launch.spawn_async_notify_as(dict_id + ".desktop", dict_argv) except SpawnError as exc: raise OperationError(exc) from exc def item_types(self): yield TextLeaf def valid_for_item(self, leaf): text = leaf.object return len(text.split("\n", 1)) <= 1 def get_description(self): curr_dict = __kupfer_settings__["dictionary"] return _("Look up word in %s") % dictionaries[curr_dict].title def get_icon_name(self): return "accessories-dictionary" kupfer-328/kupfer/plugin/documents.py000066400000000000000000000263501500175051100200320ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("Documents") __kupfer_sources__ = ("RecentsSource", "PlacesSource", "IgnoredApps") __kupfer_actions__ = ("Toggle",) __kupfer_contents__ = ("ApplicationRecentsSource",) __description__ = _("Recently used documents and bookmarked folders") __version__ = "2017.3" __author__ = "" import functools import typing as ty from os import path from pathlib import Path from gi.repository import Gio, Gtk from xdg import BaseDirectory from kupfer import icons, launch, plugin_support from kupfer.obj import Action, AppLeaf, FileLeaf, Source, SourceLeaf, UrlLeaf from kupfer.support import datatools, weaklib if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_settings__ = plugin_support.PluginSettings( { "key": "max_days", "label": _("Max recent document days"), "type": int, "value": 28, }, { "key": "check_doc_exist", "label": _("Show only existing documents"), "type": bool, "value": True, }, ) ALIASES = { "libreoffice": "soffice", } # Libreoffice doesn't separate them out, so we'll hack that in manually SEPARATE_APPS = { "libreoffice": { ".doc": "libreoffice-writer", ".docx": "libreoffice-writer", ".odt": "libreoffice-writer", ".ods": "libreoffice-calc", ".xlsx": "libreoffice-calc", ".csv": "libreoffice-calc", ".odp": "libreoffice-impress", ".ppt": "libreoffice-impress", ".pptx": "libreoffice-impress", ".odg": "libreoffice-draw", ".odf": "libreoffice-math", ".mml": "libreoffice-math", } } def _file_path(uri: str) -> str | None: try: return ty.cast("str", Gio.File.new_for_uri(uri).get_path()) except Exception: return None @datatools.simple_cache def _get( max_days: int, check_doc_exist: bool ) -> list[tuple[str, int, tuple[str, ...]]]: manager = Gtk.RecentManager.get_default() items = [] for item in manager.get_items(): if item.get_age() > max_days >= 0: continue if check_doc_exist and not item.exists(): continue if item.get_private_hint(): continue if not item.is_local(): continue uri = item.get_uri() if file_path := _file_path(uri): apps_name = tuple(_get_app_id(item)) items.append((file_path, item.get_modified(), apps_name)) return items def _get_app_id(item: Gtk.RecentInfo) -> ty.Iterator[str]: """Get applications id for given RecentInfo @item""" # some duplicates are expected but we can live with this for app in item.get_applications(): # get app_id from application info instr = item.get_application_info(app)[0] app = app.lower() # noqa:PLW2901 yield app # get first word as app id if (aid := instr.split(None, 1)[0]) != app: yield aid def _get_items( for_app_names: tuple[str, ...] | None = None, ) -> ty.Iterator[tuple[int, str]]: """Get recent items `for_app_names`. for_app_names: set of candidate app names, or None. Return iterable: tuple (modification time, file path) """ max_days = __kupfer_settings__["max_days"] check_doc_exist = __kupfer_settings__["check_doc_exist"] for file_path, modified, apps in _get(max_days, check_doc_exist): if for_app_names: if not any(a in for_app_names for a in apps): continue ext = path.splitext(file_path)[1].lower() # check is any of app_id is in separate_apps dict, then check # extension of file - if is on list and matched application # is not @for_app_names list - skip file. # this allow to filter files for applications by file extension if any( sort_table.get(ext) not in for_app_names for app_id, sort_table in SEPARATE_APPS.items() if app_id in for_app_names ): continue yield (modified, file_path) def _get_items_sorted( for_app_names: tuple[str, ...] | None = None, ) -> ty.Iterator[FileLeaf]: """Get recent documents as iterable FileLeaf for `for_app_names` sorted sorted by modified date desc.""" items = sorted(_get_items(for_app_names), reverse=True) return (FileLeaf(item[1]) for item in items) @functools.lru_cache(maxsize=10) def _has_items_for_application(app_names: tuple[str, ...]) -> bool: """Check is there any recent documents for `app_names`.""" # Cache doesn't need to be large to serve main purpose: # there will be many identical queries in a row for _item in _get_items(app_names): return True return False def _app_names(leaf: AppLeaf) -> tuple[str, ...]: """Return a tuple of names for appleaf""" # in most cases, there are only 2-3 items, so there is not need to # built set svc = launch.get_applications_matcher_service() leaf_id = leaf.get_id() ids = [leaf_id] if (exe := leaf.object.get_executable()) != leaf_id: ids.append(exe) if (app_name := svc.application_name(leaf_id)) and ( app_name := app_name.lower() ) != leaf_id: ids.append(app_name) ids.extend(v for k, v in ALIASES.items() if k in ids) # return tuple as wee need hashable object for caching return tuple(ids) class RecentsSource(Source): def __init__(self, name=None): super().__init__(name or _("Recent Items")) def initialize(self): """Set up change callback""" manager = Gtk.RecentManager.get_default() weaklib.gobject_connect_weakly( manager, "changed", self._recent_changed ) def _recent_changed(self, _rmgr: Gtk.RecentManager) -> None: # when using typeguard lru_cache is wrapped try: _get.cache_clear() except AttributeError: _get.__wrapped__.cache_clear() # type:ignore self.mark_for_update() def get_items(self): return _get_items_sorted() def get_description(self): return _("Recently used documents") def get_icon_name(self): return "document-open-recent" def provides(self): yield FileLeaf yield UrlLeaf class ApplicationRecentsSource(RecentsSource): def __init__(self, application): # TRANS: Recent Documents for application %s name = _("%s Documents") % str(application) super().__init__(name) self.application = application def repr_key(self): return self.application.repr_key() def get_items(self): app_names = _app_names(self.application) self.output_debug("Items for", app_names) return _get_items_sorted(app_names) def get_gicon(self): return icons.ComposedIcon( self.get_icon_name(), self.application.get_icon() ) def get_description(self): return _("Recently used documents for %s") % str(self.application) @classmethod def decorates_type(cls): return AppLeaf @classmethod def decorate_item(cls, leaf: AppLeaf) -> ApplicationRecentsSource | None: if IgnoredApps.contains(leaf): return None app_names = _app_names(leaf) if _has_items_for_application(app_names): return cls(leaf) return None class PlacesSource(Source): """Source for items from gtk bookmarks/""" source_scan_interval: int = 3600 def __init__(self): super().__init__(_("Places")) self.places_file = None self._version = 2 def initialize(self): self.places_file = path.join( BaseDirectory.xdg_config_home, "gtk-3.0", "bookmarks" ) def get_items(self): """ gtk-bookmarks: each line has url and optional title file:///path/to/that.end [title] """ assert self.places_file if Path(self.places_file).exists(): return self._get_places(self.places_file) return () def _get_places(self, fileloc): with open(fileloc, encoding="UTF-8") as fin: for line in fin: line = line.strip() # noqa:PLW2901 if not line: continue uri, *rest = line.split(None, 1) gfile = Gio.File.new_for_uri(uri) if rest: title = rest[0] else: disp = gfile.get_parse_name() title = path.basename(disp) if locpath := gfile.get_path(): yield FileLeaf(locpath, title) else: yield UrlLeaf(gfile.get_uri(), title) def get_description(self): return _("Bookmarked folders") def get_icon_name(self): return "system-file-manager" def provides(self): yield FileLeaf yield UrlLeaf class IgnoredApps(Source): # This Source is invisible and has no content # It exists just to store (through the config mechanism) the list of apps # we ignore for recent documents content decoration instance: IgnoredApps = None # type:ignore source_scan_interval: int = 3600 def __init__(self): super().__init__(_("Toggle Recent Documents")) self._version = 2 self.apps: set[str] = set() def config_save(self): return self.apps def config_save_name(self): return __name__ def config_restore(self, state): self.apps = state def initialize(self): IgnoredApps.instance = self def finalize(self): del IgnoredApps.instance def get_items(self): return [] def provides(self): return () @classmethod def add(cls, app_leaf): assert cls.instance cls.instance.apps.add(app_leaf.get_id()) # FIXME: Semi-hack to refresh the content cls.instance.mark_for_update() @classmethod def remove(cls, app_leaf): assert cls.instance cls.instance.apps.discard(app_leaf.get_id()) cls.instance.mark_for_update() @classmethod def contains(cls, app_leaf): assert cls.instance return app_leaf.get_id() in cls.instance.apps def get_leaf_repr(self): return InvisibleSourceLeaf(self) class Toggle(Action): rank_adjust = -5 def __init__(self): super().__init__(_("Toggle Recent Documents")) def item_types(self): yield AppLeaf def valid_for_item(self, leaf): if IgnoredApps.contains(leaf): return True app_names = _app_names(leaf) return _has_items_for_application(app_names) def has_result(self): return True def activate(self, leaf, iobj=None, ctx=None): if IgnoredApps.contains(leaf): IgnoredApps.remove(leaf) else: IgnoredApps.add(leaf) # Neat trick: We return the leaf, and that updates the decoration # pylint: disable=protected-access leaf._content_source = None # noqa: SLF001 return leaf def get_description(self): return _( "Enable/disable listing recent documents in " "content for this application" ) class InvisibleSourceLeaf(SourceLeaf): """Hack to hide this source""" def is_valid(self): return False kupfer-328/kupfer/plugin/duckduckgo.py000066400000000000000000000020231500175051100201430ustar00rootroot00000000000000""" This is a DuckDuckGo search plugin based on the Wikipedia search plugin """ __kupfer_name__ = _("DuckDuckGo Search") __kupfer_sources__ = () __kupfer_actions__ = ("DuckDuckGoSearch",) __description__ = _("Search the web securely with DuckDuckGo") __version__ = "1.0" __author__ = "Isaac Aggrey " import typing as ty import urllib.parse from kupfer import launch from kupfer.obj import Action, TextLeaf if ty.TYPE_CHECKING: from gettext import gettext as _ class DuckDuckGoSearch(Action): def __init__(self): Action.__init__(self, _("DuckDuckGo Search")) def activate(self, leaf, iobj=None, ctx=None): search_url = "https://duckduckgo.com/" query_url = ( search_url + "?" + urllib.parse.urlencode({"q": leaf.object}) ) launch.show_url(query_url) def item_types(self): yield TextLeaf def get_description(self): return _("Search the web securely with DuckDuckGo") def get_icon_name(self): return "edit-find" kupfer-328/kupfer/plugin/favorites.py000066400000000000000000000136071500175051100200340ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("Favorites") __kupfer_sources__ = ("FavoritesSource",) __kupfer_actions__ = ("AddFavorite", "RemoveFavorite") __description__ = _("Mark commonly used items and store objects for later use") __version__ = "2009-12-30" __author__ = "Ulrik Sverdrup " import typing as ty import weakref from kupfer import puid # NOTE: core import from kupfer.core import learn from kupfer.obj import Action, Leaf, Source, SourceLeaf if ty.TYPE_CHECKING: from gettext import gettext as _ class FavoritesSource(Source): """Keep a list of Leaves that the User may add and remove from""" instance: FavoritesSource = None # type:ignore source_scan_interval: int = 3600 def __init__(self): Source.__init__(self, _("Favorites")) ## these are default favorites for new users self.references: list[puid.PuID] = [ "", "", ] def config_save(self) -> dict[str, ty.Any]: references = [puid.get_unique_id(F) for F in self.favorites] return {"favorites": references, "version": self.version} def config_save_name(self) -> str: return __name__ def config_restore(self, state: dict[str, ty.Any]) -> None: self.references = state["favorites"] def _find_item(self, id_: puid.PuID) -> Leaf | None: itm = puid.resolve_unique_id(id_, excluding=self) if itm is None: return None assert isinstance(itm, Leaf) # ignore invalid objects if hasattr(itm, "is_valid") and not itm.is_valid(): return None if puid.is_reference(id_): assert isinstance(id_, str) self.reference_table[id_] = itm else: assert isinstance(id_, puid.SerializedObject) self.persist_table[id_] = itm return itm # pylint: disable=attribute-defined-outside-init def initialize(self): FavoritesSource.instance = self self.favorites: list[Leaf] = [] # persist_table map Serialized object to Leaves self.persist_table: dict[puid.SerializedObject, Leaf] = {} # reference table map reference-type id to leaf self.reference_table: weakref.WeakValueDictionary[str, Leaf] = ( weakref.WeakValueDictionary() ) self.mark_for_update() def finalize(self) -> None: learn.replace_favorites(__name__) def _update_items(self): # insert items on beginning to make last added items first on list favorites: list[Leaf] = [] for id_ in self.references: if isinstance(id_, puid.SerializedObject) and ( leaf := self.persist_table.get(id_) ): # id_ is in persist_table so is SerializedObject favorites.insert(0, leaf) continue if isinstance(id_, str) and ( leaf := self.reference_table.get(id_) ): # id_ is in reference_table, so is reference, so it's str favorites.insert(0, leaf) continue if (itm := self._find_item(id_)) is not None: favorites.insert(0, itm) else: self.output_debug("MISSING:", id_) self.favorites = favorites def add(self, itm): if id_ := puid.get_unique_id(itm): # there shouldn't be possible to add twice the same leaf so # remove should be not needed. self.remove(itm) learn.add_favorite(__name__, itm) # favorites will be rebuild, so we can append self.favorites.append(itm) self.references.append(id_) self.mark_for_update() def has_item(self, itm: Leaf) -> bool: return itm in self.favorites def remove(self, itm: Leaf) -> None: if itm not in self.favorites: return learn.remove_favorite(__name__, itm) self.favorites.remove(itm) if id_ := puid.get_unique_id(itm): try: self.references.remove(id_) except KeyError: for key, val in self.persist_table.items(): if val == itm: self.references.remove(key) self.persist_table.pop(key) break self.mark_for_update() def get_items(self): self._update_items() learn.replace_favorites(__name__, *self.favorites) return self.favorites def get_description(self): return _('Shelf of "Favorite" items') def get_icon_name(self): return "emblem-favorite" def provides(self): # returning nothing means it provides anything return () class AddFavorite(Action): # Rank down, since it applies everywhere rank_adjust = -15 def __init__(self): Action.__init__(self, _("Add to Favorites")) def activate(self, leaf, iobj=None, ctx=None): FavoritesSource.instance.add(leaf) def item_types(self): yield Leaf def valid_for_item(self, leaf): return not isinstance( leaf, SourceLeaf ) and not FavoritesSource.instance.has_item(leaf) def get_description(self): return _("Add item to favorites shelf") def get_icon_name(self): return "list-add" class RemoveFavorite(Action): rank_adjust = -15 def __init__(self): Action.__init__(self, _("Remove from Favorites")) def activate(self, leaf, iobj=None, ctx=None): FavoritesSource.instance.remove(leaf) def item_types(self): yield Leaf def valid_for_item(self, leaf): return FavoritesSource.instance.has_item(leaf) def get_description(self): return _("Remove item from favorites shelf") def get_icon_name(self): return "list-remove" kupfer-328/kupfer/plugin/fileactions.py000066400000000000000000000202311500175051100203210ustar00rootroot00000000000000__kupfer_name__ = _("File Actions") __kupfer_sources__ = () __kupfer_text_sources__ = () __kupfer_actions__ = ("MoveTo", "Rename", "CopyTo", "Edit") __description__ = _("More file actions") __version__ = "2023-02-25" __author__ = "Ulrik, KB" import os import typing as ty # since "path" is a very generic name, you often forget.. from os import path as os_path from pathlib import Path from gi.repository import Gio, GLib from kupfer import launch from kupfer.core import settings from kupfer.obj import Action, FileLeaf, OperationError, TextLeaf, TextSource from kupfer.support import pretty, task if ty.TYPE_CHECKING: from gettext import gettext as _ def _good_destination(dpath, spath): """If directory path @dpath is a valid destination for file @spath to be copied or moved to. """ if not os_path.isdir(dpath): return False spath = os_path.normpath(spath) dpath = os_path.normpath(dpath) if not os.access(dpath, os.R_OK | os.W_OK | os.X_OK): return False cpfx = os_path.commonprefix((spath, dpath)) return not (os_path.samefile(dpath, spath) or cpfx == spath) class MoveTo(Action, pretty.OutputMixin): def __init__(self): Action.__init__(self, _("Move To...")) def has_result(self): return True def activate(self, leaf, iobj=None, ctx=None): assert iobj sfile = leaf.get_gfile() bname = sfile.get_basename() dfile = iobj.get_gfile().get_child(bname) try: ret = sfile.move( dfile, Gio.FileCopyFlags.ALL_METADATA, None, None, None ) self.output_debug(f"Move {sfile} to {dfile} (ret: {ret})") except GLib.Error as exc: raise OperationError(str(exc)) from exc return FileLeaf(dfile.get_path()) def valid_for_item(self, leaf): return os.access(leaf.object, os.R_OK | os.W_OK) def requires_object(self): return True def item_types(self): yield FileLeaf def object_types(self): yield FileLeaf def valid_object(self, obj, for_item): return _good_destination(obj.object, for_item.object) def get_description(self): return _("Move file to new location") def get_icon_name(self): return "go-next" class RenameSource(TextSource): """A source for new names for a file; here we "autopropose" the source file's extension, but allow overriding it as well as renaming to without extension (either using a terminating space, or selecting the normal TextSource-returned string). """ def __init__(self, sourcefile): self.sourcefile = sourcefile name = _("Rename To...").rstrip(".") TextSource.__init__(self, name) def get_rank(self): # this should rank high return 100 def get_items(self, text): if not text: return basename = os_path.basename(self.sourcefile.object) _root, ext = os_path.splitext(basename) t_root, t_ext = os_path.splitext(text) if text.endswith(" "): yield TextLeaf(text.rstrip()) else: yield TextLeaf(text) if t_ext else TextLeaf(t_root + ext) def get_gicon(self): return self.sourcefile.get_gicon() class Rename(Action, pretty.OutputMixin): def __init__(self): Action.__init__(self, _("Rename To...")) def has_result(self): return True def activate(self, leaf, iobj=None, ctx=None): assert iobj sfile = leaf.get_gfile() dest = os_path.join(os_path.dirname(leaf.object), iobj.object) dfile = Gio.File.new_for_path(dest) try: ret = sfile.move( dfile, Gio.FileCopyFlags.ALL_METADATA, None, None, None ) self.output_debug(f"Move {sfile} to {dfile} (ret: {ret})") except GLib.Error as exc: raise OperationError(str(exc)) from exc return FileLeaf(dfile.get_path()) def activate_multiple(self, objs, iobjs): raise NotImplementedError def item_types(self): yield FileLeaf def valid_for_item(self, leaf): return os.access(leaf.object, os.R_OK | os.W_OK) def requires_object(self): return True def object_types(self): yield TextLeaf def valid_object(self, obj, for_item): dest_dir = Path(for_item.object).parent return dest_dir.is_dir() and not dest_dir.joinpath(obj.object).exists() def object_source(self, for_item=None): assert for_item return RenameSource(for_item) def get_description(self): return None class CopyTo(Action, pretty.OutputMixin): def __init__(self): Action.__init__(self, _("Copy To...")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert iobj assert ctx sfile = leaf.get_gfile() dfile = iobj.get_gfile().get_child(os_path.basename(leaf.object)) return CopyTask(str(leaf), sfile, dfile, ctx) def is_async(self): return True def item_types(self): yield FileLeaf def valid_for_item(self, leaf): return (not leaf.is_dir()) and os.access(leaf.object, os.R_OK) def requires_object(self): return True def object_types(self): yield FileLeaf def valid_object(self, obj, for_item): return _good_destination(obj.object, for_item.object) def get_description(self): return _("Copy file to a chosen location") class CopyTask(task.ThreadTask, pretty.OutputMixin): def __init__(self, name, gsource, gdest, ctx): super().__init__(name) self.gsource = gsource self.gdest = gdest self.ctx = ctx def thread_do(self): try: # FIXME: This should be async self.output_debug(f"Copy {self.gsource} to {self.gdest}") ret = self.gsource.copy( self.gdest, Gio.FileCopyFlags.ALL_METADATA, None, None, None ) self.output_debug(f"Copy ret {ret!r}") except GLib.Error as exc: # pylint: disable=no-member raise OperationError(exc.message) from exc def thread_finish(self): self.ctx.register_late_result(FileLeaf(self.gdest.get_path())) def thread_finally(self, exc_info): if exc_info is not None: self.ctx.register_late_error(exc_info) class Edit(Action): action_accelerator = "e" def __init__(self): super().__init__(_("Edit file content")) def activate(self, leaf, iobj=None, ctx=None): sett = settings.get_settings_controller() editor = sett.get_preferred_alternative("editor") if not editor: return argv: list[str] = editor["argv"] new_argv = list(_replace_argv_filename(argv, (leaf,))) if new_argv == argv: new_argv.append(leaf.object) if editor["terminal"]: launch.spawn_in_terminal(new_argv) else: launch.spawn_async(new_argv) def activate_multiple(self, objects): sett = settings.get_settings_controller() editor = sett.get_preferred_alternative("editor") if not editor: return argv: list[str] = editor["argv"] if "%f" in argv or len(objects) == 1: # editor not support probably multiple files at once for obj in objects: self.activate(obj) return new_argv = list(_replace_argv_filename(argv, objects)) if new_argv == argv: new_argv.extend(obj.object for obj in objects) if editor["terminal"]: launch.spawn_in_terminal(new_argv) else: launch.spawn_async(new_argv) def item_types(self): yield FileLeaf def valid_for_item(self, leaf): return not leaf.is_dir() def get_icon_name(self): return "edit" def get_description(self): return _("Open file in configured editor") def _replace_argv_filename( argv: list[str], leaves: ty.Iterable[FileLeaf] ) -> ty.Iterable[str]: for part in argv: if part in ("%F", "%f"): yield from (leaf.object for leaf in leaves) else: yield part kupfer-328/kupfer/plugin/firefox.py000066400000000000000000000041131500175051100174640ustar00rootroot00000000000000__kupfer_name__ = _("Firefox Bookmarks") __kupfer_sources__ = ("BookmarksSource",) __kupfer_actions__ = () __description__ = _( "Index of Firefox bookmarks. Bookmark is always opened in default browser." ) __version__ = "2023.1" __author__ = "Ulrik, William Friesen, Karol Będkowski" import typing as ty from kupfer import plugin_support from kupfer.obj import Source, UrlLeaf from kupfer.obj.apps import AppLeafContentMixin from kupfer.obj.helplib import FilesystemWatchMixin from kupfer.plugin._firefox_support import ( get_bookmarks, get_firefox_home_file, ) if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_settings__ = plugin_support.PluginSettings( { "key": "profile", "label": _("Firefox profile name or path"), "type": str, "value": "", "helper": "choose_directory", }, ) class BookmarksSource(AppLeafContentMixin, Source, FilesystemWatchMixin): appleaf_content_id = ("firefox", "firefox-esr") source_scan_interval: int = 3600 def __init__(self): self.monitor_token = None super().__init__(_("Firefox Bookmarks")) self._version = 3 def initialize(self): if ff_home := get_firefox_home_file(""): self.monitor_token = self.monitor_directories(str(ff_home)) def monitor_include_file(self, gfile): return gfile and gfile.get_basename() == "lock" def mark_for_update(self, postpone=False): super().mark_for_update(postpone=True) def _get_ffx3_bookmarks(self): """Query the firefox places bookmark database""" fpath = get_firefox_home_file( "places.sqlite", __kupfer_settings__["profile"] ) return get_bookmarks(fpath) def get_items(self): return self._get_ffx3_bookmarks() def get_description(self): return _("Index of Firefox bookmarks") def get_gicon(self): if lrepr := self.get_leaf_repr(): return lrepr.get_gicon() return None def get_icon_name(self): return "web-browser" def provides(self): yield UrlLeaf kupfer-328/kupfer/plugin/firefox_keywords.py000066400000000000000000000165701500175051100214250ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("Firefox Keywords") __kupfer_sources__ = ("KeywordsSource",) __kupfer_text_sources__ = ("KeywordSearchSource",) __kupfer_actions__ = ("SearchWithEngine",) __description__ = _("Search the web with Firefox keywords") __version__ = "2020.1" __author__ = "" import typing as ty from urllib.parse import quote, urlparse from kupfer import launch, plugin_support from kupfer.obj import ( Action, Leaf, OpenUrl, RunnableLeaf, Source, TextLeaf, TextSource, ) from kupfer.obj.apps import AppLeafContentMixin from kupfer.obj.helplib import FilesystemWatchMixin from kupfer.plugin._firefox_support import ( get_firefox_home_file, query_database, ) if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_settings__ = plugin_support.PluginSettings( { "key": "default", "label": _("Default for ?"), "type": str, "value": "https://www.google.com/search?ie=UTF-8&q=%s", }, { "key": "profile", "label": _("Firefox profile name or path"), "type": str, "value": "", "helper": "choose_directory", }, ) def _url_domain(text: str) -> str: components = list(urlparse(text)) return "".join(components[1:2]) class Keyword(Leaf): def __init__(self, title: str, kw: str, url: str) -> None: title = title or _url_domain(url) name = f"{kw} ({title})" super().__init__(url, name) self.keyword = kw self.is_search = "%s" in url def get_actions(self): if self.is_search: yield SearchFor() else: yield OpenUrl() def get_description(self): return self.object def get_icon_name(self): return "text-html" def get_text_representation(self): return self.object _KEYWORDS_SQL = """ SELECT distinct moz_places.url, moz_places.title, moz_keywords.keyword FROM moz_places, moz_keywords WHERE moz_places.id = moz_keywords.place_id """ class KeywordsSource(AppLeafContentMixin, Source, FilesystemWatchMixin): appleaf_content_id = ("firefox", "firefox-esr") source_scan_interval: int = 3600 instance: KeywordsSource | None = None def __init__(self): self.monitor_token = None super().__init__(_("Firefox Keywords")) def initialize(self): KeywordsSource.instance = self profile = __kupfer_settings__["profile"] if ff_home := get_firefox_home_file("", profile): self.monitor_token = self.monitor_directories(str(ff_home)) def finalize(self): KeywordsSource.instance = None def monitor_include_file(self, gfile): return gfile and gfile.get_basename() == "lock" def mark_for_update(self, postpone=False): super().mark_for_update(postpone=True) def get_items(self): """Query the firefox places bookmark database""" fpath = get_firefox_home_file( "places.sqlite", __kupfer_settings__["profile"] ) if not fpath: return [] return [ Keyword(title or url, kw, url) for url, title, kw in query_database(str(fpath), _KEYWORDS_SQL) ] def get_description(self): return None def get_icon_name(self): return "web-browser" def provides(self): yield Keyword class SearchWithEngine(Action): """TextLeaf -> SearchWithEngine -> Keyword""" action_accelerator = "s" def __init__(self): Action.__init__(self, _("Search With...")) def activate(self, leaf, iobj=None, ctx=None): assert iobj url = iobj.object _do_search_engine(leaf.object, url) def item_types(self): yield TextLeaf def requires_object(self): return True def object_types(self): yield Keyword def valid_object(self, obj, for_item): return obj.is_search def object_source(self, for_item=None): return KeywordsSource() def get_description(self): return _("Search the web with Firefox keywords") def get_icon_name(self): return "edit-find" class SearchFor(Action): """Keyword -> SearchFor -> TextLeaf This is the opposite action to SearchWithEngine """ action_accelerator = "s" def __init__(self): Action.__init__(self, _("Search For...")) def activate(self, leaf, iobj=None, ctx=None): assert iobj url = leaf.object terms = iobj.object _do_search_engine(terms, url) def item_types(self): yield Keyword def requires_object(self): return True def object_types(self): yield TextLeaf def object_source(self, for_item=None): return TextSource(placeholder=_("Search Terms")) def valid_object(self, obj, for_item): # NOTE: Using exact class to skip subclasses return type(obj) == TextLeaf # pylint: disable=unidiomatic-typecheck # noqa: E721 def get_description(self): return _("Search the web with Firefox keywords") def get_icon_name(self): return "edit-find" class KeywordSearchSource(TextSource): """This source allow search using firefox keywords. To use - i.e. define bookmarks for "https://hn.algolia.com/?q=%s" with keyword "hn" and then you can search by '?hn something to search' """ def __init__(self): super().__init__(_("Firefox Keywords (?-source)")) def get_text_items(self, text): if not text.startswith("?"): return parts = text[1:].split(maxsplit=1) if len(parts) < 1: return query = parts[1] if len(parts) > 1 else "" assert KeywordsSource.instance for keyword in KeywordsSource.instance.get_leaves(): assert isinstance(keyword, Keyword) if keyword.is_search and keyword.keyword == parts[0]: yield SearchWithKeyword(keyword, query) return if default := __kupfer_settings__["default"].strip(): if "%s" not in default: default += "%s" yield SearchWithKeyword(Keyword("", "", default), text[1:]) def get_description(self): return None def get_icon_name(self): return "web-browser" def provides(self): yield SearchWithKeyword def get_rank(self): return 80 class SearchWithKeyword(RunnableLeaf): object: tuple[Keyword, str] def __init__(self, keyword: Keyword, text: str): super().__init__((keyword, text), _('Search for "%s"') % (text,)) def run(self, ctx=None): kwl = self.keyword_leaf _do_search_engine(self.query, kwl.object) @property def keyword_leaf(self) -> Keyword: return self.object[0] @property def query(self) -> str: return self.object[1] def get_icon_name(self): return "web-browser" def get_description(self): return _("Search using %s") % self.keyword_leaf def get_text_representation(self): kwl = self.keyword_leaf return _query_url(self.query, kwl.object) def _do_search_engine( terms: str, search_url: str, encoding: str = "UTF-8" ) -> None: """Show an url searching for @search_url with @terms""" launch.show_url(_query_url(terms, search_url)) def _query_url(terms: str, search_url: str) -> str: """Show an url searching for @search_url with @terms""" return search_url.replace("%s", quote(terms)) kupfer-328/kupfer/plugin/firefox_tags.py000066400000000000000000000070211500175051100205030ustar00rootroot00000000000000__kupfer_name__ = _("Firefox Tags") __kupfer_sources__ = ("TagsSource",) __description__ = _("Browse Firefox bookmarks by tags") __version__ = "2021-09-05" __author__ = "Karol Będkowski" import itertools import typing as ty from kupfer import plugin_support from kupfer.obj import Leaf, Source, UrlLeaf from kupfer.obj.apps import AppLeafContentMixin from kupfer.obj.helplib import FilesystemWatchMixin from kupfer.plugin._firefox_support import ( get_firefox_home_file, query_database, ) if ty.TYPE_CHECKING: from gettext import gettext as _ MAX_ITEMS = 10000 __kupfer_settings__ = plugin_support.PluginSettings( { "key": "profile", "label": _("Firefox profile name or path"), "type": str, "value": "", "helper": "choose_directory", }, ) class FirefoxTag(Leaf): def get_icon_name(self): return "text-html" def has_content(self): return True def content_source(self, alternate=False): return TagBookmarksSource(self.object, self.name) _TAGS_SQL = """ SELECT id, title FROM moz_bookmarks mb WHERE mb.parent = 4 AND mb.fk IS NULL """ class TagsSource(AppLeafContentMixin, Source, FilesystemWatchMixin): appleaf_content_id = ("firefox", "firefox-esr") source_scan_interval: int = 3600 def __init__(self): super().__init__(_("Firefox Tags")) self.monitor_token = None def initialize(self): profile = __kupfer_settings__["profile"] if ff_home := get_firefox_home_file("", profile): self.monitor_token = self.monitor_directories(str(ff_home)) def monitor_include_file(self, gfile): return gfile and gfile.get_basename() == "lock" def mark_for_update(self, postpone=False): super().mark_for_update(postpone=True) def get_items(self): """Get tags from firefox places database""" fpath = get_firefox_home_file( "places.sqlite", __kupfer_settings__["profile"] ) if not fpath: return [] return list( itertools.starmap( FirefoxTag, query_database(str(fpath), _TAGS_SQL) ) ) def get_description(self): return _("Index of Firefox bookmarks by tags") def get_gicon(self): if lrepr := self.get_leaf_repr(): return lrepr.get_gicon() return None def get_icon_name(self): return "web-browser" def provides(self): yield FirefoxTag _TAG_BOOKMARKS_SQL = """ SELECT mp.url, mp.title FROM moz_places mp JOIN moz_bookmarks mb ON mp.id = mb.fk WHERE mb.keyword_id IS NULL AND mb.parent = ? ORDER BY visit_count DESC LIMIT ?""" class TagBookmarksSource(Source): def __init__(self, tag_id: int, tag: str): super().__init__(_("Firefox Bookmarks by tag")) self.tag = tag self.tag_id = tag_id def get_items(self): """Query the firefox places database for bookmarks with tag""" fpath = get_firefox_home_file( "places.sqlite", __kupfer_settings__["profile"] ) if not fpath: return [] return list( itertools.starmap( UrlLeaf, query_database( str(fpath), _TAG_BOOKMARKS_SQL, (self.tag_id, MAX_ITEMS) ), ) ) def get_gicon(self): if lrepr := self.get_leaf_repr(): return lrepr.get_gicon() return None def get_icon_name(self): return "web-browser" def provides(self): yield UrlLeaf kupfer-328/kupfer/plugin/glob.py000066400000000000000000000044111500175051100167460ustar00rootroot00000000000000# TRANS: "Glob" is the matching files like a shell with "*.py" etc. __kupfer_name__ = _("Glob") __kupfer_actions__ = ("Glob",) __description__ = _("Select objects using '*' and '?' as wildcards.") __version__ = "" __author__ = "" import fnmatch import re import typing as ty from kupfer.obj import Action, Leaf, OperationError, TextLeaf, TextSource from kupfer.obj.compose import MultipleLeaf if ty.TYPE_CHECKING: from gettext import gettext as _ class Glob(Action): def __init__(self): Action.__init__(self, _("Glob")) def activate(self, leaf, iobj=None, ctx=None): assert iobj return self.activate_multiple((leaf,), (iobj,)) def activate_multiple(self, objects, iobjects): ## Do case-insensitive matching ## As a special case, understand '**/' prefix as recursive def get_subcatalog_matches(subcatalog, pat, recursive, paths): if len(paths) > 1000: # noqa:PLR2004 raise OperationError("Globbing way too many objects") for content in subcatalog.content_source().get_leaves(): if recursive and content.has_content(): get_subcatalog_matches(content, pat, recursive, paths) elif re.match(pat, str(content), flags=re.IGNORECASE): paths.append(content) paths: list[str] = [] for iobj in iobjects: glob = iobj.object if glob.startswith("**/"): glob = glob[3:] recursive = True else: recursive = False pat = fnmatch.translate(glob) for obj in objects: get_subcatalog_matches(obj, pat, recursive, paths) if paths: return MultipleLeaf(paths) return None def has_result(self): return True def item_types(self): yield Leaf def valid_for_item(self, leaf): return leaf.has_content() def requires_object(self): return True def object_types(self): yield TextLeaf def object_source(self, for_item=None): return TextSource() def valid_object(self, iobj, for_item): return ("*" in iobj.object) or ("?" in iobj.object) def get_description(self): return __description__ kupfer-328/kupfer/plugin/gtg.py000066400000000000000000000175641500175051100166210ustar00rootroot00000000000000""" Changes: 2012-06-21 Karol Będkowski: * support new dbus api introduced in GTG 0.2.9 """ __kupfer_name__ = _("Getting Things GNOME") __kupfer_sources__ = ("TasksSource",) __kupfer_actions__ = ("CreateNewTask", "CreateNewEmptyTask") __description__ = _("Browse and create new tasks in GTG") __version__ = "2017.2" __author__ = "Karol Będkowski , US" import typing as ty import dbus from kupfer import plugin_support from kupfer.obj import ( Action, AppLeaf, Leaf, NotAvailableError, Source, TextLeaf, ) from kupfer.obj.apps import AppLeafContentMixin from kupfer.support import pretty, textutils, weaklib if ty.TYPE_CHECKING: from gettext import gettext as _ plugin_support.check_dbus_connection() _GTG_ID = "gtg" _SERVICE_NAME2 = "org.gnome.GTG" _OBJECT_NAME2 = "/org/gnome/GTG" _IFACE_NAME2 = "org.gnome.GTG" _STATUS_RANK = { s: i for i, s in enumerate(("Active", "Postponed", "Dismiss", "Done")) } _STATUS_RANK_DEFAULT = len(_STATUS_RANK) def _create_dbus_connection_gtg(iface, obj, service, activate=False): """Create dbus connection to GTG @activate: if True, start program if not running """ interface = None sbus = dbus.SessionBus() try: proxy_obj = sbus.get_object( "org.freedesktop.DBus", "/org/freedesktop/DBus" ) dbus_iface = dbus.Interface(proxy_obj, "org.freedesktop.DBus") if (activate or dbus_iface.NameHasOwner(iface)) and ( obj := sbus.get_object(service, obj) ): interface = dbus.Interface(obj, iface) except dbus.exceptions.DBusException as err: pretty.print_debug(__name__, err) return interface def _create_dbus_connection(activate=False): interface = _create_dbus_connection_gtg( _IFACE_NAME2, _OBJECT_NAME2, _SERVICE_NAME2, activate ) if interface is None: pretty.print_error(__name__, "Cannot connect to GTG via DBus") if activate: raise NotAvailableError(_("Getting Things GNOME")) return interface def _truncate_long_text(text, maxlen=80): if len(text) > maxlen: return text[: maxlen - 1] + "…" return text def _load_tasks(interface): """Load task by dbus interface""" tasks = interface.GetTasks() if not tasks: tasks = interface.GetTasksFiltered("") for task in tasks: title = task["title"].strip() if not title: title = task["text"].strip() title = _truncate_long_text(title) otask = Task(task["id"], title, task["status"]) otask.duedate = task["duedate"] otask.startdate = task["startdate"] otask.tags = task["tags"] yield otask def _change_task_status(task_id, status): interface = _create_dbus_connection(True) task = interface.GetTask(task_id) task["status"] = status interface.ModifyTask(task_id, task) class Task(Leaf): def __init__(self, task_id, title, status): Leaf.__init__(self, task_id, title) self.status = status self.tags = None self.duedate = None self.startdate = None def get_description(self): descr = [self.status] if self.duedate: descr.append(_("due: %s") % self.duedate) if self.startdate: descr.append(_("start: %s") % self.startdate) if self.tags: descr.append(_("tags: %s") % " ".join(self.tags)) return " ".join(descr) def get_icon_name(self): return "gtg" def get_actions(self): yield OpenEditor() yield Delete() if self.status != "Done": yield MarkDone() if self.status != "Dismiss": yield Dismiss() def sort_key(self): return _STATUS_RANK.get(self.status, _STATUS_RANK_DEFAULT) class OpenEditor(Action): rank_adjust = 1 action_accelerator = "o" def __init__(self): Action.__init__(self, _("Open")) def activate(self, leaf, iobj=None, ctx=None): interface = _create_dbus_connection(True) interface.OpenTaskEditor(leaf.object) def get_icon_name(self): return "document-open" def get_description(self): return _("Open task in Getting Things GNOME!") class Delete(Action): rank_adjust = -10 def __init__(self): Action.__init__(self, _("Delete")) def activate(self, leaf, iobj=None, ctx=None): interface = _create_dbus_connection(True) interface.DeleteTask(leaf.object) def get_icon_name(self): return "edit-delete" def get_description(self): return _("Permanently remove this task") class MarkDone(Action): action_accelerator = "d" def __init__(self): Action.__init__(self, _("Mark Done")) def activate(self, leaf, iobj=None, ctx=None): _change_task_status(leaf.object, "Done") def get_icon_name(self): return "gtk-yes" def get_description(self): return _("Mark this task as done") class Dismiss(Action): action_accelerator = "i" def __init__(self): Action.__init__(self, _("Dismiss")) def activate(self, leaf, iobj=None, ctx=None): _change_task_status(leaf.object, "Dismiss") def get_icon_name(self): return "gtk-cancel" def get_description(self): return _("Mark this task as not to be done anymore") class CreateNewTask(Action): def __init__(self): Action.__init__(self, _("Create Task")) def activate(self, leaf, iobj=None, ctx=None): interface = _create_dbus_connection(True) title, body = textutils.extract_title_body(leaf.object) interface.OpenNewTask(title, body) def item_types(self): yield TextLeaf def get_icon_name(self): return "document-new" def get_description(self): return _("Create new task in Getting Things GNOME") class CreateNewEmptyTask(Action): def __init__(self): Action.__init__(self, _("Create Task")) def activate(self, leaf, iobj=None, ctx=None): interface = _create_dbus_connection(True) interface.OpenNewTask("", "") def item_types(self): yield AppLeaf def valid_for_item(self, leaf): return leaf.get_id() == _GTG_ID def get_icon_name(self): return "document-new" def get_description(self): return _("Create new task in Getting Things GNOME") class TasksSource(AppLeafContentMixin, Source): appleaf_content_id = _GTG_ID source_scan_interval: int = 3600 def __init__(self, name=None): Source.__init__(self, name or __kupfer_name__) self._tasks = [] self._version = 3 def initialize(self): bus = dbus.SessionBus() weaklib.dbus_signal_connect_weakly( bus, "TaskAdded", self._on_tasks_updated, dbus_interface=_IFACE_NAME2, ) weaklib.dbus_signal_connect_weakly( bus, "TaskModified", self._on_tasks_updated, dbus_interface=_IFACE_NAME2, ) weaklib.dbus_signal_connect_weakly( bus, "TaskDeleted", self._on_tasks_updated, dbus_interface=_IFACE_NAME2, ) weaklib.dbus_signal_connect_weakly( bus, "NameOwnerChanged", self._name_owner_changed, dbus_interface="org.freedesktop.DBus", arg0=_SERVICE_NAME2, ) def _name_owner_changed(self, name, old, new): if new and not self._tasks: self.mark_for_update() def _on_tasks_updated(self, task_id): self.mark_for_update() def get_items(self): if (interface := _create_dbus_connection()) is not None: self._tasks = list(_load_tasks(interface)) self._tasks.sort(key=Task.sort_key) return self._tasks def get_icon_name(self): return "gtg" def provides(self): yield Task kupfer-328/kupfer/plugin/higherorder.py000066400000000000000000000070211500175051100203250ustar00rootroot00000000000000__kupfer_name__ = _("Higher-order Actions") __kupfer_actions__ = ("Select", "TakeResult", "DiscardResult") __description__ = _("Tools to work with commands as objects") __version__ = "2010-01-11" __author__ = "Ulrik Sverdrup " import typing as ty from kupfer.core import commandexec from kupfer.obj import Action, Leaf, Source from kupfer.obj.compose import ComposedLeaf, MultipleLeaf from kupfer.support import pretty if ty.TYPE_CHECKING: from gettext import gettext as _ class Select(Action): rank_adjust = -15 def __init__(self): Action.__init__(self, _("Select in Kupfer")) def has_result(self): return True def activate(self, leaf, iobj=None, ctx=None): return leaf def item_types(self): yield Leaf def _exec_no_show_result(composedleaf): pretty.print_debug(__name__, "Evaluating command", composedleaf) _obj, action, _iobj = composedleaf.object ret: commandexec.ActionResult = commandexec.activate_action( # type: ignore None, *composedleaf.object ) result_type = commandexec.parse_action_result(action, ret) if result_type == commandexec.ExecResult.OBJECT: return ret if result_type == commandexec.ExecResult.SOURCE: assert isinstance(ret, Source) leaves = list(ret.get_leaves()) if not leaves: return None if len(leaves) == 1: return leaves[0] return MultipleLeaf(leaves) return None def _save_result(cleaf): # Save the result of @cleaf into a ResultObject # When the ResultObject is to be restored from serialized state, # @cleaf is executed again. # NOTE: This will have unintended consequences outside Trigger use. leaf = _exec_no_show_result(cleaf) if leaf is None: return None class ResultObject(Leaf): serializable = 1 def __init__(self, leaf, cleaf): Leaf.__init__(self, leaf.object, str(leaf)) vars(self).update(vars(leaf)) self.name = _("Result of %s (%s)") % (cleaf, self) self.__composed_leaf = cleaf self.__class__.__bases__ = (leaf.__class__, Leaf) def get_gicon(self): return None def get_icon_name(self): return Leaf.get_icon_name(self) def __reduce__(self): return (_save_result, (self.__composed_leaf,)) return ResultObject(leaf, cleaf) class TakeResult(Action): def __init__(self): Action.__init__(self, _("Run (Take Result)")) def has_result(self): return True def activate(self, leaf, iobj=None, ctx=None): return _save_result(leaf) def item_types(self): yield ComposedLeaf def valid_for_item(self, leaf): action = leaf.object[1] return ( action.has_result() or action.is_factory() ) and not action.wants_context() def get_description(self): return _("Take the command result as a proxy object") class DiscardResult(Action): """Run ComposedLeaf without showing the result""" def __init__(self): Action.__init__(self, _("Run (Discard Result)")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx commandexec.activate_action(ctx, *leaf.object) def item_types(self): yield ComposedLeaf def valid_for_item(self, leaf): action = leaf.object[1] return action.has_result() or action.is_factory() def get_description(self): return None kupfer-328/kupfer/plugin/image.py000066400000000000000000000122201500175051100171020ustar00rootroot00000000000000__kupfer_name__ = _("Image Tools") __kupfer_sources__ = () __kupfer_text_sources__ = () __kupfer_actions__ = ("Scale", "Rotate90", "Rotate270", "Autorotate") __description__ = _( "Image transformation tools using 'convert' from ImageMagick" ) __version__ = "2017.1" __author__ = "Ulrik Sverdrup " import subprocess import typing as ty from contextlib import suppress # since "path" is a very generic name, you often forget.. from os import path as os_path from kupfer import launch, plugin_support, runtimehelper from kupfer.obj import Action, FileLeaf, OperationError, TextLeaf from kupfer.support import fileutils, pretty if ty.TYPE_CHECKING: from gettext import gettext as _ # TODO: use imagemagick -auto-orient ?? plugin_support.check_any_command_available("convert", "jpegtran", "jhead") def _spawn_operation_err(argv): try: launch.spawn_async_raise(argv) except launch.SpawnError as exc: raise OperationError(exc.args[0].message) from exc class Scale(Action): def __init__(self): Action.__init__(self, _("Scale...")) def has_result(self): return True def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert iobj size = self._make_size(iobj.object) fpath = leaf.object dirname = os_path.dirname(fpath) head, ext = os_path.splitext(os_path.basename(fpath)) filename = f"{head}_{size}{ext}" dpath = fileutils.get_destpath_in_directory(dirname, filename) argv = ["convert", "-scale", str(size), fpath, dpath] runtimehelper.register_async_file_result(ctx, dpath) _spawn_operation_err(argv) return FileLeaf(dpath) def item_types(self): yield FileLeaf def valid_for_item(self, leaf): return leaf.is_content_type("image/*") def requires_object(self): return True def object_types(self): yield TextLeaf @classmethod def _make_size(cls, text): size = None # Allow leading = text = text.strip("= ") try: size = str(float(text.strip())) except ValueError: with suppress(ValueError): twoparts = text.split("x", 1) xval = float(twoparts[0].strip()) yval = float(twoparts[1].strip()) size = f"{xval:g}x{yval:g}" return size def valid_object(self, obj, for_item=None): return self._make_size(obj.object) def get_description(self): return _("Scale image to fit inside given pixel measure(s)") class RotateBase(Action): def __init__(self, name, rotation): Action.__init__(self, name) self.rotation = rotation def has_result(self): return True def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx fpath = leaf.object dirname = os_path.dirname(fpath) head, ext = os_path.splitext(os_path.basename(fpath)) filename = f"{head}_{self.rotation}{ext}" dpath = fileutils.get_destpath_in_directory(dirname, filename) argv = [ "jpegtran", "-copy", "all", "-rotate", self.rotation, "-outfile", dpath, fpath, ] runtimehelper.register_async_file_result(ctx, dpath) _spawn_operation_err(argv) return FileLeaf(dpath) def item_types(self): yield FileLeaf def valid_for_item(self, leaf): return leaf.is_content_type("image/*") class Rotate90(RotateBase): def __init__(self): RotateBase.__init__(self, _("Rotate Clockwise"), "90") def get_icon_name(self): return "object-rotate-right" class Rotate270(RotateBase): def __init__(self): RotateBase.__init__(self, _("Rotate Counter-Clockwise"), "270") def get_icon_name(self): return "object-rotate-left" class Autorotate(Action): def __init__(self): Action.__init__(self, _("Autorotate")) def has_result(self): return True def activate(self, leaf, iobj=None, ctx=None): fpath = leaf.object argv = ["jhead", "-autorot", fpath] launch.spawn_async(argv) def item_types(self): yield FileLeaf def valid_for_item(self, leaf): _root, ext = os_path.splitext(leaf.object) if ext.lower() not in (".jpeg", ".jpg"): return False # Launch jhead to see if 1) it is installed, 2) Orientation nondefault try: cmdargs = ("jhead", leaf.object) with subprocess.Popen(cmdargs, stdout=subprocess.PIPE) as proc: out, _err = proc.communicate() pretty.print_debug(__name__, "Running", cmdargs) return any( li.decode("UTF-8").startswith("Orientation") for li in out.splitlines() ) except OSError: pretty.print_debug(__name__, f"Action {self} needs 'jhead'") return False def get_description(self): return _("Rotate JPEG (in-place) according to its EXIF metadata") kupfer-328/kupfer/plugin/instapaper.py000066400000000000000000000013751500175051100201770ustar00rootroot00000000000000__kupfer_name__ = _("Instapaper") __kupfer_sources__ = () __kupfer_actions__ = ("SaveToInstapaper",) __description__ = _("Save url to Instapaper") __version__ = "2020-11-15" __author__ = "Peter Stuifzand " import typing as ty from kupfer import launch from kupfer.obj import Action, TextLeaf, UrlLeaf if ty.TYPE_CHECKING: from gettext import gettext as _ class SaveToInstapaper(Action): def __init__(self): Action.__init__(self, _("Save to Instapaper")) def activate(self, leaf, iobj=None, ctx=None): launch.show_url(f"https://www.instapaper.com/edit?url={leaf.object}") def item_types(self): yield UrlLeaf yield TextLeaf def get_description(self): return _("Save url to Instapaper") kupfer-328/kupfer/plugin/kupfer_actions.py000066400000000000000000000026401500175051100210410ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("Kupfer Actions") __kupfer_sources__ = ("KupferActions",) __description__ = _( "'Inverse' action executions - look for action and then select object to " "execute on." ) __version__ = "2023-12-17" __author__ = "KB" import typing as ty from kupfer import icons from kupfer.core import settings, sources from kupfer.obj import Source from kupfer.obj.objects import ActionLeaf if ty.TYPE_CHECKING: from gettext import gettext as _ class KupferActions(Source): """Get all global actions that don't require additional object.""" def __init__(self): Source.__init__(self, _("Kupfer Actions")) def _on_plugin_enabled( self, _setctl: ty.Any, _plugin_id: str, _enabled: bool | int ) -> None: self.mark_for_update() def initialize(self): setctl = settings.get_settings_controller() setctl.connect("plugin-enabled-changed", self._on_plugin_enabled) def get_items(self): # we can skip action_generators sctl = sources.get_source_controller() for actions in sctl.action_decorators.values(): for action in actions: # skip actions that require extra object if action.requires_object(): continue yield ActionLeaf(action) def get_gicon(self): return icons.ComposedIcon("kupfer", "kupfer-execute") kupfer-328/kupfer/plugin/kupfer_plugins.py000066400000000000000000000101451500175051100210610ustar00rootroot00000000000000__kupfer_name__ = _("Kupfer Plugins") __kupfer_sources__ = ("KupferPlugins",) __description__ = _("Access Kupfer's plugin list in Kupfer") __version__ = "" __author__ = "Ulrik Sverdrup " import importlib.util import os import typing as ty from pathlib import Path # Since this is a core plugin we break some rules # These modules are normally out of bounds for plugins from kupfer.core import plugins, settings from kupfer.obj import Action, FileLeaf, Leaf, Source, TextLeaf from kupfer.ui import preferences if ty.TYPE_CHECKING: from gettext import gettext as _ class ShowInfo(Action): def __init__(self): Action.__init__(self, _("Show Information")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx plugin_id = leaf.object["name"] preferences.show_plugin_info(plugin_id, ctx.environment) def get_description(self): pass def get_icon_name(self): return "dialog-information" class ShowSource(Action): def __init__(self): Action.__init__(self, _("Show Source Code")) def has_result(self): return True def activate(self, leaf, iobj=None, ctx=None): # Try to find the __file__ attribute for the plugin # It will fail for files inside zip packages, but that is # uncommon for now. # Additionally, it will fail for fake plugins plugin_id = leaf.object["name"] filename: str = plugins.get_plugin_attribute( # type:ignore plugin_id, plugins.PluginAttr.FILE ) if not filename: return leaf root, ext = os.path.splitext(filename) if ext.lower() == ".pyc" and Path(root + ".py").exists(): return FileLeaf(root + ".py") if not Path(filename).exists(): # handle modules in zip or eggs pfull = "kupfer.plugin." + plugin_id try: spec = importlib.util.find_spec(pfull) except (ImportError, AttributeError, TypeError, ValueError): pass else: loader = spec.loader if spec is not None else None if loader: return TextLeaf(loader.get_source(pfull)) # type:ignore return FileLeaf(filename) def get_description(self): pass def get_icon_name(self): return "dialog-information" class Plugin(Leaf): # NOTE: Just to be sure that a plugin ranks lower than a # like-named other object by default. rank_adjust = -1 def __init__(self, obj, name): Leaf.__init__(self, obj, name) def get_actions(self): yield ShowInfo() yield ShowSource() def get_description(self): setctl = settings.get_settings_controller() enabled = setctl.get_plugin_enabled(self.object["name"]) enabled_str = _("enabled") if enabled else _("disabled") return f"{self.object['description']} ({enabled_str})" def get_icon_name(self): return "package-x-generic" class KupferPlugins(Source): def __init__(self): Source.__init__(self, _("Kupfer Plugins")) def get_items(self): setctl = settings.get_settings_controller() for info in plugins.get_plugin_info(): plugin_id = info["name"] if setctl.get_plugin_is_hidden(plugin_id): continue yield Plugin(info, info["localized_name"]) def should_sort_lexically(self): return True def provides(self): yield Plugin def get_icon_name(self): return "package-x-generic" @classmethod def decorates_type(cls): return Plugin @classmethod def decorate_item(cls, obj): if cls.is_self_plugin(obj): return cls() return None @classmethod def is_self_plugin(cls, obj): self_plug_id = __name__.rsplit(".", maxsplit=1)[-1] return obj.object["name"] == self_plug_id def get_leaf_repr(self): for obj in self.get_leaves() or []: if self.is_self_plugin(obj): return obj return None kupfer-328/kupfer/plugin/librewolf.py000066400000000000000000000041261500175051100200130ustar00rootroot00000000000000__kupfer_name__ = _("Librewolf Bookmarks") __kupfer_sources__ = ("BookmarksSource",) __kupfer_actions__ = () __description__ = _( "Index of Librewolf bookmarks. " "Bookmark is always opened in default browser." ) __version__ = "2023.1" __author__ = "Ulrik, William Friesen, Karol Będkowski" import typing as ty from kupfer import plugin_support from kupfer.obj import Source, UrlLeaf from kupfer.obj.apps import AppLeafContentMixin from kupfer.obj.helplib import FilesystemWatchMixin from kupfer.plugin._firefox_support import ( get_bookmarks, get_librewolf_home_file, ) if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_settings__ = plugin_support.PluginSettings( { "key": "profile", "label": _("Librewolf profile name or path"), "type": str, "value": "", "helper": "choose_directory", }, ) class BookmarksSource(AppLeafContentMixin, Source, FilesystemWatchMixin): appleaf_content_id = "librewolf" source_scan_interval: int = 3600 def __init__(self): self.monitor_token = None super().__init__(_("Librewolf Bookmarks")) self._version = 3 def initialize(self): if ff_home := get_librewolf_home_file(""): self.monitor_token = self.monitor_directories(str(ff_home)) def monitor_include_file(self, gfile): return gfile and gfile.get_basename() == "lock" def mark_for_update(self, postpone=False): super().mark_for_update(postpone=True) def _get_ffx3_bookmarks(self): """Query the librewolf places bookmark database""" fpath = get_librewolf_home_file( "places.sqlite", __kupfer_settings__["profile"] ) return get_bookmarks(fpath) def get_items(self): return self._get_ffx3_bookmarks() def get_description(self): return _("Index of Librewolf bookmarks") def get_gicon(self): if lrepr := self.get_leaf_repr(): return lrepr.get_gicon() return None def get_icon_name(self): return "web-browser" def provides(self): yield UrlLeaf kupfer-328/kupfer/plugin/libvirt.py000066400000000000000000000161731500175051100175060ustar00rootroot00000000000000# Copyright © 2022 Karol Będkowski # # Distributed under terms of the GPLv3 license. """ Plugin allow control domains (virtual machines) managed by libvirt. """ from __future__ import annotations __kupfer_name__ = _("Libvirt") __kupfer_sources__ = ("LibvirtDomainsSource",) __description__ = _("Control libvirt guest domains.") __version__ = "0.1" __author__ = "Karol Będkowski " import threading import typing as ty import libvirt from kupfer import icons, launch, plugin_support from kupfer.obj import Action, Leaf, Source from kupfer.obj.apps import AppLeafContentMixin from kupfer.support import pretty if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_settings__ = plugin_support.PluginSettings( { "key": "connection", "label": _("Connection"), "type": str, "value": "qemu:///system", }, ) class Domain(Leaf): def __init__(self, obj, name, description): Leaf.__init__(self, obj, name) self.description = description def get_description(self): return self.description def get_actions(self): conn = _ConnManager.instance().get_conn() if not conn: return domain = conn.lookupByName(self.object) state, _reason = domain.state() # https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainState if state == libvirt.VIR_DOMAIN_RUNNING: yield DomAction(_("Pause"), "pause", "pause") yield DomAction(_("Reboot"), "system-reboot", "reboot", -5) yield DomAction( _("Send Power Off Signal"), "system-shutdown", "poweroff-signal", -10, ) yield DomAction(_("Power Off"), "system-shutdown", "poweroff", -15) elif state in ( libvirt.VIR_DOMAIN_PAUSED, libvirt.VIR_DOMAIN_PMSUSPENDED, ): yield DomAction(_("Resume"), "system-run", "resume") elif state in ( libvirt.VIR_DOMAIN_BLOCKED, libvirt.VIR_DOMAIN_SHUTDOWN, ): pass else: # libvirt.VIR_DOMAIN_SHUTOFF: yield DomAction(_("Power On"), "system-run", "start") yield OpenConsoleAction() def get_gicon(self): return icons.ComposedIconSmall("computer", "virt-manager") class DomAction(Action): def __init__(self, name, icon, command, rank_adjust=0): Action.__init__(self, name) self._icon = icon self.rank_adjust = rank_adjust self.command = command def get_icon_name(self): return self._icon def item_types(self): yield Domain def activate(self, leaf, iobj=None, ctx=None): with libvirt.open(__kupfer_settings__["connection"] or None) as conn: domain = conn.lookupByName(leaf.object) if self.command == "poweroff": domain.shutdown() elif self.command == "pause": domain.suspend() elif self.command == "reboot": domain.reboot(libvirt.VIR_DOMAIN_REBOOT_DEFAULT) elif self.command == "resume": domain.resume() elif self.command == "start": domain.create() elif self.command == "poweroff-signal": domain.shutdownFlags(libvirt.VIR_DOMAIN_SHUTDOWN_DEFAULT) def _get_domain_metadata(domain, key): try: return domain.metadata(key, None) except libvirt.libvirtError: pass return None class _ConnManager(pretty.OutputMixin): """Libvirt connection manager. Only for read-only connections.""" _instance: _ConnManager | None = None @classmethod def instance(cls) -> _ConnManager: if not cls._instance: cls._instance = _ConnManager() return cls._instance def __init__(self): self.conn: libvirt.virConnect | None = None self._start_event_loop() __kupfer_settings__.connect( "plugin-setting-changed", self._on_setting_changed ) def _event_loop(self) -> None: while True: libvirt.virEventRunDefaultImpl() def _start_event_loop(self) -> None: libvirt.virEventRegisterDefaultImpl() thr = threading.Thread( target=self._event_loop, name="libvirtEventLoop", daemon=True ) thr.start() def _open(self) -> None: connstr = __kupfer_settings__["connection"] or None self.output_debug("LibVirt Connection open", connstr) self.conn = libvirt.openReadOnly(connstr) if self.conn: self.conn.setKeepAlive(5, 3) def close(self): if self.conn: self.conn.close() self.conn = None def _on_setting_changed(self, settings, key, value): if self.conn: self.conn.close() self._open() def get_conn(self) -> libvirt.virConnect | None: if self.conn is None: self._open() return self.conn class LibvirtDomainsSource(AppLeafContentMixin, Source): source_use_cache = False appleaf_content_id = "virt-manager" def __init__(self, name=_("Libvirt domains")): Source.__init__(self, name) self.cmgr: _ConnManager | None = None def initialize(self): # prevent logging errors from libvirt libvirt.registerErrorHandler(lambda _userdata, _err: None, ctx=None) self.cmgr = _ConnManager.instance() if conn := self.cmgr.get_conn(): conn.domainEventRegister(self._callback, None) def finalize(self): if self.cmgr: self.cmgr.close() self.cmgr = None def _callback(self, _conn, dom, event, detail, _opaque): pretty.print_debug( "LibvirtDomainsSource event", dom.name(), dom.ID(), event, detail ) self.mark_for_update() def get_items(self): assert self.cmgr conn = self.cmgr.get_conn() if not conn: return for dom in conn.listAllDomains(): name = dom.name() title = _get_domain_metadata( dom, libvirt.VIR_DOMAIN_METADATA_TITLE ) descr = _get_domain_metadata( dom, libvirt.VIR_DOMAIN_METADATA_DESCRIPTION ) yield Domain(name, title or name, descr) def get_description(self): return None def provides(self): yield Domain def should_sort_lexically(self): return True class OpenConsoleAction(Action): def __init__(self): Action.__init__(self, name=_("Open console")) def get_icon_name(self): return "virt-manager" def item_types(self): yield Domain def activate(self, leaf, iobj=None, ctx=None): conn = __kupfer_settings__["connection"] or "qemu:///system" domain = leaf.object launch.spawn_async( [ "virt-manager", "--connect", conn, "--show-domain-console", domain, ] ) def get_description(self): return _("Open Virtual Machine Manager console for domain") kupfer-328/kupfer/plugin/locate.py000066400000000000000000000056711500175051100173030ustar00rootroot00000000000000__kupfer_name__ = _("Locate Files") __kupfer_actions__ = ("Locate",) __description__ = _("Search filesystem using locate") __version__ = "" __author__ = "Ulrik Sverdrup " import shutil import subprocess import typing as ty from kupfer import icons, plugin_support from kupfer.obj import Action, Leaf, Source, TextLeaf from kupfer.obj.filesrc import construct_file_leaf from kupfer.obj.special import CommandNotAvailableLeaf from kupfer.support import kupferstring if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_settings__ = plugin_support.PluginSettings( { "key": "ignore_case", "label": _("Ignore case distinctions when searching files"), "type": bool, "value": True, }, ) plugin_support.check_command_available("locate") class Locate(Action): rank_adjust: int = -5 def __init__(self): Action.__init__(self, _("Locate Files")) def is_factory(self): return True def activate(self, leaf, iobj=None, ctx=None): return LocateQuerySource(leaf.object) def item_types(self): yield TextLeaf def get_description(self): return _("Search filesystem using locate") def get_gicon(self): return icons.ComposedIcon("gnome-terminal", self.get_icon_name()) def get_icon_name(self): return "edit-find" class LocateQuerySource(Source): def __init__(self, query): Source.__init__(self, name=_('Results for "%s"') % query) self.query = query self.max_items = 500 def repr_key(self): return self.query def get_items(self): locate_cmd = shutil.which("locate") if not locate_cmd: yield CommandNotAvailableLeaf(__name__, __kupfer_name__, "locate") return ignore_case = ( "--ignore-case" if __kupfer_settings__["ignore_case"] else "" ) # Start two processes, one to take the first hits, one # to take the remaining up to maximum. We start both at the same time # (regrettably, locate wont output streamingly to stdout) # but we ask the second for results only after iterating the first few first_num = 12 def load(limit: int, offset: int) -> ty.Iterator[Leaf]: command = [ locate_cmd, "--null", "--limit", str(limit), ignore_case, self.query, ] with subprocess.Popen(command, stdout=subprocess.PIPE) as proc: out, ignored_err = proc.communicate() for f in out.split(b"\x00")[offset:-1]: yield construct_file_leaf(kupferstring.fromlocale(f)) yield from load(first_num, 0) yield from load(self.max_items, first_num) def get_gicon(self): return icons.ComposedIcon("gnome-terminal", self.get_icon_name()) def get_icon_name(self): return "edit-find" kupfer-328/kupfer/plugin/mediaplayers.py000066400000000000000000000105551500175051100205100ustar00rootroot00000000000000__kupfer_name__ = _("Media Player Control") __kupfer_sources__ = ("Players",) __description__ = _("Playback control for media players") __version__ = "2017.1" __author__ = "US" import typing as ty import dbus from kupfer import plugin_support from kupfer.obj import OperationError, RunnableLeaf, Source from kupfer.support import weaklib if ty.TYPE_CHECKING: from gettext import gettext as _ plugin_support.check_dbus_connection() _MPRIS_PREFIX = "org.mpris.MediaPlayer2." _MPRIS_PLAYER = "org.mpris.MediaPlayer2.Player" _MPRIS_OBJ = "/org/mpris/MediaPlayer2" class Players(Source): source_use_cache = False def __init__(self): super().__init__(_("Media Player Control")) def initialize(self): bus = dbus.SessionBus() weaklib.dbus_signal_connect_weakly( bus, "NameOwnerChanged", self._name_owner_changed, dbus_interface="org.freedesktop.DBus", ) def finalize(self): pass def _name_owner_changed(self, name, old, new): if name.startswith(_MPRIS_PREFIX): self.mark_for_update() def get_items(self): bus_names = [] for bus_name in dbus.SessionBus().list_names(): if bus_name.startswith(_MPRIS_PREFIX): name = bus_name[len(_MPRIS_PREFIX) :] yield PlayPause(bus_name, name) yield Next(bus_name, name) yield Previous(bus_name, name) yield Stop(bus_name, name) bus_names.append(bus_name) if bus_names: yield PauseAll(bus_names) def provides(self): yield RunnableLeaf def description(self): return __description__ def get_icon_name(self): return "applications-multimedia" def mpris_connection(bus_name, activate=False, operation_error=True): try: if obj := dbus.SessionBus().get_object(bus_name, _MPRIS_OBJ): return dbus.Interface(obj, _MPRIS_PLAYER) except dbus.exceptions.DBusException as err: raise OperationError(str(err)) from err return None class MprisAction(RunnableLeaf): def __init__(self, bus_name, name): super().__init__(str(bus_name), name=name) @property def bus_name(self): return self.object def repr_key(self): return self.bus_name def run(self, ctx: ty.Any = None) -> None: raise NotImplementedError class PlayPause(MprisAction): def __init__(self, bus_name, name): # TRANS: %s is a media player name super().__init__(bus_name, name=_("Play/Pause (%s)") % name) def run(self, ctx=None): mpris_connection(self.bus_name).PlayPause() def get_description(self): return _("Resume playback") def get_icon_name(self): return "media-playback-start" def _reply_nop(*args): pass class PauseAll(RunnableLeaf): def __init__(self, bus_names): super().__init__(name=_("Pause All")) self.bus_names = bus_names def run(self, ctx=None): for name in self.bus_names: mpris_connection(name).Pause( reply_handler=_reply_nop, error_handler=_reply_nop ) def get_icon_name(self): return "media-playback-pause" class Next(MprisAction): def __init__(self, bus_name, name): # TRANS: %s is a media player name super().__init__(bus_name, name=_("Next (%s)") % name) def run(self, ctx=None): mpris_connection(self.bus_name).Next() def get_description(self): return _("Skip to next track") def get_icon_name(self): return "media-skip-forward" class Previous(MprisAction): def __init__(self, bus_name, name): # TRANS: %s is a media player name super().__init__(bus_name, name=_("Previous (%s)") % name) def run(self, ctx=None): mpris_connection(self.bus_name).Previous() def get_description(self): return _("Skip to previous track") def get_icon_name(self): return "media-skip-backward" class Stop(MprisAction): def __init__(self, bus_name, name): # TRANS: %s is a media player name super().__init__(bus_name, name=_("Stop (%s)") % name) def run(self, ctx=None): mpris_connection(self.bus_name).Stop() def get_description(self): return _("Stop playback") def get_icon_name(self): return "media-playback-stop" kupfer-328/kupfer/plugin/nemo.py000066400000000000000000000123261500175051100167650ustar00rootroot00000000000000__kupfer_name__ = _("Nemo") __kupfer_sources__ = ("FmObjects",) __kupfer_actions__ = ("Reveal", "GetInfo", "CopyTo") __description__ = _("File manager actions") __version__ = "2017.1" __author__ = "" import os import typing as ty import dbus from kupfer import plugin_support from kupfer.obj import Action, FileLeaf, OperationError, RunnableLeaf, Source from kupfer.obj.apps import AppLeafContentMixin from kupfer.support import pretty if ty.TYPE_CHECKING: from gettext import gettext as _ plugin_support.check_dbus_connection() _SERVICE_NAME = "org.Nemo" _FO_OBJECT = "/org/Nemo" _FO_IFACE = "org.Nemo.FileOperations" _FM_OBJECT = "/org/freedesktop/FileManager1" _FM_IFACE = "org.freedesktop.FileManager1" def _get_fm1(): bus = dbus.SessionBus() try: proxy_obj = bus.get_object(_SERVICE_NAME, _FM_OBJECT) except dbus.DBusException as exc: raise OperationError(exc) from exc return dbus.Interface(proxy_obj, _FM_IFACE) def _get_nemo(): bus = dbus.SessionBus() try: proxy_obj = bus.get_object(_SERVICE_NAME, _FO_OBJECT) except dbus.DBusException as exc: raise OperationError(exc) from exc return dbus.Interface(proxy_obj, _FO_IFACE) def _dummy(*args): pass def make_error_handler(ctx): def error_handler(exc): ctx.register_late_error(exc) return error_handler class Reveal(Action): def __init__(self): Action.__init__(self, _("Select in File Manager")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx return self.activate_multiple((leaf,), ctx) def activate_multiple(self, leaves, ctx): uris = [leaf_uri(leaf) for leaf in leaves] id_ = ctx.environment.get_startup_notification_id() _get_fm1().ShowItems( uris, id_, reply_handler=_dummy, error_handler=make_error_handler(ctx), ) def item_types(self): yield FileLeaf class GetInfo(Action): def __init__(self): Action.__init__(self, _("Show Properties")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx return self.activate_multiple((leaf,), ctx) def activate_multiple(self, leaves, ctx): uris = [leaf_uri(leaf) for leaf in leaves] id_ = ctx.environment.get_startup_notification_id() _get_fm1().ShowItemProperties( uris, id_, reply_handler=_dummy, error_handler=make_error_handler(ctx), ) def item_types(self): yield FileLeaf def get_description(self): return _("Show information about file in file manager") def get_icon_name(self): return "dialog-information" def _good_destination(dpath, spath): """If directory path @dpath is a valid destination for file @spath to be copied or moved to. """ if not os.path.isdir(dpath): return False spath = os.path.normpath(spath) dpath = os.path.normpath(dpath) cpfx = os.path.commonprefix((spath, dpath)) return not (os.path.samefile(dpath, spath) or cpfx == spath) def leaf_uri(leaf): return leaf.get_gfile().get_uri() class CopyTo(Action, pretty.OutputMixin): def __init__(self): Action.__init__(self, _("Copy To...")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert iobj assert ctx return self.activate_multiple((leaf,), (iobj,), ctx) def activate_multiple(self, leaves, iobjects, ctx): # Unroll by looping over the destinations, # copying everything into each destination nemo = _get_nemo() source_uris = [leaf_uri(L) for L in leaves] def _reply(*args): self.output_debug("reply got for copying", *args) for dest_iobj in iobjects: desturi = leaf_uri(dest_iobj) nemo.CopyURIs( source_uris, desturi, reply_handler=_reply, error_handler=make_error_handler(ctx), ) def item_types(self): yield FileLeaf def valid_for_item(self, leaf): return True def requires_object(self): return True def object_types(self): yield FileLeaf def valid_object(self, obj, for_item): return _good_destination(obj.object, for_item.object) def get_description(self): return _("Copy file to a chosen location") class EmptyTrash(RunnableLeaf): def __init__(self): RunnableLeaf.__init__(self, None, _("Empty Trash")) def wants_context(self): return True def run(self, ctx=None): assert ctx _get_nemo().EmptyTrash( reply_handler=_dummy, error_handler=make_error_handler(ctx) ) def get_description(self): return None def get_icon_name(self): return "user-trash-full" class FmObjects(AppLeafContentMixin, Source): appleaf_content_id = "nemo" def __init__(self): Source.__init__(self, _("Nemo")) def get_items(self): yield EmptyTrash() def provides(self): yield RunnableLeaf def get_icon_name(self): return "nemo" kupfer-328/kupfer/plugin/nm.py000066400000000000000000000305541500175051100164440ustar00rootroot00000000000000""" Network Manager plugin. """ from __future__ import annotations __kupfer_name__ = _("NetworkManager") __kupfer_sources__ = ("DevicesSource",) __kupfer_actions__ = ("ToggleWireless",) __description__ = _("Manage NetworkManager connections") __version__ = "2023.01" __author__ = "Karol Będkowski " import time import typing as ty import dbus from kupfer import icons, plugin_support from kupfer.obj import Action, Leaf, NotAvailableError, Source from kupfer.support import pretty, weaklib from kupfer.ui import uiutils if ty.TYPE_CHECKING: from gettext import gettext as _ plugin_support.check_dbus_connection() _NM_SERVICE = "org.freedesktop.NetworkManager" _NM_OBJECT = "/org/freedesktop/NetworkManager" _NM_IFACE = "org.freedesktop.NetworkManager" _DEVICE_IFACE = "org.freedesktop.NetworkManager.Device" _PROPS_IFACE = "org.freedesktop.DBus.Properties" _CONNECTION_IFACE = "org.freedesktop.NetworkManager.Settings.Connection" _SETTINGS_OBJECT = "/org/freedesktop/NetworkManager/Settings" _SETTINGS_IFACE = "org.freedesktop.NetworkManager.Settings" def _create_dbus_connection(iface, obj, service, /, sbus=None): """Create dbus connection to NetworkManager""" try: sbus = sbus or dbus.SystemBus() if dobj := sbus.get_object(service, obj): return dbus.Interface(dobj, iface) except dbus.exceptions.DBusException as err: pretty.print_debug(__name__, err) raise NotAvailableError(_("NetworkManager")) def _create_dbus_connection_nm(sbus=None): return _create_dbus_connection( _NM_IFACE, _NM_OBJECT, _NM_SERVICE, sbus=sbus ) def _create_dbus_connection_device(obj, /, sbus=None): return _create_dbus_connection(_DEVICE_IFACE, obj, _NM_SERVICE, sbus=sbus) _NM_DEVICE_STATE: ty.Final[dict[int, str]] = { # TRANS: network device status 0: _("unknown"), # TRANS: network device status 10: _("unmanaged"), # TRANS: network device status 20: _("unavailable"), # TRANS: network device status 30: _("disconnected"), # TRANS: network device status 40: _("prepare"), # TRANS: network device status 50: _("config"), # TRANS: network device status 60: _("need auth"), # TRANS: network device status 70: _("ip config"), # TRANS: network device status 80: _("ip check"), # TRANS: network device status 90: _("secondaries"), # TRANS: network device status 100: _("activated"), # TRANS: network device status 110: _("deactivating"), # TRANS: network device status 120: _("failed"), } _DEVICE_ACTIVATED: ty.Final[int] = 100 _NM_DEVICE_TYPES: ty.Final[dict[int, str]] = { 0: "unknown", 1: "ethernet", 2: "wifi", 3: "unused1", 4: "unused2", 5: "bt", 6: "olpc mesh", 7: "wimax", 8: "modem", 9: "infiniband", 10: "bond", 11: "vlan", 12: "adsl", 13: "bridge", 14: "generic", 15: "team", 16: "tun", 17: "ip tunnel", 18: "macvlan", 19: "vxlan", 20: "veth", 21: "macsec", 22: "dummy", 23: "ppp", 24: "ovs interface", 25: "ovs port", 26: "ovs bridge", 27: "wpan", 28: "6lowpan", 29: "wireguard", 30: "wifi_p2p", 31: "vrf", } _DEV_TYPE_WIRELESS: ty.Final[int] = 2 _DEV_TYPE_VPN: ty.Final[int] = 29 class Device(Leaf): def __init__( self, path: str, name: str, status: int, managed: bool, devtype: int ): Leaf.__init__(self, path, name) self._status = status self.managed = managed self.devtype = devtype def get_description(self): return _("Network device %(dtype)s; state: %(state)s") % { "dtype": _NM_DEVICE_TYPES.get(self.devtype) or "unknown", "state": _NM_DEVICE_STATE.get(self._status) or str(self._status), } def get_icon_name(self): if self.devtype == _DEV_TYPE_WIRELESS: return "network-wireless" if self.devtype == _DEV_TYPE_VPN: return "network-vpn" return "network-wired" def get_actions(self): yield Disconnect() yield Connect() yield ShowInfo() def status(self) -> int: conn = _create_dbus_connection(_PROPS_IFACE, self.object, _NM_SERVICE) self._status = int(conn.Get(_DEVICE_IFACE, "State")) return self._status class Disconnect(Action): def __init__(self): Action.__init__(self, _("Disconnect")) def activate(self, leaf, iobj=None, ctx=None): bus = dbus.SystemBus() try: interface = _create_dbus_connection_device(leaf.object, sbus=bus) interface.Disconnect() time.sleep(1) except Exception: pretty.print_exc(__name__) # return leaf with updated status leaf.status() return leaf def get_icon_name(self): return "disconnect" def get_description(self): return _("Disconnect connection") def valid_for_item(self, leaf): return leaf.status() == _DEVICE_ACTIVATED def has_result(self): return True class Connect(Action): def __init__(self): # TRANS: activate connection (connect) Action.__init__(self, _("Connect...")) def activate(self, leaf, iobj=None, ctx=None): assert iobj bus = dbus.SystemBus() try: interface = _create_dbus_connection_nm(sbus=bus) interface.ActivateConnection(iobj.object, leaf.object, "/") time.sleep(1) except Exception: pretty.print_exc(__name__) leaf.status() return leaf def get_description(self): return _("Activate connection") def get_icon_name(self): return "connect" def requires_object(self): return True def object_types(self): yield Connection def object_source(self, for_item=None): return ConnectionsSource(for_item.object, for_item.name) def valid_for_item(self, leaf): return leaf.status() != _DEVICE_ACTIVATED def has_result(self): return True def _get_info_recursive(item, level=0): prefix = " " * level if isinstance(item, (dict, dbus.Dictionary)): for key, val in item.items(): yield (f"{prefix}{key}:") yield from _get_info_recursive(val, level + 1) elif isinstance(item, (tuple, list, dbus.Array)): for val in item: yield from _get_info_recursive(val) elif level > 0: # skip garbage on first level yield (f"{prefix}{item}") class ShowInfo(Action): def __init__(self): Action.__init__(self, _("Show information")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx conn_info = "" props_info = "" bus = dbus.SystemBus() try: interface = _create_dbus_connection_device(leaf.object, sbus=bus) info = interface.GetAppliedConnection(0) except Exception as err: conn_info = f"Error: {err}" else: conn_info = "\n".join(_get_info_recursive(info)) try: interface = _create_dbus_connection( _PROPS_IFACE, leaf.object, _NM_SERVICE, sbus=bus ) props = interface.GetAll(_DEVICE_IFACE) except Exception as err: props_info = f"Error: {err}" else: props_info = "\n".join(_get_info_recursive(props)) msg = f"DEVICE\n{props_info}\n------------\n\nCONNECTION\n{conn_info}" uiutils.show_text_result(msg, title=_("Connection details"), ctx=ctx) def get_description(self): return _("Show information about device") class Connection(Leaf): def __init__(self, path: str, name: str, descr: str): Leaf.__init__(self, path, name) self.descr = descr def get_description(self): return self.descr @staticmethod def from_setting(conn: str, settings: dict[str, ty.Any]) -> Connection: conn_id = str(settings["id"]) conn_type = str(settings["type"]) return Connection(conn, conn_id, conn_type) class ConnectionsSource(Source): source_use_cache = False def __init__(self, device_path, interface): super().__init__(_("Connections")) self.device = device_path self.interface = interface def get_items(self): sbus = dbus.SystemBus() dconn = _create_dbus_connection( _PROPS_IFACE, self.device, _NM_SERVICE, sbus=sbus ) if not dconn: return # get available connection for device need_check_conn = False connections = dconn.Get(_DEVICE_IFACE, "AvailableConnections") if not connections: # no connections for given device, check all dconn = _create_dbus_connection( _SETTINGS_IFACE, _SETTINGS_OBJECT, _NM_SERVICE, sbus=sbus ) if not dconn: return need_check_conn = True connections = dconn.ListConnections() for conn in connections: cset = _create_dbus_connection( _CONNECTION_IFACE, conn, _NM_SERVICE, sbus=sbus ) settings = cset.GetSettings() settings_connection = settings.get("connection") if need_check_conn: iface_name = str(settings_connection.get("interface-name")) if iface_name != self.interface: continue yield Connection.from_setting(conn, settings_connection) class DevicesSource(Source): source_scan_interval: int = 3600 def __init__(self, name=None): Source.__init__(self, name or __kupfer_name__) def initialize(self): bus = dbus.SystemBus() weaklib.dbus_signal_connect_weakly( bus, "StateChanged", self._on_nm_updated, dbus_interface=_NM_IFACE, ) weaklib.dbus_signal_connect_weakly( bus, "DeviceAdded", self._on_nm_updated, dbus_interface=_NM_IFACE, ) weaklib.dbus_signal_connect_weakly( bus, "DeviceRemoved", self._on_nm_updated, dbus_interface=_NM_IFACE, ) def _on_nm_updated(self, *args): self.mark_for_update() def get_items(self): sbus = dbus.SystemBus() if interface := _create_dbus_connection_nm(sbus=sbus): for dev in interface.GetAllDevices(): if conn := _create_dbus_connection( _PROPS_IFACE, dev, _NM_SERVICE, sbus=sbus ): yield Device( str(dev), str(conn.Get(_DEVICE_IFACE, "Interface")), int(conn.Get(_DEVICE_IFACE, "State")), bool(conn.Get(_DEVICE_IFACE, "Managed")), int(conn.Get(_DEVICE_IFACE, "DeviceType")), ) def provides(self): yield Device def get_icon_name(self): return "network-wired" class ToggleWireless(Action): def __init__(self): Action.__init__(self, "Toggle wireless") def _activate(self, sbus: dbus.Bus) -> str | None: if interface := _create_dbus_connection( _PROPS_IFACE, _NM_OBJECT, _NM_SERVICE, sbus=sbus ): if not bool(interface.Get(_NM_IFACE, "WirelessHardwareEnabled")): # TRANS: notification text when wireless is disabled by hardware return _("Hardware wireless disabled") state = not bool(interface.Get(_NM_IFACE, "WirelessEnabled")) interface.Set(_NM_IFACE, "WirelessEnabled", state) if state: # TRANS: notification text after wireless enabled return _("Wireless enabled") # TRANS: notification text after wireless disabled return _("Wireless disabled") return None def activate(self, leaf, iobj=None, ctx=None): sbus = dbus.SystemBus() if msg := self._activate(sbus): uiutils.show_notification("Kupfer", msg) def get_description(self): return "Toggle wireless by NetworkManager" def get_gicon(self): return icons.ComposedIcon("network-wireless", "emblem-system") def item_types(self): yield Leaf def valid_for_item(self, leaf: Leaf) -> bool: return bool(leaf.object) and isinstance(leaf.object, DevicesSource) kupfer-328/kupfer/plugin/notes.py000066400000000000000000000334401500175051100171570ustar00rootroot00000000000000""" It *should* be possible to support Tomboy and Gnote equally since they support the same DBus protocol. This plugin takes this assumption. """ __kupfer_name__ = _("Notes") __kupfer_sources__ = ("NotesSource",) __kupfer_actions__ = ( "AppendToNote", "AppendTextToNote", "CreateNote", "GetNoteSearchResults", ) __description__ = _("Gnote or Tomboy notes") __version__ = "2017.2" __author__ = "" import os import time import typing as ty import xml.sax.saxutils import dbus from gi.repository import GLib from xdg import BaseDirectory from kupfer import icons, plugin_support from kupfer.obj import ( Action, Leaf, NotAvailableError, Source, TextLeaf, TextSource, ) from kupfer.obj.apps import ApplicationSource from kupfer.support import pretty, textutils, weaklib if ty.TYPE_CHECKING: from gettext import gettext as _ PROGRAM_IDS = ["gnote", "tomboy", "kzrnote"] __kupfer_settings__ = plugin_support.PluginSettings( { "key": "notes_application", "label": _("Work with application"), "type": str, "value": "", "alternatives": ["", *PROGRAM_IDS], }, ) plugin_support.check_dbus_connection() ## Tuples of service name, object name, interface name _PROGRAM_SERVICES = { "gnote": ( "org.gnome.Gnote", "/org/gnome/Gnote/RemoteControl", "org.gnome.Gnote.RemoteControl", ), "tomboy": ( "org.gnome.Tomboy", "/org/gnome/Tomboy/RemoteControl", "org.gnome.Tomboy.RemoteControl", ), "kzrnote": ( "io.github.kupferlauncher.kzrnote", "/io/github/kupferlauncher/kzrnote", "io.github.kupferlauncher.kzrnote", ), } def _get_notes_interface(activate=False): """Return the dbus proxy object for our Note Application. if @activate, we will activate it over d-bus (start if not running) """ bus = dbus.SessionBus() set_prog = __kupfer_settings__["notes_application"] programs = (set_prog,) if set_prog else PROGRAM_IDS for program in programs: service_name, obj_name, iface_name = _PROGRAM_SERVICES[program] if activate: bus.start_service_by_name(service_name) elif not bus.name_has_owner(service_name): continue try: searchobj = bus.get_object(service_name, obj_name) except dbus.DBusException as exc: pretty.print_error(__name__, exc) return None return dbus.Interface(searchobj, iface_name) return None def _get_notes_interactive(): """Return the dbus proxy object, activate if necessary, raise an OperationError if not available.""" if (obj := _get_notes_interface(activate=True)) is not None: return obj raise NotAvailableError(__kupfer_settings__["notes_application"]) def _reply_noop(*args): pass class RetryDbusCalls(pretty.OutputMixin): """A d-bus interface wrapper for a proxy object; will retry a method call if it fails (a limited number of times). The method call must be async (with reply_handler and error_handler) """ def __init__(self, proxy_object, retries=10): self.__obj = proxy_object self.__retries = retries @property def proxy_obj(self): """Return the inner proxy object. You can call methods synchronously on it.""" return self.__obj def __getattr__(self, name): x = 0 def proxy_method(*args, error_handler=None, **kwargs): def make_call(): getattr(self.__obj, name)( *args, error_handler=error_handler_, **kwargs ) def error_handler_(exc): nonlocal x x += 1 if ( x > self.__retries or exc.get_dbus_name() != "org.freedesktop.DBus.Error.UnknownMethod" ): return error_handler(exc) self.output_debug("retrying", name, "because of", exc) GLib.timeout_add(25 * x, make_call) return None return make_call() return proxy_method def _make_error_handler(ctx): def error_handler(exc): pretty.print_debug(__name__, exc) ctx.register_late_error( NotAvailableError(__kupfer_settings__["notes_application"]) ) return error_handler class Open(Action): action_accelerator = "o" def __init__(self): Action.__init__(self, _("Open")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx noteuri = leaf.object notes = RetryDbusCalls(_get_notes_interactive()) notes.DisplayNote( noteuri, reply_handler=_reply_noop, error_handler=_make_error_handler(ctx), ) def get_description(self): return _("Open with notes application") def get_gicon(self): app_icon = icons.get_gicon_with_fallbacks(None, PROGRAM_IDS) return icons.ComposedIcon(self.get_icon_name(), app_icon) class AppendToNote(Action): def __init__(self, name=None): Action.__init__(self, name or _("Append to Note...")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert iobj assert ctx notes = RetryDbusCalls(_get_notes_interactive()) noteuri = iobj.object text = leaf.object def reply_note_plain_text(contents): if not contents.endswith("\n"): contents += "\n" contents += text if not text.endswith("\n"): contents += "\n" notes.SetNoteContents( noteuri, contents, reply_handler=_reply_noop, error_handler=_make_error_handler(ctx), ) def reply_note_xml(xmlcontents): # NOTE: We search and replace in the XML here endtag = "" xmltext = xml.sax.saxutils.escape(text) xmlcontents = xmlcontents.replace(endtag, f"\n{xmltext}{endtag}") notes.SetNoteCompleteXml( noteuri, xmlcontents, reply_handler=_reply_noop, error_handler=_make_error_handler(ctx), ) if __kupfer_settings__["notes_application"] == "kzrnote": notes.GetNoteContents( noteuri, reply_handler=reply_note_plain_text, error_handler=_make_error_handler(ctx), ) else: notes.GetNoteCompleteXml( noteuri, reply_handler=reply_note_xml, error_handler=_make_error_handler(ctx), ) def item_types(self): yield TextLeaf def requires_object(self): return True def object_types(self): yield Note def object_source(self, for_item=None): return NotesSource() def get_description(self): return _("Add text to existing note") def get_icon_name(self): return "list-add" class AppendTextToNote(AppendToNote): def __init__(self): super().__init__(_("Append...")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert iobj leaf, iobj = iobj, leaf return super().activate(leaf, iobj, ctx) def item_types(self): return super().object_types() def requires_object(self): return True def object_types(self): return super().item_types() def object_source(self, for_item=None): return TextSource() def _prepare_note_text(text): ## split the text into a title + newline + rest of the text ## if we only get the title, put in two helpful newlines title, body = textutils.extract_title_body(text) if body.lstrip(): return f"{title}\n{body}" return f"{title}\n\n" class CreateNote(Action): def __init__(self): Action.__init__(self, _("Create Note")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx notes = RetryDbusCalls(_get_notes_interactive()) text = _prepare_note_text(leaf.object) def _created_note(noteuri): nonlocal notes notes = notes.proxy_obj # FIXME: For Gnote we have to call DisplayNote # else we can't change its contents notes.DisplayNote(noteuri) notes.SetNoteContents(noteuri, text) notes.CreateNote( reply_handler=_created_note, error_handler=_make_error_handler(ctx) ) def item_types(self): yield TextLeaf def get_description(self): return _("Create a new note from this text") def get_icon_name(self): return "document-new" class GetNoteSearchResults(Action): def __init__(self): Action.__init__(self, _("Get Note Search Results...")) def is_factory(self): return True def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx query = leaf.object.lower() notes = RetryDbusCalls(_get_notes_interactive()) def search_reply(noteuris): ctx.register_late_result(NoteSearchSource(query, noteuris)) notes.SearchNotes( query, False, reply_handler=search_reply, error_handler=_make_error_handler(ctx), ) def item_types(self): yield TextLeaf def get_description(self): return _("Show search results for this query") class NoteSearchSource(Source): def __init__(self, query, noteuris): self.query = query.lower() Source.__init__(self, _("Notes")) self.noteuris = noteuris def get_items(self): notes = _get_notes_interactive() for noteuri in self.noteuris: title = notes.GetNoteTitle(noteuri) date = notes.GetNoteChangeDate(noteuri) yield Note(noteuri, title, date) def repr_key(self): return self.query def get_gicon(self): return icons.get_gicon_with_fallbacks(None, PROGRAM_IDS) def provides(self): yield Note class Note(Leaf): """The Note Leaf's represented object is the Note URI""" def __init__(self, obj, name, date): self.changedate = date Leaf.__init__(self, obj, name) def get_actions(self): yield Open() def repr_key(self): # the Note URI is unique&persistent for each note return self.object def get_description(self): today_date = time.localtime()[:3] yest_date = time.localtime(time.time() - 3600 * 24)[:3] change_time = time.localtime(self.changedate) if today_date == change_time[:3]: time_str = _("today, %s") % time.strftime("%X", change_time) elif yest_date == change_time[:3]: time_str = _("yesterday, %s") % time.strftime("%X", change_time) else: time_str = time.strftime("%c", change_time) # TRANS: Note description, %s is last changed time in locale format return _("Last updated %s") % time_str def get_icon_name(self): return "text-x-generic" class ClassProperty(property): """Subclass property to make classmethod properties possible""" def __get__( self, cls: ty.Any, owner: ty.Optional[type] = None, / ) -> ty.Any: # pylint: disable=no-member return self.fget.__get__(None, owner)() # type: ignore class NotesSource(ApplicationSource): source_scan_interval: int = 3600 def __init__(self): super().__init__(_("Notes")) self._notes = [] self.monitor_token = None def initialize(self): """Set up filesystem monitors to catch changes""" # We monitor all directories that exist of a couple of candidates dirs: list[str] = [] for program in PROGRAM_IDS: dirs.extend( ( os.path.join(BaseDirectory.xdg_data_home, program), os.path.expanduser(f"~/.{program}"), ) ) self.monitor_token = self.monitor_directories(*dirs) set_prog = __kupfer_settings__["notes_application"] if set_prog in _PROGRAM_SERVICES: bus_name = _PROGRAM_SERVICES[set_prog][0] bus = dbus.SessionBus() weaklib.dbus_signal_connect_weakly( bus, "NameOwnerChanged", self._name_owner_changed, dbus_interface="org.freedesktop.DBus", arg0=bus_name, ) def _name_owner_changed(self, name, old, new): if new: self.mark_for_update() def _update_cache(self, notes): try: noteuris = notes.ListAllNotes() except dbus.DBusException as exc: self.output_error(f"{type(exc).__name__}: {exc}") return templates = notes.GetAllNotesWithTag("system:template") self._notes = [] for noteuri in noteuris: if noteuri not in templates: title = notes.GetNoteTitle(noteuri) date = notes.GetNoteChangeDate(noteuri) self._notes.append((noteuri, title, date)) def get_items(self): notes = _get_notes_interface() if notes: self._update_cache(notes) for noteuri, title, date in self._notes: yield Note(noteuri, title, date=date) def provides(self): yield Note def get_gicon(self): return icons.get_gicon_with_fallbacks(None, PROGRAM_IDS) def get_icon_name(self): return "gnote" @ClassProperty @classmethod def appleaf_content_id(cls): return __kupfer_settings__["notes_application"] or PROGRAM_IDS kupfer-328/kupfer/plugin/pidgin.py000066400000000000000000000275311500175051100173050ustar00rootroot00000000000000"""Inspiration from the deskbar pidgin plugin and from the gajim kupfer plugin""" __kupfer_name__ = _("Pidgin") __kupfer_sources__ = ("ContactsSource",) __kupfer_actions__ = ("OpenChat", "SendMessage") __description__ = _("Access to Pidgin Contacts") __author__ = ( "Chmouel Boudjnah , " "Ulrik Sverdrup " ) __version__ = "2017.1" import typing as ty import dbus from kupfer import icons, plugin_support from kupfer.obj import Action, Leaf, TextLeaf, TextSource from kupfer.obj.apps import AppLeafContentMixin from kupfer.obj.contacts import EMAIL_KEY, NAME_KEY, ContactLeaf from kupfer.obj.grouping import ToplevelGroupingSource from kupfer.support import pretty, scheduler, weaklib from kupfer.support.validators import is_valid_email if ty.TYPE_CHECKING: from gettext import gettext as _ from gettext import ngettext __kupfer_settings__ = plugin_support.PluginSettings( { "key": "show_offline", "label": _("Show offline contacts"), "type": bool, "value": False, }, ) plugin_support.check_dbus_connection() # Contact data constants _PIDGIN_ACCOUNT = "_PIDGIN_ACCOUNT" _PIDGIN_JID = "_PIDGIN_JID" # D-Bus "addresses" _SERVICE_NAME = "im.pidgin.purple.PurpleService" _OBJECT_NAME = "/im/pidgin/purple/PurpleObject" _IFACE_NAME = "im.pidgin.purple.PurpleInterface" def _create_dbus_connection(activate=False): """Create dbus connection to Pidgin @activate: true=starts pidgin if not running """ interface = None obj = None sbus = dbus.SessionBus() try: # check for running pidgin (code from note.py) proxy_obj = sbus.get_object( "org.freedesktop.DBus", "/org/freedesktop/DBus" ) dbus_iface = dbus.Interface(proxy_obj, "org.freedesktop.DBus") if activate or dbus_iface.NameHasOwner(_SERVICE_NAME): obj = sbus.get_object(_SERVICE_NAME, _OBJECT_NAME) if obj: interface = dbus.Interface(obj, _IFACE_NAME) except dbus.exceptions.DBusException as err: pretty.print_debug(err) return interface def _send_message_to_contact(pcontact, message, present=False): """Send @message to PidginContact @pcontact""" interface = _create_dbus_connection() if not interface: return account = pcontact[_PIDGIN_ACCOUNT] jid = pcontact[_PIDGIN_JID] conversation = interface.PurpleConversationNew(1, account, jid) imiface = interface.PurpleConvIm(conversation) interface.PurpleConvImSend(imiface, message) if present: interface.PurpleConversationPresent(conversation) class ContactAction(Action): def get_required_slots(self) -> tuple[str]: raise NotImplementedError def item_types(self): yield ContactLeaf def valid_for_item(self, leaf: Leaf) -> bool: leaf = ty.cast("ContactLeaf", leaf) return all(slot in leaf for slot in self.get_required_slots()) class OpenChat(ContactAction): """Open Chat Conversation Window with jid""" # consider it as main action for pidgin contacts rank_adjust = 5 def __init__(self): super().__init__(_("Open Chat")) def activate(self, leaf, iobj=None, ctx=None): _send_message_to_contact(leaf, "", present=True) def get_required_slots(self): return (_PIDGIN_ACCOUNT, _PIDGIN_JID) class ChatTextSource(TextSource): def get_rank(self): return 100 def get_text_items(self, text): textlen = len(text) summary = text[:10] + (text[10:11] and "..") desc_template = ngettext( "%s (%d character)", "%s (%d characters)", textlen ) yield TextLeaf(text, desc_template % (summary, textlen)) def get_items(self, text): return self.get_text_items(text) class SendMessage(ContactAction): """Send chat message directly from Kupfer""" def __init__(self): super().__init__(_("Send Message...")) def activate(self, leaf, iobj=None, ctx=None): assert iobj _send_message_to_contact(leaf, iobj.object) def get_required_slots(self): return (_PIDGIN_ACCOUNT, _PIDGIN_JID) def requires_object(self): return True def object_types(self): yield TextLeaf def object_source(self, for_item=None): return TextSource() def valid_object(self, iobj, for_item=None): # ugly, but we don't want derived text return type(iobj) == TextLeaf # pylint: disable=unidiomatic-typecheck # noqa: E721 class PidginContact(ContactLeaf): """Leaf represent single contact from Pidgin""" grouping_slots = (*ContactLeaf.grouping_slots, EMAIL_KEY) def __init__( self, jid, name, account, icon, protocol, available, status_message ): slots = { EMAIL_KEY: jid, NAME_KEY: name or jid, _PIDGIN_ACCOUNT: account, _PIDGIN_JID: jid, } if not is_valid_email(jid): slots[EMAIL_KEY] = None ContactLeaf.__init__(self, slots, name or jid) self.kupfer_add_alias(jid) self._description = _("[%(status)s] %(userid)s/%(service)s") % { "status": _("Available") if available else _("Away"), "userid": jid, "service": protocol, } if status_message: self._description += f"\n{status_message}" self.account = account self.jid = jid self.icon = icon self.protocol = protocol def repr_key(self): # the repr key should be persistent and hopefully unique return f"{self.protocol}, {self.object[_PIDGIN_JID]}" def get_description(self): return self._description def get_thumbnail(self, width, height): if not self.icon: return None return icons.get_pixbuf_from_file(self.icon, width, height) def get_icon_name(self): return "stock_person" class ContactsSource(AppLeafContentMixin, ToplevelGroupingSource): """Get contacts from all on-line accounts in Pidgin via DBus""" appleaf_content_id = "pidgin" source_use_cache = False def __init__(self): ToplevelGroupingSource.__init__(self, _("Pidgin Contacts"), "Contacts") self._version = 5 self.all_buddies = {} self._buddy_update_timer = None self._buddy_update_queue = None def initialize(self): ToplevelGroupingSource.initialize(self) self._install_dbus_signal() self._buddy_update_timer = scheduler.Timer() self._buddy_update_queue = set() def _get_pidgin_contact( self, interface, buddy, account=None, protocol=None ): if not account: account = interface.PurpleBuddyGetAccount(buddy) if not protocol: protocol = interface.PurpleAccountGetProtocolName(account) jid = interface.PurpleBuddyGetName(buddy) name = interface.PurpleBuddyGetAlias(buddy) icon = None if (_icon := interface.PurpleBuddyGetIcon(buddy)) != 0: icon = interface.PurpleBuddyIconGetFullPath(_icon) presenceid = interface.PurpleBuddyGetPresence(buddy) statusid = interface.PurplePresenceGetActiveStatus(presenceid) availability = interface.PurplePresenceIsAvailable(presenceid) status_message = interface.PurpleStatusGetAttrString( statusid, "message" ) return PidginContact( jid, name, account, icon, protocol, availability, status_message ) def _get_all_buddies(self): interface = _create_dbus_connection() if interface is None: return accounts = interface.PurpleAccountsGetAllActive() show_offline = __kupfer_settings__["show_offline"] for account in accounts: buddies = interface.PurpleFindBuddies(account, dbus.String("")) protocol = interface.PurpleAccountGetProtocolName(account) for buddy in buddies: if not (show_offline or interface.PurpleBuddyIsOnline(buddy)): continue self.all_buddies[buddy] = self._get_pidgin_contact( interface, buddy, protocol=protocol, account=account ) def _remove_buddies_not_connected(self): """Remove buddies that belong to accounts no longer connected""" if not self.all_buddies: return interface = _create_dbus_connection() if interface is None: self.all_buddies = {} return try: # extra careful as this will fail when Pidgin is Quitting accounts = interface.PurpleAccountsGetAllActive() except dbus.DBusException: self.all_buddies = {} return is_disconnected = interface.PurpleAccountIsDisconnected conn_accounts = {a for a in accounts if not is_disconnected(a)} for buddy, pcontact in list(self.all_buddies.items()): if pcontact.account not in conn_accounts: del self.all_buddies[buddy] def _signing_off(self, conn): self.output_debug("Pidgin Signing Off", conn) self._remove_buddies_not_connected() self.mark_for_update() def _update_pending(self): """Update all buddies in the update queue""" assert self._buddy_update_queue interface = _create_dbus_connection() if interface is None: self._buddy_update_queue.clear() return show_offline = __kupfer_settings__["show_offline"] for buddy in self._buddy_update_queue: if show_offline or interface.PurpleBuddyIsOnline(buddy): self.output_debug("updating buddy", buddy) pcontact = self._get_pidgin_contact(interface, buddy) self.all_buddies[buddy] = pcontact else: self.all_buddies.pop(buddy, None) self._buddy_update_queue.clear() self.mark_for_update() def _buddy_needs_update(self, buddy): """add @buddy to the update queue""" assert self._buddy_update_timer if self._buddy_update_queue is not None: self._buddy_update_queue.add(buddy) self._buddy_update_timer.set(1, self._update_pending) def _buddy_signed_on(self, buddy): if buddy not in self.all_buddies: self._buddy_needs_update(buddy) def _buddy_signed_off(self, buddy): if buddy in self.all_buddies: del self.all_buddies[buddy] self.mark_for_update() def _buddy_status_changed(self, buddy, old, new): """Callback when status is changed reload the entry which get the new status""" self._buddy_needs_update(buddy) def _install_dbus_signal(self): """Add signals to pidgin when buddy goes offline or online to update the list""" try: session_bus = dbus.Bus() except dbus.DBusException: return weaklib.dbus_signal_connect_weakly( session_bus, "SigningOff", self._signing_off, dbus_interface=_IFACE_NAME, ) weaklib.dbus_signal_connect_weakly( session_bus, "BuddySignedOn", self._buddy_signed_on, dbus_interface=_IFACE_NAME, ) weaklib.dbus_signal_connect_weakly( session_bus, "BuddyStatusChanged", self._buddy_status_changed, dbus_interface=_IFACE_NAME, ) weaklib.dbus_signal_connect_weakly( session_bus, "BuddySignedOff", self._buddy_signed_off, dbus_interface=_IFACE_NAME, ) def get_items(self): if not self.all_buddies: self._get_all_buddies() return list(self.all_buddies.values()) def should_sort_lexically(self): return True def get_icon_name(self): return "pidgin" def provides(self): yield PidginContact kupfer-328/kupfer/plugin/pinboard.py000066400000000000000000000024571500175051100176310ustar00rootroot00000000000000__kupfer_name__ = _("Pinboard") __kupfer_sources__ = ("PinboardBookmarkSource",) __kupfer_actions__ = () __description__ = _("Manage and use bookmarks from Pinboard") __version__ = "2020-11-15" __author__ = "Peter Stuifzand " import typing as ty import pinboard # pylint: disable=import-error from kupfer import plugin_support from kupfer.obj import Source, UrlLeaf if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_settings__ = plugin_support.PluginSettings( { "key": "token", "label": _("Pinboard API Token"), "type": str, "value": "", }, ) class PinboardBookmarkSource(Source): def __init__(self): super().__init__(_("Pinboard Bookmarks")) def get_items(self): token = __kupfer_settings__["token"] if token == "": return [] pinb = pinboard.Pinboard(token) bookmarks = pinb.posts.all(start=0, results=100) return [UrlLeaf(b.url, b.description) for b in bookmarks] def get_description(self): return _("Index of Pinboard bookmarks") def get_gicon(self): if lrepr := self.get_leaf_repr(): return lrepr.get_gicon() return None def get_icon_name(self): return "web-browser" def provides(self): yield UrlLeaf kupfer-328/kupfer/plugin/qsicons/000077500000000000000000000000001500175051100171305ustar00rootroot00000000000000kupfer-328/kupfer/plugin/qsicons/Action.png000066400000000000000000000334371500175051100210650ustar00rootroot00000000000000PNG  IHDR>a IDATx ]Uw[}4"OVl"J0%5H#vD ` pTEL!B9~ZuSM*};^5Zc1xᇻ׿~߶x/~փ>Ru7և>֕W^ٺ 8FO1f"</կ~RK{m}}/y'4XzZ wGi * @U=Ӻ[g+?hy睭G} j9aPψ==P~_Wgկ HM7ݴj:jpӣ=+چ_ފO~׾W/| {sO/#RN}N}WO=X~{;h|ͭo||+H ‰\3:q!?E?K.vm|3}w[w_e`'*@&qPFhϋyor[o~%0 ~/̵k>`h/;s*†QWq?^ $X ,8k5@? ⬳Κ|;+~$+0k5|V@G?V oP7pCG5p"`->>я^ǷX CL <\:h}Sj}_]a$߱t\p.{O~+b]:M?@<~, 7u@Ӑ!@H.\puu.قZO|bn&N;J@'x7^ \2!Xn}w? X5d'[е^{-7|6efϞ='BH ۽[nZ!Jg:%Fqc i.$;1$2@K|&XT&;S;tA/ƎMp?OUcj)3A0k֬; e@wR$s%\ UY'!E gP_* 0,PZwuZAwcRoCH|BG>R/}K+-Q%ݧcyGB抠l /|YDgǃ`%3L<  ` $bu\6 7G48 ΄rd-?p{_+Յ5B:߳dɒ<1G[^ziu?6†XTď^v9߁[Ä3PM(uL>DrO1P~Bt}iAπV0HlD瞋:[ny H|} Z JTXAE 2,}&"@x 5چI:7˲AAOۙ D:g"!8>}{Y:~@C0rTe]Vq=9 Ì駟ޚ3gNkܹN: {X64}t+Pqc@P?&{~ɃмH0D:{ҥ+ kYs//] L;no;HΧ=39S?_`?ug_*Q̜?F\B %~l"~LܿD7#$c  c( a$y)sXg%3yfAT$``GP.`{ .'ܚ={6? "4Hl !>segf#I%B* q1e! v`Jo =14ź`GB`$Ix!8M^ƨ`AC/\0э2CRU@PhaT1_.zsG)nHA UBՆ,`K"e G ᵢd0pﻁ$"LDqU*gWBP<Bs?! + r@5`' -ZiU܏>(LO^0͜C qx^}gmʮ0] (c"B&IF?߅uo0$A{.ȫ\kmdvB@!hgUUϽ0lgѺ{>^ fwi -9m$KlѺh7nY@1 [ iPupu  2ٸ836[!>ay!h+4|wRICx c8Jv,涙}9uC J rUEG{]ݢDh I(ۃKbk=7y a Gy V ز,<&T TLC gP%b27} ~H9mvb3ׯkޤ XR#E#R瞋bأCfE\FhJ!} *400 }}AZ`& 8=gh!}*+_>ğ\k36Ҵ52g^5PZ¨Irv;!l~y|=5REIV"!ܭhHAD{!mAF#KUU͜o`ȸ??o~{sUD 7N .1x(L`~kApm8=s7{ }%}>r-@Մ?Uӯ/ Z0;>$QWIꀉV+T92sgi\bA\}3%o.4R!ć&++*g^fm2LcU 3p`]lVq%e9&k~sV!bkPQE|qMEXC0wF io;yEyy B*a20lo1gu<} Io,+2|!z0R/^Iܛ$f{J!G%ƠBoVE'xR{(À>A!l&8A%IK_Ϣ7bLkCQ XX_iӦ}Ͽ18a3D/~ BA1ȸݍ2LCCE(?B!o0·LAL>e3Rň$z1cL4 0`4W/;x4BsM&BsϽ/xRjz1ӢW_5CWg}. 5uo/A붱W: R](})U*7 B?qнr??w2-1r%vusJ!8f h*Mw4l'ю)5(D &\KZ[E8w.upP H+FNL916?aj0w}9WwI~ 0M7H[KJMx8AtvPw_}o[J:ԛ.R?&h|HDٍfU.lsw[b_,}.G t[7[ԛ'y|qF{S/ Rmh{z?^jɀT3Ν9mh2-dՁ`7 cvIu4(mب.]p+u*@o@[8[JM7Rk^jA!6gPRo2he+7o(5 y@jr̙38s gU }4QkӜx}y&Rc0'Xp(^ Agl˗mQcA|#PV a-I6ږ&R/K zAMRMKN[ڵ@@" ]؛?vW!H-36`+Ru;X)j2A7\,cm,crvhTh@ń4QI zCUO8%X"DXlI,X>+g7_GKXB% :2li[I8| P%BC `3] 141p7X׆pO\Z~p#\BCxљ8MVbGl{0yHѥH±0)"yfm63}f=!tJ|_ j#,U,u/*^ҥ?RN u6]Zo-cq # c"r͚N\oRA=`/ 0&8D;?cB|#v@ts Q> cFAGE7] ǚ́@1xſ!X!S4<{&fmQ|4\x8L?~ IU@pTHX`ɻt3DxGKuQncRK4l&~P^?rlD>Vp#MqwbU oãfap i8 جbvY^Grwh0j1s R͛QYj NWLtρ. 0bo;s$!s\nr׿'z eljI:ĉ49] xQCy a~kFjwY1c^ ,/)1(M[wWܧkɒ%]w^j nJ vƎ K7m]?f24-`&גV'=RKm1 D4ctG o7xD9،pœ.HrH(1f0n3ܛ$Q1͏{:S z==l==@w0@D@h7=D\'Cy9WalTR_vhm2F}7rE _0kXQ}-T[jP1x9;^uoN @pZ}K ̅3ӈ^JvqGvp"q`Yoϐ@ LQϬ# C JFe0O Ǵ{8#7<Jx3Km#M<!s 'rNf$D%-Jfzx^I@@$GJ[\J iN\y`baPlz@~O1=bU*)i'lҷ% uNS[fx\ΟtB &V*sYG3]zyc$K"vKT[Hvw#D`% d&眶g0ːSە~!R5q9 N[4`ؽ֮^>\#WRi|Uq@r4Fa׭7?z^RHQm{ )|&M`"6v6 &v.{cpPky0# lE2l".r1KK_E m!'$ ݊qCiA&6co/Q{y4ɜC#o% du4AP'õr>~"ԴlrOupzyhh(9JyLkd>.rb0e93[VP#q&g@`NRZI:h gM<>W7`'=PIfU/CsB<|k(fDzJܠR:Xw)5VV$Y*[{LBJ:b-;ڵ $ݡo ip+zw AlD>L(И+9Qnˀ6vA6eurm츐&E`輎!8`X`RJ+q>.aScǎeӥi is 78b93; fƳ3eж͞Wgdn!g[fG̣\_nH!$ht ;R+8<7C 9"9$s3teϬZ1B|Aeu0Q⁚Ghkoy#3gQD:Fॗ^:1'ZWp@ܻ8:t _PY&N8cwysƍw{R&mnw}i atKdʼ?s&SO=]x¡r{BK>:ܒ5zC] h['M\%MlA˥tЅz9GuYf!A@*uQ<7P`ʮ }X#B4>72zB4:HG_9 <IDATa`$[T}ss@l{<?wk̓5h-) .6Mӑb5ldsW\qK޹Αnx0!w|E1sGodo c,b⹆z[oi&@̓5h-)]o3ԻY۱>eЮmf!/ҷӈu_Cz˪ohMpRĵ6BO@Léaa-e/,C7SoR&Bە6mZD`AK_1z}{o?D D`Ҡ=KƠ BU`%0&($ [ TrʋBx̓!-Xm8<͢W4;&: 5 4ڮ/ ԮL\ dlڮҗHyHt-SgY'gȘSZ̈F1B£t@@H2Ӱ̈́wSǽ  }q-.}LT%8fuBەB:҆m͛b +ਡ~˗/qhRIQsyUޔi3i#o]H>/(1$,$sX52e~[񱉓?s?YjJ^"b#f7AChiJ!aBK[ p`skи0@ {w=: @@{ٲrgL.Mz n=q̓,p1>*PܷWw2^07KfzGZoBەBɑ|n}fӞ DY "w N#=;CPݖyCk-aIuV&z_&IݭχY ~+!\~,XmGC!m#4ɱ-EL8,/kZF%'QZKafAd2=s=568I 5@цC2I]Ǡ|HuT Jà5#F0cƌa+oT9IzN558"ķ *:~A]ZjΜ9DA $;2=<cYN\hrDG1`l+9+A [HƌǮo 9" 8@UgEp5a=`FmCog@tq8>{T-k\)3-OAj)., qsXѲ,<[ݮ P s !6 1d䚀l Tvn溼d:`vM `fm&JF`y/H#8(hS:}*e$Gy(?)yV9;mD6s}A0쁍A{/`jIK =LgիR/[4\.["T8~8ᵾSV-WA@3v gT.T`gy7CUiKh9#0f'i!u]\ډJh] 7y Q% 2qS*@@(,b6`gyɾJG/z<-ݯ ֝XwdtAc@V¦D @A3Mӱ l'P+<(vau}zyT<{JD$Na|c#>FhF-&Dsxy-y z&x+i &B?J G$Jpȳ| %cJ!pw X%|& [Ɖ5d";hIˡe6ce4$g4\r~T僬%I]1^~PH$AAEfyF 9-_3]o :[/3w %@` BJ=m4'dgfZYDGlCs_ E:QawpT_o2Q?ruHHOUdb1P \|!vcﴧf74ːnlcǒW/J3h~Tw(:2,7ǹa1 <4ɵ&mqi+_='ѰruNZ/*fV8~ͼ=S-`Msg>Ydtّ4 }xb 16ȘnX-gܨ W}&*,ʤB4.r5m& Ai̽Y8|9gψ]z}I/Z Xqog&y|-sW =Ӹ>I=gʄxB{||Q\]KPՒ"^qmEN\트wCñVẈs7x0$=x 06~l򧧒ʉͭx GbMopL#KQB-3n!'oQgBP$f7kh1dE~.QjS7 E!{ C*pEf2\v{q_|kk 1.~k=1zv,$çzՙ^yD3qC'AX%ݠYN09.gJ3׻4s?ŹB9Lzѳ:bP?MwnJNܾg|{v6sh 7Ƀ*r!ACb` ,a߿oVw)VjAxұ![{47c|  X R(}3lѿDtP>M0 B,Aykrۢsȳ@^h-5! H7xG}83|Hp ˗/. +0軄gb7ԙo+ !Mzu2Y)?ۛ{P? XY¾^ p&=3՟ ,@;p g*3~IC&T QL&G> fp<@70W)*.^=P|=܎0!v_ȯ2?k$uЌ@aϽzz!&5sc2GTN"|畯|RO|^ypT@"~l9n'CL$Q .iN*% p; -Tb :/:~-`YG@тHf 1T?6hw7~Is7| $ܜʫp 'Ӄ!:hSW:LlfJ+OpXJm!vE?h8o!~= ?1@ `J\'ܯo@e7)(@[37omu<} D%D7c8upᅤ[[ .Xo/kv`ܹn Ϝtz+挹c;>A~sN,fAs=8gu, 0־T {>  X僪V?3 愹a40;u<}d1KUM-WWX[{{if'`_戹bΘ;p߇ @Ojav][pgO= w&MϹn 9Zu]U s1WsRIxޠJ_z>9ˀR6,h@=H ϙ3gκ}f.4d׸pydkݶʕ@S `:~`b"`Vя~9sT>u 2P}1{c-=`ʔ)S!:;K>6TU:P:Fk'OJ8+ #ͣJaÝJu9NZM@w4m?z8p-KMa IDATx}XUklQlH"HWb]Q" ("MzWX=,{-bIb^MgosBM^%癇v8e;3 TUVժZUjUԙ2}PgЄ!1eA GD'}(21ix\{ S%-0gd?S75~ π0;Of͉ {<*6qrJ:eeQ^^!-˩֭[K֭,׉?^SFŴtrZ{/qnJEJ9q)G6?pR}Ǐm>=8j쨤kht]V֗ӆ 멜xq!effRjj*P KZZ*ϟOdڴq#޵G**hTl%-0ohpy`n:ޡ13&KNbrZl[{͝;WPrss#GGG8p 2ƌC{/// HFВ%Kh5sg9mt.)JZmZDD}M)_gRТ}HGG[Rv4p@Xv锗b6֭i۶mcvoYvA۶o0Eqq,0=U|.<#g;K,$P gi&qwuumے ijjQΝi=%$ ighl b*do_,oqO9y?d+sS -N-\WT\M>|a:x0߷O$;wdR(ɲիctW͙m{9 vI?1i.[}ii^r*0tƆ>Z\/eKU??M[+N;guʕ'O{G"9<{rqIؼ%EˊorÇ![7o|`N8A׮}M7u_\j9;4ܹ)T񷰠}KndӾ=%%ц(#3楤Ҝ{IVl۱kڅK^޽{=zdʊnbb)6,,Z,j,-YTX4`R]~_Μ9Ϟ.`e+Vmt 8UI/\Dq utM:뱱S ~6{\}%,X3Y|\mܰp ΎLBEm߶RR_ 03gþ޸s'OXiXHқ'KWI7`aT@sI&J`ScTMR-X2nɊ~ڽB$yybiU*us89We P O]2evfai4q/Y)>}:4\!,% tae,߄ňEO|u,-$7ei()&<.dTiduޒ9ekma2l)7_ߠs.> Gy~a߇>2)mUxt,&c J'X׼狗,9եKX#Y),cXFIWnmDjM$nPKEY N!<犉ME 3w¹XUJN KZj⡒wYf(9uHv={Ċb UR~wbb1o%7}{OVu: |W>@!*"駟cOf8^_䐰ȘIII駟\D|ܑ#GV*=~V#'a$ܾlp,aڈwiɤ%ʊ*}VrZZeKX!JX!sFVwnCTXXj.V 3D%叮aVzSߕ8 luҥ/PDEkٲ]xR8;:8 ,vH*[U¹t͜9222h߾'JO0IGT"|1_|vm8ׯ_Wc/PU7 )`99ˆ}f{@"SΉfE˩-u?lV8I+}nm~g PÇ zP~%&o_ߟ~yӐokvH9O)+[CvE6nxv/0ك§LVR܇ EߝXv|cV>\[[[[˯)I !'?9x k׭ ]ws̊ AWPHH͚50رs'NWRҽ`׿zc@5+ ʿwoiP&f'˂\}IFHדK-c%:Kw)]gdweBp<01?gBqP 6bũ4ciDEC* ~ߊ9 dc=_B\NNN]f1.>?K:Ao좿K+00Q?hΕ0Zf5[(lo޾=E(Y }@V~V>\'9Zrjgve+WO_KKcAp("X4YtXp YYڲXJb%}~JD2?+x$p1gdEK-;9Qnv֏Ɂ/^r["}+1,XKd+q֭[6׮]aqikN!͌l(֬͂lAv,fB6,X:tŻdҗ?%[z | !u` :IF" l۱¬7v߅yΘX*Mёs.:vD&+t|J߁? ~vX}vܸqٳg;ܹmsssmAڂºQpCaPxG[.,BX(|00,cXYXƳLI=3$ /6-cTuo&;"snYQRpw+hw|7$w?M)Gx9=#XCX}dW_u۷o_7 {򂒡(p($P<SxX9ҲBcY&Lcaecfd,(1XzN6B 8 D5X[wj8ʒUbqhF .DAĸL;+v>|VDg;8r20 ^_'Om۶^+WܹͬsL4G}$m(V޹tR^zV  Oa2%%%eK;…e> :VA8p{׈ T<|STT$N.[N8oZI["~$ρ?cлwtRg_XX8(99yHllpww͛7Rx.KGI ভߓ; 7§3IH8xI3?xFReoPs1=i?mߵѣP')2 [3#1G;wnԞ={F rv7bĈ5kք;H #mEFֈ,e'FZիWOnݺ:uhKҍ0^Ppp$, Y o ( RODj <~㧷G8:_(j}<7^ruL%?őؾlL8w}Å >s5k֌e4.44ʟ6mdrKúE A@T6l(JFjjj67,[VQUUmۂWKM4lܸБAЇJY%({xM8.=o^ mظ59|Y0۟듏?sNvSOMOOwgLf0z޼yx/yIP>\>7hީS^z9r*'On OU ӧOo)l ?d"0GC1 ("E >"(<BEV-sW7#ΟU,haɣwzM?BBܕ|k֭ӋxeddLaşR;*ׇy},3y(755mnUnTtzu#lŚlZP-V6{m6, BM~SRR0Z֚A*@P^J( PmD0%APիWw:b'NУG)i^.i\^>~?$Nj]FQjJ5VZ]v S>Y'w)ߌe˖|ݐ ڸqc(UPT~|l9U;wzEųuX~-=+W۴i.៵&``PHcc~FFF" Q_)"JA Æ指=%$&ݳ;xtxO9!.Xq@) eeei^7nLc~_&~3"d7ٿDy$~{Y-P8*jQfm-uttZ---[WׯƨQ\\\===uقxV+ԐAfb ~-C~۷o7p_QQ.__T@@ tС AWPG:Q  {o߽g}xG6n#FRBRy-x3^dO1?<+ÕJΏ֏B+˗\C6665b@3ftҀh 6xcV={ cǎ=zͩSN#=zϏ/?VB@IIߪUwfKgv&(`hʇlPA|P=q:ن1{8Lmf^ȔmzYK.|m9<_p T#P^*pP2Sx$N%KLzxLSǏ͛Kok̀qѴb7qNM^3 5j?c _TvoYV^@Voo߾Al8DtP?_F֏4L~`Y }&~FlƜMcݎ;ڱRk_ro5ݾ}۔@`oep @vP/F=BP@ Qpgs_ў]w4nqZLWiAz:cپ=w5Ӊs `vWgO߲e~_Av{Bl_YP\1b?<~WM:L%:;;q7 lߌS< V 8+&Vm8`ΐSSki {3x/СC^5 ]d.2@J 0 HG?Lq8bsUUxXO ߛ5= 806oDLh'w&D* 9n`VLi'rؗ]nwU ee ݵkW]@_#Ս9lphDSIZqat\X?N/FxФi3lG#Ǫ6lXKyzܷuef~?g9sc sdrΝ n />*h?o D 0-4s///:**}ZZZG3[L8uܵkWG:08۳YV,Pf̞D_M%t^ ӧO):&WDh% $}}$OӂY4l}9[i(&~d7fcX8b-@@3;@`T2,,, d/̔gAPP5&p8w`vXd J΢ٰҭVhb 1o܆ɤz .ˈV3f !(@JiU< e9Y; mbt1׈pE®iéx%$7ϛh6֭6zxpCg?ГYw>K|"i r@Ե u,--zi1ppp0A`ÜSCζ0YVL-Y73~)xΜ9F)?&f |  $ {cמ_Ue/JЕA٦{}5l7zh3&ɓEc dnΜv1MYrцɞ!+^ &(3P>N0|ygބ Sl\Sm=͂bJ(V5xc9aaha{ ~ѵ{/ɡMh~(wAn`#e  AP> {] p&q0/#V gmgc JF-0pteĜ?&^g<s|p p}[eTTT^@L +q?@DQؚ_ɐ!Cڠ̡Jp=tbƜN0vc miX<~p+ +=ƌMEKP>bGxa9fmdN Is);+ )&!!q]~Os*hY+J䢐ְ2 ^ @=AE?F-f CiA|IPbױ'OܺeHp"jJjcMm} 9D )04Zn$ʕ+)`1{`bf5/((@p]+-X cp OhXeOD AjT!h,kďUGmgtтCK(XtůϟI7ظa㋁ll!!Lagy>(Q~bqyp?Y͙@W%f)..y{=@ {<&+Accc-J(U;AQVוܾwժz (r}ҒNȨ>v hui)-YÌ)`ݻ+{Ύف He A!+ˊ;e/(U{={߷x://o*))Ĺ/,l$(`[96`XE }|p'wt|9=AfV6^ RE&bbӦMZ f+9}.+nǃ_ ^#^A""?NV:^y”)7lx6|Ο?_ܴXI]{Ap~ ׏ 2.܂[m:t C99]:W^C "bzp7G˗/)W: RHP2'PzeW*0َ vxiIN.΢)(d@l1l AKAa@Wҭ[pRB+HK[@F‡+laLz 5k&-w@ Yd`("lDJHzԩS'wPc(A!֕iڴm{хKF;cOf)=,2S׆A 'PXy;Y,̹s#{/fϞM^mbmdbCz8./l8M'!I 쒽xKiib+v+؛.+)%?=t,o (zJR2^B{Y[t[7E ˤI`SlnN6 afJ'`c<,!Lc[E'h;lذy=Hq|iZ>?rT10Q.$~*V Eӱh^n V 4ϏM&6pדD0>qppyW֏% RxРAsrn',-vlN7mm:vV߈8Sĭx^h*{y E&{DG ݸqLxΞ=Kq4>|8ӭ[^rzj@k Mm]y& #dp^;AĒKÐ$9G|hًJ))ނ;+Xv-۟e->=#0lk\Tlrุ=ߪ)g{DFfN޽O>{ ak߾},Ӱ{⽎PJHHS^]PPP {NoݱaAN!T֯d/YxL\|ůyJA۷[mΊϨ|&7dl9;$*qnSv~Q6'z9;;7ۇ 0&yMLݺ~8yN:CΜS_e9G'O/KWkt uݹ}G+ԩSkWx;zܯG;266:иc),8 )}~M48ÆݮMb#ܹspGԩsprr"svFm۝cZ,|xy8z8 ,:=|֔۶u3Rc~"߈HA}q2)/H|qKsip;q҈#wdkI(,++JJVdd?ŰoذDץ3f΢#SXXmٲEwP~h„ biȈ4m\WWU !!A)KbddyL쌌̋˟˖R>+6X*F^guޅ:{GwplFi{;I@׃ ȶ] 8.fόuqI'.ebZɌRV,_F3-Ĺf8DZO+\nxKz9rcj-\V2Zȴw#+O>Թsg#+++1űLPdOLn 2++KRiւCF6.9Ob>N̅E J">񱱱INt:Ͷ{zwm~{ۮwJ2 2K] ^@Br*x8u o7|lΌuFbRIUU $f D Ltq!K +RkтLۚ1m.d(+<JG8o$PzH.cX<Մ sϫV&M[oܤ֭ښz)JSSSb"Jd?hG!MMMRm_61_gbyV(X=|G00wB| :jA$NmA@h7TW qaMxX;6Aϰzp> tG}Q͚5թS羊 P׮]j!A <%dxB P&I][n)Ò!y;p2?`ECP:H&naYoӼ-[V>>"f̢"jjh:ZIUҒIp`9WOb|H$1H瀗lYDaE-Uַ >׏P`gg'C'/u֕T[4#=}]z7yYY yTR<|(LN $єDM*oàX={5Up0^޺u>Pѣ d y%% U׬UlP_pj $m۶I/֏aAVYp5Z805kD ROqͩ!l=ر -}}˷X mdQ#jժUԮ]gLaH <D 6'UC^^^dlԆ43UMw|$i ?d0)XCClll^(HH!?9HC:OMA0WwaJ=DzCP b,f͚6l(*\y D 9s^*tr!bhC9zЬYoUPr F׬UB ^@8Ǩb844T /.#qge椧I&ǫZgHB> F-T ʙ>Fn޼I֭BӧONICMTMKW#1b=uIA 1<SaP>5ö&ԪTUCX-~7r  \!I `yN;\^'HS˰} & eiRK EeGjթs:_ji 13:9IDATT  ~GU`Ʌ"3+`A:{K7~>+Hq29H!NLA3@ tLZvN[\-.&lE˪Q#Bl7CFYBT I\jqϡY[ې>*oU0G3Ǧ_ dRN:?H$Ac \>:O*6l8@" u ]?Te!Z`36fl~T 3P.V._,L5aDqۙ?z$(W߃%`4 E=i)4 h9DJ8 g,$:UP̪FR(D 'k׾ڴ GF x&H5ɤRp&q5ykjWDSիWOV=AO/v߃-y"5kV_S^g14 ժU[PdIB{5~!jV|%cPO$؞ЀLW\;!UNuօ_fcs ,pySt{[C\qt2FzVaKBZUjU_{ IIENDB`kupfer-328/kupfer/plugin/qsicons/Object.png000066400000000000000000000255231500175051100210530ustar00rootroot00000000000000PNG  IHDR>agAMAOX2tEXtSoftwareAdobe ImageReadyqe<*IDATx}k$Uwzuc絻ڇ+vFa!0Xa2ap@+ ;01,0Hh%jyXkЮVZ>f=={{3ofeUWtϻ"r*+wwνI"EܐU]p?|+_M{`.wύo_#ht0zkk)zK1FA2Aam5Łmdc2:-@DFظsph#BTp⮎{i#|@|E 808}zto7a||+G6! 0@^R7K}JM\[6:›!&<%@" L ϽHn7}rWc3 C  sFπJ8BAKra5wy׮GtD ~t] V.!# $ LD!'Mӿ~-i韦Ur;{EiϏno߷Ju)&v\Y 6˒Ck݈BP4Amz^{~=ɿWDvoq5z[Sǫ+ F-yh ë9eDS< ?:YE{- gn`27@>578TFբD(As<& ϸ#M Ok#hz ou Zn4А%`vG% ! 5ZT1wRold_>濻{w򛷷!EgntD @ —Dw; J%w% kQ]\OUI8x9x@Ci@w<6_gwQDBUv>+3}vy5aZBEi6a 2-,? TV6Cyh4n'zہERr <~z5 (V޸N*t(/SY6c mʧ%~-K捽^nh|m |5P_  [@<. yOE)/ߤZ  WD@:/Aˮ kُ|3i:k@1}P.u 20F7*Sjn@!ZyE*=tc!ѳ w0N @6g_Vc//m:+Wk@fbxɒ57]  `WeUm h粜كG}Ϟ֏uWBr@UuAPćxrHejXh>YD@*065xjg+iSTRb ?m?Pɿ%Q\id>{vsWƿ?VtCLKHsFsGؿIy Ko&j)@itՒR+W"ʈ0ȾOlpP0j,x⎬+h5YRveP1JF[io8T@0*4n"*>/)(*S1{n\,Ԑ?x|'~-:"씒I0:q['}r*R0b ')ެ ȥ e=8aL|( J4ha6ב%vAeQ\k'À`84z.n?+J zUNǢ\T{N"T6"Uï77t5ȂHShQ@3| jF]ti$,2~׉G#A+u HIO},^3{x2O"4lTGiph ti: h eZ Ee%q)ƤKQ㑹o]g7՚)FcqDcz D4f, ҰT1|ժY:8U0&x/R4&hu5}6wMH%c%Zq/=J5a rިKBW o* rTzRU0)mbEd9:wv^<>/jebE;Cg$AIaDLTʻ x0:H)A*,"N/xy{pd9{nWW."g Jԃ$H hyx4I'u/+sK㕦ԅ5;R PI%ip.#w;>|?J\1<.M n8AS,\2VE.ݙSVT`,Ld[B4Z#þAU0ߣQ66biud)MxsOl|8~x-7]6pdƯ@„(_']w"F?_De?Mr'L E[kl CګE.QkI,dp+iUʭ&Ok-<_TɭwCHU.@M4jv`+fDVt4i%܉D"%F+1UU*T./'WȎBn  BAE5"/֭/ϵ#g ok"rHioYJQ`)bN9Ve\P Pldue@.s͔@)|-dWcS-PG f-|}੸u]&{Pm}4a^bg4,)ݽȈP1HN, Ԋ3ۅ&9-|+s-J<)@Ћ19`Ydgc.^e 'Ao;W@8A+Px,9gJK[pL2k 7dk;E+,5& t_ƬZ:r*vU-IeR0 ȽT"EW(l}̰o${JksoR 2s)M*\"sGb ++B *\)*fƶH~.۞C } , _ 5 ?$cxHumAniQŒl.HeQ$OLg TYfWv~VYc%۴blNG@:k$(u$|BikY3vfzNFܹu3\ to:aJ} 8R[8 Zj"Hir"cl4rүL-mJ+@RK?w$/pewղ5Ʌ't'4*E.8t'G>I\P[{HѾV⸨!dq6_`8&;Ƴ=N5E gamO~2-^"2>sBuO/b6ht$Cx e=ۮ+K9峱$v{r@0ցؓGUX!`H CTMvц?iH4J >%ƯZ_܂-Xl `x+eS"hgSjm[Xeh0S8 +&w9 ?IYq]v1h˹'6eIilfk(.EZmQ`*aJYp Iտ&k. 9KiH*Be| (D@1$ D! `w,@㖯 Pm| wj}b Wu^P+U7%,Bu)0L@=x|BP:p`QDJ\oRbɠW jg LĦv%.TY'[ xPDh+W>԰]e$:K;~_+|袺S+ mu P)ZF >H4e4@ .CC}{)\qyGq̞JaPJ@#({ mW؜r=ȡS-* :@M]p\!]@mzY V=d{m9* ( yd|Xp rC@9bbh) FNvBeKOU`14l0W+}\)qc`~wSrF Fkh !Fi bg ^O7c_e$4 QF@)4vI.ag22#|v#w}dvâ63T2 eux2l,JmzFp-b_*`:[`w}"Ơ @*"bA ߦ\\Q! hLTi6(/ sILuE6c߱#NuQ` 6 []#/SO;-v;%d8cem`^;&l=bָO ;NnNl0X̀'J[s5naWAǛ P+s6@Hel␳̴w-"2 v#N(Xذ ]وk(QhBxAYXW%L0"]ݦx,u[vaK@CMxe#0RvPx"; h?Xnrw \$Pp87d"6Ç!i{4gt; Ȃo໅~ -Q}K+aKbmxb#kXLsF\I`6F,7n+J- Tk+9"(`s ZYD;ե J wrKtIj 9зQanO׆a6rn^j'IJ A?'C9aHٞF$sG+W/mD:z m|D"ienJv3Ɇfft~m0RZVQPfjAYRJȮ$mRZnՕ#x))D ҹ3SAe3,Z4ȌK zP )bUnH$r M!bM/)}=\Zքuch\<#]0AAkDRpİVrFZ[E ,%^ܶ2 ͬDHdǮB]VM6!Ckcrf[xJċ\JQoL6Z@TE@186Btʔ0R'QJTN1Ca cCmo.= _vꌰ@ʶ-QgV)&"];C/Q'zV8rpieDπ_P?\x O~OW|p׷sUmx/L+E FHsEGkaLd_X^^j'n{Fp ~ JR,TF:pbU_:"^\IX#HZbwe܎hzqYŢ9(}~b B, &Kg%,(Q̬B*j{<p $ڍ)TCHnxܜR22#%]E(bmDsNFDn˒<^]^ITł#:Ev%Qdƭ(V3_9nn;YYHfhp#?,) w-]|Y#~YO Dn@]Z7~q2O7 Æwq3DJ,7ND6H]![DT0f8§l֪Aܶ|*=F)XX(bůiPZ2w4(uVk z C8P} FNr#E"й"U4xDl(OӼkEG>}Pζh;ڄy&ear|jR.X 䖋L Gp|ڽj[qj)A" Pp55# t׏<9wR-"R1D|P[U'\@ Wׇ1kqqn"bXJPLYY煏Oҭv,I찅wf)Gt_MU`7 GYnޜ'3YʕYˢԋeg!: F8s؉hrM(6jEcH9Iv?o=g$l=dPAfH/=wZ-P J|/ahxÔ`n.0Oxߠ[!u@C+s>^|~ RJ*DBjypMF/ xpB?9y hqe. 6YpOg><Ϫ#bR2`b2ЍlߩQ>>^dLb *Yӭx}482hN=Gߎj-u]NRUA9`^^r? drGy3Bc{-&R?vG¦;^yK}_o}Um ` /vcqFg._kADDYPh8Jst84E? _@یg>?}_E;mdKHAW0+hF/ ?it/m[Z6̔Qq2B- A$ < O3w};MxTbZ[7{.6ʕoRB 8~7@EI\o0T@MgyVG^<~=y}H(D~NkM+RpL; B$Q+Ag SL>(A]j a_ rG q"Qx$*Pw}3k!SFn8T!΄IMW@LYuÇY7:VVW|&;?^||D0piڽΧM#O,hp@h@_;ywįbi5`O&P8x1,bzHӃn/#J-i(6g?~g2 wOkl*f R(5D=H~hL}'E[CΫ+e /4]>u„Vx /j'(?yd|)y: `~fSMr0OQM!/K_Ïw_,@)W 4w/M`j$@#P@Gnb=ѧYY?'.rфӿԌY9C5^M>%2Tz7oH>L!l 2eHR{ U7 ^S'cJ:̅v¨뵙;F.P'[] O0iuxrw|[8Ϛ@Pd3l6vT _y Il#|O?p™ {2Ύ 1v0AD2`LLhq2L:v p^P-M)a-4r,kI SɬsG ƌ{an,,֦̭nQ&pCNJ_e|dPw!'@ vpy=s9GϞݏg+GO$uep?ui穜z8M/hSAn=_3C vw0o LT:[XSJkDZq^y {8='d4_LWzwn* .M䰮D! A/|ns11:Cfp<+SĚyr;A1h&/<'{,=8&#!͈&0h`:k6u9BFqzP(mo8KAPA9ΰC#EiF$rSQ鬷SׂV2_ȏ>KfkQ,6f󚗛Z2}.l&Q@vbu^&*I?)~ݻDo5&-v"L1z(ے"DIB)J͉Gʞ̙=m++!OئsM0ФZ4jeb uHv\3i@XH|1Ξl7&H]p Oaq'vّ~,?'sϼhG_Ѥ5n8MkF.C F1ցRQk׮5>u׽U8 lJ0sF?Ī975cU!JXuŧ/| fgg5k!5G.C U&6pS~I 2^gOD/{w (^Yf4z{!)@){ Eԑ_yȜOZ)OcB9w~ Ed]lo6<; $/@Ei I> p_q~?~Ļt($OKtzW? TzB覅xSKri&&.$amsĉuy/w+8BԶҬY;+}!{铏1QPє\ܤe Ư5c'#P^0-TLs߃3nw 'sϞvFi͈><lLj\)_M`nIC/!T @tt~@_3x|cOg r̪B&y 3nV9VP!h`-Z~X{ݷD=S| ԅAS4RP!C&O 5cݷ<LW{كѼYES#r94@* &'jC]ޠyڶ'W_ U)qƋtдmVnʫ1_h2 >k^F mD,@H$͍&o󄫒hh&L^# )u7k Kr O\&w~`"PcRMȔn_`Z4L]-o-k?WgIENDB`kupfer-328/kupfer/plugin/qsicons/Rocket.png000066400000000000000000000222231500175051100210660ustar00rootroot00000000000000PNG  IHDR>agAMAOX2tEXtSoftwareAdobe ImageReadyqe<$%IDATx}ku `%^A(^Bg6J^`=#@1J Pi>2#G?e6@ ^ֿGy?B@EcCGTPF?/zl[a r:ޡj)@ɬ[c`@}vرQ`=a4NW!ޝ$@i`1CKr1;vlݲ'̎[3gB? : D`\Ҏ)B$D0r3#r-ѾN^d QeGEFom.>[@a2++dWAdw ,tnݺ;v$|Le$dwzǒNAJ a4O4GzUicǎbI{KہA'?876b`=L$'/ z'}IH$}W/H_šS4MV W %" [lЊ`(=Gdv"7ΣeweUm۟ٲ5<&,XrMH$5ADЄah4D'MZ5}3eJ\={4CFBJت96^siF-|NJX3Dԉ ~pA^f7P/cc;q}ǹ! y`9GBvtq'f+D"J n۾s)yj бcwn&ي.9,L-9MI H$DՈzz>@?*`%2FG^2l^[("i*B<ͥ2HJ`YhpȪ*R@4A8el-440i)`#G73<80X# dkuH^T_9)yjl,A$uIy8b$оAR &~.fOVBFd+qA:TF(sϿ_z@5!`sOs~>1~e4X~7hcԦtp8;(FE"$"bM6WFGG72?ǝ{yKgYU2M9/p\?Pm.`9_ J>-@BW7(CB\#:rtRV$[Мo}/i|g|< 8@ "HH5 x@2!LsLUI$`) B>j{+U-蘐]IÿgiJarPn0Vɚe|"H@>c4$ժmmGִ QY6:zQ&1'~|Et+[M($XZ|! )skx%DrILzw{GkF-s?o8'D%#MzNj/`$k^@þj(h "#҅E$%BK!ZX1{>HK?+3~>J{_\p~hkˆ?N8lo%$ 聮7 vJvJ=Hw/].}625VIn{q/t܍Y|hpȳX,_z bi j80YƜi=۶nxKl{"cW|b:k]]˦sBg+mB0v6v(LDM7p d) E)j x`CXu`JMBaxl)N>}5~XEđWWHj jG66ylME֭X0Y0~3ac?f:e6)`|~so!ṑ^B$8!6pf4ʌ!CFaJJk}r0`919K8i@@5rx+|cyEd a55# ^Uxڃ)hxOzu!E,v%,̌?(<N$l`]6WD<+[ns7$ůseDœ#<Ӛr!Z0jaQh''d"pi\U:bsh0;"odu5\("p^ .!| d1D2`1! =8Zϭt bVq"(qŶ79ɸ~︑g. ?|$ӺWJ_GڡJ_G^:rBB  HH8j-(\,b. P s y+Kͥ^ u@]el\,}usՂPh A=E"F4eד7rI)VxF IxJ mRh)~6<$N[iy<## E\k,7|c»w]A\cSt G3<HC04ն(KLa}D;c9H* ifxw#hng|~9Kgi0cG|%Kj7n[NXt]4Bk70d:D1GQ(@H똴|B]g.g$_(RYߝ$ "OW"Nb@y=vo#7`yKCHΊ_tA4ʐM¶v q,I y. ui.GGLW*S?WyOdsZ,UHIn}L"7 ]B2qh&P 8(cx{D} pNI Pyj==e!P^*arc,kuB;a-Ouc}\4 ;k1raFtT!>>.|3d 43Gp7Bi( \ xXj|Dzkv6-A+cϕ6jP-iand !gDV#M.]H_V+y-p'697?x7ҪԤOӵ~Rk˙%\B\Q#b3Ī$#ED .΄P_\\ tedJr |1Oټ\XK u.BV K`d?X},N"biqQPխx H&[JjaR"Y:﫯Z%( {P\?7?;J+DO3q9kvr +, OyF7:Pqf`9F5yBg>h[ p_Rw 5ibܑjz ö+LYDZ 1t]}3'͡NҔi52&FC._}IUqK ܧ~.,.=fĿ bH$szn֩a P]99؇E"u Ya{~'':q5e?19ٳgeY 'ަDƦ9ەu'dZտ&ѵxMDgp sI)c,)c%Z$>Lf=`x 0pW[\^<[Q\vmEsH(jđ L%c7Z@XE|~8$ yt˥ˏ~4z٧Ν@o)neEo99G,!(HEld',r:eTbFS\t2qNvꟛwz"YKVƑ(,JrNEXj.$b@4rm ro"p)ڕ˟2%JHԻ}2ڶcߗ''/ԏ|Th䏮%zg{!i-?Z\ J'҇Y/_6q}ڜ_G 4g4.U/[k|%p3&34(P`e.[^ZZ6/gff.UJ-W.ԯn4l|S!f 3z$%\r;8'R#y܇uaJssի[J =ٙsVBϷUWוHR °wa%ȍ.:!7#{ʕB4%Jۇ̿;1{ҥO,-..(m[8_+}L #aHm㩱iCs҅e[ 0eitggtv?qx(eBf yIy39L!)w:rR7eiDC'~3;9e'gr֐?* wX> # iJ ͻ\y35utuuFOƺ@Ʀ2*A)A;JdЌ_ff,Wc7nHߜ6 ͻˢ N&Dʱ0ׯ]3{ݻiس4Z O FcMׯ 릦 @VqMo ?$J{kN9@ w1fa!m6/Is̙- f[C<033 mcFʤ$nB{sW/`ek.]sYadmp|DkŖ `];6bmd ~iBPo5<"k0AFjc?0R )=peQd߽m۶߿,Y:Fw%mj _x\f ҁE7R;i-o4bQ&]x?BF/[> iTߋkjN9O@]K5W^y}(U%>FYU @јSVW݉w@tS:$_1\$w**a!/P?w1Gw (*R*3}z+W|\|!(]zb ܴl 0d _pIENDB`kupfer-328/kupfer/plugin/qsicons/__init__.py000066400000000000000000000016511500175051100212440ustar00rootroot00000000000000""" Acquired from https://github.com/quicksilver/Quicksilver Which says ''' Licensed under the Apache License, Version 2.0 (the "License"); you may not use this software 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. ''' Apache License 2-0 is GPLv3+ compatible --ulrik """ __kupfer_name__ = _("Quicksilver Icons") __description__ = "" __version__ = "" __author__ = "Quicksilver Authors. License: Apache 2.0" import typing as ty if ty.TYPE_CHECKING: from gettext import gettext as _ # noqa def initialize_plugin(name): pass kupfer-328/kupfer/plugin/qsicons/icon-list000066400000000000000000000005121500175051100207520ustar00rootroot00000000000000# ID File flags # !override means that it overrides the current icon theme # (the default is to not override it) kupfer-launch Rocket.png !override kupfer-object Object.png !override kupfer-object-multiple Object.png !override kupfer-execute Action.png !override kupfer-catalog Find.png !override kupfer-search Find.png !override kupfer-328/kupfer/plugin/quickview.py000066400000000000000000000060131500175051100200320ustar00rootroot00000000000000__kupfer_name__ = _("Quick Image Viewer") __kupfer_actions__ = ("View",) __description__ = "" __version__ = "" __author__ = "" import shutil import typing as ty from gi.repository import Gdk, GdkPixbuf, GLib, Gtk from kupfer import launch from kupfer.obj import Action, FileLeaf, OperationError if ty.TYPE_CHECKING: from gettext import gettext as _ def _on_size_prepared(loader, width, height, max_w, max_h): if width <= max_w and height <= max_h: return w_scale = max_w * 1.0 / width h_scale = max_h * 1.0 / height scale = min(w_scale, h_scale) loader.set_size(int(width * scale), int(height * scale)) def load_image_max_size( filename: str, width: int, height: int ) -> GdkPixbuf.Pixbuf: pbloader = GdkPixbuf.PixbufLoader() pbloader.connect("size-prepared", _on_size_prepared, width, height) try: with open(filename, "rb") as fin: shutil.copyfileobj(fin, pbloader) pbloader.close() except (GLib.GError, OSError) as exc: raise OperationError(exc) from exc return pbloader.get_pixbuf() class View(Action): def __init__(self): Action.__init__(self, _("View Image")) self.open_windows = {} def item_types(self): yield FileLeaf def valid_for_item(self, leaf): return leaf.is_content_type("image/*") def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx ## If the same file @obj is already open, ## then close its window. if leaf.object in self.open_windows: open_window = self.open_windows.pop(leaf.object) open_window.destroy() return image_widget = Gtk.Image() image_widget.set_from_pixbuf( load_image_max_size( leaf.object, Gdk.Screen.height(), Gdk.Screen.width() ) ) image_widget.show() window = Gtk.Window() window.set_title(str(leaf)) # pylint: disable=no-member window.set_position(Gtk.WindowPosition.CENTER) # pylint: disable=no-member window.add(image_widget) ctx.environment.present_window(window) window.connect( "key-press-event", self._on_window_key_press, leaf.object ) window.connect("delete-event", self._on_window_deleted, leaf.object) self.open_windows[leaf.object] = window def _on_window_deleted(self, window, event, filename): self.open_windows.pop(filename, None) return False def _on_window_key_press(self, window, event, filepath): if Gdk.keyval_name(event.keyval) == "Escape": self._on_window_deleted(window, event, filepath) window.destroy() return True if Gdk.keyval_name(event.keyval) == "Return": self._on_window_deleted(window, event, filepath) launch.show_path(filepath) window.destroy() return True return False def get_description(self): return None kupfer-328/kupfer/plugin/recoll.py000066400000000000000000000066701500175051100173140ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("Recoll") __kupfer_actions__ = ("Recoll", "OpenInRecoll") __description__ = _("Search in Recoll full text search system") __version__ = "" __author__ = "KB" import base64 import shutil import subprocess import typing as ty from contextlib import suppress from gi.repository import Gio from kupfer import launch, plugin_support from kupfer.obj import Action, FileLeaf, OperationError, Source, TextLeaf from kupfer.obj.special import CommandNotAvailableLeaf if ty.TYPE_CHECKING: from gettext import gettext as _ plugin_support.check_command_available("recoll") class RecollLeaf(FileLeaf): def __init__(self, fpath: str, title: str, mtype: str): super().__init__(fpath) self._title = title self._mtype = mtype if title != fpath: self.kupfer_add_alias(title) def get_description(self) -> str | None: return self._title def get_content_type(self) -> str | None: return self._mtype or super().get_content_type() class Recoll(Action): rank_adjust: int = -5 def __init__(self): Action.__init__(self, _("Search in Recoll")) def is_factory(self): return True def activate(self, leaf, iobj=None, ctx=None): return RecollQuerySource(leaf.object) def item_types(self): yield TextLeaf def get_description(self): return _("Search for text in Recoll database") def get_icon_name(self): return "find" class OpenInRecoll(Action): rank_adjust: int = -4 def __init__(self): Action.__init__(self, _("Open in Recoll")) def activate(self, leaf, iobj=None, ctx=None): try: launch.spawn_async_raise(["recoll", "-q", str(leaf)]) except launch.SpawnError as exc: raise OperationError(exc) from exc def item_types(self): yield TextLeaf def get_description(self): return _("Open Recoll and search for text") def get_icon_name(self): return "find" class RecollQuerySource(Source): def __init__(self, query): Source.__init__(self, name=_('Results for "%s"') % query) self._query = query.strip() self._max_items = 100 def repr_key(self): return f"recoll_query:{self._query}" def get_items(self): recoll_cmd = shutil.which("recoll") if not recoll_cmd: yield CommandNotAvailableLeaf(__name__, __kupfer_name__, "recoll") return if not self._query: return command = [ recoll_cmd, "-t", "-n", str(self._max_items), "-F", "url filename title mtype", "-S", "relevancyrating", "-D", self._query, ] with subprocess.Popen(command, stdout=subprocess.PIPE) as proc: out, _error = proc.communicate() for line in out.splitlines(): if line.startswith(b"Recoll") or b"results" in line: continue uri, filename, title, mtype, *_dummy = tuple( base64.b64decode(v).decode() for v in line.split(b" ") ) with suppress(OSError): gfile = Gio.File.new_for_uri(uri) fpath = gfile.get_path() yield RecollLeaf(fpath, title or filename, mtype) def has_parent(self) -> bool: return False kupfer-328/kupfer/plugin/rhythmbox.py000066400000000000000000000405431500175051100200550ustar00rootroot00000000000000""" Changes: 2012-10-17 Karol Będkowski: + control rhythmbox via dbus interface + load songs via dbus interface 2023-02-19 KB: + catch errors when no mpris is available via dbus + simplify dbus string conversion NOTE: this require Rhythmbox with mpris support (i.e. rhythmbox-plugins package installed) """ from __future__ import annotations __kupfer_name__ = _("Rhythmbox") __kupfer_sources__ = ("RhythmboxSource",) __description__ = _("Play and enqueue tracks and browse the music library") __version__ = "2023.1" __author__ = "US, Karol Będkowski" import itertools import operator import os import typing as ty from collections import defaultdict from hashlib import md5 import dbus from gi.repository import Gio from kupfer import config, icons, launch, plugin_support from kupfer.obj import ( Action, FileLeaf, Leaf, NotAvailableError, OperationError, RunnableLeaf, Source, SourceLeaf, ) from kupfer.obj.apps import AppLeafContentMixin from kupfer.obj.helplib import PicklingHelperMixin from kupfer.plugin import rhythmbox_support from kupfer.support import kupferstring, pretty, weaklib if ty.TYPE_CHECKING: from gettext import gettext as _ plugin_support.check_dbus_connection() plugin_support.check_command_available("rhythmbox-client") __kupfer_settings__ = plugin_support.PluginSettings( { "key": "toplevel_artists", "label": _("Include artists in top level"), "type": bool, "value": True, }, { "key": "toplevel_albums", "label": _("Include albums in top level"), "type": bool, "value": False, }, { "key": "toplevel_songs", "label": _("Include songs in top level"), "type": bool, "value": False, }, ) _BUS_NAME = "org.gnome.Rhythmbox3" _OBJ_PATH_MPRIS = "/org/mpris/MediaPlayer2" _OBJ_NAME_MPRIS_PLAYER = "org.mpris.MediaPlayer2.Player" _OBJ_PATH_MEDIASERVC_ALL = "/org/gnome/UPnP/MediaServer2/Library/all" _OBJ_NAME_MEDIA_CONT = "org.gnome.UPnP.MediaContainer2" def _toutf8_lossy(ustr): return ustr.encode("UTF-8", "replace") def _create_dbus_connection_mpris(obj_name, obj_path, activate=False): """Create dbus connection to Rhytmbox @activate: if True, start program if not running """ interface = None sbus = dbus.SessionBus() try: proxy_obj = sbus.get_object( "org.freedesktop.DBus", "/org/freedesktop/DBus" ) dbus_iface = dbus.Interface(proxy_obj, "org.freedesktop.DBus") if (activate or dbus_iface.NameHasOwner(_BUS_NAME)) and ( obj := sbus.get_object(_BUS_NAME, obj_path) ): interface = dbus.Interface(obj, obj_name) except dbus.exceptions.DBusException as err: pretty.print_debug(err) return interface def _tracknr(string: ty.Any) -> int | None: try: return int(string) except ValueError: return None def _get_all_songs_via_dbus(): try: iface = _create_dbus_connection_mpris( _OBJ_NAME_MEDIA_CONT, _OBJ_PATH_MEDIASERVC_ALL ) if iface: for item in iface.ListItems(0, 9999, ["*"]): yield { "album": str(item["Album"]), "artist": str(item["Artist"]), "title": str(item["DisplayName"]), "track-number": _tracknr(item["TrackNumber"]), "location": str(item["URLs"][0]), "date": str(item["Date"]), } except Exception: pretty.print_exc(__name__, "_get_all_songs_via_dbus error") def spawn_async(argv): try: launch.spawn_async_raise(argv) except launch.SpawnError as exc: raise OperationError(exc) from exc def enqueue_songs(info, clear_queue=False, play_first=False): songs = list(info) if not songs: return qargv = ["rhythmbox-client"] if clear_queue: qargv.append("--clear-queue") if play_first and songs: song = songs[0] songs = songs[1:] uri = song["location"] qargv.extend(("--play-uri", uri)) for song in songs: uri = song["location"] qargv.extend(("--enqueue", uri)) spawn_async(qargv) class ClearQueue(RunnableLeaf): def __init__(self): RunnableLeaf.__init__(self, name=_("Clear Queue")) def run(self, ctx=None): spawn_async(("rhythmbox-client", "--no-start", "--clear-queue")) def get_icon_name(self): return "edit-clear" def _songs_from_leaf(leaf): "return a sequence of songs from @leaf" if isinstance(leaf, SongLeaf): return (leaf.object,) if isinstance(leaf, TrackCollection): return tuple(leaf.object) return () class PlayTracks(Action): action_accelerator = "o" rank_adjust = 5 def __init__(self): Action.__init__(self, _("Play")) def activate(self, leaf, iobj=None, ctx=None): self.activate_multiple((leaf,)) def activate_multiple(self, objects): # for multiple dispatch, play the first and enqueue the rest to_enqueue = [] for leaf in objects: to_enqueue.extend(_songs_from_leaf(leaf)) if to_enqueue: enqueue_songs( to_enqueue, clear_queue=len(to_enqueue) > 1, play_first=True ) def get_description(self): return _("Play tracks in Rhythmbox") def get_icon_name(self): return "media-playback-start" class Enqueue(Action): action_accelerator = "e" def __init__(self): Action.__init__(self, _("Enqueue")) def activate(self, leaf, iobj=None, ctx=None): self.activate_multiple((leaf,)) def activate_multiple(self, objects): to_enqueue = [] for leaf in objects: to_enqueue.extend(_songs_from_leaf(leaf)) enqueue_songs(to_enqueue) def get_description(self): return _("Add tracks to the play queue") def get_gicon(self): return icons.ComposedIcon("gtk-execute", "media-playback-start") def get_icon_name(self): return "media-playback-start" class SongLeaf(Leaf): serializable = 1 def __init__(self, info, name=None): """Init with song info @info: Song information dictionary """ Leaf.__init__(self, info, name or info["title"]) def repr_key(self): """To distinguish songs by the same name""" return ( self.object["title"], self.object["artist"], self.object["album"], ) def get_actions(self): yield PlayTracks() yield Enqueue() yield GetFile() def get_description(self): # TRANS: Song description return _("by %(artist)s from %(album)s") % { "artist": self.object["artist"], "album": self.object["album"], } def get_icon_name(self): return "audio-x-generic" def get_text_representation(self): return self.name class GetFile(Action): def __init__(self): super().__init__(_("Get File")) def has_result(self): return True def activate(self, leaf, iobj=None, ctx=None): gfile = Gio.File.new_for_uri(leaf.object["location"]) try: path = gfile.get_path() except Exception as exc: # On utf-8 decode error # FIXME: Unrepresentable path raise OperationError(exc) from exc if path: result = FileLeaf(path) if result.is_valid(): return result raise NotAvailableError(str(leaf)) class CollectionSource(Source): def __init__(self, leaf): Source.__init__(self, str(leaf)) self.leaf = leaf def get_items(self): for song in self.leaf.object: yield SongLeaf(song) def repr_key(self): return self.leaf.repr_key() def get_description(self): return self.leaf.get_description() def get_thumbnail(self, width, height): return self.leaf.get_thumbnail(width, height) def get_gicon(self): return self.leaf.get_gicon() def get_icon_name(self): return self.leaf.get_icon_name() class TrackCollection(Leaf): """A generic track collection leaf, such as one for an Album or an Artist """ def __init__(self, info, name): """Init with track collection @info: Should be a sequence of song information dictionaries """ Leaf.__init__(self, info, name) def get_actions(self): yield PlayTracks() yield Enqueue() def has_content(self): return True def content_source(self, alternate=False): return CollectionSource(self) def get_icon_name(self): return "media-optical" class AlbumLeaf(TrackCollection): def get_description(self): artist = None for song in self.object: if not artist: artist = song["artist"] elif artist != song["artist"]: # TRANS: Multiple artist description "Artist1 et. al. " artist = _("%s et. al.") % artist break # TRANS: Album description "by Artist" return _("by %s") % (artist,) def _get_thumb_local(self): # try local filesystem uri = self.object[0]["location"] artist = self.object[0]["artist"].lower() album = self.object[0]["album"].lower() gfile = Gio.File.new_for_uri(uri) cdir = gfile.resolve_relative_path("../").get_path() # We don't support unicode ATM bs_artist_album = " - ".join([artist, album]) bs_artist_album2 = "-".join([artist, album]) # " - ".join([us.encode("ascii", "ignore") for us in (artist, album)]) cover_names = ( "cover.jpg", "album.jpg", "albumart.jpg", "cover.gif", "album.png", ".folder.jpg", "folder.jpg", bs_artist_album + ".jpg", bs_artist_album2 + ".jpg", ) try: for cover_name in os.listdir(cdir): if cover_name.lower() in cover_names: cfile = gfile.resolve_relative_path("../" + cover_name) return cfile.get_path() except OSError: pretty.print_exc(__name__) return None def _get_thumb_mediaart(self): """old thumb location""" ltitle = str(self).lower() # ignore the track artist -- use the space fallback # hash of ' ' as fallback hspace = "7215ee9c7d9dc229d2921a40e899ec5f" htitle = md5(_toutf8_lossy(ltitle)).hexdigest() hartist = hspace cache_name = f"album-{hartist}-{htitle}.jpeg" return config.get_cache_file(("media-art", cache_name)) def get_thumbnail(self, width, height): if not hasattr(self, "cover_file"): # pylint: disable=attribute-defined-outside-init self.cover_file = ( self._get_thumb_mediaart() or self._get_thumb_local() ) return icons.get_pixbuf_from_file(self.cover_file, width, height) class ArtistAlbumsSource(CollectionSource): def get_items(self): albums: dict[str, list[dict[str, ty.Any]]] = defaultdict(list) for song in self.leaf.object: albums[song["album"]].append(song) names = kupferstring.locale_sort(albums.keys()) names.sort(key=lambda name: albums[name][0]["date"]) for album in names: yield AlbumLeaf(albums[album], album) def should_sort_lexically(self): return False class ArtistLeaf(TrackCollection): def get_description(self): # TRANS: Artist songs collection description return _("Tracks by %s") % (str(self),) def get_gicon(self): return icons.ComposedIcon("media-optical", "system-users") def content_source(self, alternate=False): if alternate: return CollectionSource(self) return ArtistAlbumsSource(self) class RhythmboxAlbumsSource(Source): def __init__(self, library): Source.__init__(self, _("Albums")) self.library = library def get_items(self): for album in self.library: yield AlbumLeaf(self.library[album], album) def should_sort_lexically(self): return True def get_description(self): return _("Music albums in Rhythmbox Library") def get_gicon(self): return icons.ComposedIcon( "rhythmbox", "media-optical", emblem_is_fallback=True ) def get_icon_name(self): return "rhythmbox" def provides(self): yield AlbumLeaf class RhythmboxArtistsSource(Source): def __init__(self, library): Source.__init__(self, _("Artists")) self.library = library def get_items(self): for artist in self.library: yield ArtistLeaf(self.library[artist], artist) def should_sort_lexically(self): return True def get_description(self): return _("Music artists in Rhythmbox Library") def get_gicon(self): return icons.ComposedIcon( "rhythmbox", "system-users", emblem_is_fallback=True ) def get_icon_name(self): return "rhythmbox" def provides(self): yield ArtistLeaf def _locale_sort_artist_album_songs(artists): """Locale sort dictionary @artists by Artist, then Album; each artist in @artists should already contain songs grouped by album and sorted by track number. """ for artist in kupferstring.locale_sort(artists): artist_songs = artists[artist] albums: dict[str, list[rhythmbox_support.Song]] = defaultdict(list) for album, songs in itertools.groupby( artist_songs, operator.itemgetter("album") ): albums[album].extend(songs) for album in kupferstring.locale_sort(albums): yield from albums[album] class RhythmboxSongsSource(Source): """The whole song library in Leaf representation""" def __init__(self, library): Source.__init__(self, _("Songs")) self.library = library def get_items(self): for song in _locale_sort_artist_album_songs(self.library): yield SongLeaf(song) def get_actions(self): return () def get_description(self): return _("Songs in Rhythmbox library") def get_gicon(self): return icons.ComposedIcon( "rhythmbox", "audio-x-generic", emblem_is_fallback=True ) def provides(self): yield SongLeaf class RhythmboxSource(AppLeafContentMixin, Source, PicklingHelperMixin): appleaf_content_id = ("rhythmbox", "org.gnome.Rhythmbox3") source_scan_interval: int = 3600 def __init__(self): super().__init__(_("Rhythmbox")) self._version = 3 self._songs = [] def initialize(self): bus = dbus.SessionBus() weaklib.dbus_signal_connect_weakly( bus, "NameOwnerChanged", self._name_owner_changed, dbus_interface="org.freedesktop.DBus", arg0=_BUS_NAME, ) def _name_owner_changed(self, name, old, new): if new: self.mark_for_update() def pickle_prepare(self): self.mark_for_update() def get_items(self): # first try to load songs via dbus songs = list(_get_all_songs_via_dbus()) self._songs = songs = songs or self._songs albums = rhythmbox_support.parse_rhythmbox_albums(songs) artists = rhythmbox_support.parse_rhythmbox_artists(songs) yield ClearQueue() artist_source = RhythmboxArtistsSource(artists) album_source = RhythmboxAlbumsSource(albums) songs_source = RhythmboxSongsSource(artists) yield SourceLeaf(artist_source) yield SourceLeaf(album_source) yield SourceLeaf(songs_source) # we use get_leaves here to get sorting etc right if __kupfer_settings__["toplevel_artists"]: yield from artist_source.get_leaves() if __kupfer_settings__["toplevel_albums"]: yield from album_source.get_leaves() if __kupfer_settings__["toplevel_songs"]: yield from songs_source.get_leaves() def get_description(self): return _("Play and enqueue tracks and browse the music library") def get_icon_name(self): return "rhythmbox" def provides(self): yield RunnableLeaf yield SourceLeaf yield SongLeaf kupfer-328/kupfer/plugin/rhythmbox_support.py000066400000000000000000000032641500175051100216500ustar00rootroot00000000000000import operator import typing as ty from collections import defaultdict Song = dict[str, ty.Any] def _sort_album(album: list[Song]) -> None: """Sort album in track order""" def get_track_number(rec): try: tnr = int(rec["track-number"]) except (KeyError, ValueError): tnr = 0 return tnr album.sort(key=get_track_number) def _sort_album_order(songs: list[Song]) -> None: """Sort songs in order by album then by track number >>> songs = [ ... {"title": "a", "album": "B", "track-number": 2}, ... {"title": "b", "album": "A", "track-number": 1}, ... {"title": "c", "album": "B", "track-number": 1}, ... ] >>> _sort_album_order(songs) >>> [s["title"] for s in songs] ['b', 'c', 'a'] """ songs.sort(key=operator.itemgetter("date", "album", "track-number")) def parse_rhythmbox_albums(songs: ty.Iterable[Song]) -> dict[str, list[Song]]: albums: dict[str, list[Song]] = defaultdict(list) for song in songs: if not song["artist"]: continue if song_album := song["album"]: albums[song_album].append(song) # sort album in track order for album in albums.values(): _sort_album(album) return albums def parse_rhythmbox_artists(songs: ty.Iterable[Song]) -> dict[str, list[Song]]: artists: dict[str, list[Song]] = defaultdict(list) for song in songs: if song_artist := song["artist"]: artists[song_artist].append(song) # sort in album + track order for artist in artists.values(): _sort_album_order(artist) return artists if __name__ == "__main__": import doctest doctest.testmod() kupfer-328/kupfer/plugin/screen.py000066400000000000000000000071221500175051100173040ustar00rootroot00000000000000__kupfer_name__ = _("GNU Screen") __kupfer_sources__ = ("ScreenSessionsSource",) __description__ = _("Active GNU Screen sessions") __version__ = "" __author__ = "Ulrik Sverdrup " import os import pwd import typing as ty from pathlib import Path from kupfer import launch, plugin_support from kupfer.obj import Action, Leaf, Source from kupfer.obj.helplib import FilesystemWatchMixin if ty.TYPE_CHECKING: from gettext import gettext as _ plugin_support.check_command_available("screen") def screen_sessions_infos(): """ Yield tuples of pid, name, time, status for running screen sessions """ with os.popen("screen -list") as pipe: output = pipe.read() for line in output.splitlines(): fields = line.split("\t") if len(fields) == 4: # noqa:PLR2004 _empty, pidname, time, status = fields pid, name = pidname.split(".", 1) time = time.strip("()") status = status.strip("()") yield (pid, name, time, status) def get_username(): """Return username for current user""" info = pwd.getpwuid(os.geteuid()) return info[0] class ScreenSession(Leaf): """Represented object is the session pid as string""" def get_actions(self): return (AttachScreen(),) def is_valid(self): for pid, *_rest in screen_sessions_infos(): if self.object == pid: return True return False def get_description(self): for pid, _name, time, status in screen_sessions_infos(): if self.object == pid: # Handle localization of status status_human = status if status == "Attached": status_human = _("Attached") elif status == "Detached": status_human = _("Detached") return _("%(status)s session (%(pid)s) created %(time)s") % { "status": status_human, "pid": pid, "time": time, } return f"{self.name} ({self.object})" def get_icon_name(self): return "gnome-window-manager" class ScreenSessionsSource(Source, FilesystemWatchMixin): """Source for GNU Screen sessions""" source_scan_interval: int = 3600 def __init__(self): super().__init__(_("Screen Sessions")) self.screen_dir = None self.monitor_token = None def initialize(self): ## the screen dir might not exist when we start ## luckily, gio can monitor directories before they exist self.screen_dir = ( os.getenv("SCREENDIR") or f"/var/run/screen/S-{get_username()}" ) if not Path(self.screen_dir).exists(): self.output_debug("Screen socket dir or SCREENDIR not found") self.monitor_token = self.monitor_directories( self.screen_dir, force=True ) def get_items(self): assert self.screen_dir if not Path(self.screen_dir).exists(): return for pid, name, _time, _status in screen_sessions_infos(): yield ScreenSession(pid, name) def get_description(self): return _("Active GNU Screen sessions") def get_icon_name(self): return "terminal" def provides(self): yield ScreenSession class AttachScreen(Action): def __init__(self): super().__init__(name=_("Attach")) def activate(self, leaf, iobj=None, ctx=None): pid = leaf.object action_argv = ["screen", "-x", "-R", str(pid)] launch.spawn_in_terminal(action_argv) kupfer-328/kupfer/plugin/screenshot.py000066400000000000000000000122701500175051100202020ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("Screenshot") __kupfer_sources__ = ("ScreenshotTools",) __kupfer_text_sources__ = () __kupfer_actions__ = () __description__ = _("Take screenshot of screen using Scrot or Flameshot.") __version__ = "2023.1" __author__ = "KB" import os import shutil import tempfile import typing as ty from pathlib import Path from gi.repository import Gdk, Gtk from kupfer import icons, launch, plugin_support, runtimehelper from kupfer.obj import FileLeaf, OperationError, RunnableLeaf, Source from kupfer.obj.special import CommandNotAvailableLeaf if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_settings__ = plugin_support.PluginSettings( { "key": "tool", "label": _("Tool:"), "type": str, "value": "scrot", "alternatives": [ "Scrot", "Flameshot", ], }, { "key": "format", "label": _("Format:"), "type": str, "value": "jpg", "alternatives": [ "JPG", "PNG", ], }, ) def _tool_cmd_path(tool: str) -> str | None: if tool == "Flameshot": return shutil.which("flameshot") if tool == "Scrot": return shutil.which("scrot") return None class ScreenshotToFile(RunnableLeaf): def __init__(self, name=_("Take Screenshot To File")): super().__init__(name=name) def has_result(self): return True def wants_context(self): return True def run(self, ctx=None): assert ctx ext = __kupfer_settings__["format"].lower() # take temp file name file, path = tempfile.mkstemp(f".{ext}", prefix="screenshot") os.close(file) # file must be deleted Path(path).unlink() runtimehelper.register_async_file_result(ctx, path) tool = __kupfer_settings__["tool"] cmd = _tool_cmd_path(tool) if not cmd: return CommandNotAvailableLeaf(__name__, __kupfer_name__, tool) argv: tuple[str, ...] if tool == "Flameshot": argv = ("flameshot", "gui", "--path", path, "--delay", "1000") elif tool == "scrot": argv = ("scrot", "--file", path, "--delay", "1") else: return None try: launch.spawn_async_raise(argv) except launch.SpawnError as exc: raise OperationError(exc.args[0].message) from exc return FileLeaf(path) def item_types(self): yield FileLeaf def get_gicon(self): return icons.ComposedIcon( "video-display", "document-save", minimum_icon_size=16 ) class _SSToClipboardNative(RunnableLeaf): """Take screenshot and put image to the clipboard using native method provided by tool.""" def __init__(self, name=_("Take Screenshot to the Clipboard")): super().__init__(name=name) def wants_context(self): return True def run(self, ctx=None): assert ctx argv = ("flameshot", "gui", "--clipboard") try: launch.spawn_async_raise(argv) except launch.SpawnError as exc: raise OperationError(exc.args[0].message) from exc def get_gicon(self): return icons.ComposedIcon( "video-display", "document-save", minimum_icon_size=16 ) class SSToClipboard(RunnableLeaf): """Take screenshot and put image to the clipboard for tools that not provided clipboard support. Take screenshot to file, read image from file and put it in the clipboard.""" def __init__(self, name=_("Take Screenshot to the Clipboard")): super().__init__(name=name) def wants_context(self): return True def run(self, ctx=None): assert ctx # take temp file name file, path = tempfile.mkstemp(".png", prefix="screenshot") os.close(file) # for now only scrot argv = ["scrot", "--file", path, "--delay", "1", "--overwrite"] def finish_callback(acommand, stdout, stderr): if not acommand.exit_status and ( pixbuf := icons.get_pixbuf_from_file(path) ): clip = Gtk.Clipboard.get_default(Gdk.Display.get_default()) clip.set_image(pixbuf) Path(path).unlink() launch.AsyncCommand(argv, finish_callback, 10) def get_gicon(self): return icons.ComposedIcon( "video-display", "document-save", minimum_icon_size=16 ) class ScreenshotTools(Source): serializable = None def __init__(self, name=_("Screenshot tools")): super().__init__(name) def is_dynamic(self): return True def get_items(self): yield ScreenshotToFile() tool = __kupfer_settings__["tool"] if not _tool_cmd_path(tool): yield CommandNotAvailableLeaf(__name__, __kupfer_name__, tool) return if tool == "Flameshot": yield _SSToClipboardNative() elif tool == "Scrot": yield SSToClipboard() def provides(self): yield RunnableLeaf def get_gicon(self): return icons.ComposedIcon( "video-display", "document-save", minimum_icon_size=16 ) kupfer-328/kupfer/plugin/sendkeys.py000066400000000000000000000106241500175051100176530ustar00rootroot00000000000000__kupfer_name__ = _("Send Keys") __kupfer_actions__ = ("CopyAndPaste", "SendKeys", "TypeText") __description__ = _("Send synthetic keyboard events using xautomation") __version__ = "" __author__ = "" import typing as ty from contextlib import suppress from gi.repository import Gdk, Gtk from kupfer import interface, launch from kupfer.obj import Action, Leaf, OperationError, TextLeaf if ty.TYPE_CHECKING: from gettext import gettext as _ # delay for first keypress and all following _INIT_DELAY = "usleep 300000" _INTER_DELAY = "usleep 50000" class CopyAndPaste(Action): # rank down since it applies everywhere rank_adjust = -2 def __init__(self): Action.__init__(self, _("Paste to Foreground Window")) def activate(self, leaf, iobj=None, ctx=None): clip = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) interface.copy_to_clipboard(leaf, clip) xte_paste_argv = [ "xte", _INIT_DELAY, "keydown Control_L", "key v", "keyup Control_L", ] try: launch.spawn_async_raise(xte_paste_argv) except launch.SpawnError as exc: raise OperationError(exc) from exc def item_types(self): yield Leaf def valid_for_item(self, leaf): with suppress(AttributeError): return bool(interface.get_text_representation(leaf)) def get_description(self): return _("Copy to clipboard and send Ctrl+V to foreground window") def get_icon_name(self): return "edit-paste" class SendKeys(Action): def __init__(self): Action.__init__(self, _("Send Keys")) def activate(self, leaf, iobj=None, ctx=None): return self.activate_multiple((leaf,)) def activate_multiple(self, objects): xte_sendkey_argv = ["xte", _INIT_DELAY] iterobjects = iter(objects) for obj in iterobjects: xte_sendkey_argv.extend(self.make_keystr_arguments(obj.object)) break for obj in iterobjects: xte_sendkey_argv.append(_INTER_DELAY) xte_sendkey_argv.extend(self.make_keystr_arguments(obj.object)) try: launch.spawn_async_raise(xte_sendkey_argv) except launch.SpawnError as exc: raise OperationError(exc) from exc def make_keystr_arguments(self, keystr): keys, orig_mods = Gtk.accelerator_parse(keystr) modifiers = { Gdk.ModifierType.SHIFT_MASK: "Shift_L", Gdk.ModifierType.CONTROL_MASK: "Control_L", Gdk.ModifierType.SUPER_MASK: "Super_L", Gdk.ModifierType.MOD1_MASK: "Alt_L", # pylint: disable=no-member } mod_names = [] mods = orig_mods for mod, value in modifiers.items(): if mod & mods: mod_names.append(value) mods &= ~mod if mods != 0: label = Gtk.accelerator_get_label(keys, orig_mods) raise OperationError(f"Keys not yet implemented: {label}") mods_down = ["keydown " + n for n in mod_names] mods_up = ["keyup " + n for n in reversed(mod_names)] return [*mods_down, f"key {Gdk.keyval_name(keys)}", *mods_up] def item_types(self): yield TextLeaf def valid_for_item(self, leaf): text = leaf.object keys, _mods = Gtk.accelerator_parse(text) return bool(keys) def get_description(self): return _("Send keys to foreground window") class TypeText(Action): rank_adjust = -2 def __init__(self): Action.__init__(self, _("Type Text")) def activate(self, leaf, iobj=None, ctx=None): text = interface.get_text_representation(leaf) if not text: return xte_paste_argv = ["xte", "usleep 300000"] # replace all newlines with 'key Return' for line in text.splitlines(True): xte_paste_argv.append("str " + line.rstrip("\r\n")) if line.endswith("\n"): xte_paste_argv.append("key Return") try: launch.spawn_async_raise(xte_paste_argv) except launch.SpawnError as exc: raise OperationError(exc) from exc def item_types(self): yield Leaf def valid_for_item(self, leaf): with suppress(AttributeError): return bool(interface.get_text_representation(leaf)) def get_description(self): return _("Type the text to foreground window") kupfer-328/kupfer/plugin/session_gnome.py000066400000000000000000000024061500175051100206750ustar00rootroot00000000000000""" Changes: 2012-10-16 Karol Będkowski: + support Gnome3; closes lp#788713; author: Joseph Lansdowne """ __kupfer_name__ = _("GNOME Session Management") __kupfer_sources__ = ("GnomeItemsSource",) __description__ = _("Special items and actions for GNOME environment") __version__ = "2012-10-16" __author__ = "Ulrik Sverdrup " import typing as ty from kupfer.plugin import session_support as support if ty.TYPE_CHECKING: from gettext import gettext as _ # sequences of argument lists LOGOUT_CMD = ( ["gnome-panel-logout"], ["gnome-session-save", "--kill"], ["gnome-session-quit", "--logout"], ) SHUTDOWN_CMD = ( ["gnome-panel-logout", "--shutdown"], ["gnome-session-save", "--shutdown-dialog"], ["gnome-session-quit", "--power-off"], ) LOCKSCREEN_CMD = ( ["gnome-screensaver-command", "--lock"], ["xdg-screensaver", "lock"], ) class GnomeItemsSource(support.CommonSource): source_scan_interval: int = 36000 def __init__(self): support.CommonSource.__init__(self, _("GNOME Session Management")) def get_items(self): return ( support.Logout(LOGOUT_CMD), support.LockScreen(LOCKSCREEN_CMD), support.Shutdown(SHUTDOWN_CMD), ) kupfer-328/kupfer/plugin/session_lxqt.py000066400000000000000000000016721500175051100205640ustar00rootroot00000000000000__kupfer_name__ = _("LXQT Session Management") __kupfer_sources__ = ("LxqtItemsSource",) __description__ = _("Actions for LXQT desktop") __version__ = "2020-08-23" __author__ = "Leonardo Masuero " # Based on XFCE Session Management by Karol Będkowski import typing as ty from kupfer.plugin import session_support as support if ty.TYPE_CHECKING: from gettext import gettext as _ # sequences of argument lists _LOGOUT_CMD = (["lxqt-leave", "--logout"],) _SHUTDOWN_CMD = (["lxqt-leave", "--shutdown"],) _LOCKSCREEN_CMD = (["lxqt-leave", "--lockscreen"],) class LxqtItemsSource(support.CommonSource): source_scan_interval: int = 36000 def __init__(self): support.CommonSource.__init__(self, _("LXQT Session Management")) def get_items(self): return ( support.Logout(_LOGOUT_CMD), support.LockScreen(_LOCKSCREEN_CMD), support.Shutdown(_SHUTDOWN_CMD), ) kupfer-328/kupfer/plugin/session_support.py000066400000000000000000000046051500175051100213070ustar00rootroot00000000000000""" Common objects for session_* plugins. """ import typing as ty from kupfer import launch from kupfer.obj import RunnableLeaf, Source from kupfer.support import pretty from kupfer.ui import uiutils if ty.TYPE_CHECKING: from gettext import gettext as _ __version__ = "2009-12-05" __author__ = "Ulrik Sverdrup " def launch_argv_with_fallbacks( commands: list[str], print_error: bool = True ) -> bool: """Try the sequence of @commands with launch.spawn_async, and return with the first successful command. return False if no command is successful and log an error """ for argv in commands: if ret := launch.spawn_async(argv): return ret pretty.print_error(__name__, "Unable to run command(s)", commands) return False class CommandLeaf(RunnableLeaf): """The represented object of the CommandLeaf is a list of commandlines""" def run(self, ctx=None): launch_argv_with_fallbacks(self.object) class Logout(CommandLeaf): """Log out from desktop""" def __init__(self, commands, name=None): super().__init__(commands, name or _("Log Out...")) def get_description(self): return _("Log out or change user") def get_icon_name(self): return "system-log-out" def run(self, ctx=None): if uiutils.confirm_dialog(_("Please confirm log out"), _("Log Out")): super().run(ctx) class Shutdown(CommandLeaf): """Shutdown computer or reboot""" def __init__(self, commands, name=None): super().__init__(commands, name or _("Shut Down...")) def get_description(self): return _("Shut down, restart or suspend computer") def get_icon_name(self): return "system-shutdown" def run(self, ctx=None): if uiutils.confirm_dialog( _("Please confirm system shut down."), _("Shut down") ): super().run(ctx) class LockScreen(CommandLeaf): """Lock screen""" def __init__(self, commands, name=None): super().__init__(commands, name or _("Lock Screen")) def get_description(self): return _("Enable screensaver and lock") def get_icon_name(self): return "system-lock-screen" class CommonSource(Source): def is_dynamic(self): return True def get_icon_name(self): return "system-shutdown" def provides(self): yield RunnableLeaf kupfer-328/kupfer/plugin/session_xfce.py000066400000000000000000000071401500175051100205150ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("XFCE Session Management") __kupfer_sources__ = ("XfceItemsSource", "XfceWhskerFavoritesSource") __description__ = _("Special items and actions for XFCE environment") __version__ = "2023-05-17" __author__ = "Karol Będkowski " import typing as ty from pathlib import Path from kupfer import plugin_support, puid from kupfer.core import learn from kupfer.obj import Leaf, Source from kupfer.plugin import session_support as support from kupfer.support import pretty if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_settings__ = plugin_support.PluginSettings( { "key": "lock_cmd", "label": _("Screen lock command"), "type": str, "value": "xflock4", }, { "key": "whisker_favs", "label": _("Load Whisker Menu Favorite applications"), "type": bool, "value": True, }, ) # sequences of argument lists _LOGOUT_CMD = (["xfce4-session-logout", "--logout"],) _SHUTDOWN_CMD = (["xfce4-session-logout"],) class XfceItemsSource(support.CommonSource): source_scan_interval: int = 36000 def __init__(self): support.CommonSource.__init__(self, _("XFCE Session Management")) def get_items(self): lockscreen_cmd = ( __kupfer_settings__["lock_cmd"] or "xdg-screensaver lock" ) return ( support.Logout(_LOGOUT_CMD), support.LockScreen((lockscreen_cmd.split(" "),)), support.Shutdown(_SHUTDOWN_CMD), ) def _find_whisher_conf_file() -> Path | None: base = Path("~/.config/xfce4/panel/").expanduser() files = (f for f in base.glob("whiskermenu*.rc") if f.is_file()) sorted_files = sorted(files, key=lambda f: f.stat().st_mtime, reverse=True) return sorted_files[0] if sorted_files else None def _get_whisker_conf_favs() -> list[str]: # find most recent configuration file conf_file = _find_whisher_conf_file() if not conf_file: return [] pretty.print_debug(__name__, "loading whisker rc file", conf_file) with open(conf_file, encoding="UTF-8") as conf: for line in conf: if not line.startswith("favorites="): continue *_pref, favs = line.strip().partition("=") return favs.split(",") return [] def _load_whisher_favs() -> ty.Iterator[Leaf]: # simplified version for fav in _get_whisker_conf_favs(): name, *_rest = fav.rpartition(".") id_ = f"" # ignore invalid objects if ( (itm := puid.resolve_unique_id(id_)) and (not hasattr(itm, "is_valid") or itm.is_valid()) and isinstance(itm, Leaf) ): yield itm class XfceWhskerFavoritesSource(Source): source_scan_interval: int = 1800 serializable = None def __init__(self): Source.__init__(self, _("Whisker Favorites")) def initialize(self): self.mark_for_update() def finalize(self) -> None: learn.replace_favorites(__name__) def get_items(self): if not __kupfer_settings__["whisker_favs"]: return [] try: favs = list(_load_whisher_favs()) except OSError: favs = [] else: learn.replace_favorites(__name__, *favs) return favs def get_description(self): return _("Favorite items from Xfce Whisker Menu") def get_icon_name(self): return "emblem-favorite" def is_valid(self): # for future use return __kupfer_settings__["whisker_favs"] kupfer-328/kupfer/plugin/shorten_links.py000066400000000000000000000061671500175051100207170ustar00rootroot00000000000000__kupfer_name__ = _("Shorten Links") __kupfer_actions__ = ("ShortenLinks",) __description__ = _("Create short aliases of long URLs") __version__ = "2017.1" __author__ = "Karol Będkowski , US" import typing as ty import urllib.parse import urllib.request from kupfer.obj import Action, Leaf, OperationError, Source, UrlLeaf from kupfer.support import pretty if ty.TYPE_CHECKING: from gettext import gettext as _ class _ShortLinksService(Leaf): def __init__(self, name): Leaf.__init__(self, name, name) def get_icon_name(self): return "text-html" class _GETService(_ShortLinksService, pretty.OutputMixin): """A unified shortener service working with GET requests""" host: str path: str url_key = "url" use_https = False def process(self, url: str) -> str: """Shorten @url or raise ValueError""" assert self.path query_string = urllib.parse.urlencode({self.url_key: url}) try: pretty.print_debug(__name__, "Request", self.path + query_string) with urllib.request.urlopen(self.path + query_string) as resp: if resp.status != 200: # noqa:PLR2004 raise ValueError( f"Invalid response {resp.status}, {resp.reason}" ) result: bytes = resp.read() return result.strip().decode("utf-8") except OSError as exc: raise ValueError(exc) from exc return _("Error") # NOTE: It's important that we use only sites that provide a stable API class IsGd(_GETService): """ Website: http://is.gd Reference: http://is.gd/apishorteningreference.php """ path = "https://is.gd/create.php?format=simple&" def __init__(self): super().__init__("Is.gd") class VGd(_GETService): """ Website: http://v.gd Reference: http://v.gd/apishorteningreference.php Like is.gd, but v.gd always shows a preview page. """ path = "https://v.gd/create.php?format=simple&" def __init__(self): super().__init__("V.gd") class ShortenLinks(Action): """Shorten links with selected engine""" def __init__(self): super().__init__(_("Shorten With...")) def has_result(self): return True def activate(self, leaf, iobj=None, ctx=None): try: result = iobj.process(leaf.object) except ValueError as exc: raise OperationError(str(exc)) from exc return UrlLeaf(result, result) def item_types(self): yield UrlLeaf def requires_object(self): return True def object_types(self): yield _ShortLinksService def object_source(self, for_item=None): return ServicesSource() def get_description(self): return __description__ class ServicesSource(Source): source_use_cache = False def __init__(self): super().__init__(_("Services")) def get_items(self): yield IsGd() yield VGd() def should_sort_lexically(self): return True def get_icon_name(self): return "applications-internet" kupfer-328/kupfer/plugin/show_qrcode.py000066400000000000000000000125511500175051100203440ustar00rootroot00000000000000"""Create QRCodes from texts or urls. Useful for smartphones with QRCode readers: Create some url with kupfer and QRCode it. Get it with the phone and use it's browser to display""" __kupfer_name__ = _("Show QRCode") __kupfer_actions__ = ("ShowQRCode", "CreateQRCode", "CreateTextQRCode") __description__ = _("Display text as QRCode in a window") __version__ = "2.0.0" __author__ = "Thomas Renard , KB" import io import tempfile import typing as ty from contextlib import closing import qrcode from gi.repository import GdkPixbuf, Gtk from kupfer import plugin_support from kupfer.obj import Action, FileLeaf, Leaf, TextLeaf from kupfer.ui import uiutils if ty.TYPE_CHECKING: from gettext import gettext as _ if not hasattr(qrcode, "QRCode"): raise ImportError("missing (right) qrcode package") __kupfer_settings__ = plugin_support.PluginSettings( { "key": "max_size", "label": _("Max QRCode size (pixels)"), "type": int, "value": 800, }, ) class ShowQRCode(Action): """Create QRCode windows from text or url""" rank_adjust = -5 def __init__(self): """initialize action""" Action.__init__(self, _("Show QRCode")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): """Create the image from leaf text and display it on window""" assert ctx try: text = leaf.get_text_representation() image = _create_image(text) except ValueError as err: uiutils.show_text_result( _("Cannot create QRCode: %s") % err, _("Show QRCode"), ctx ) return width, height = image.size with io.BytesIO() as image_file: image.save(image_file, "ppm") image_contents = image_file.getvalue() with closing(GdkPixbuf.PixbufLoader.new()) as loader: loader.write(image_contents) pixbuf = loader.get_pixbuf() window = Gtk.Window() window.set_default_size(width, height) image = Gtk.Image() image.set_from_pixbuf(pixbuf) image.show() window.add(image) # pylint: disable=no-member ctx.environment.present_window(window) def item_types(self): yield Leaf def valid_for_item(self, leaf): return hasattr(leaf, "get_text_representation") def get_description(self): """The Action description""" return _("Display text as QRCode in a window") def get_icon_name(self): """Name of the icon""" return "format-text-bold" class CreateQRCode(Action): rank_adjust = -5 def __init__(self): """initialize action""" Action.__init__(self, _("Create QRCode image")) def wants_context(self): return True def has_result(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx try: text = leaf.get_text_representation() image = _create_image(text) except ValueError as err: uiutils.show_text_result( _("Cannot create QRCode: %s") % err, _("Show QRCode"), ctx ) return None with tempfile.NamedTemporaryFile( suffix=".png", prefix="qrcode_", delete=False ) as file: image.save(file, "png") return FileLeaf(file.name) def item_types(self): yield Leaf def valid_for_item(self, leaf): return hasattr(leaf, "get_text_representation") def get_description(self): """The Action description""" return _("Create PNG file with QRCode") def get_icon_name(self): """Name of the icon""" return "document-new" class CreateTextQRCode(Action): """Create QRCode as unicode text and return it""" rank_adjust = -5 def __init__(self): """initialize action""" Action.__init__(self, _("Create QRCode text")) def wants_context(self): return True def has_result(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx try: text = leaf.get_text_representation() qrc = qrcode.QRCode(box_size=10) qrc.add_data(text) qrc.make(fit=True) except ValueError as err: uiutils.show_text_result( _("Cannot create QRCode: %s") % err, _("Show QRCode"), ctx ) return None with io.StringIO() as buf: qrc.print_ascii(out=buf) buf.seek(0) return TextLeaf(buf.getvalue()) def item_types(self): yield Leaf def valid_for_item(self, leaf): return hasattr(leaf, "get_text_representation") def get_description(self): """The Action description""" return _("Create QRCode as text with unicode characters") def get_icon_name(self): """Name of the icon""" return "document-new" def _create_image(text): qrc = qrcode.QRCode(box_size=10) qrc.add_data(text) qrc.make(fit=True) # scale barcode if necessary by change box_size max_size = int(__kupfer_settings__["max_size"] or 800) if max_size < 0: max_size = 800 if qrc.modules_count * 10 > max_size: qrc.box_size = max(1, max_size // qrc.modules_count) return qrc.make_image(fit=True).get_image() kupfer-328/kupfer/plugin/show_text.py000066400000000000000000000044571500175051100200610ustar00rootroot00000000000000__kupfer_name__ = _("Show Text") __kupfer_actions__ = ("ShowText", "LargeType", "ShowNotification") __description__ = _("Display text in a window") __version__ = "" __author__ = "US" import typing as ty from kupfer import icons from kupfer.obj import Action, Leaf, TextLeaf from kupfer.support import textutils from kupfer.ui import uiutils if ty.TYPE_CHECKING: from gettext import gettext as _ class ShowText(Action): rank_adjust = -10 def __init__(self): Action.__init__(self, _("Show Text")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx uiutils.show_text_result( leaf.get_text_representation(), title=_("Show Text"), ctx=ctx ) def item_types(self): yield TextLeaf def get_description(self): return _("Display text in a window") def get_icon_name(self): return "format-text-bold" class LargeType(Action): rank_adjust = -10 def __init__(self): Action.__init__(self, _("Large Type")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx return self.activate_multiple((leaf,), ctx) def activate_multiple(self, objects, ctx): all_texts = [obj.get_text_representation() for obj in objects] uiutils.show_large_type("\n".join(all_texts), ctx) def item_types(self): yield Leaf def valid_for_item(self, leaf): return hasattr(leaf, "get_text_representation") def get_description(self): return _("Display text in a window") def get_gicon(self): return icons.ComposedIcon.new("format-text-bold", "zoom-in") def get_icon_name(self): return "format-text-bold" class ShowNotification(Action): rank_adjust = -10 def __init__(self): Action.__init__(self, _("Show Notification")) def activate(self, leaf, iobj=None, ctx=None): title, body = textutils.extract_title_body(leaf.object) if body: uiutils.show_notification( title, body, icon_name=self.get_icon_name() ) else: uiutils.show_notification(title) def item_types(self): yield TextLeaf def get_icon_name(self): return "format-text-bold" kupfer-328/kupfer/plugin/ssh_hosts.py000066400000000000000000000167071500175051100200530ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("SSH Hosts") __description__ = _("Adds the SSH hosts found in ~/.ssh/config.") __version__ = "2023-11-04" __author__ = "Fabian Carlström, Karol Będkowski" __kupfer_sources__ = ("SSHSource",) __kupfer_actions__ = ("SSHConnect", "ScpFile") import os import typing as ty from contextlib import suppress from kupfer import icons, launch from kupfer.obj import Action, FileLeaf from kupfer.obj.grouping import ToplevelGroupingSource from kupfer.obj.helplib import FilesystemWatchMixin from kupfer.obj.hosts import ( HOST_ADDRESS_KEY, HOST_NAME_KEY, HOST_SERVICE_NAME_KEY, HOST_SERVICE_USER_KEY, HostLeaf, ) if ty.TYPE_CHECKING: from gettext import gettext as _ class SSHLeaf(HostLeaf): """The SSH host. Using name defined in `Host` or by `Match` statement. If `Hostname` is not defined in ssh config - is set to `name`. """ def __init__( self, name: str, hostname: str | None = None, user: str | None = None ) -> None: slots = { HOST_NAME_KEY: name, HOST_ADDRESS_KEY: hostname or name, HOST_SERVICE_NAME_KEY: "ssh", } if user: slots[HOST_SERVICE_USER_KEY] = user HostLeaf.__init__(self, slots, name) def get_description(self) -> str: host = str(self[HOST_ADDRESS_KEY]) with suppress(KeyError): if user := self[HOST_SERVICE_USER_KEY]: host = f"{user}@{host}" return _("SSH host: %s") % host def get_gicon(self): return icons.ComposedIconSmall(self.get_icon_name(), "terminal") def get_text_representation(self) -> str: host = str(self[HOST_ADDRESS_KEY]) with suppress(KeyError): if user := self[HOST_SERVICE_USER_KEY]: host = f"{user}@{host}" return f"ssh://{host}" def get_urilist_representation(self) -> list[str]: return [self.get_text_representation()] class SSHConnect(Action): """Used to launch a terminal connecting to the specified SSH host. HOST_NAME_KEY is used for making connections. """ def __init__(self): Action.__init__(self, name=_("Connect")) self.kupfer_add_alias("scp") def activate(self, leaf, iobj=None, ctx=None): host = leaf[HOST_NAME_KEY] with suppress(KeyError): if user := leaf[HOST_SERVICE_USER_KEY]: host = f"{user}@{host}" launch.spawn_in_terminal(["ssh", host]) def get_description(self): return _("Connect to SSH host") def get_icon_name(self): return "network-server" def item_types(self): yield HostLeaf def valid_for_item(self, leaf): if leaf.check_key(HOST_SERVICE_NAME_KEY): return leaf[HOST_SERVICE_NAME_KEY] == "ssh" return False class ScpFile(Action): """Send file or directory to remote host via scp.""" def __init__(self): super().__init__(name=_("Send file to...")) def activate(self, leaf, iobj=None, ctx=None): assert leaf and isinstance(leaf, FileLeaf) assert iobj and isinstance(iobj, SSHLeaf) host = iobj[HOST_NAME_KEY] with suppress(KeyError): if user := iobj[HOST_SERVICE_USER_KEY]: host = f"{user}@{host}" cmd = ["scp"] if leaf.is_dir(): cmd += ["-r"] cmd += [leaf.object, f"{host}:"] launch.spawn_in_terminal(cmd) def valid_for_item(self, leaf): return os.access(leaf.object, os.R_OK) def requires_object(self): return True def item_types(self): yield FileLeaf def object_types(self): yield SSHLeaf def get_description(self): return _("Copy file or directory to remote host using scp") def get_icon_name(self): return "go-next" def _parse_host_stms(args: list[str]) -> ty.Iterator[tuple[str, str | None]]: """Load names from `Host` statement. Ignore names with `*` and exclusions.""" for host in args: if "*" in host or host[0] == "!": continue user, _, host = host.partition("@") # noqa:PLW2901 if user and host: yield host, user else: yield user, None def _parse_match_stmt(args: list[str]) -> tuple[str, str | None] | None: """Parse `Match` arguments and return tuple of (host, optional user) or None. Load only `User` and `Host` keys from this statement. """ user = None host = None for key, val in zip(args, args[1:]): if "*" in val or val[0] == "!": continue key = key.lower() # noqa:PLW2901 if key == "host": host = val elif key == "user": user = val if not host: return None return host, user class SSHSource(ToplevelGroupingSource, FilesystemWatchMixin): """Reads ~/.ssh/config and creates leaves for the hosts found.""" source_scan_interval: int = 3600 _ssh_home = os.path.expanduser("~/.ssh") _config_path = os.path.join(_ssh_home, "config") def __init__(self, name=_("SSH Hosts")): ToplevelGroupingSource.__init__(self, name, "hosts") self._version = 2 self.monitor_token = None def initialize(self): ToplevelGroupingSource.initialize(self) self.monitor_token = self.monitor_files(self._config_path) def monitor_include_file(self, gfile): return gfile.get_path() in (self._config_path, self._ssh_home) def _get_items(self) -> ty.Iterable[SSHLeaf]: with open(self._config_path, encoding="UTF-8") as cfile: current_hosts: list[tuple[str, str | None]] = [] current_hostname: str | None = None for line in cfile: line = line.strip() # noqa:PLW2901 if not line: continue head, *args = line.split() head = head.lower() if head in ("host", "match"): # new restriction, flush current data for host, user in current_hosts: yield SSHLeaf(host, current_hostname, user) current_hosts.clear() current_hostname = None if head == "host": # process only 'host' restriction; skip wildcard and # negative entries current_hosts = list(_parse_host_stms(args)) elif len(args) > 1 and ( hostuser := _parse_match_stmt(args) ): # process "key val" parameters of match current_hosts = [hostuser] elif head == "hostname" and args: # if found hostname use is as HOST_ADDRESS_KEY current_hostname = args[0] for host, user in current_hosts: yield SSHLeaf(host, current_hostname, user) def get_items(self): try: return list(self._get_items()) except OSError as exc: self.output_error(exc) except UnicodeError as exc: self.output_error( f"File {self._config_path} not in expected encoding (UTF-8)" ) self.output_error(exc) return () def get_description(self): return _("SSH hosts as specified in ~/.ssh/config") def get_icon_name(self): return "network-workgroup" def provides(self): yield SSHLeaf kupfer-328/kupfer/plugin/ssl_support.py000066400000000000000000000006511500175051100204220ustar00rootroot00000000000000""" Stub implementation of HTTPS connections. """ # pylint: disable=too-few-public-methods class VerifiedHTTPSConnection: "implementation stub" def __init__(self, host, *args, **kwargs): pass @classmethod def is_ssl_supported(cls): return False def is_supported(): return ( VerifiedHTTPSConnection # type: ignore and VerifiedHTTPSConnection.is_ssl_supported() ) kupfer-328/kupfer/plugin/templates.py000066400000000000000000000114661500175051100200310ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("Document Templates") __kupfer_sources__ = ("TemplatesSource",) __kupfer_actions__ = ("CreateNewDocument",) __description__ = _("Create new documents from your templates") __version__ = "" __author__ = "Ulrik Sverdrup " import os import typing as ty from pathlib import Path from gi.repository import Gio, GLib from kupfer import icons from kupfer.obj import Action, FileLeaf, Leaf, Source, helplib from kupfer.obj.helplib import FilesystemWatchMixin from kupfer.support import fileutils, pretty if ty.TYPE_CHECKING: from gettext import gettext as _ DEFAULT_TMPL_DIR = "~/Templates" class Template(FileLeaf): def __init__(self, path): basename = GLib.filename_display_basename(path) nameroot, _ext = os.path.splitext(basename) FileLeaf.__init__(self, path, _("%s template") % nameroot) def get_actions(self): yield CreateDocumentIn() yield from FileLeaf.get_actions(self) def get_gicon(self): file_gicon = FileLeaf.get_gicon(self) return icons.ComposedIcon("text-x-generic-template", file_gicon) class EmptyFile(Leaf): def __init__(self): Leaf.__init__(self, None, _("Empty File")) def repr_key(self): return None def get_actions(self): yield CreateDocumentIn() def get_icon_name(self): return "text-x-generic" class NewFolder(Leaf): def __init__(self): Leaf.__init__(self, None, _("New Folder")) def repr_key(self): return None def get_actions(self): yield CreateDocumentIn() def get_icon_name(self): return "folder" class CreateNewDocument(Action): def __init__(self): Action.__init__(self, _("Create New Document...")) def has_result(self): return True def activate(self, leaf, iobj=None, ctx=None): destpath: str | None if iobj.object is not None: # Copy the template to destination directory basename = os.path.basename(iobj.object) tmpl_gfile = Gio.File.new_for_path(iobj.object) destpath = fileutils.get_destpath_in_directory( leaf.object, basename ) destfile = Gio.File.new_for_path(destpath) tmpl_gfile.copy( destfile, Gio.FileCopyFlags.ALL_METADATA, None, None, None ) elif isinstance(iobj, NewFolder): filename = str(iobj) destpath = fileutils.get_destpath_in_directory( leaf.object, filename ) Path(destpath).mkdir(parents=True) else: # create new empty file filename = str(iobj) destfile, destpath = fileutils.get_destfile_in_directory( leaf.object, filename ) if destfile: destfile.close() return FileLeaf(destpath) if destpath else None def item_types(self): yield FileLeaf def valid_for_item(self, leaf): return leaf.is_dir() def requires_object(self): return True def object_types(self): yield Template yield EmptyFile yield NewFolder def object_source(self, for_item=None): return TemplatesSource() def get_description(self): return _("Create a new document from template") def get_icon_name(self): return "document-new" class CreateDocumentIn( helplib.reverse_action(CreateNewDocument) # type:ignore ): rank_adjust = 10 # pylint: disable=super-init-not-called,non-parent-init-called def __init__(self): Action.__init__(self, _("Create Document In...")) def _get_tmpl_dir(): tmpl_dir = GLib.get_user_special_dir( GLib.UserDirectory.DIRECTORY_TEMPLATES ) if tmpl_dir == os.path.expanduser("~"): tmpl_dir = None if not tmpl_dir: tmpl_dir = os.path.expanduser(DEFAULT_TMPL_DIR) pretty.print_debug(__name__, tmpl_dir) return tmpl_dir class TemplatesSource(Source, FilesystemWatchMixin): source_scan_interval: int = 3600 def __init__(self): Source.__init__(self, _("Document Templates")) self.monitor_token = None def initialize(self): self.monitor_token = self.monitor_directories(_get_tmpl_dir()) def get_items(self): tmpl_dir = _get_tmpl_dir() yield EmptyFile() yield NewFolder() try: with os.scandir(tmpl_dir) as entries: for entry in entries: yield Template(entry.path) except OSError as exc: self.output_error(exc) def should_sort_lexically(self): return True def get_description(self): return None def get_icon_name(self): return "system-file-manager" def provides(self): yield Template kupfer-328/kupfer/plugin/textfiles.py000066400000000000000000000122761500175051100200420ustar00rootroot00000000000000""" Work with Textfiles: Allow appending and writing new files, or extracting the content of files. All Text in Kupfer is in unicode. When we read from textfiles or write to textfiles, we always work in the locale-defined encoding. FIXME: Be less strict (use UTF-8 if locale says Ascii) """ __kupfer_name__ = _("Textfiles") __kupfer_actions__ = ( "AppendTo", "AppendText", "WriteTo", "GetTextContents", "CopyContent", ) __description__ = _("Action for text files") __version__ = "2017.1" __author__ = "" import typing as ty from pathlib import Path from gi.repository import Gdk, Gtk from kupfer.obj import Action, FileLeaf, TextLeaf, helplib from kupfer.support import fileutils, kupferstring, validators if ty.TYPE_CHECKING: from gettext import gettext as _ class AppendTo(Action): def __init__(self, name=None): super().__init__(name or _("Append To...")) def activate(self, leaf, iobj=None, ctx=None): with open( iobj.object, "a", encoding=kupferstring.get_encoding() ) as outfile: outfile.write(leaf.object) outfile.write("\n") def item_types(self): yield TextLeaf def requires_object(self): return True def object_types(self): yield FileLeaf def valid_object(self, iobj, for_item=None): # K: allow select all writable FileLeaves; filtering by content # prevent navigate between directories return iobj.is_writable() # return iobj.is_content_type("text/plain") def get_icon_name(self): return "list-add" class AppendText(helplib.reverse_action(AppendTo)): # type: ignore def __init__(self): super().__init__(_("Append...")) class WriteTo(Action): def __init__(self): super().__init__(_("Write To...")) def has_result(self): return True def activate(self, leaf, iobj=None, ctx=None): assert iobj if isinstance(iobj, TextLeaf): outfile, outpath = fileutils.get_destfile(iobj.object) elif isinstance(iobj, FileLeaf): outfile, outpath = fileutils.get_destfile_in_directory( iobj.object, _("Empty File") ) else: # TODO: raise TypeError raise ValueError # noqa:TRY004 if not outfile or not outpath: return None try: text = str(leaf.object).encode() outfile.write(text) if not text.endswith(b"\n"): outfile.write(b"\n") finally: outfile.close() return FileLeaf(outpath) def item_types(self): yield TextLeaf def requires_object(self): return True def object_types(self): yield FileLeaf yield TextLeaf def valid_object(self, iobj, for_item=None): if isinstance(iobj, FileLeaf): return iobj.is_dir() # we accept TextLeaf if it look like path path_str = str(iobj.object) if not validators.is_valid_file_path(path_str): return False path = Path(path_str) # file should not exist if path.exists(): return False # but parent dir must exists and be writable return fileutils.is_directory_writable(path.parent) def get_description(self): return _("Write the text to a new file in specified directory") def get_icon_name(self): return "document-new" class GetTextContents(Action): def __init__(self): super().__init__(_("Get Text Contents")) def has_result(self): return True def activate(self, leaf, iobj=None, ctx=None): text = Path(leaf.object).read_text( encoding=kupferstring.get_encoding() ) return TextLeaf(text) def item_types(self): yield FileLeaf def valid_for_item(self, leaf): return leaf.is_content_type("text/plain") def get_icon_name(self): return "edit-copy" class CopyContent(Action): action_accelerator = "c" def __init__(self): super().__init__(_("Copy content")) def has_result(self): return True def item_types(self): yield FileLeaf def valid_for_item(self, leaf): return leaf.is_content_type("text/plain") def get_icon_name(self): return "edit-copy" def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx self.activate_multiple((leaf,), ctx=ctx) def activate_multiple(self, objs, iobjects=None, ctx=None): assert ctx clip = Gtk.Clipboard.get_for_display( ctx.environment.get_screen().get_display(), Gdk.SELECTION_CLIPBOARD ) content = [] for obj in objs: try: content.append( Path(obj.object).read_text( encoding=kupferstring.get_encoding() ) ) except Exception as err: # noqa: PERF203 content.append(f"Read file {obj.object} error: {err}") clip.set_text("\n".join(content), -1) # -1 for computed string length def get_description(self): return _("Copy file content to clipboard") kupfer-328/kupfer/plugin/textutils.py000066400000000000000000000271431500175051100200770ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("Textutils") __kupfer_actions__ = ( "Convert", "LineConvert", "Format", ) __kupfer_sources__ = ("Generators",) __description__ = _("Action for text, useful text generators and converters.") __version__ = "2023.1" __author__ = "Karol Będkowski" import base64 import datetime import json import secrets import string import typing as ty import urllib.parse import uuid import xml.dom.minidom from contextlib import suppress from functools import partial from kupfer import icons from kupfer.obj import ( Action, Leaf, OperationError, RunnableLeaf, Source, TextLeaf, ) from kupfer.ui import getdata_dialog if ty.TYPE_CHECKING: from gettext import gettext as _ TextConverter = ty.Callable[[str], ty.Optional[str]] class _Converter(Leaf): object: TextConverter def __init__( self, func: TextConverter, name: str, description: str | None = None ): super().__init__(func, name) self.description = description def get_description(self) -> str | None: return self.description class _ConvertersSource(Source): def __init__( self, items_gen: ty.Callable[[Leaf], ty.Iterator[_Converter]], for_item: Leaf, ) -> None: super().__init__("Converters") self.items_gen = items_gen self.for_item = for_item def get_items(self): yield from self.items_gen(self.for_item) class _ConvertAction(Action): def has_result(self): return True def activate(self, leaf, iobj=None, ctx=None): assert isinstance(leaf, TextLeaf) assert iobj and isinstance(iobj, _Converter) converter = iobj.object try: if (result := converter(leaf.object)) is not None: return TextLeaf(result) except Exception as err: raise OperationError(f"Error: {err}") from err return None def requires_object(self): return True def object_source(self, for_item=None): return _ConvertersSource(self._get_converters, for_item) def object_types(self): yield _Converter def item_types(self): yield TextLeaf def _get_converters(self, for_leaf: Leaf) -> ty.Iterator[_Converter]: raise NotImplementedError def get_gicon(self): return icons.ComposedIcon("text-x-generic", "kupfer-execute") def get_icon_name(self): return "text-x-generic" def _str_to_unix_ts(inp: str) -> str: """Convert int or float from `inp` do date.""" ts = float(inp) # check is ns/ms precision if ts > 9999999999999.0: # noqa: PLR2004 ts /= 1000000.0 elif ts > 9999999999.0: # noqa: PLR2004 ts /= 1000.0 return str(datetime.datetime.fromtimestamp(ts)) def _uncamellcase(text: str) -> str: """Convert 'SomeTextInCamelCase' into 'some text in camel case'.""" res: list[str] = [] for let in text: if let.isupper(): if res and res[-1] != " ": res.append(" ") res.append(let.lower()) else: res.append(let) return "".join(res) def _camelcase(instr: str) -> str: words = instr.split(" ") if words: return words[0].lower() + "".join(p.capitalize() for p in words[1:]) return instr def _trim_to_len_sep( instr: str, max_len: int, sep: str, min_len: int = 10 ) -> str: """If length of `instr` excess `max_len` trim it to this length. If `sep` is given also try to trim string to last found `sep` but keep `min_len` characters.""" if len(instr) > max_len: instr = instr[:max_len] if sep and (idx := instr.rfind(sep)) > min_len: instr = instr[:idx] return instr def _to_filename(instr: str) -> str: """Remove/replace characters that may be not allowed in filename. May be not necessary for posix filesystems, but there are still fat/ntfs/etc around.""" unprintable = ( "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0e\x0f" "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a" "\x1b\x1c\x1d\x1e\x1f\x7f" ) transtable = str.maketrans( "\n\r/\\ :<>?*|\"'", "__--_-_______", unprintable ) res = ( instr.strip() .translate(transtable) .replace("-_", "-") .replace("_-", "-") ) while "--" in res: res = res.replace("__", "_") if len(res) > 255: # noqa: PLR2004 base, _sep, ext = res.rpartition(".") if ext and len(ext) < len(base): base = _trim_to_len_sep(base, 250 - len(ext), "_") return f"{base}.{ext}" return _trim_to_len_sep(res, 255, "_") class Convert(_ConvertAction): def __init__(self, name=_("Convert…")): super().__init__(name) def get_description(self): return _("Convert text with selected tool") def _get_converters(self, for_leaf: Leaf) -> ty.Iterator[_Converter]: yield _Converter( lambda x: base64.b64encode(x.encode()).decode(), _("Encode text with Base64"), ) yield _Converter( lambda x: base64.b64decode(x.encode()).decode(), _("Decode text with Base64"), ) yield _Converter( urllib.parse.quote, _("Quote URL"), _("Replace special characters in string using the %%xx escape."), ) yield _Converter( urllib.parse.unquote, _("Unquote URL"), _("Replace %%xx escapes with their single-character equivalent."), ) with suppress(ValueError): if float(for_leaf.object) > 0.0: yield _Converter(_str_to_unix_ts, _("Unix timestamp to date")) yield _Converter(str.lower, _("to lower case")) yield _Converter(str.upper, _("to upper case")) yield _Converter(str.capitalize, _("to sentence case")) yield _Converter( lambda x: " ".join(p.capitalize() for p in x.split(" ")), _("Capitalize words"), _("Convert 'some string' to 'Some String'"), ) yield _Converter( _camelcase, _("To camel case"), _("Convert 'Some string' to 'comeString'"), ) yield _Converter( lambda x: "".join(p.capitalize() for p in x.split(" ")), _("To pascal case"), _("Convert 'Some string' to 'SomeString'"), ) yield _Converter( lambda x: x.upper().replace(" ", "_"), _("To constant case"), _("Convert 'some string' to 'SOME_STRING'"), ) yield _Converter( _uncamellcase, _("Camel case to lowercase"), _("Convert 'SomeString' do 'some string'"), ) yield _Converter( lambda x: x.lower().replace("_", " "), _("Constant case to lowercase"), _("Convert 'SOME_STRING' do 'some string'"), ) yield _Converter( _to_filename, _("To valid filename"), _("Convert string to usable file name"), ) def _ask_and_join_lines(inp: str) -> str | None: res = getdata_dialog.ask_for_text( _("Join lines options"), _("Please enter characters to join with"), _("Separator"), ";", ) if res: return res.join(filter(None, map(str.strip, inp.split("\n")))) return None def _ask_and_quote_join_lines(inp: str) -> str | None: dlg = getdata_dialog.GetDataDialog(_("Quote and join lines options")) dlg.add_field("sep", _("Separator:"), ";") dlg.add_field("qchar", _("Quotation character:"), '"') res = dlg.run() if res and (sep := res["sep"]) and (quot := res["qchar"]): return sep.join( f"{quot}{t}{quot}" for i in inp.split("\n") if (t := i.strip()) ) return None class LineConvert(_ConvertAction): def __init__(self, name=_("Convert lines…")): super().__init__(name) def get_description(self): return _("Convert multiline text with selected tool") def _get_converters(self, for_leaf: Leaf) -> ty.Iterator[_Converter]: yield _Converter( _ask_and_join_lines, _("Join lines with..."), _("Join lines with user selected separator"), ) yield _Converter( _ask_and_quote_join_lines, _("Quote and join lines..."), _("Wrap with quote characters and join lines."), ) class Format(_ConvertAction): def __init__(self, name=_("Format…")): super().__init__(name) def get_description(self): return _("Format text using selected formatter") def _get_converters(self, for_leaf: Leaf) -> ty.Iterator[_Converter]: yield _Converter( lambda x: "\n".join(line.strip() for line in x.split("\n")), _("strip whitespaces"), ) yield _Converter( lambda x: json.dumps(json.loads(x), sort_keys=True, indent=4), _("format json"), ) yield _Converter( lambda x: json.dumps(json.loads(x), separators=(",", ":")), _("compress json"), ) yield _Converter( lambda x: xml.dom.minidom.parseString(x).toprettyxml(), _("format xml"), ) class _GeneratorLeaf(RunnableLeaf): def __init__( self, name: str, func: ty.Callable[[], str], description: str | None = None, ) -> None: super().__init__(func, name=name) self.description = description def has_result(self): return True def run(self, ctx=None): try: if res := self.object(): return TextLeaf(res) except Exception as err: raise OperationError(f"Generator error: {err}") from err return None def get_description(self): return self.description def get_icon(self): return icons.ComposedIcon("stock_new-text", "kupfer-execute") def _generate_alfanum_token(size: int) -> str: alphabet = string.ascii_letters + string.digits return "".join(secrets.choice(alphabet) for i in range(size)) class Generators(Source): serializable = None def __init__(self, name=_("Generators")): super().__init__(name) def is_dynamic(self): return True def get_items(self): for size in (16, 32, 64): yield _GeneratorLeaf( _("Random %(size)d-bytes hex token") % {"size": size}, partial(secrets.token_hex, size), ) for size in (16, 32, 64): yield _GeneratorLeaf( _("Random %(size)d-bytes alpha-numeric token") % {"size": size}, partial(_generate_alfanum_token, size), ) yield _GeneratorLeaf( _("UUID based on host and time"), lambda: str(uuid.uuid1()), ) yield _GeneratorLeaf(_("Random UUID"), lambda: str(uuid.uuid4())) yield _GeneratorLeaf( _("Current time in ISO8601 format"), datetime.datetime.now().isoformat, ) yield _GeneratorLeaf( _("Current time as Unix timestamp"), lambda: str(int(datetime.datetime.now().timestamp())), ) yield _GeneratorLeaf( _("Current time as timestamp"), lambda: str(int(datetime.datetime.now().timestamp() * 1000)), ) def provides(self): yield RunnableLeaf def get_gicon(self): return icons.ComposedIcon("stock_new-text", "kupfer-execute") def get_icon_name(self): return "stock_new-text" def get_description(self): return _("Generate text content with selected tool") kupfer-328/kupfer/plugin/thunar.py000066400000000000000000000312761500175051100173350ustar00rootroot00000000000000__kupfer_name__ = _("Thunar") __kupfer_sources__ = ("ThunarObjects",) __kupfer_actions__ = ( "Reveal", "GetInfo", "SendTo", "CopyTo", "LinkTo", "MoveTo", ) __description__ = _("File manager Thunar actions") __version__ = "" __author__ = "Ulrik Sverdrup " import os import typing as ty from contextlib import suppress import dbus from kupfer import config, plugin_support from kupfer.obj import ( Action, AppLeaf, FileLeaf, NotAvailableError, RunnableLeaf, Source, ) from kupfer.obj.apps import AppLeafContentMixin from kupfer.obj.exceptions import InvalidDataError, NoMultiError from kupfer.support import pretty if ty.TYPE_CHECKING: from gettext import gettext as _ plugin_support.check_dbus_connection() _SERVICE_NAME = "org.xfce.Thunar" _OBJECT_PATH = "/org/xfce/FileManager" _IFACE_NAME = "org.xfce.FileManager" _TRASH_IFACE_NAME = "org.xfce.Trash" def _get_thunar(): """Return the dbus proxy object for Thunar we will activate it over d-bus (start if not running) """ bus = dbus.SessionBus() try: proxy_obj = bus.get_object(_SERVICE_NAME, _OBJECT_PATH) except dbus.DBusException as exc: pretty.print_error(__name__, exc) return None return dbus.Interface(proxy_obj, _IFACE_NAME) def _get_thunar_trash(): """Return the dbus proxy object for Thunar we will activate it over d-bus (start if not running) """ bus = dbus.SessionBus() try: proxy_obj = bus.get_object(_SERVICE_NAME, _OBJECT_PATH) except dbus.DBusException as exc: pretty.print_error(__name__, exc) return None return dbus.Interface(proxy_obj, _TRASH_IFACE_NAME) def _dummy(*args): pass class Reveal(Action): def __init__(self): Action.__init__(self, _("Select in File Manager")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx gfile = leaf.get_gfile() parent = gfile.get_parent() if not parent: return uri = parent.get_uri() bname = gfile.get_basename() id_ = ctx.environment.get_startup_notification_id() display = ctx.environment.get_display() try: # Thunar 1.2 Uses $DISPLAY and $STARTUP_ID args _get_thunar().DisplayFolderAndSelect( uri, bname, display, id_, reply_handler=_dummy, error_handler=_dummy, ) except TypeError: # Thunar 1.0 Uses $DISPLAY _get_thunar().DisplayFolderAndSelect( uri, bname, display, reply_handler=_dummy, error_handler=_dummy ) def item_types(self): yield FileLeaf class GetInfo(Action): def __init__(self): Action.__init__(self, _("Show Properties")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx gfile = leaf.get_gfile() uri = gfile.get_uri() id_ = ctx.environment.get_startup_notification_id() display = ctx.environment.get_display() try: # Thunar 1.2 Uses $DISPLAY and $STARTUP_ID args _get_thunar().DisplayFileProperties( uri, display, id_, reply_handler=_dummy, error_handler=_dummy ) except TypeError: # Thunar 1.0 Uses $DISPLAY _get_thunar().DisplayFileProperties( uri, display, reply_handler=_dummy, error_handler=_dummy ) def item_types(self): yield FileLeaf def get_description(self): return _("Show information about file in file manager") def get_icon_name(self): return "dialog-information" class SendTo(Action): """Send files to selected app from "send to" list""" def __init__(self): Action.__init__(self, _("Send To...")) def activate_multiple(self, leaves, iobjs): for app in iobjs: app.launch(paths=[leaf.object for leaf in leaves]) def activate(self, leaf, iobj=None, ctx=None): assert iobj self.activate_multiple((leaf,), (iobj,)) def item_types(self): yield FileLeaf def requires_object(self): return True def object_types(self): yield AppLeaf def object_source(self, for_item=None): return _SendToAppsSource() def _good_destination(dpath: str, spath: str) -> bool: """If directory path @dpath is a valid destination for file @spath to be copied or moved to. """ if not os.path.isdir(dpath): return False spath = os.path.normpath(spath) dpath = os.path.normpath(dpath) cpfx = os.path.commonprefix((spath, dpath)) return not os.path.samefile(dpath, spath) and cpfx != spath def leaf_uri(leaf): return leaf.get_gfile().get_uri() class CopyTo(Action, pretty.OutputMixin): def __init__(self): Action.__init__(self, _("Copy To...")) def wants_context(self): return True def activate_multiple(self, leaves, iobjects, ctx): # Unroll by looping over the destinations, # copying everything into each destination thunar = _get_thunar() work_dir = os.path.expanduser("~/") display = ctx.environment.get_display() notify_id = ctx.environment.get_startup_notification_id() sourcefiles = [leaf_uri(L) for L in leaves] def _reply(*args): self.output_debug("reply got for copying", *args) def _reply_error(exc): self.output_debug(exc) ctx.register_late_error(NotAvailableError(_("Thunar"))) for dest_iobj in iobjects: desturi = leaf_uri(dest_iobj) thunar.CopyInto( work_dir, sourcefiles, desturi, display, notify_id, reply_handler=_reply, error_handler=_reply_error, ) def activate(self, leaf, iobj=None, ctx=None): return self.activate_multiple([leaf], [iobj], ctx) def item_types(self): yield FileLeaf def valid_for_item(self, leaf): return True def requires_object(self): return True def object_types(self): yield FileLeaf def valid_object(self, obj, for_item): return _good_destination(obj.object, for_item.object) def get_description(self): return _("Copy file to a chosen location") class MoveTo(Action, pretty.OutputMixin): def __init__(self): Action.__init__(self, _("Move To...")) def wants_context(self): return True def activate_multiple(self, leaves, iobjects, ctx): if len(iobjects) != 1: raise NoMultiError def _reply(): self.output_debug("reply got for moving") def _reply_error(exc): self.output_debug(exc) ctx.register_late_error(NotAvailableError(_("Thunar"))) (dest_iobj,) = iobjects # Move everything into the destination thunar = _get_thunar() if not thunar: return work_dir = os.path.expanduser("~/") display = ctx.environment.get_display() notify_id = ctx.environment.get_startup_notification_id() sourcefiles = [leaf_uri(L) for L in leaves] desturi = leaf_uri(dest_iobj) thunar.MoveInto( work_dir, sourcefiles, desturi, display, notify_id, reply_handler=_reply, error_handler=_reply_error, ) def activate(self, leaf, iobj=None, ctx=None): assert iobj assert ctx return self.activate_multiple([leaf], [iobj], ctx) def item_types(self): yield FileLeaf def valid_for_item(self, leaf): return True def requires_object(self): return True def object_types(self): yield FileLeaf def valid_object(self, obj, for_item): return _good_destination(obj.object, for_item.object) def get_description(self): return _("Move file to new location") def get_icon_name(self): return "go-next" class LinkTo(Action, pretty.OutputMixin): def __init__(self): Action.__init__(self, _("Symlink In...")) def wants_context(self): return True def activate_multiple(self, leaves, iobjects, ctx): # Unroll by looping over the destinations, # copying everything into each destination thunar = _get_thunar() if not thunar: return work_dir = os.path.expanduser("~/") display = ctx.environment.get_display() notify_id = ctx.environment.get_startup_notification_id() sourcefiles = [leaf_uri(L) for L in leaves] def _reply(*args): self.output_debug("reply got for copying", *args) def _reply_error(exc): self.output_debug(exc) ctx.register_late_error(NotAvailableError(_("Thunar"))) for dest_iobj in iobjects: desturi = leaf_uri(dest_iobj) thunar.LinkInto( work_dir, sourcefiles, desturi, display, notify_id, reply_handler=_reply, error_handler=_reply_error, ) def activate(self, leaf, iobj=None, ctx=None): assert iobj assert ctx return self.activate_multiple([leaf], [iobj], ctx) def item_types(self): yield FileLeaf def valid_for_item(self, leaf): return True def requires_object(self): return True def object_types(self): yield FileLeaf def valid_object(self, obj, for_item): return _good_destination(obj.object, for_item.object) def get_description(self): return _("Create a symlink to file in a chosen location") class OpenTrash(RunnableLeaf): def __init__(self): RunnableLeaf.__init__(self, None, _("Open Trash")) def wants_context(self): return True def run(self, ctx=None): assert ctx id_ = ctx.environment.get_startup_notification_id() thunar = _get_thunar_trash() try: # Thunar 1.2 Uses $DISPLAY and $STARTUP_ID args thunar.DisplayTrash( ctx.environment.get_display(), id_, ) except TypeError: # Thunar 1.0 uses only $DISPLAY arg thunar.DisplayTrash( ctx.environment.get_display(), ) def get_description(self): return _("Open Trash in Thunar") def get_icon_name(self): return "user-trash" class EmptyTrash(RunnableLeaf): def __init__(self): RunnableLeaf.__init__(self, None, _("Empty Trash")) def wants_context(self): return True def run(self, ctx=None): assert ctx id_ = ctx.environment.get_startup_notification_id() thunar = _get_thunar_trash() try: # Thunar 1.2 Uses $DISPLAY and $STARTUP_ID args thunar.EmptyTrash( ctx.environment.get_display(), id_, reply_handler=_dummy, error_handler=_dummy, ) except TypeError: # Thunar 1.0 uses only $DISPLAY arg thunar.EmptyTrash( ctx.environment.get_display(), reply_handler=_dummy, error_handler=_dummy, ) def get_description(self): return None def get_icon_name(self): return "user-trash-full" class ThunarObjects(AppLeafContentMixin, Source): appleaf_content_id = ("Thunar", "thunar") source_scan_interval: int = 36000 serializable = None def __init__(self): Source.__init__(self, _("Thunar")) def get_items(self): yield EmptyTrash() yield OpenTrash() def provides(self): yield RunnableLeaf def get_icon_name(self): return "Thunar" class _SendToAppsSource(Source): """Send To items source""" def __init__(self): Source.__init__(self, _("Thunar Send To Objects")) def get_items(self): for data_dir in config.get_data_dirs("sendto", package="Thunar"): with os.scandir(data_dir) as sd: for dir_entry in sd: if not dir_entry.is_file() or not dir_entry.name.endswith( ".desktop" ): continue with suppress(InvalidDataError): yield AppLeaf( init_path=dir_entry.path, require_x=False ) def get_icon_name(self): return "Thunar" def provides(self): yield AppLeaf kupfer-328/kupfer/plugin/thunderbird.py000066400000000000000000000123711500175051100203410ustar00rootroot00000000000000""" Thunderbird plugin. Changes: 2012-03-15: Karol Będkowski + activate_multiple for new mail action """ __kupfer_name__ = _("Thunderbird") __kupfer_sources__ = ("ContactsSource",) __kupfer_actions__ = ( "NewMailAction", "AttachToNewMail", "NewMailWithBody", ) __description__ = _("Thunderbird/Icedove Contacts and Actions") __version__ = "2017.2" __author__ = "Karol Będkowski , US" import typing as ty from kupfer import icons, launch, plugin_support from kupfer.obj import Action, FileLeaf, RunnableLeaf, TextLeaf, UrlLeaf from kupfer.obj.apps import AppLeafContentMixin from kupfer.obj.contacts import ContactLeaf, EmailContact, email_from_leaf from kupfer.obj.grouping import ToplevelGroupingSource from kupfer.obj.helplib import FilesystemWatchMixin from kupfer.plugin import thunderbird_support as support if ty.TYPE_CHECKING: from gettext import gettext as _ plugin_support.check_any_command_available("thunderbird", "icedove") class ComposeMail(RunnableLeaf): """Create new mail without recipient""" def __init__(self): RunnableLeaf.__init__(self, name=_("Compose New Email")) def run(self, ctx=None): if not launch.spawn_async(["thunderbird", "--compose"]): launch.spawn_async(["icedove", "--compose"]) def get_description(self): return _("Compose a new message in Thunderbird") def get_icon_name(self): return "mail-message-new" class NewMailAction(Action): """Create new mail to selected leaf (Contact or TextLeaf)""" def __init__(self): Action.__init__(self, _("Compose Email To")) def activate(self, leaf, iobj=None, ctx=None): self.activate_multiple((leaf,)) def activate_multiple(self, objects): recipients = ",".join( filter(None, (email_from_leaf(L) for L in objects)) ) if not recipients: return if not launch.spawn_async(["thunderbird", f"mailto:{recipients}"]): launch.spawn_async(["icedove", f"mailto:{recipients}"]) def get_icon_name(self): return "mail-message-new" def item_types(self): yield ContactLeaf # we can enter email yield TextLeaf yield UrlLeaf def valid_for_item(self, leaf): return bool(email_from_leaf(leaf)) class AttachToNewMail(Action): def __init__(self): super().__init__(_("Attach in Email To...")) def activate(self, leaf, iobj=None, ctx=None): assert iobj self.activate_multiple((leaf,), (iobj,)) def activate_multiple(self, objects, iobjects): attachments = ",".join(L.object for L in objects) recipients = ",".join( filter(None, (email_from_leaf(L) for L in iobjects)) ) if not recipients: return args = ["-compose", f"to='{recipients}',attachment='{attachments}'"] if not launch.spawn_async(["thunderbird", *args]): launch.spawn_async(["icedove", *args]) def get_icon_name(self): return "mail-message-new" def item_types(self): yield FileLeaf def valid_for_item(self, leaf): return not leaf.is_dir() def requires_object(self): return True def object_types(self): yield ContactLeaf # we can enter email yield TextLeaf yield UrlLeaf def valid_object(self, iobj, for_item=None): return bool(email_from_leaf(iobj)) class NewMailWithBody(Action): def __init__(self): super().__init__(_("Compose Email With")) def activate(self, leaf, iobj=None, ctx=None): args = ["-compose", f"body='{leaf.object}'"] if not launch.spawn_async(["thunderbird", *args]): launch.spawn_async(["icedove", *args]) def get_icon_name(self): return "mail-message-new" def item_types(self): yield TextLeaf def get_description(self): return _("Compose a new message using the text as body") class ContactsSource( AppLeafContentMixin, ToplevelGroupingSource, FilesystemWatchMixin ): appleaf_content_id = ("thunderbird", "icedove") source_scan_interval: int = 3600 def __init__(self, name=_("Thunderbird Address Book")): ToplevelGroupingSource.__init__(self, name, "Contacts") self._version = 2 self.monitor_token = None def initialize(self): ToplevelGroupingSource.initialize(self) if abook_dirs := list(support.get_addressbook_dirs()): self.monitor_token = self.monitor_directories(*abook_dirs) def monitor_include_file(self, gfile): return gfile and ( gfile.get_basename().endswith(".mab") or gfile.get_basename() == "localstore.rdf" ) def mark_for_update(self, postpone=False): super().mark_for_update(postpone=True) def get_items(self): for name, email in support.get_contacts(): yield EmailContact(email, name) yield ComposeMail() def should_sort_lexically(self): return True def get_description(self): return _("Contacts from Thunderbird Address Book") def get_gicon(self): return icons.get_gicon_with_fallbacks(None, ("thunderbird", "icedove")) def provides(self): yield ContactLeaf yield RunnableLeaf kupfer-328/kupfer/plugin/thunderbird_support.py000066400000000000000000000323301500175051100221320ustar00rootroot00000000000000""" Module provide function to read Thunderbird's address book. Concept for mork parser from: - demork.py by Kumaran Santhanam - mork.cs from GnomeDo by Pierre Östlund 2021-01-01 Add support sqlite address book file format 2022-06-14 Support new (?) sqlite address book file format; load also history.sqlite """ import os import re import sqlite3 import time import typing as ty from configparser import RawConfigParser from contextlib import closing from kupfer.support import pretty __version__ = "2021-01-01" __author__ = "Karol Będkowski " _THUNDERBIRD_HOME = [ os.path.expanduser(name) for name in ("~/.mozilla-thunderbird/", "~/.thunderbird", "~/.icedove/") ] _THUNDERBIRD_PROFILES = [ (thome, os.path.join(thome, "profiles.ini")) for thome in _THUNDERBIRD_HOME ] _RE_COLS = re.compile(r"<\s*<\(a=c\)>\s*(\/\/)?\s*(\(.+?\))\s*>") _RE_CELL = re.compile(r"\((.+?)\)") _RE_ATOM = re.compile(r"<\s*(\(.+?\))\s*>") _RE_TABLE = re.compile( r"\{-?(\d+):\^(..)\s*\{\(k\^(..):c\)\(s=9u?\)\s*(.*?)\}\s*(.+?)\}" ) _RE_ROW = re.compile(r"(-?)\s*\[(.+?)((\(.+?\)\s*)*)\]") _RE_CELL_TEXT = re.compile(r"\^(.+?)=(.*)") _RE_CELL_OID = re.compile(r"\^(.+?)\^(.+)") _RE_TRAN_BEGIN = re.compile(r"@\$\$\{.+?\{\@") _RE_TRAN_END = re.compile(r"@\$\$\}.+?\}\@") _COLS_TO_KEEP = ( "DisplayName", "FirstName", "LastName", "PrimaryEmail", "SecondEmail", ) SPECIAL_CHARS = ( ("\\\\", "\\"), ("\\$", "$"), ("\\t", chr(9)), ("\\n", chr(10)), ) RE_ESCAPED = re.compile(r"(\$[a-f0-9]{2})", re.IGNORECASE) RE_ESCAPEDB = re.compile(rb"(\$[a-f0-9]{2})", re.IGNORECASE) RE_HEADER = re.compile(r'// ') class _Table: def __init__(self, tableid): self.tableid = tableid self.rows = {} def __repr__(self): return f"Table {self.tableid!r}: {self.rows!r}" def add_cell(self, rowid: str, col: str, atom: str) -> None: if ":" in rowid: rowid = rowid.split(":")[0] row = self.rows.get(rowid) if not row: row = self.rows[rowid] = {} row[col] = _unescape_data(atom) def del_row(self, rowid: str) -> None: if ":" in rowid: rowid = rowid.split(":")[0] if rowid in self.rows: del self.rows[rowid] def _unescape_byte(match: re.Match[bytes]) -> bytes: value = match.group() return bytes([int(value[1:], 16)]) def _unescape_data(instr: str) -> str: for src, dst in SPECIAL_CHARS: instr = instr.replace(src, dst) if RE_ESCAPED.search(instr) is not None: inbytes = instr.encode("utf-8") instr = RE_ESCAPEDB.sub(_unescape_byte, inbytes).decode( "utf-8", "replace" ) return instr def _read_mork_filecontent(filename: str) -> ty.Iterable[str]: with open(filename, encoding="UTF-8") as mfile: header = mfile.readline().strip() # check header if not RE_HEADER.match(header): pretty.print_debug(__name__, "_read_mork: header error", header) return for line in mfile: # remove blank lines and comments line = line.strip() # noqa: PLW2901 if not line: continue # remove comments if (comments := line.find("// ")) > -1: line = line[:comments].strip() # noqa: PLW2901 if line: yield line.replace("\\)", "$29") # pylint: disable=too-many-locals,too-many-nested-blocks,too-many-branches # pylint: disable=too-many-statements def _read_mork(filename: str) -> dict[str, _Table]: # noqa:PLR0915,PLR0912 """Read mork file, return tables from file""" data = "".join(_read_mork_filecontent(filename)) if not data: return {} # decode data cells = {} atoms = {} tables: dict[str, _Table] = {} pos = 0 active_trans = False while data: data = data[pos:].lstrip() if not data: break # cols if match := _RE_COLS.match(data): for cell in _RE_CELL.findall(match.group()): key, val = cell.split("=", 1) if val in _COLS_TO_KEEP: # skip necessary columns cells[key] = val pos = match.span()[1] continue # atoms if match := _RE_ATOM.match(data): for cell in _RE_CELL.findall(match.group()): if "=" in cell: key, val = cell.split("=", 1) atoms[key] = val pos = match.span()[1] continue # tables if match := _RE_TABLE.match(data): tableid = ":".join(match.groups()[0:2]) table = tables.get(tableid) if not table: table = tables[tableid] = _Table(tableid) for row in _RE_ROW.findall(match.group()): tran, rowid = row[:2] if active_trans and rowid[0] == "-": rowid = rowid[1:] table.del_row(rowid) if not active_trans or tran != "-": rowdata = row[2:] rowcell: str for rowcell in filter(None, rowdata): for cell in _RE_CELL.findall(rowcell): atom, col = None, None if cmatch := _RE_CELL_TEXT.match(cell): col = cells.get(cmatch.group(1)) atom = cmatch.group(2) elif cmatch := _RE_CELL_OID.match(cell): col = cells.get(cmatch.group(1)) atom = atoms.get(cmatch.group(2)) if col and atom: table.add_cell(rowid, col, atom) pos = match.span()[1] continue # transaction if _RE_TRAN_BEGIN.match(data): active_trans = True continue if _RE_TRAN_END.match(data): tran = True continue # dangling rows if match := _RE_ROW.match(data): row = match.groups() tran, rowid = row[:2] table = tables.get("1:80") # bind to default table if rowid[0] == "-": rowid = rowid[1:] if table: table.del_row(rowid) if tran != "-" and (rowdata := row[2:]): if not table: table = tables["1:80"] = _Table("1:80") for rowcell in filter(None, rowdata): for cell in _RE_CELL.findall(rowcell): atom, col = None, None if cmatch := _RE_CELL_TEXT.match(cell): col = cells.get(cmatch.group(1)) atom = cmatch.group(2) elif cmatch := _RE_CELL_OID.match(cell): col = cells.get(cmatch.group(1)) atom = atoms.get(cmatch.group(2)) if col and atom: table.add_cell(rowid, col, atom) pos = match.span()[1] continue pos = 1 return tables def _mork2contacts(tables: dict[str, _Table]) -> ty.Iterator[tuple[str, str]]: """Get contacts from mork table prepared by _read_mork""" if not tables: return # get only default table if table := tables.get("1:80"): for row in table.rows.values(): display_name = row.get("DisplayName") if not display_name: first_name = row.get("FirstName", "") last_name = row.get("LastName", "") display_name = " ".join((first_name, last_name)) if display_name: display_name = display_name.strip() for key in ("PrimaryEmail", "SecondEmail"): if email := row.get(key): yield (display_name or email[: email.find("@")], email) _ABOOK_CONTACTS_SQL = """ select (select value from properties where card = c.uid and name = 'FirstName' ) as FirstName, (select value from properties where card = c.uid and name = 'LastName' ) as LastName, (select value from properties where card = c.uid and name = 'DisplayName' ) as DisplayName, (select value from properties where card = c.uid and name = 'PrimaryEmail' ) as PrimaryEmail, (select value from properties where card = c.uid and name = 'SecondEmail' ) as SecondEmail from cards c """ # new version of abook.sqlite file _ABOOK_CONTACTS_SQL2 = """ select (select value from properties where card = c.card and name = 'FirstName' ) as FirstName, (select value from properties where card = c.card and name = 'LastName' ) as LastName, (select value from properties where card = c.card and name = 'DisplayName' ) as DisplayName, (select value from properties where card = c.card and name = 'PrimaryEmail' ) as PrimaryEmail, (select value from properties where card = c.card and name = 'SecondEmail' ) as SecondEmail from (select distinct card from properties) c """ def _load_abook_sqlite(filename: str) -> ty.Iterator[tuple[str, str]]: """Load contacts from abook.sqlite filename. Thunderbird (like firefox) lock database, so it mus be opened as immutable and read-only. Also changes may be not visible immediate - require close sqlite file by thunderbird. """ dbfpath = filename.replace("?", "%3f").replace("#", "%23") dbfpath = "file:" + dbfpath + "?immutable=1&mode=ro" for _ in range(2): try: pretty.print_debug(__name__, "_load_abook_sqlite load:", dbfpath) with closing( sqlite3.connect(dbfpath, uri=True, timeout=1) ) as conn: cur = conn.cursor() # check db version cur.execute( "select count(*) from sqlite_schema " "where name = 'list_cards'" ) ver = cur.fetchone()[0] abook_query = ( _ABOOK_CONTACTS_SQL2 if ver else _ABOOK_CONTACTS_SQL ) cur.execute(abook_query) for ( first_name, last_name, display_name, primary_email, second_email, ) in cur: display_name = display_name or " ".join( # noqa: PLW2901 filter(None, (first_name, last_name)) ) for email in (primary_email, second_email): if email: yield ( display_name or email.partition("@")[0], email, ) return except sqlite3.Error as err: # noqa: PERF203 # Something is wrong with the database # wait short time and try again pretty.print_debug(__name__, "_load_abook_sqlite error:", str(err)) time.sleep(1) def get_addressbook_dirs() -> ty.Iterator[str]: """Get path to addressbook file from default profile.""" for thome, tprofile in _THUNDERBIRD_PROFILES: if os.path.isfile(tprofile): config = RawConfigParser() config.read(tprofile) for section in config.sections(): if config.has_option(section, "Path"): path = config.get(section, "Path") if not os.path.isabs(path): path = os.path.join(thome, path) if os.path.isdir(path): yield path def get_addressbook_files() -> ty.Iterator[str]: """Get full path to all Thunderbird address book files.""" for path in get_addressbook_dirs(): pretty.print_debug(__name__, "get_addressbook_files dir:", path) with os.scandir(path) as entries: for entry in entries: if not entry.is_file(): continue if ( entry.name.endswith(".mab") or ( entry.name.endswith(".sqlite") and entry.name.startswith("abook") ) or entry.name == "history.sqlite" ): yield entry.path def get_contacts() -> ty.Iterator[tuple[str, str]]: """Get all contacts from all Thunderbird address books as ((contact name, contact email))""" for abook in get_addressbook_files(): pretty.print_debug(__name__, "get_contacts:", abook) if abook.endswith(".sqlite"): try: yield from _load_abook_sqlite(abook) except Exception as err: pretty.print_error(__name__, "get_contacts error", abook, err) else: try: tables = _read_mork(abook) except OSError as err: pretty.print_error(__name__, "get_contacts error", abook, err) else: yield from _mork2contacts(tables) if __name__ == "__main__": print("\n".join(map(str, sorted(get_contacts())))) kupfer-328/kupfer/plugin/tmux.py000066400000000000000000000110211500175051100170130ustar00rootroot00000000000000""" This plugin for simplicity use cli interface instead of api, so we don't need additional modules. """ from __future__ import annotations __kupfer_name__ = _("Tmux / Tmuxp") __kupfer_sources__ = ("TmuxSessionsSource", "TmuxpWorkspacesSource") __description__ = _("Manage tmux and tmuxp sessions") __version__ = "2023.1" __author__ = "Karol Będkowski" import datetime import os import typing as ty from kupfer import launch, plugin_support from kupfer.obj import Action, Leaf, Source from kupfer.obj.helplib import FileMonitorToken, FilesystemWatchMixin if ty.TYPE_CHECKING: from gettext import gettext as _ try: import libtmux except ImportError: libtmux = None plugin_support.check_command_available("tmux") class TmuxSession(Leaf): """Represented object is the session_id as string""" def __init__( self, sid: str, name: str, attached: str, created: str ) -> None: super().__init__(sid, name) self._attached = attached != "0" self._created = datetime.datetime.fromtimestamp(int(created)) def get_actions(self): yield Attach() def get_description(self) -> str: return _("%(status)s tmux session, created %(time)s") % { "status": _("Attached") if self._attached else _("Detached"), "time": self._created, } def get_icon_name(self): return "gnome-window-manager" def tmux_sessions( session_id: str | None = None, ) -> ty.Iterator[ty.Collection[str]]: if libtmux and (srv := libtmux.Server()): for sess in srv.sessions: if not sess.session_id: continue yield ( sess.session_id, sess.session_name or f"session {sess.session_id}", sess.session_attached or "", sess.session_created or "", ) return # fallback cmd = ( "tmux list-sessions -F " "'#{session_id}\t#{session_name}\t" "#{session_attached}\t#{session_created}'" ) if session_id is not None: cmd += f" -f '#{{m:{session_id},#{{session_id}}}}'" with os.popen(cmd) as pipe: output = pipe.read() for line in output.splitlines(): yield line.split("\t") class TmuxSessionsSource(Source): """Source for tmux sessions""" source_use_cache = False def __init__(self): super().__init__(_("tmux Sessions")) def is_dynamic(self): return True def get_items(self): for session in tmux_sessions(): yield TmuxSession(*session) def get_description(self): return _("Active tmux sessions") def get_icon_name(self): return "terminal" def provides(self): yield TmuxSession class Attach(Action): def __init__(self): name = _("Attach") super().__init__(name) def activate(self, leaf, iobj=None, ctx=None): sid = leaf.object action_argv = ["tmux", "attach-session", "-t", sid, "-d"] launch.spawn_in_terminal(action_argv) class TmuxpSession(Leaf): def __init__(self, name: str) -> None: super().__init__(name, name.capitalize()) def get_actions(self): yield StartTmuxpSession() def get_description(self) -> str: return _("tmuxp saved session") def get_icon_name(self): return "gnome-window-manager" class StartTmuxpSession(Action): def __init__(self): name = _("Start session") super().__init__(name) def activate(self, leaf, iobj=None, ctx=None): action_argv = ["tmuxp", "load", leaf.object] launch.spawn_in_terminal(action_argv) class TmuxpWorkspacesSource(Source, FilesystemWatchMixin): """Source for tmuxp workspaces""" source_scan_interval: int = 3600 _tmuxp_home = "~/.tmuxp/" def __init__(self): super().__init__(_("tmuxp Workspaces")) self._monitor_token: FileMonitorToken | None = None def initialize(self): tmux_ws_dir = os.path.expanduser(self._tmuxp_home) self._monitor_token = self.monitor_directories(tmux_ws_dir, force=True) def finalize(self): self.stop_monitor_fs_changes(self._monitor_token) def get_items(self): with os.popen("tmuxp ls") as pipe: output = pipe.read() for line in output.splitlines(): if line := line.strip(): yield TmuxpSession(line) def get_description(self): return _("Configured tmuxp workspaces") def get_icon_name(self): return "terminal" def provides(self): yield TmuxSession kupfer-328/kupfer/plugin/top.py000066400000000000000000000113431500175051100166270ustar00rootroot00000000000000__kupfer_name__ = _("Top") __kupfer_sources__ = ("TaskSource",) __description__ = _("Show running tasks and allow sending signals to them") __version__ = "2023-04-29" __author__ = "Karol Będkowski " import operator import os import signal import subprocess import typing as ty from pathlib import Path from kupfer import plugin_support from kupfer.obj import Action, Leaf, Source if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_settings__ = plugin_support.PluginSettings( { "key": "sort_order", "label": _("Sort Order"), "type": str, "value": _("Commandline"), "alternatives": [ _("Commandline"), _("CPU usage (descending)"), _("Memory usage (descending)"), ], }, ) class Task(Leaf): def __init__(self, path, name, description=None): Leaf.__init__(self, path, name) self._description = description def get_description(self): return self._description def get_actions(self): yield SendSignal() def get_icon_name(self): return "applications-system" class SendSignal(Action): def __init__(self): Action.__init__(self, _("Send Signal...")) def activate(self, leaf, iobj=None, ctx=None): assert iobj os.kill(leaf.object, iobj.object) def requires_object(self): return True def object_types(self): yield _Signal def object_source(self, for_item=None): return _SignalsSource() class _Signal(Leaf): def get_description(self): return f"kill -{self.object} ..." # get all signals from signal package _SIGNALS = tuple( _Signal(getattr(signal, signame), signame[3:]) for signame in sorted(dir(signal)) if signame.startswith("SIG") and not signame.startswith("SIG_") ) class _SignalsSource(Source): def __init__(self): Source.__init__(self, _("Signals")) def get_items(self): return _SIGNALS def provides(self): yield _Signal class TaskSource(Source): task_update_interval_sec = 5 source_use_cache = False source_prefer_sublevel = True def __init__(self, name=_("Running Tasks")): Source.__init__(self, name) self._version = 3 def is_dynamic(self): return True def get_items(self): uid = os.getuid() with subprocess.Popen( ["top", "-b", "-n", "1", "-u", str(uid)], stdout=subprocess.PIPE, env={"LC_NUMERIC": "C"}, ) as proc: if proc.stdout: content = proc.stdout.read() else: return processes = parse_top_output(content) sort_order = __kupfer_settings__["sort_order"] if sort_order == _("Memory usage (descending)"): processes = sorted( processes, key=operator.itemgetter(2), reverse=True ) elif sort_order == _("Commandline"): processes = sorted(processes, key=operator.itemgetter(4)) # default: by cpu fields = _( "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" ) for pid, cpu, mem, ptime, cmd in processes: description = fields % { "pid": pid, "cpu": cpu, "mem": mem, "time": ptime, } yield Task(pid, cmd, description) def get_description(self): return _("Running tasks for current user") def get_icon_name(self): return "system" def provides(self): yield Task def parse_top_output(out): """ Yield tuples of (pid, cpu, mem, ptime, cmd) """ # Assuming UTF-8 output fields_map = {} fields_count = 0 header_read = False for line in out.split(b"\n"): line = line.decode("utf-8", "replace").strip() # noqa: PLW2901 if line == "": header_read = True continue if not header_read: continue if line.startswith("PID"): # assume pid is first col fields_map = {name: pos for pos, name in enumerate(line.split())} fields_count = len(fields_map) continue # skip header line_fields = line.split(None, fields_count - 1) pid = line_fields[0] cpu = line_fields[fields_map["%CPU"]] mem = line_fields[fields_map["%MEM"]] ptime = line_fields[fields_map["TIME+"]] cmd = line_fields[-1] # read command line proc_file = Path(f"/proc/{pid}/cmdline") if proc_file.is_file(): # also skip (finished) missing tasks cmd = proc_file.read_text(encoding="UTF=8").replace("\x00", " ") yield (int(pid), float(cpu), float(mem), ptime, cmd) kupfer-328/kupfer/plugin/tracker1.py000066400000000000000000000210551500175051100175420ustar00rootroot00000000000000""" Tracker plugins are versioned by the D-Bus API version This is version works with Tracker1. """ __kupfer_name__ = _("Tracker") __kupfer_sources__ = () __kupfer_text_sources__ = ("TrackerFulltext",) __kupfer_contents__ = ("TrackerQuerySource",) __kupfer_actions__ = ("TrackerSearch", "TrackerSearchHere") __description__ = _("Tracker desktop search integration") __version__ = "2017.2" __author__ = "US" import os import typing as ty from contextlib import suppress from xml.etree.ElementTree import ElementTree import dbus from gi.repository import Gio from kupfer import launch, plugin_support from kupfer.obj import ( Action, FileLeaf, OperationError, Source, TextLeaf, TextSource, ) from kupfer.support import pretty if ty.TYPE_CHECKING: from gettext import gettext as _ plugin_support.check_dbus_connection() # SERVICE_NAME = "org.freedesktop.Tracker" # SEARCH_OBJECT_PATH = "/org/freedesktop/Tracker/Search" # SEARCH_INTERFACE = "org.freedesktop.Tracker.Search" _SERVICE1_NAME = "org.freedesktop.Tracker1" _SEARCH_OBJECT1_PATH = "/org/freedesktop/Tracker1/Resources" _SEARCH1_INTERFACE = "org.freedesktop.Tracker1.Resources" TRACKER_GUI_SEARCH = "tracker-needle" class TrackerSearch(Action): def __init__(self): Action.__init__(self, _("Search in Tracker")) def activate(self, leaf, iobj=None, ctx=None): try: launch.spawn_async_raise([TRACKER_GUI_SEARCH, leaf.object]) except launch.SpawnError as exc: raise OperationError(exc) from exc def get_description(self): return _("Open Tracker Search Tool and search for this term") def get_icon_name(self): return "system-search" def item_types(self): yield TextLeaf class TrackerSearchHere(Action): action_accelerator = "t" def __init__(self): super().__init__(_("Get Tracker Results...")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx query = leaf.object def error(exc): ctx.register_late_error(exc) def reply(results): ret = [] new_file = Gio.File.new_for_uri for result in results: with suppress( Exception ): # This very vague exception is from getpath ret.append(FileLeaf(new_file(result[0]).get_path())) ctx.register_late_result( TrackerQuerySource(query, search_results=ret) ) for _ignore in get_tracker_filequery( query, max_items=500, operation_err=True, reply_handler=reply, error_handler=error, ): pass def get_description(self): return _("Show Tracker results for query") def get_icon_name(self): return "tracker" def item_types(self): yield TextLeaf def sparql_escape(ustr): """Escape unicode string @ustr for insertion into a SPARQL query Implemented to behave like tracker_sparql_escape in libtracker-client """ sparql_escape_table = { ord("\t"): r"\t", ord("\n"): r"\n", ord("\r"): r"\r", ord("\b"): r"\b", ord("\f"): r"\f", ord('"'): r"\"", ord("\\"): "\\\\", # Extra rule: Can't have ? ord("?"): "", } return ustr.translate(sparql_escape_table) ORDER_BY = { "rank": "ORDER BY DESC (fts:rank(?s))", "recent": "ORDER BY DESC (nfo:fileLastModified(?s))", } def get_file_results_sparql( searchobj, query, max_items=50, order_by="rank", location=None, **kwargs ): clean_query = sparql_escape(query) if location: location_filter = ( "FILTER(tracker:uri-is-descendant " f'("{sparql_escape(location)}", nie:url (?s)))' ) else: location_filter = "" sql = """SELECT tracker:coalesce (nie:url (?s), ?s) WHERE { ?s fts:match "%(query)s" . ?s tracker:available true . %(location_filter)s } %(order_by)s OFFSET 0 LIMIT %(limit)d""" % { "query": clean_query, "location_filter": location_filter, "order_by": ORDER_BY[order_by], "limit": int(max_items), } pretty.print_debug(__name__, sql) results = searchobj.SparqlQuery(sql, **kwargs) if results is None: return new_file = Gio.File.new_for_uri for result in results: with suppress(Exception): # This very vague exception is from getpath yield FileLeaf(new_file(result[0]).get_path()) _USE_VERSION = "0.8" _VERSIONS = { "0.8": (_SERVICE1_NAME, _SEARCH_OBJECT1_PATH, _SEARCH1_INTERFACE), } version_query = { "0.8": get_file_results_sparql, } def get_searchobject(sname, opath, sinface, operation_err=False): bus = dbus.SessionBus() searchobj = None try: tobj = bus.get_object(sname, opath) searchobj = dbus.Interface(tobj, sinface) except dbus.DBusException as exc: if operation_err: raise OperationError(exc) from exc pretty.print_debug(__name__, exc) return searchobj def get_tracker_filequery(query, operation_err=False, **kwargs): searchobj = get_searchobject( *_VERSIONS[_USE_VERSION], operation_err=operation_err ) if searchobj is None: pretty.print_error(__name__, "Could not connect to Tracker") return () queryfunc = version_query[_USE_VERSION] return queryfunc(searchobj, query, **kwargs) class TrackerQuerySource(Source): def __init__(self, query, search_results=None, **search_args): Source.__init__(self, name=_('Tracker Search for "%s"') % query) self.query = query self.search_args = search_args self.search_results = None def repr_key(self): return self.query def get_items(self): if self.search_results: return self.search_results return get_tracker_filequery(self.query, **self.search_args) def provides(self): yield FileLeaf def get_description(self): return _('Results for "%s"') % self.query def get_icon_name(self): return "tracker" @classmethod def decorates_type(cls): return FileLeaf @classmethod def decorate_item(cls, leaf): # FIXME: Very simplified .savedSearch parsing, so far we only support # the query, without additional filtering. The simplest form of # .savedSearch file is saved by nautilus as following: # # QUERY GOES HERE # if not leaf.object.endswith(".savedSearch"): return None try: etree = ElementTree(file=leaf.object) text_elem = etree.getroot().find("text") if not text_elem: return None query = text_elem.text if not query: return None location_tag = etree.getroot().find("location") location = location_tag.text if location_tag is not None else None return cls(query, location=location_uri(location)) except Exception: pretty.print_exc(__name__) return None def location_uri(location): if location is None: return None if not os.path.isabs(location): location = os.path.expanduser("~/" + location) return Gio.File.new_for_path(location).get_uri() # FIXME: Port tracker tag sources and actions # to the new, much more powerful sparql + dbus API # (using tracker-tag as in 0.6 is a plain hack and a dead end) class TrackerFulltext(TextSource): def __init__(self): TextSource.__init__(self, name=_("Tracker Full Text Search")) def get_description(self): return _("Use '?' prefix to get full text results") def get_text_items(self, text): if text.startswith("?"): rank = "rank" if text.startswith("?~"): rank = "recent" query = text.lstrip("? ~") if len(query) > 2 and not has_parsing_error(query): # noqa: PLR2004 yield from TrackerQuerySource( query, order_by=rank, max_items=50 ).get_items() def provides(self): yield FileLeaf def get_rank(self): return 80 def has_parsing_error(query): "Check common parsing errors" words = query.split() # Unfinshed "" and OR, AND without following won't parse if words and words[-1] in ("OR", "AND"): return True return query.count('"') % 2 != 0 kupfer-328/kupfer/plugin/tracker3.py000066400000000000000000000063331500175051100175460ustar00rootroot00000000000000# pylint: disable=wrong-import-position """ Tracker3 plugin using gir1.2-tracker-3.0 """ from __future__ import annotations __kupfer_name__ = _("Tracker3") __kupfer_sources__ = () __kupfer_text_sources__ = ("Tracker3Fulltext",) __kupfer_contents__ = () __kupfer_actions__ = ("TrackerSearch",) __description__ = _("Tracker3 search integration") __version__ = "2023-04-30" __author__ = "KB" import typing as ty import gi try: gi.require_version("Tracker", "3.0") except ValueError as exc: raise ImportError( f"{exc}: missing GIRepository Tracker library (gir1.2-tracker-3.0)" ) from exc # pylint: disable=no-name-in-module from gi.repository import Gio, Tracker from kupfer.obj import ( Action, FileLeaf, Source, TextLeaf, TextSource, ) if ty.TYPE_CHECKING: from gettext import gettext as _ class TrackerSearch(Action): def __init__(self): Action.__init__(self, _("Search in Tracker3")) def is_factory(self): return True def activate(self, leaf, iobj=None, ctx=None): return QuerySource(leaf.object.strip()) def get_description(self): return _("Search in Tracker3") def get_icon_name(self): return "system-search" def item_types(self): yield TextLeaf _QUERY = """ SELECT ?uri max(?rank) as ?rank WHERE { { SELECT (?s AS ?uri) (fts:rank(?s) AS ?rank) { GRAPH tracker:FileSystem { ?s a nfo:FileDataObject ; fts:match "%(term)s" ; nie:dataSource ?ds . } } } UNION { SELECT ?uri (fts:rank(?uri) AS ?rank) { GRAPH ?g { ?s a nie:InformationElement ; fts:match "%(term)s" ; nie:isStoredAs ?uri . } GRAPH tracker:FileSystem { ?uri nie:dataSource ?ds . } } } } GROUP BY ?uri ORDER BY ?rank OFFSET 0 LIMIT %(limit)s """ def _query(term: str, limit: int) -> ty.Iterator[FileLeaf]: miner_fs = Tracker.SparqlConnection.bus_new( "org.freedesktop.Tracker3.Miner.Files", None, None ) term = Tracker.sparql_escape_string(term) query = _QUERY % {"term": term, "limit": limit} if cursor := miner_fs.query(query, None): while cursor.next(None): if uri := cursor.get_string(0)[0]: path = Gio.File.new_for_uri(uri).get_path() yield FileLeaf(path) class QuerySource(Source): def __init__(self, query: str, limit: int = 100) -> None: Source.__init__(self, name=_('Results for "%s"') % query) self.query = query self.limit = limit def repr_key(self): return self.query def get_items(self): return tuple(_query(self.query, self.limit)) class Tracker3Fulltext(TextSource): def __init__(self): TextSource.__init__(self, name=_("Tracker3 Full Text Search")) def get_description(self): return _("Use '?' prefix to get full text results") def get_text_items(self, text): if text.startswith("?") and (term := text.lstrip("? ")): return tuple(_query(term, 25)) return () def provides(self): yield FileLeaf def get_rank(self): return 80 kupfer-328/kupfer/plugin/trash.py000066400000000000000000000207221500175051100171470ustar00rootroot00000000000000__kupfer_name__ = _("Trash") __kupfer_actions__ = ("MoveToTrash", "EmptyTrash") __kupfer_sources__ = ("TrashSource",) __description__ = _("Access trash contents") __version__ = "2017.2" __author__ = "Ulrik Sverdrup " import typing as ty from contextlib import suppress from gi.repository import Gio, GLib from kupfer import icons, launch from kupfer.obj import ( Action, FileLeaf, Leaf, OperationError, Source, SourceLeaf, ) from kupfer.obj.fileactions import Open from kupfer.support import pretty from kupfer.ui import uiutils if ty.TYPE_CHECKING: from gettext import gettext as _ from gettext import ngettext _TRASH_URI = "trash://" class MoveToTrash(Action): # this should never be default rank_adjust = -10 def __init__(self): Action.__init__(self, _("Move to Trash")) def activate(self, leaf, iobj=None, ctx=None): if not uiutils.confirm_dialog( _("Move file %s to trash?") % leaf.object, _("Move") ): return gfile = leaf.get_gfile() try: gfile.trash() except GLib.Error as exc: # pylint: disable=no-member raise OperationError(exc.message) from exc def activate_multiple(self, objs, iobjects=None, ctx=None): objs = list(objs) objs_count = len(objs) if not uiutils.confirm_dialog( ngettext( "Move one file to trash?", "Move %(num)s files to trash?", objs_count, ) % {"num": objs_count}, _("Move"), ): return try: for leaf in objs: gfile = leaf.get_gfile() gfile.trash() except GLib.Error as exc: # pylint: disable=no-member raise OperationError(exc.message) from exc def valid_for_item(self, leaf): gfile = leaf.get_gfile() if not gfile.query_exists(None): return False info = gfile.query_info( Gio.FILE_ATTRIBUTE_ACCESS_CAN_TRASH, Gio.FileQueryInfoFlags.NONE, None, ) return info.get_attribute_boolean(Gio.FILE_ATTRIBUTE_ACCESS_CAN_TRASH) def get_description(self): return _("Move this file to trash") def get_icon_name(self): return "user-trash-full" def item_types(self): yield FileLeaf class RestoreTrashedFile(Action): def __init__(self): Action.__init__(self, _("Restore")) def has_result(self): return True def activate(self, leaf, iobj=None, ctx=None): orig_path = leaf.get_orig_path() if not orig_path: return None orig_gfile = Gio.File.new_for_path(orig_path) cur_gfile = leaf.get_gfile() if orig_gfile.query_exists(): raise OperationError( f"Target file exists at {orig_gfile.get_path()}" ) pretty.print_debug(__name__, f"Move {cur_gfile} to {orig_gfile}") ret = cur_gfile.move( orig_gfile, Gio.FileCopyFlags.ALL_METADATA, None, None, None ) pretty.print_debug(__name__, f"Move ret={ret}") return FileLeaf(orig_gfile.get_path()) def get_description(self): return _("Move file back to original location") def get_icon_name(self): return "edit-undo" class EmptyTrash(Action): rank_adjust = -1 def __init__(self): Action.__init__(self, _("Empty Trash")) def activate(self, leaf, iobj=None, ctx=None): gfile = Gio.File.new_for_uri(_TRASH_URI) failed = [] for info in gfile.enumerate_children( "standard::*,trash::*", Gio.FileQueryInfoFlags.NONE, None ): name = info.get_name() if not gfile.get_child(name).delete(): failed.append(name) if failed: err = _("Could not delete files:\n ") raise OperationError(err + "\n ".join(failed)) def get_icon_name(self): return "user-trash-full" class TrashFile(Leaf): """A file in the trash. Represented object is a file info object""" def __init__(self, trash_uri, info): name = info.get_display_name() Leaf.__init__(self, info, name) self._trash_uri = trash_uri def get_actions(self): if self.get_orig_path(): yield RestoreTrashedFile() def get_gfile(self): return Gio.File.new_for_uri(self._trash_uri).get_child( self.object.get_name() ) def get_orig_path(self): with suppress(AttributeError): return self.object.get_attribute_byte_string("trash::orig-path") return None def is_valid(self): return self.get_gfile().query_exists() def get_description(self): orig_path = self.get_orig_path() return ( launch.get_display_path_for_bytestring(orig_path) if orig_path else None ) def get_gicon(self): return self.object.get_icon() def get_icon_name(self): return "text-x-generic" class TrashContentSource(Source): def __init__(self, trash_uri, name): Source.__init__(self, name) self._trash_uri = trash_uri def is_dynamic(self): return True def get_items(self): gfile = Gio.File.new_for_uri(self._trash_uri) for info in gfile.enumerate_children( "standard::*,trash::*", Gio.FileQueryInfoFlags.NONE, None ): yield TrashFile(self._trash_uri, info) def should_sort_lexically(self): return True def get_gicon(self): return icons.get_gicon_for_file(self._trash_uri) class SpecialLocation(Leaf): """Base class for Special locations (in GIO/GVFS), such as trash:/// Here we assume they are all "directories" """ def __init__(self, location, name=None, description=None, icon_name=None): """Special location with @location and @name. If unset, we find @name from filesystem @description is Leaf description""" gfile = Gio.File.new_for_uri(location) info = gfile.query_info( Gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, Gio.FileQueryInfoFlags.NONE, None, ) name = ( info.get_attribute_string(Gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME) or location ) Leaf.__init__(self, location, name) self.description = description self.icon_name = icon_name def get_actions(self): yield OpenTrash() def get_description(self): return self.description or self.object def get_gicon(self): # Get icon return icons.get_gicon_for_file(self.object) def get_icon_name(self): return "folder" class Trash(SpecialLocation): def __init__(self, trash_uri, name=None): SpecialLocation.__init__(self, trash_uri, name=name) def has_content(self): return self.get_item_count() def content_source(self, alternate=False): return TrashContentSource(self.object, name=str(self)) def get_actions(self): yield from SpecialLocation.get_actions(self) if self.get_item_count(): yield EmptyTrash() def get_item_count(self): gfile = Gio.File.new_for_uri(self.object) info = gfile.query_info( Gio.FILE_ATTRIBUTE_TRASH_ITEM_COUNT, Gio.FileQueryInfoFlags.NONE, None, ) return info.get_attribute_uint32(Gio.FILE_ATTRIBUTE_TRASH_ITEM_COUNT) def get_description(self): item_count = self.get_item_count() if not item_count: return _("Trash is empty") # proper translation of plural return ngettext( "Trash contains one file", "Trash contains %(num)s files", item_count, ) % {"num": item_count} class InvisibleSourceLeaf(SourceLeaf): """Hack to hide this source""" def is_valid(self): return False class TrashSource(Source): def __init__(self): Source.__init__(self, _("Trash")) def get_items(self): try: yield Trash(_TRASH_URI) except GLib.Error: self.output_exc() def get_leaf_repr(self): return InvisibleSourceLeaf(self) def provides(self): yield SpecialLocation def get_icon_name(self): return "user-trash" class OpenTrash(Open): def activate(self, leaf, iobj=None, ctx=None): launch.show_url(leaf.object) kupfer-328/kupfer/plugin/triggers.py000066400000000000000000000134151500175051100176550ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("Triggers") __kupfer_sources__ = ("Triggers",) __kupfer_actions__ = ("AddTrigger",) __description__ = _( "Assign global keybindings (triggers) to objects created " "with 'Compose Command'." ) __version__ = "2009-12-30" __author__ = "Ulrik Sverdrup " import typing as ty from gi.repository import GLib, Gtk from kupfer import plugin_support, puid from kupfer.core import commandexec from kupfer.obj import Action, OperationError, RunnableLeaf, Source from kupfer.obj.compose import ComposedLeaf from kupfer.support import task from kupfer.ui import getkey_dialog, keybindings, uievents if ty.TYPE_CHECKING: from gettext import gettext as _ plugin_support.check_keybinding_support() class Trigger(RunnableLeaf): def get_actions(self): yield from RunnableLeaf.get_actions(self) yield RemoveTrigger() def wants_context(self): return True def is_valid(self): return Triggers.has_trigger(self.object) def run(self, ctx=None): assert ctx return Triggers.perform_trigger(ctx, self.object) def repr_key(self): return self.object class Triggers(Source): instance: Triggers | None = None def __init__(self): Source.__init__(self, _("Triggers")) self.trigger_table = {} def config_save(self): return {"triggers": self.trigger_table, "version": self.version} def config_save_name(self): return __name__ def config_restore(self, state): self.trigger_table = state["triggers"] return True def initialize(self): Triggers.instance = self keybindings.get_keybound_object().connect( "keybinding", self._on_keybinding_callback ) for target, (keystr, _name, _id) in self.trigger_table.items(): keybindings.bind_key(keystr, target) self.output_debug("Loaded triggers, count:", len(self.trigger_table)) def finalize(self): for target in self.trigger_table: keybindings.bind_key(None, target) def _on_keybinding_callback(self, keyobj, target, display, event_time): if not self.has_trigger(target): return ui_ctx = uievents.gui_context_from_keyevent(event_time, display) ctx = commandexec.default_action_execution_context() exec_token = ctx.make_execution_token(ui_ctx) self.perform_trigger(exec_token, target) def get_items(self): for target, (keystr, name, _id) in self.trigger_table.items(): label = Gtk.accelerator_get_label(*Gtk.accelerator_parse(keystr)) yield Trigger(target, f"{label or keystr} ({name})") def should_sort_lexically(self): return True def provides(self): yield Trigger @classmethod def has_trigger(cls, target): assert cls.instance return target in cls.instance.trigger_table @classmethod def perform_trigger(cls, ctx, target): assert cls.instance try: _, _, id_ = cls.instance.trigger_table[target] except KeyError as exc: raise OperationError(f"Trigger '{target}' does not exist") from exc if (obj := puid.resolve_unique_id(id_)) is not None: return obj.run(ctx) # type:ignore return None @classmethod def add_trigger(cls, leaf, keystr): assert cls.instance # pylint: disable=protected-access cls.instance._add_trigger(leaf, keystr) # noqa:SLF001 @classmethod def remove_trigger(cls, target): assert cls.instance # pylint: disable=protected-access cls.instance._remove_trigger(target) # noqa:SLF001 def _add_trigger(self, leaf, keystr): for target in range(*keybindings.KEYRANGE_TRIGGERS): if target not in self.trigger_table: break keybindings.bind_key(keystr, target) name = str(leaf) self.trigger_table[target] = (keystr, name, puid.get_unique_id(leaf)) self.mark_for_update() def _remove_trigger(self, target): self.trigger_table.pop(target, None) keybindings.bind_key(None, target) self.mark_for_update() def get_icon_name(self): return "key_bindings" def _try_bind_key(keystr): label = Gtk.accelerator_get_label(*Gtk.accelerator_parse(keystr)) if label is None: return False if len(label) == 1 and label.isalnum(): return False target = keybindings.KEYRANGE_TRIGGERS[-1] - 1 if succ := keybindings.bind_key(keystr, target): keybindings.bind_key(None, target) return succ class BindTask(task.Task): def __init__(self, leaf, screen): super().__init__() self.leaf = leaf self.screen = screen def start(self, finish_callback): GLib.idle_add(self.ask_key, finish_callback) def ask_key(self, finish_callback): keystr = getkey_dialog.ask_for_key( _try_bind_key, screen=self.screen, show_clear=False ) if keystr: Triggers.add_trigger(self.leaf, keystr) finish_callback(self) class AddTrigger(Action): def __init__(self): Action.__init__(self, _("Add Trigger...")) def is_async(self): return True def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx return BindTask(leaf, ctx.environment.get_screen()) def item_types(self): yield ComposedLeaf def get_icon_name(self): return "list-add" class RemoveTrigger(Action): def __init__(self): Action.__init__(self, _("Remove Trigger")) def activate(self, leaf, iobj=None, ctx=None): Triggers.remove_trigger(leaf.object) def get_icon_name(self): return "list-remove" kupfer-328/kupfer/plugin/urlactions.py000066400000000000000000000105401500175051100202060ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("URL Actions") __kupfer_sources__ = () __kupfer_text_sources__ = () __kupfer_actions__ = ("DownloadAndOpen", "DownloadTo") __description__ = _("URL Actions") __version__ = "" __author__ = "Ulrik Sverdrup " import os import shutil import typing as ty import urllib.error import urllib.parse import urllib.request from kupfer import launch from kupfer.obj import Action, FileLeaf, UrlLeaf from kupfer.support import fileutils, task if ty.TYPE_CHECKING: import http.client from gettext import gettext as _ def get_dest_name(response: http.client.HTTPResponse) -> str: headers = response.headers # try get filename from content-disposition header content_disp = headers.get("Content-Disposition", "") for part in content_disp.split(";"): key, _sep, val = part.strip().partition("=") if key.lower() == "filename": return val name = "index" # try get filename from url url = urllib.parse.urlparse(response.url) if url.path not in ("", "/"): name = os.path.basename(url.path.rstrip("/")) # if name have extension - return it if os.path.splitext(name)[1]: return name # if name not contain extension, try guess it from content-type. # only basic types content_type = headers.get("Content-Type", "") content_type = content_type.split(";", 1)[0].strip() if content_type == "text/html": return f"{name}.html" if content_type == "text/plain": return f"{name}.txt" return name class DownloadTask(task.ThreadTask): def __init__( self, uri, destdir=None, tempfile=False, finish_callback=None ): super().__init__() self.uri = uri self.download_finish_callback = finish_callback self.destdir = destdir self.use_tempfile = tempfile self.destpath = None def _get_dst_file( self, destname: str ) -> tuple[ty.BinaryIO | None, str | None]: if self.use_tempfile: return fileutils.get_safe_tempfile() return fileutils.get_destfile_in_directory(self.destdir, destname) def thread_do(self): with urllib.request.urlopen(self.uri) as response: if response.status >= 300 or response.status < 200: # noqa: PLR2004 raise RuntimeError( f"Could not download file; status: {response.status}" ) destname = get_dest_name(response) destfile, self.destpath = self._get_dst_file(destname) if not destfile: raise OSError("Could not write output file") try: shutil.copyfileobj(response, destfile) finally: destfile.close() def thread_finish(self): if self.download_finish_callback: self.download_finish_callback(self.destpath) class DownloadAndOpen(Action): """Asynchronous action to download file and open it""" def __init__(self): Action.__init__(self, _("Download and Open")) def is_async(self): return True def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx def finish_action(filename): launch.show_path(filename) ctx.register_late_result(FileLeaf(filename), show=False) uri = leaf.object return DownloadTask(uri, None, True, finish_action) def item_types(self): yield UrlLeaf def get_description(self): return None class DownloadTo(Action): def __init__(self): Action.__init__(self, _("Download To...")) def is_async(self): return True def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx assert iobj def finish_action(filename): ctx.register_late_result(FileLeaf(filename)) uri = leaf.object return DownloadTask(uri, iobj.object, False, finish_action) def item_types(self): yield UrlLeaf def requires_object(self): return True def object_types(self): yield FileLeaf def valid_object(self, obj, for_item=None): return fileutils.is_directory_writable(obj.object) def get_description(self): return _("Download URL to a chosen location") kupfer-328/kupfer/plugin/vim.py000066400000000000000000000157111500175051100166230ustar00rootroot00000000000000#! /usr/bin/env python3 """ Plugin generate recent opened files for vim/gvim. """ from __future__ import annotations __kupfer_name__ = _("Vim") __kupfer_sources__ = ("VimRecentsSource", "VimWikiSource") __description__ = _("Load recent files edited in VIM/GVIM") __version__ = "2023-04-02" __author__ = "Karol Będkowski " import os import shutil import typing as ty from pathlib import Path from kupfer import icons, launch, plugin_support from kupfer.obj import Action, FileLeaf, Source, SourceLeaf from kupfer.obj.apps import AppLeafContentMixin from kupfer.obj.helplib import FileMonitorToken, FilesystemWatchMixin from kupfer.support.datatools import simple_cache if ty.TYPE_CHECKING: from gettext import gettext as _ from gi.repository import Gio plugin_support.check_any_command_available("vim", "gvim") __kupfer_settings__ = plugin_support.PluginSettings( { "key": "wikis", "label": _("VimWiki directories:"), "type": list, "value": [], "helper": "choose_directory", }, { "key": "limit", "label": _("Max recent documents:"), "type": int, "value": 25, "min": 1, "max": 100, }, ) @simple_cache def _load_recent_files(viminfo: Path, limit: int, stamp: float) -> list[Path]: # stamp is file modification timestamp used to evict old cache items files = [] with viminfo.open("rt", encoding="UTF-8", errors="replace") as fin: for line in fin: if not line.startswith("> "): continue if filepath := line[2:].strip(): files.append(Path(filepath).expanduser()) limit -= 1 if not limit: break return files class VimRecentsSource(AppLeafContentMixin, Source, FilesystemWatchMixin): appleaf_content_id = ("vim", "gvim") source_scan_interval: int = 3600 def __init__(self, name=None): super().__init__(name=_("Vim Recent Documents")) self._monitor_token: FileMonitorToken | None = None self._viminfo = Path("~/.viminfo").expanduser() def initialize(self): self._monitor_token = self.monitor_files(self._viminfo) def finalize(self): self.stop_monitor_fs_changes(self._monitor_token) def monitor_include_file(self, gfile: Gio.File) -> bool: return bool(gfile) and gfile.get_basename() == ".viminfo" def get_items_forced(self): try: _load_recent_files.cache_clear() except AttributeError: _load_recent_files.__wrapped__.cache_clear() # type:ignore return self.get_items() def get_items(self): viminfo = self._viminfo if not viminfo.exists(): self.output_debug("Viminfo not found at", viminfo) return () limit = __kupfer_settings__["limit"] try: return map( FileLeaf, _load_recent_files(viminfo, limit, viminfo.stat().st_mtime), ) except OSError: self.output_exc() return () def get_icon_name(self): return "document-open-recent" def provides(self): yield FileLeaf class VimWikiFile(FileLeaf): def __init__(self, path: Path, name: str, wikiname: str) -> None: super().__init__(path, name) self.kupfer_add_alias(f"vimwiki {wikiname} {name}") def get_actions(self): yield OpenVimWiki() class VimWiki(SourceLeaf): def __init__(self, source: VimWikiFilesSource, name: str) -> None: super().__init__(source, name) def get_gicon(self): return icons.ComposedIconSmall("gvim", "emblem-documents") def get_description(self): return _("VimWiki in %s") % self.object.wikipath class VimWikiSource(Source): def __init__(self): super().__init__(name=_("VimWiki Wikis")) def get_items(self): existing_wiki = [] for path in __kupfer_settings__["wikis"] or (): filepath = Path(path).expanduser().resolve() if filepath.is_dir(): name = filepath.name # make names unique (simple and not perfect) if name in existing_wiki: name = f"{name} ({filepath.parent.name})" existing_wiki.append(name) yield VimWiki(VimWikiFilesSource(filepath), name) def provides(self): yield VimWiki def get_gicon(self): return icons.ComposedIconSmall("gvim", "emblem-documents") class VimWikiFilesSource(Source, FilesystemWatchMixin): source_scan_interval: int = 3600 def __init__(self, wikipath: Path) -> None: super().__init__(wikipath.name) self.wikipath = wikipath self._viminfo = Path("~/.viminfo").expanduser() self._monitor_token: FileMonitorToken | None = None def initialize(self): self._monitor_token = self.monitor_files(self._viminfo) def finalize(self): self.stop_monitor_fs_changes(self._monitor_token) def monitor_include_file(self, gfile: Gio.File) -> bool: if not gfile or gfile.get_basename() != ".viminfo": return False viminfo = self._viminfo if not viminfo.exists(): return False # check is last modified files in vim belong do this wiki limit = __kupfer_settings__["limit"] for fname in _load_recent_files( viminfo, limit, viminfo.stat().st_mtime ): if fname.is_relative_to(self.wikipath): return True return False def mark_for_update(self, postpone=False): super().mark_for_update(postpone=True) def repr_key(self) -> str: return str(self.wikipath) def get_items(self) -> ty.Iterable[VimWikiFile]: # wiki can keep various files (txt, md, etc). Instead of read index # and guess extension - load add files in wiki wikipath = self.wikipath wikiname = self.wikipath.name for dirname, dirs, files in os.walk(wikipath): dirp = Path(dirname) # skip hidden directories if dirp.name[0] == ".": dirs.clear() continue for file in files: # skip hidden files if file[0] == ".": continue filepath = dirp.joinpath(file) yield VimWikiFile( filepath, str(filepath.relative_to(wikipath)), wikiname ) def provides(self): yield VimWikiFile def should_sort_lexically(self): return True class OpenVimWiki(Action): rank_adjust = 20 def __init__(self): super().__init__(name=_("Open in Vim")) def activate(self, leaf, iobj=None, ctx=None): if cmd := shutil.which("gvim"): launch.spawn_async([cmd, leaf.object]) elif cmd := shutil.which("vim"): launch.spawn_in_terminal([cmd, leaf.object]) def get_icon_name(self) -> str: return "gvim" kupfer-328/kupfer/plugin/virtualbox/000077500000000000000000000000001500175051100176505ustar00rootroot00000000000000kupfer-328/kupfer/plugin/virtualbox/__init__.py000066400000000000000000000127741500175051100217740ustar00rootroot00000000000000__kupfer_name__ = _("VirtualBox") __kupfer_sources__ = ("VBoxMachinesSource",) __description__ = _( "Control VirtualBox Virtual Machines. " "Supports both Sun VirtualBox and Open Source Edition." ) __version__ = "0.4" __author__ = "Karol Będkowski " import typing as ty from contextlib import suppress from kupfer import plugin_support from kupfer.obj import Action, Leaf from kupfer.obj.apps import ApplicationSource from kupfer.plugin.virtualbox import constants as vbox_const from kupfer.plugin.virtualbox import ose_support from kupfer.support import pretty if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_settings__ = plugin_support.PluginSettings( { "key": "force_cli", "label": _("Force use CLI interface"), "type": bool, "value": False, }, ) def _get_vbox(): if __kupfer_settings__["force_cli"]: pretty.print_info(__name__, "Using cli...") return ose_support with suppress(ImportError): # pylint: disable=import-outside-toplevel from kupfer.plugin.virtualbox import vboxapi4_support pretty.print_info(__name__, "Using vboxapi4...") return vboxapi4_support with suppress(ImportError): # pylint: disable=import-outside-toplevel from kupfer.plugin.virtualbox import vboxapi_support pretty.print_info(__name__, "Using vboxapi...") return vboxapi_support pretty.print_info(__name__, "Using cli...") return ose_support class _VBoxSupportProxy: _vbox = None def __getattr__(self, attr): if not self._vbox: self.reload_settings() return getattr(self._vbox, attr) def reload_settings(self): pretty.print_debug(__name__, "_VBoxSupportProxy.reloading...") self.unload_module() self._vbox = _get_vbox() def unload_module(self): if self._vbox: self._vbox.unload() self._vbox = None def __bool__(self): return self._vbox is not None vbox_support = _VBoxSupportProxy() class VirtualMachine(Leaf): def __init__(self, obj, name, description): Leaf.__init__(self, obj, name) self.description = description def get_description(self): return self.description def get_icon_name(self): return vbox_support.ICON def get_actions(self): state = vbox_support.get_machine_state(self.object) if state == vbox_const.VM_STATE_POWEROFF: yield VMAction( _("Power On"), "system-run", vbox_const.VM_START_NORMAL ) yield VMAction( _("Power On Headless"), "system-run", vbox_const.VM_START_HEADLESS, -5, ) elif state == vbox_const.VM_STATE_POWERON: yield VMAction( _("Send Power Off Signal"), "system-shutdown", vbox_const.VM_ACPI_POWEROFF, -5, ) yield VMAction(_("Pause"), "pause", vbox_const.VM_PAUSE) yield VMAction( _("Reboot"), "system-reboot", vbox_const.VM_REBOOT, -10 ) elif state == vbox_const.VM_STATE_SAVED: yield VMAction( _("Power On"), "system-run", vbox_const.VM_START_NORMAL ) yield VMAction( _("Power On Headless"), "system-run", vbox_const.VM_START_HEADLESS, -5, ) else: # VM_STATE_PAUSED yield VMAction(_("Resume"), "resume", vbox_const.VM_RESUME) if state in (vbox_const.VM_STATE_POWERON, vbox_const.VM_STATE_PAUSED): yield VMAction( _("Save State"), "system-suspend", vbox_const.VM_SAVE ) yield VMAction( _("Power Off"), "system-shutdown", vbox_const.VM_POWEROFF, -10 ) class VMAction(Action): def __init__(self, name, icon, command, rank_adjust=0): Action.__init__(self, name) self._icon = icon self.rank_adjust = rank_adjust self.command = command def get_icon_name(self): return self._icon def item_types(self): yield VirtualMachine def activate(self, leaf, iobj=None, ctx=None): vbox_support.vm_action(self.command, leaf.object) class VBoxMachinesSource(ApplicationSource): appleaf_content_id = ("virtualbox-ose", "virtualbox") def __init__(self, name=_("VirtualBox Machines")): super().__init__(name) self.monitor_token = None def initialize(self): if vbox_support.MONITORED_DIRS: self.monitor_token = self.monitor_directories( *vbox_support.MONITORED_DIRS ) __kupfer_settings__.connect( "plugin-setting-changed", self._on_setting_changed ) def finalize(self): if vbox_support: vbox_support.unload_module() def is_dynamic(self): return vbox_support.IS_DYNAMIC def get_items(self): for ( machine_id, machine_name, machine_desc, ) in vbox_support.get_machines(): yield VirtualMachine(machine_id, machine_name, machine_desc) def get_description(self): return None def get_icon_name(self): return vbox_support.ICON def provides(self): yield VirtualMachine def _on_setting_changed(self, _setting, _key, _value): if vbox_support: vbox_support.reload_settings() kupfer-328/kupfer/plugin/virtualbox/constants.py000066400000000000000000000006331500175051100222400ustar00rootroot00000000000000""" virtualbox_const_support.py Constants for VirtualBox. """ __author__ = "Karol Będkowski " __version__ = "0.4" # virtual machine states VM_STATE_POWEROFF = 0 VM_STATE_POWERON = 1 VM_STATE_PAUSED = 2 VM_STATE_SAVED = 3 # virtual machine actions VM_START_NORMAL = 1 VM_START_HEADLESS = 2 VM_PAUSE = 3 VM_POWEROFF = 4 VM_ACPI_POWEROFF = 5 VM_REBOOT = 6 VM_RESUME = 7 VM_SAVE = 8 kupfer-328/kupfer/plugin/virtualbox/ose_support.py000066400000000000000000000110521500175051100226030ustar00rootroot00000000000000""" virtualbox_ose_support.py Control VirtualBox via command-line interface. Support both Sun VirtualBox and VirtualBox OpenSource Edition. """ __author__ = "Karol Będkowski " __version__ = "2018-10-21" import os from pathlib import Path from xml.dom import minidom from kupfer import launch from kupfer.plugin.virtualbox import constants as vbox_const from kupfer.support import pretty _VBOX_CONFIG_DIRS = ( Path("~/.config/VirtualBox/").expanduser(), Path("~/.VirtualBox/").expanduser(), ) _VBOX_CONFIG_FILE = "VirtualBox.xml" MONITORED_DIRS = _VBOX_CONFIG_DIRS IS_DYNAMIC = False ICON = "virtualbox-ose" APP_ID = "virtualbox-ose" # parameters for VBoxManage _ACTIONS = { vbox_const.VM_POWEROFF: "poweroff", vbox_const.VM_ACPI_POWEROFF: "acpipowerbutton", vbox_const.VM_PAUSE: "pause", vbox_const.VM_REBOOT: "reset", vbox_const.VM_RESUME: "resume", vbox_const.VM_SAVE: "savestate", } def get_machine_state(vm_uuid): """check vms state (on/off/paused)""" state = vbox_const.VM_STATE_POWEROFF try: str_state = "poweroff" with os.popen( f"VBoxManage showvminfo {vm_uuid} --machinereadable" ) as pinfo: for line in pinfo: if line.startswith('VMState="'): str_state = line.strip()[9:-1] break if str_state == "paused": state = vbox_const.VM_STATE_PAUSED elif str_state == "running": state = vbox_const.VM_STATE_POWERON elif str_state == "saved": state = vbox_const.VM_STATE_SAVED except OSError as err: pretty.print_error( __name__, "get_machine_state", vm_uuid, "error", err ) state = vbox_const.VM_STATE_POWEROFF return state def vm_action(action, vm_uuid): """change state of the virtual machine. Call VBoxManage. @param action - one of the const VM_* @param vm_uuid - virtual machine uuid """ if action == vbox_const.VM_START_NORMAL: launch.spawn_async(["VBoxManage", "startvm", vm_uuid, "--type", "gui"]) elif action == vbox_const.VM_START_HEADLESS: launch.spawn_async( ["VBoxManage", "startvm", vm_uuid, "--type", "headless"] ) else: command = _ACTIONS[action] launch.spawn_async(["VBoxManage", "controlvm", vm_uuid, command]) def _get_virtual_machines(config_file): """load (virtual machine uuid, path to vm config) from virtualbox configuration. @param config_file - path to VirtualBox.xml file """ try: dtree = minidom.parse(config_file) machine_registry = dtree.getElementsByTagName("MachineRegistry")[0] for machine in machine_registry.getElementsByTagName("MachineEntry"): yield ( machine.getAttribute("uuid")[1:-1], machine.getAttribute("src"), ) except Exception as err: pretty.print_error( __name__, "_get_virtual_machines", config_file, "error", err ) def _get_machine_info(vm_uuid, config_file): """load information about virtual machines from its configuration file. @param vm_uuid - uuid virtual machine @param config_file - path to vm configuration file """ if not os.path.isfile(config_file): return None, None try: dtree = minidom.parse(config_file) machine_registry = dtree.getElementsByTagName("Machine")[0] os_type = machine_registry.getAttribute("OSType") name = machine_registry.getAttribute("name") description = None for machine_registry_child in machine_registry.childNodes: if machine_registry_child.nodeName == "Description": if machine_registry_child.hasChildNodes(): description = machine_registry_child.firstChild.nodeValue break return (name, description or os_type) except Exception as err: pretty.print_error( __name__, "_get_machine_info", vm_uuid, "error" + config_file, err ) return None, None def get_machines(): for dirname in _VBOX_CONFIG_DIRS: vbox_conf = Path(dirname, _VBOX_CONFIG_FILE) if not vbox_conf.is_file(): continue for vm_uuid, config in _get_virtual_machines(vbox_conf): if not os.path.isabs(config): config = os.path.join(dirname, config) # noqa: PLW2901 name, description = _get_machine_info(vm_uuid, config) if name: yield (vm_uuid, name, description) def unload(): pass kupfer-328/kupfer/plugin/virtualbox/vboxapi4_support.py000066400000000000000000000103111500175051100235460ustar00rootroot00000000000000""" virtualbox_vboxapi_support.py Control VirtualBox via Python interface (vboxapi). Only (?) Sun VirtualBox (no OSE). """ __author__ = "Karol Będkowski " __version__ = "2018-10-21" import vboxapi # pylint: disable=import-error from kupfer.plugin.virtualbox import constants as vbox_const from kupfer.support import pretty # check api try: _x = vboxapi.VirtualBoxReflectionInfo(None).SessionState_Locked except AttributeError as exc: raise ImportError from exc MONITORED_DIRS = None IS_DYNAMIC = False ICON = "VBox" APP_ID = "virtualbox" _ACTIONS = { vbox_const.VM_POWEROFF: lambda c: c.powerDown(), vbox_const.VM_ACPI_POWEROFF: lambda c: c.powerButton(), vbox_const.VM_PAUSE: lambda c: c.pause(), vbox_const.VM_REBOOT: lambda c: c.reset(), vbox_const.VM_RESUME: lambda c: c.resume(), vbox_const.VM_SAVE: lambda c: c.saveState(), } _VBOX = vboxapi.VirtualBoxManager(None, None) def get_machine_by_id(mid): try: mach = _VBOX.getVirtualBox().getMachine(mid) except AttributeError: mach = _VBOX.getVirtualBox().findMachine(mid) return mach def get_machine_state(machine_id): """check vms state (on/off/paused)""" if _VBOX is None: return vbox_const.VM_STATE_POWEROFF state = vbox_const.VM_STATE_POWERON machine_state = None try: machine = get_machine_by_id(machine_id) pretty.print_debug(__name__, "machine ", machine) machine_state = machine.state if machine_state == _VBOX.constants.MachineState_Paused: state = vbox_const.VM_STATE_PAUSED elif machine_state in ( _VBOX.constants.MachineState_PoweredOff, _VBOX.constants.MachineState_Aborted, _VBOX.constants.MachineState_Starting, ): state = vbox_const.VM_STATE_POWEROFF elif machine_state == _VBOX.constants.MachineState_Saved: state = vbox_const.VM_STATE_SAVED except Exception as err: # exception == machine is off (xpcom.Exception) pretty.print_debug(__name__, "get_machine_state", machine_state, err) # silently set state to off state = vbox_const.VM_STATE_POWEROFF return state def _machine_start(vm_uuid, mode): """Start virtual machine @param vm_uuid - uuid of virtual machine @param mode - mode: gui, headless """ try: session = _VBOX.getSessionObject() mach = get_machine_by_id(vm_uuid) remote_sess = mach.launchVMProcess(session, mode, "") remote_sess.waitForCompletion(-1) session.unlockMachine() except Exception as err: pretty.print_error( __name__, "StartVM:", vm_uuid, "Mode ", mode, "error", err ) def _execute_machine_action(vm_uuid, action): """Start virtual machine @param vm_uuid - uuid of virtual machine @param action - function called on _VBOX session """ try: session = _VBOX.getSessionObject() mach = get_machine_by_id(vm_uuid) mach.lockMachine(session, _VBOX.constants.LockType_Shared) action(session.console) session.unlockMachine() except Exception as err: pretty.print_error( __name__, "_execute_machine_action:", action, " vm:", vm_uuid, "error", err, ) def vm_action(action, vm_uuid): """change state of the virtual machine @param action - one of the const VM_* @param vm_uuid - virtual machine uuid """ if _VBOX is None: return if action == vbox_const.VM_START_NORMAL: _machine_start(vm_uuid, "gui") elif action == vbox_const.VM_START_HEADLESS: _machine_start(vm_uuid, "headless") else: command = _ACTIONS[action] _execute_machine_action(vm_uuid, command) def get_machines(): """Get generator of items: (machine uuid, machine name, machine description) """ if _VBOX is None: return machines = _VBOX.getArray(_VBOX.getVirtualBox(), "machines") for machine in machines: if machine.accessible: description = machine.description or machine.OSTypeId yield (machine.id, machine.name, description) def unload(): pass kupfer-328/kupfer/plugin/virtualbox/vboxapi_support.py000066400000000000000000000130531500175051100234700ustar00rootroot00000000000000""" virtualbox_vboxapi_support.py Control VirtualBox via Python interface (vboxapi). Only (?) Sun VirtualBox (no OSE). """ __author__ = "Karol Będkowski " __version__ = "2018-09-07" from contextlib import suppress import vboxapi # pylint: disable=import-error from kupfer.plugin.virtualbox import constants as vbox_const from kupfer.support import pretty MONITORED_DIRS = None IS_DYNAMIC = False ICON = "VBox" APP_ID = "virtualbox" _ACTIONS = { vbox_const.VM_POWEROFF: lambda c: c.powerDown(), vbox_const.VM_ACPI_POWEROFF: lambda c: c.powerButton(), vbox_const.VM_PAUSE: lambda c: c.pause(), vbox_const.VM_REBOOT: lambda c: c.reset(), vbox_const.VM_RESUME: lambda c: c.resume(), vbox_const.VM_SAVE: lambda c: c.saveState(), } def _get_object_session(): """get new session to vm""" pretty.print_debug(__name__, "_get_object_session start") vbox, session = None, None try: vbox = vboxapi.VirtualBoxManager(None, None) session = vbox.mgr.getSessionObject(vbox.vbox) except Exception as err: pretty.print_error(__name__, "virtualbox: get session error ", err) pretty.print_debug(__name__, "_get_object_session finished", vbox, session) return vbox, session def _get_existing_session(vm_uuid): """get existing session by machine uuid""" pretty.print_debug(__name__, "_get_existing_session start") vbox, session = None, None try: vbox = vboxapi.VirtualBoxManager(None, None) session = vbox.mgr.getSessionObject(vbox.vbox) vbox.vbox.openExistingSession(session, vm_uuid) except Exception as err: pretty.print_error( __name__, "virtualbox: get session error", vm_uuid, err ) pretty.print_debug( __name__, "_get_existing_session finished", vbox, session ) return vbox, session def get_machine_state(machine_id): """check vms state (on/off/paused)""" pretty.print_debug(__name__, "get_machine_state", machine_id) vbox, vbox_sess = _get_object_session() if vbox_sess is None: return vbox_const.VM_STATE_POWEROFF state = vbox_const.VM_STATE_POWERON try: vbox.vbox.openExistingSession(vbox_sess, machine_id) machine_state = vbox_sess.machine.state if machine_state == vbox.constants.MachineState_Paused: state = vbox_const.VM_STATE_PAUSED elif machine_state in ( vbox.constants.MachineState_PoweredOff, vbox.constants.MachineState_Aborted, vbox.constants.MachineState_Starting, ): state = vbox_const.VM_STATE_POWEROFF elif machine_state == vbox.constants.MachineState_Saved: state = vbox_const.VM_STATE_SAVED except Exception as err: # exception == machine is off (xpcom.Exception) # silently set state to off state = vbox_const.VM_STATE_POWEROFF pretty.print_debug(__name__, "get_machine_state error", err) with suppress(Exception): if vbox_sess.state == vbox.constants.SessionState_Open: vbox_sess.close() pretty.print_debug(__name__, "get_machine_state finish", machine_id, state) return state def _machine_start(vm_uuid, mode): """Start virtual machine @param vm_uuid - uuid of virtual machine @param mode - mode: gui, headless """ vbox, session = _get_object_session() if session: try: remote_sess = vbox.vbox.openRemoteSession( session, vm_uuid, mode, "" ) remote_sess.waitForCompletion(-1) except Exception as err: pretty.print_error( __name__, "StartVM:", vm_uuid, "Mode ", mode, "error", err ) with suppress(Exception): # various errors (xpcom.Exception) if session.state == vbox.constants.SessionState_Open: session.close() def _execute_machine_action(vm_uuid, action): """Start virtual machine @param vm_uuid - uuid of virtual machine @param action - function called on vbox session """ vbox, session = _get_existing_session(vm_uuid) try: action(session.console) except Exception as err: pretty.print_error( __name__, "_execute_machine_action:", action, " vm:", vm_uuid, "error", err, ) with suppress(Exception): # various errors (xpcom.Exception) if session.state == vbox.constants.SessionState_Open: session.close() def vm_action(action, vm_uuid): """change state of the virtual machine @param action - one of the const VM_* @param vm_uuid - virtual machine uuid """ if action == vbox_const.VM_START_NORMAL: _machine_start(vm_uuid, "gui") elif action == vbox_const.VM_START_HEADLESS: _machine_start(vm_uuid, "headless") else: command = _ACTIONS[action] _execute_machine_action(vm_uuid, command) def get_machines(): """Get generator of items: (machine uuid, machine name, machine description) """ pretty.print_debug(__name__, "get_machines start") vbox, vbox_sess = _get_object_session() if vbox_sess is None: return machines = vbox.getArray(vbox.vbox, "machines") for machine in machines: pretty.print_debug( __name__, "get_machines; found machine", machine.id, machine.name ) description = machine.description or machine.OSTypeId yield (machine.id, machine.name, description) pretty.print_debug(__name__, "get_machines finished") def unload(): pass kupfer-328/kupfer/plugin/volumes.py000066400000000000000000000162621500175051100175240ustar00rootroot00000000000000__kupfer_name__ = _("Volumes and Disks") __kupfer_sources__ = ("VolumesSource",) __description__ = _("Mounted volumes and disks") __version__ = "2023-05-01" __author__ = "US, KB" import typing as ty from gi.repository import Gio, GLib from kupfer import launch from kupfer.core import commandexec from kupfer.obj import Action, FileLeaf, Leaf, OpenTerminal, Source from kupfer.obj.fileactions import Open from kupfer.ui import uiutils if ty.TYPE_CHECKING: from gettext import gettext as _ _VOLUME_ICON_NAME = "drive-removable-media" class Volume(FileLeaf): """ The Volume class actually represents one instance of GIO's GMount (as long as it is mounted) """ # NOTE: marking as non-serializable serializable = None def __init__(self, volume): self.volume = volume fil = self.volume.get_root() path = fil.get_path() super().__init__(obj=path, name=volume.get_name()) self.kupfer_add_alias(fil.get_basename()) def get_actions(self): yield Open() yield OpenTerminal() if self.volume.can_eject(): yield Eject() if self.volume.can_unmount(): yield Unmount() def is_valid(self): vmgr = Gio.VolumeMonitor.get() return self.volume in vmgr.get_mounts() def get_description(self): # TRANS: %s is path where volume is mounted return _( "Volume mounted at %s" ) % launch.get_display_path_for_bytestring(self.object) def get_gicon(self): return self.volume.get_icon() def get_icon_name(self): return _VOLUME_ICON_NAME class VolumeNotMounted(Leaf): """The Volume class actually represents one instance of GIO's GMount that is not mounted anywhere.""" # NOTE: marking as non-serializable serializable = None def __init__(self, volume, device): super().__init__(volume, name=volume.get_name()) self.device = device def get_actions(self): if self.object.can_mount(): yield Mount() def get_description(self): # TRANS: %s is name of device with volume return _("Volume on %s") % self.device.get_name() def get_gicon(self): return self.device.get_icon() def get_icon_name(self): return _VOLUME_ICON_NAME class Mount(Action): def __init__(self, name=None): super().__init__(name or _("Mount")) def mount_callback( self, volume: Gio.Volume, async_result: ty.Any, ctx: commandexec.ExecutionToken, ) -> None: try: volume.mount_finish(async_result) except GLib.Error: ctx.register_late_error() else: uiutils.show_notification( _("Mount finished"), # TRANS: %s is name of volume _('"%s" was successfully mounted') % volume.get_name(), icon_name=_VOLUME_ICON_NAME, ) ctx.register_late_result(commandexec.ActionResultRefresh) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx vol = leaf.object if vol.can_mount(): vol.mount( Gio.MountMountFlags.NONE, None, None, self.mount_callback, ctx, ) def get_description(self): return _("Mount this volume") class Unmount(Action): # prefer eject over umount rank_adjust = -5 def __init__(self, name=None): super().__init__(name or _("Unmount")) def unmount_callback( self, mount: Gio.Mount, async_result: ty.Any, ctx: commandexec.ExecutionToken, ) -> None: try: mount.unmount_with_operation_finish(async_result) except GLib.Error: # FIXME: argument ctx.register_late_error() else: self.success(mount.get_name()) ctx.register_late_result(commandexec.ActionResultRefresh) def success(self, name: str) -> None: uiutils.show_notification( _("Unmount finished"), # TRANS: %s is name of volume _('"%s" was successfully unmounted') % name, icon_name=_VOLUME_ICON_NAME, ) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx if not leaf.is_valid(): return vol = leaf.volume if vol.can_unmount(): vol.unmount_with_operation( Gio.MountUnmountFlags.NONE, None, None, self.unmount_callback, ctx, ) def get_description(self): return _("Unmount this volume") def get_icon_name(self): return "media-eject" class Eject(Unmount): def __init__(self): super().__init__(_("Eject")) def get_description(self): return _("Unmount and eject this media") def activate(self, leaf, iobj=None, ctx=None): assert ctx if not leaf.is_valid(): return vol = leaf.volume if vol.can_eject(): vol.eject_with_operation( Gio.MountUnmountFlags.NONE, None, None, self.eject_callback, ctx, ) def eject_callback( self, mount: Gio.Mount, async_result: ty.Any, ctx: commandexec.ExecutionToken, ) -> None: try: mount.eject_with_operation_finish(async_result) except GLib.Error: ctx.register_late_error() else: self.success(mount.get_name()) ctx.register_late_result(commandexec.ActionResultRefresh) class VolumesSource(Source): source_use_cache = False def __init__(self, name=_("Volumes and Disks")): self.volmon = None super().__init__(name) def initialize(self): self.volmon = Gio.VolumeMonitor.get() self.volmon.connect("mount-added", self._update) self.volmon.connect("mount-changed", self._update) self.volmon.connect("mount-removed", self._update) self.volmon.connect("drive-connected", self._update) self.volmon.connect("drive-changed", self._update) self.volmon.connect("drive-disconnected", self._update) def _update(self, *args): self.mark_for_update() GLib.timeout_add_seconds(1, self.mark_for_update) def finalize(self): del self.volmon def get_items(self): assert self.volmon # get_mounts gets all mounted removable media volumes = self.volmon.get_mounts() yield from map(Volume, volumes) # add unmounted removable devices for dev in self.volmon.get_connected_drives(): if not dev.is_removable(): continue for vol in dev.get_volumes(): if vol.can_mount(): yield VolumeNotMounted(vol, dev) def get_description(self): return _("Mounted volumes and disks") def get_icon_name(self): return "drive-removable-media" def provides(self): yield Volume yield VolumeNotMounted kupfer-328/kupfer/plugin/websearch.py000066400000000000000000000231451500175051100177730ustar00rootroot00000000000000from __future__ import annotations __kupfer_name__ = _("Search the Web") __kupfer_sources__ = ("OpenSearchSource",) __kupfer_text_sources__ = () __kupfer_actions__ = ( "SearchFor", "SearchWithEngine", "SearchWithDefaultEngine", ) __description__ = _( "Search the web with OpenSearch and user defined search engines" ) __version__ = "2023-12-23" __author__ = "Ulrik Sverdrup , KB" import locale import os import typing as ty import urllib.parse from pathlib import Path from xml.etree import ElementTree as ET from kupfer import config, launch, plugin_support from kupfer.obj import Action, Leaf, Source, TextLeaf from kupfer.plugin._firefox_support import get_firefox_home_file if ty.TYPE_CHECKING: from gettext import gettext as _ # default search engine when user no configure default_engine and there is no # extra_engines _DEFAULT_ENGINE = "https://duckduckgo.com/?q=%s" __kupfer_settings__ = plugin_support.PluginSettings( { "key": "extra_engines", "label": _("User search engines:"), "type": str, "multiline": True, "value": "https://www.qwant.com/?q=%s\n" "https://search.brave.com/search?q=%s", "tooltip": _( "Define URLs for search engines; '%s' is replaced by search term." ), }, { "key": "default_engine", "label": _("Default search engine:"), "type": str, "value": "", "tooltip": _( "Define URL for default search engine; '%s' is replaced by " "search term. If empty, use first engine from 'User search engines'" " or DuckDuckGo" ), }, ) def _noescape_urlencode(items): """Assemble an url param string from @items, without using any url encoding. """ return "?" + "&".join(f"{n}={v}" for n, v in items) def _urlencode(word): """Urlencode a single string of bytes @word""" return urllib.parse.urlencode({"q": word})[2:] def _do_search_engine(terms, search_url, encoding="UTF-8"): """Show an url searching for @search_url with @terms""" terms = _urlencode(terms) if "{searchTerms}" in search_url: query_url = search_url.replace("{searchTerms}", terms) else: query_url = search_url.replace("%s", terms) launch.show_url(query_url) def _get_custom_engine_name(url: str) -> str | None: if not url: return None components = urllib.parse.urlparse(url) if netloc := components.netloc: return ( netloc.removeprefix("www.") .removesuffix(".com") .replace(".", " ") .capitalize() ) return None class SearchWithDefaultEngine(Action): """Search for term in default search engine.""" action_accelerator = "s" def __init__(self): Action.__init__(self, _("Search...")) def activate(self, leaf, iobj=None, ctx=None): url = __kupfer_settings__["default_engine"].strip() if not url and (urls := __kupfer_settings__["extra_engines"]): url = urls.replace(";", "\n").split("\n", 1)[0].strip() url = url or _DEFAULT_ENGINE _do_search_engine(leaf.object, url) def item_types(self): yield TextLeaf def get_description(self): return _("Search the web with default search engines") def get_icon_name(self): return "edit-find" class SearchWithEngine(Action): """TextLeaf -> SearchWithEngine -> SearchEngine""" def __init__(self): Action.__init__(self, _("Search With...")) def activate(self, leaf, iobj=None, ctx=None): coding = iobj.object.get("InputEncoding") url = iobj.object["Url"] _do_search_engine(leaf.object, url, encoding=coding) def item_types(self): yield TextLeaf def requires_object(self): return True def object_types(self): yield SearchEngine def object_source(self, for_item=None): return OpenSearchSource() def get_description(self): return _("Search the web with OpenSearch search engines") def get_icon_name(self): return "edit-find" class SearchFor(Action): """SearchEngine -> SearchFor -> TextLeaf This is the opposite action to SearchWithEngine """ action_accelerator = "s" def __init__(self): Action.__init__(self, _("Search For...")) def activate(self, leaf, iobj=None, ctx=None): coding = leaf.object.get("InputEncoding") url = leaf.object["Url"] terms = iobj.object _do_search_engine(terms, url, encoding=coding) def item_types(self): yield SearchEngine def requires_object(self): return True def object_types(self): yield TextLeaf def get_description(self): return _("Search the web with OpenSearch search engines") def get_icon_name(self): return "edit-find" class SearchEngine(Leaf): def get_description(self): desc = self.object.get("Description") return desc if desc != str(self) else None def get_icon_name(self): return "text-html" class OpenSearchParseError(Exception): pass def gettagname(tag): return tag.rsplit("}", 1)[-1] def _get_plugin_dirs() -> ty.Iterator[Path]: """Get all possible plugins path (may not exists)""" # accept in kupfer data dirs yield from map(Path, config.get_data_dirs("searchplugins")) # firefox in home directory if ffx_home := get_firefox_home_file("searchplugins"): yield ffx_home yield from map( Path, config.get_data_dirs("searchplugins", package="firefox") ) yield from map( Path, config.get_data_dirs("searchplugins", package="iceweasel") ) suffixes = ["en-US"] if cur_lang := locale.getlocale(locale.LC_MESSAGES)[0]: suffixes = [cur_lang.replace("_", "-"), cur_lang[:2], *suffixes] addon_dir = Path("/usr/lib/firefox-addons/searchplugins") for suffix in suffixes: if (addon_lang_dir := addon_dir.joinpath(suffix)).exists(): yield addon_lang_dir break # debian iceweasel yield Path("/etc/iceweasel/searchplugins/common") for suffix in suffixes: yield Path("/etc/iceweasel/searchplugins/locale", suffix) # try to find all versions of firefox for prefix in ("/usr/lib", "/usr/share"): with os.scandir(prefix) as entries: for entry in entries: if entry.name.startswith(("firefox", "iceweasel")): yield Path(entry.path, "searchplugins") yield Path( entry.path, "distribution", "searchplugins", "common" ) _OS_VITAL_KEYS = {"Url", "ShortName"} _OS_KEYS = ("Description", "Url", "ShortName", "InputEncoding") _OS_ROOTS = ("OpenSearchDescription", "SearchPlugin") def _parse_etree(etree, name=None): if gettagname(etree.getroot().tag) not in _OS_ROOTS: raise OpenSearchParseError(f"Search {name} has wrong type") search = {} for child in etree.getroot(): tagname = gettagname(child.tag) if tagname not in _OS_KEYS: continue # Only pick up Url tags with type="text/html" if tagname == "Url": if child.get("type") == "text/html" and child.get("template"): text = child.get("template") params = tuple( (ch.get("name"), ch.get("value")) for ch in child if gettagname(ch.tag) == "Param" ) if params: text += _noescape_urlencode(params) else: continue else: text = (child.text or "").strip() search[tagname] = text if not _OS_VITAL_KEYS.issubset(list(search.keys())): raise OpenSearchParseError(f"Search {name} missing _OS_KEYS") return search class OpenSearchSource(Source): def __init__(self): Source.__init__(self, _("Search Engines")) def initialize(self): __kupfer_settings__.connect( "plugin-setting-changed", self._on_setting_changed ) def _on_setting_changed(self, settings, key, value): self.mark_for_update() def _parse_opensearch(self, path: str) -> dict[str, ty.Any] | None: try: etree = ET.parse(path) return _parse_etree(etree, name=path) # type:ignore except Exception as exc: self.output_debug(f"{type(exc).__name__}: {exc}") return None def get_items(self) -> ty.Iterator[SearchEngine]: # files are unique by filename to allow override visited_files = set() for pdir in _get_plugin_dirs(): if not pdir.is_dir(): continue self.output_debug("Processing searchplugins dir", pdir) with os.scandir(pdir) as entries: for entry in entries: if entry.path in visited_files: continue visited_files.add(entry.path) if not entry.is_dir() and ( search := self._parse_opensearch(entry.path) ): yield SearchEngine(search, search["ShortName"]) # add user search engines if custom_ses := __kupfer_settings__["extra_engines"]: for url in custom_ses.replace(";", "\n").split(): if name := _get_custom_engine_name(url.strip()): yield SearchEngine({"Url": url, "Description": url}, name) def should_sort_lexically(self): return True def provides(self): yield SearchEngine def get_icon_name(self): return "applications-internet" kupfer-328/kupfer/plugin/whatsapp.py000066400000000000000000000026411500175051100176550ustar00rootroot00000000000000"""This plugin opens WhatsApp Web in the browser, and can send messages to numbers that are not scheduled """ __kupfer_name__ = _("WhatsApp Web") __kupfer_sources__ = () __kupfer_actions__ = ("WhatsApp",) __description__ = _( """Open a new number in WhatsApp Web The number format must respect: "Country Code" + "Area Code" + "Number" Example for a New York number: 12129999999 Country Code: 1 Area Code: 212 Number: 9999999 WhatsApp Web will open in the browser. For help visit https://faq.whatsapp.com/general/chats/how-to-use-click-to-chat/ """ ) __version__ = "1.0" __author__ = "Leonardo Masuero " import typing as ty from contextlib import suppress from kupfer import launch from kupfer.obj import Action, TextLeaf if ty.TYPE_CHECKING: from gettext import gettext as _ class WhatsApp(Action): def __init__(self): Action.__init__(self, _("WhatsApp Web")) def activate(self, leaf, iobj=None, ctx=None): url_w = "https://web.whatsapp.com/send?phone=" url_number = url_w + leaf.object launch.show_url(url_number) def item_types(self): yield TextLeaf def valid_for_item(self, leaf): with suppress(BaseException): text = leaf.object return bool(text) and int(text) def get_description(self): return _("Send a WhatsApp to a new number.") def get_icon_name(self): return "message-new" kupfer-328/kupfer/plugin/wikipedia.py000066400000000000000000000053561500175051100200020ustar00rootroot00000000000000""" This is a simple plugin demonstration, how to add single, simple actions """ __kupfer_name__ = _("Wikipedia") __kupfer_sources__ = () __kupfer_actions__ = ("WikipediaSearch",) __description__ = _("Search in Wikipedia") __version__ = "2017.1" __author__ = "US" import typing as ty import urllib.parse from kupfer import launch, plugin_support from kupfer.obj import Action, Leaf, Source, TextLeaf if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_settings__ = plugin_support.PluginSettings( { "key": "lang", "label": _("Wikipedia languages (;-separated)"), "type": str, # TRANS: Default wikipedia language code "value": _("en"), }, ) class Lang(Leaf): def __init__(self, lang): super().__init__(lang, name=f"{lang}.wikipedia.org") def get_icon_name(self): return self.object class LangSource(Source): def __init__(self, languages): super().__init__("Languages") self.languages = languages def get_items(self): return map(Lang, self.languages) class WikipediaSearch(Action): action_accelerator = "w" def __init__(self): Action.__init__(self, _("Search in Wikipedia")) self._update_settings() def initialize(self): __kupfer_settings__.connect_settings_changed_cb(self._update_settings) self._update_settings() def _update_settings(self, *_args): languages: tuple[str, ...] = tuple( filter( None, ( lang.strip() for lang in __kupfer_settings__["lang"].split(";") ), ) ) if not languages: languages = (_("en"),) self._languages = languages def activate(self, leaf, iobj=None, ctx=None): # Send in UTF-8 encoding lang_code = iobj.object if iobj else self._languages[0] search_url = f"https://{lang_code}.wikipedia.org/w/index.php?title=Special:Search&go=Go&" # will encode search=text, where `text` is escaped query_url = search_url + urllib.parse.urlencode( {"search": leaf.object} ) launch.show_url(query_url) def item_types(self): yield TextLeaf def get_description(self): if len(self._languages) == 1: lang_code = self._languages[0] return _("Search for this term in %s.wikipedia.org") % lang_code return _("Search for this term in %s.wikipedia.org") % "" def get_icon_name(self): return "edit-find" def requires_object(self): return len(self._languages) > 1 def object_source(self, for_item=None): return LangSource(self._languages) def object_types(self): yield Lang kupfer-328/kupfer/plugin/windows.py000066400000000000000000000276641500175051100175340ustar00rootroot00000000000000__kupfer_name__ = _("Window List") __kupfer_sources__ = ("WindowsSource", "WorkspacesSource") __description__ = _("All windows on all workspaces") __version__ = "2020-04-14" __author__ = "" import typing as ty # pylint: disable=no-name-in-module from gi.repository import Wnck from kupfer.obj import Action, Leaf, Source from kupfer.support import system, weaklib if ty.TYPE_CHECKING: from gettext import gettext as _ from gettext import ngettext def _get_window(xid): """Get wnck window by xid.""" if not xid: return None if scr := Wnck.Screen.get_default(): for wnd in scr.get_windows(): if wnd.get_xid() == xid: return wnd return None def _get_workspace(idx): """Get wnck workspacke by its number.""" if scr := Wnck.Screen.get_default(): return scr.get_workspace(idx) return None class WindowLeaf(Leaf): # object = window xid def get_actions(self): yield WindowActivateWorkspace() yield WindowMoveToWorkspace() yield WindowAction(_("Activate"), "activate", time=True) win = _get_window(self.object) if not win: return win_type = type(win) yield ToggleAction( _("Shade"), _("Unshade"), "shade", "unshade", win.is_shaded(), win_type.is_shaded, ) yield ToggleAction( _("Minimize"), _("Unminimize"), "minimize", "unminimize", win.is_minimized(), win_type.is_minimized, time=True, icon="list-remove", ) yield ToggleAction( _("Maximize"), _("Unmaximize"), "maximize", "unmaximize", win.is_maximized(), win_type.is_maximized, icon="list-add", ) yield ToggleAction( _("Maximize Vertically"), _("Unmaximize Vertically"), "maximize_vertically", "unmaximize_vertically", win.is_maximized_vertically(), win_type.is_maximized_vertically, icon="list-add", ) yield WindowAction(_("Close"), "close", time=True, icon="window-close") def is_valid(self): wnd = _get_window(self.object) return wnd and wnd.get_xid() == self.object def get_description(self): wnd = _get_window(self.object) if not wnd: return "" workspace = wnd.get_workspace() if not workspace: return "" _nr, name = workspace.get_number(), workspace.get_name() # TRANS: Window on (Workspace name), window description return _("Window on %(wkspc)s") % {"wkspc": name} def get_icon_name(self): return "kupfer-window" class FrontmostWindow(WindowLeaf): qf_id = "frontwindow" def __init__(self): WindowLeaf.__init__(self, None, _("Frontmost Window")) # HACK: Make self.object a property # so that this leaf is *not* immutable def _set_object(self, obj): pass def _get_object(self): scr = Wnck.Screen.get_default() if scr is None: return None active = scr.get_active_window() or scr.get_previously_active_window() if ( active and active.get_application().get_name() not in ( "kupfer.py", system.get_application_filename(), ) and not active.is_skip_tasklist() ): return active wspc = scr.get_active_workspace() for win in reversed(scr.get_windows_stacked()): if not win.is_skip_tasklist() and win.is_on_workspace(wspc): return win return None object = property(_get_object, _set_object) def repr_key(self): return None def get_description(self): return self.object and self.object.get_name() class NextWindow(WindowLeaf): qf_id = "nextwindow" def __init__(self): WindowLeaf.__init__(self, None, _("Next Window")) def _set_object(self, obj): pass def _get_object(self): scr = Wnck.Screen.get_default() if scr is None: return None wspc = scr.get_active_workspace() for win in scr.get_windows_stacked(): if not win.is_skip_tasklist() and win.is_on_workspace(wspc): return win return None object = property(_get_object, _set_object) def repr_key(self): return None def get_description(self): return self.object and self.object.get_name() class WindowActivateWorkspace(Action): def __init__(self, name=_("Go To")): super().__init__(name) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx window = _get_window(leaf.object) if not window: return workspace = window.get_workspace() time = ctx.environment.get_timestamp() workspace.activate(time) window.activate(time) def get_description(self): return _("Jump to this window's workspace and focus") def get_icon_name(self): return "go-jump" class WindowMoveToWorkspace(Action): def __init__(self): Action.__init__(self, _("Move To...")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert iobj assert ctx window = _get_window(leaf.object) if not window: return workspace = _get_workspace(iobj.object) if not workspace: return window.move_to_workspace(workspace) time = ctx.environment.get_timestamp() workspace.activate(time) window.activate(time) def requires_object(self): return True def object_types(self): yield Workspace def object_source(self, for_item=None): return WorkspacesSource() def valid_object(self, iobj, for_item): window = _get_window(for_item.object) return window and window.get_workspace().get_number() != iobj.object def get_icon_name(self): return "forward" class WindowAction(Action): def __init__(self, name, action, time=False, icon=None): super(Action, self).__init__(name) self.action = action or name.lower() self.time = time self.icon_name = icon def repr_key(self): return self.action def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx time = self._get_time(ctx) if self.time else None self._perform_action(self.action, leaf, time) @classmethod def _perform_action(cls, action_attr, leaf, time=None): window = _get_window(leaf.object) if not window: return action_method = getattr(window, action_attr) if time is not None: action_method(time) else: action_method() @classmethod def _get_time(cls, ctx): # @time will be != 0 if we are "inside" # a current gtk event return ctx.environment.get_timestamp() def get_icon_name(self): if not self.icon_name: return super().get_icon_name() return self.icon_name class ToggleAction(WindowAction): """A toggle action, performing the enable / disable action as needed, for example minimize/unminimize. @istate: Initial state @predicate: Callable for state taking the window object as only argument """ # pylint: disable=too-many-arguments def __init__( self, ename, uname, eaction, uaction, istate, predicate, time=False, icon=None, ): name = uname if istate else ename WindowAction.__init__(self, name, eaction, time=time, icon=icon) self.predicate = predicate self.uaction = uaction def activate(self, leaf, iobj=None, ctx=None): assert ctx wnd = _get_window(leaf.object) if not wnd: return if self.predicate(wnd): # only use time on the disable action time = self._get_time(ctx) if self.time else None self._perform_action(self.uaction, leaf, time) else: self._perform_action(self.action, leaf) class WindowsSource(Source): def __init__(self, name=_("Window List")): super().__init__(name) def initialize(self): # "preload" windows: Ask for them early # since the first call "primes" the event loop # and always comes back empty if (screen := Wnck.Screen.get_default()) is not None: screen.get_windows_stacked() def is_dynamic(self): return True def get_items(self): # wnck should be "primed" now to return the true list screen = Wnck.Screen.get_default() if screen is None: self.output_debug("Environment not supported") return yield FrontmostWindow() yield NextWindow() for win in reversed(screen.get_windows_stacked()): if not win.is_skip_tasklist(): name, app = (win.get_name(), win.get_application().get_name()) if name != app and app not in name: name = f"{name} ({app})" yield WindowLeaf(win.get_xid(), name) def get_description(self): return _("All windows on all workspaces") def get_icon_name(self): return "kupfer-window" def provides(self): yield WindowLeaf class Workspace(Leaf): # object = number def get_actions(self): yield ActivateWorkspace() def repr_key(self): return self.object def get_icon_name(self): return "kupfer-window" def get_description(self): screen = Wnck.Screen.get_default() if screen: n_windows = sum( 1 for w in screen.get_windows() if (wsp := w.get_workspace()) and wsp.get_number() == self.object ) w_msg = ngettext("%d window", "%d windows", n_windows) % n_windows active_wspc = screen.get_active_workspace() if active_wspc.get_number() == self.object: return _("Active workspace") + " (" + w_msg + ")" if n_windows: return f"({w_msg})" return None class ActivateWorkspace(Action): action_accelerator = "o" rank_adjust = 5 def __init__(self): Action.__init__(self, _("Go To")) def wants_context(self): return True def activate(self, leaf, iobj=None, ctx=None): assert ctx if workspace := _get_workspace(leaf.object): time = ctx.environment.get_timestamp() workspace.activate(time) def get_description(self): return _("Jump to this workspace") def get_icon_name(self): return "go-jump" class WorkspacesSource(Source): source_use_cache = False source_scan_interval: int = 3600 def __init__(self): super().__init__(_("Workspaces")) def initialize(self): if (screen := Wnck.Screen.get_default()) is not None: screen.get_workspaces() weaklib.gobject_connect_weakly( screen, "workspace-created", self._changed ) weaklib.gobject_connect_weakly( screen, "workspace-destroyed", self._changed ) def _changed(self, screen, workspace): self.mark_for_update() def get_items(self): # wnck should be "primed" now to return the true list screen = Wnck.Screen.get_default() if screen is None: return for wspc in screen.get_workspaces(): yield Workspace(wspc.get_number(), wspc.get_name()) def get_icon_name(self): return "kupfer-window" def provides(self): yield Workspace kupfer-328/kupfer/plugin/zeal.py000066400000000000000000000140231500175051100167560ustar00rootroot00000000000000""" This is a Zeal search plugin. """ from __future__ import annotations __kupfer_name__ = _("Zeal Search") __kupfer_sources__ = ("ZealDocsetsSource",) __kupfer_actions__ = ("ZealSearch", "ZealSearchInDocset", "ZealSearchFor") __description__ = _( "Search in Zeal, offline documentation browser for software developers." ) __version__ = "1.1" __author__ = "Karol Będkowski" import json import os import typing as ty from pathlib import Path from kupfer import icons, launch, plugin_support from kupfer.obj import Action, Leaf, Source, TextLeaf from kupfer.obj.apps import AppLeafContentMixin from kupfer.obj.helplib import FilesystemWatchMixin, NonpersistentToken if ty.TYPE_CHECKING: from gettext import gettext as _ plugin_support.check_command_available("zeal") class ZealSearch(Action): def __init__(self): Action.__init__(self, _("Zeal Search")) def activate(self, leaf, iobj=None, ctx=None): launch.spawn_async(["zeal", leaf.object]) def get_description(self): return _("Search in Zeal") def get_gicon(self): return icons.ComposedIcon("zeal", "edit-find") def get_icon_name(self): return "zeal" def item_types(self): yield TextLeaf class ZealDocsetsSource(AppLeafContentMixin, Source, FilesystemWatchMixin): appleaf_content_id = ("zeal", "org.zealdocs.zeal") source_scan_interval: int = 3600 def __init__(self): self.docsets_home = os.path.expanduser( "~/.local/share/Zeal/Zeal/docsets" ) super().__init__(_("Zeal Docsets")) self.monitor_token = None def initialize(self): self.monitor_token = self.monitor_directories(self.docsets_home) def monitor_include_file(self, gfile): return gfile and gfile.get_basename().endswith(".docset") def get_items(self): docsets_home = Path(self.docsets_home) if not docsets_home.is_dir(): return with os.scandir(docsets_home) as docdirs: for docdir in docdirs: if not docdir.is_dir() or not docdir.name.endswith(".docset"): continue meta_file = Path(docdir.path, "meta.json") if not meta_file.is_file(): continue try: with meta_file.open("r", encoding="UTF-8") as meta: content = json.load(meta) except OSError: continue docset_dir = Path(docdir.path) name = content.get("name") or docset_dir.stem title = content.get("title") or name.replace("_", " ") # zeal require prefix without any _/' '. this may cause # finding in wrong docsets if prefix is the same (ie java_se17, # java_se19) but we can't do anything with this name = name.partition("_")[0] # take part before "_" keywords = None extra = content.get("extra") if extra: keywords = extra.get("keywords") icon_filename = None if (icon := docset_dir.joinpath("icon@2x.png")).is_file(): icon_filename = str(icon) yield ZealDocset(name, title, keywords, icon_filename) def get_icon_name(self): return "zeal" def provides(self): yield ZealDocset def should_sort_lexically(self): return True class ZealDocset(Leaf): def __init__(self, name, title, keywords, icon): super().__init__(name, title) self.icon = icon self._icon: NonpersistentToken[icons.ComposedIcon] | None = None if keywords: for alias in keywords: self.kupfer_add_alias(alias) def get_description(self): return _("Zeal %s Docset") % self.name def get_gicon(self): """Because of we read gicon from file, cache whole icon.""" if self._icon: return self._icon.data icon = None if self.icon: try: icon = icons.ComposedIcon( "zeal", icons.get_gicon_from_file(self.icon) ) self._icon = NonpersistentToken(icon) except Exception: # do not try load icon again self.icon = None else: return icon # this is cached in icons return icons.ComposedIcon("zeal", "emblem-documents") def get_icon_name(self): return "zeal" class ZealSearchInDocset(Action): """TextLeaf -> ZealSearchInDocset -> ZealDocset""" def __init__(self): Action.__init__(self, _("Search In Zeal docset...")) def activate(self, leaf, iobj=None, ctx=None): assert iobj docset = iobj.object terms = leaf.object launch.spawn_async(["zeal", docset + ":" + terms]) def item_types(self): yield TextLeaf def requires_object(self): return True def object_types(self): yield ZealDocset def object_source(self, for_item=None): return ZealDocsetsSource() def get_description(self): return _("Search in Zeal docsets") def get_gicon(self): return icons.ComposedIcon("zeal", "edit-find") def get_icon_name(self): return "zeal" class ZealSearchFor(Action): """ZealDocset -> ZealSearchFor -> TextLeaf This is the opposite action to ZealSearchInDocset """ def __init__(self): Action.__init__(self, _("Search For...")) def activate(self, leaf, iobj=None, ctx=None): assert iobj docset = leaf.object terms = iobj.object launch.spawn_async(["zeal", docset + ":" + terms]) def item_types(self): yield ZealDocset def requires_object(self): return True def object_types(self): yield TextLeaf def get_description(self): return _("Search in Zeal docsets") def get_gicon(self): return icons.ComposedIcon("zeal", "edit-find") def get_icon_name(self): return "zeal" kupfer-328/kupfer/plugin/zoxide.py000066400000000000000000000130701500175051100173260ustar00rootroot00000000000000""" Load directories from zoxide (https://github.com/ajeetdsouza/zoxide) with configured, minimal score. Optionally, some directories can be excluded (by path) and only existing files may be presented (this may slowdown loading when turned on). """ __kupfer_name__ = _("Zoxide Directories") __kupfer_sources__ = ("ZoxideDirSource",) __description__ = _("Load top directories from zoxide database") __version__ = "2023-04-02" __author__ = "Karol Będkowski " import os.path import subprocess import typing as ty from kupfer import config, icons, plugin_support from kupfer.core.datactrl import DataController from kupfer.obj import Action, FileLeaf, Leaf, Source, fileactions from kupfer.obj.helplib import FilesystemWatchMixin if ty.TYPE_CHECKING: from gettext import gettext as _ __kupfer_settings__ = plugin_support.PluginSettings( { "key": "exclude", "label": _("Exclude directories:"), "type": list, "value": [], "helper": "choose_directory", }, { "key": "min_score", "label": _("Minimal score:"), "type": int, "value": 1, "min": 1, "tooltip": _( "Load only directories that score is equal " "or higher than configured minimum" ), }, { "key": "max_items", "label": _("Load limit:"), "type": int, "value": 50, "min": 1, "tooltip": _("Maximal number of directories to load"), }, { "key": "existing", "label": _("Show only existing directories"), "type": bool, "value": True, }, { "key": "record_enabled", "label": _("Update database after activate"), "type": bool, "value": False, "tooltip": _( "When enabled open files and directories will update zoxide database" ), }, ) plugin_support.check_command_available("zoxide") class LaunchRecorder: """Launch recorder listen for 'launched-action' signals after Open action on FileLeaves and update zoxide about access to file folder.""" def __init__(self): self._enabled = False self._cb_pointer = None def connect(self): data_controller = DataController.instance() self._cb_pointer = data_controller.connect( "launched-action", self._on_launched_action ) __kupfer_settings__.connect( "plugin-setting-changed", self._on_setting_changed ) self._enabled = __kupfer_settings__["record_enabled"] def disconnect(self): if self._cb_pointer: data_controller = DataController.instance() data_controller.disconnect(self._cb_pointer) self._cb_pointer = None def _on_launched_action( self, sender: ty.Any, leaf: Leaf, action: Action, *_args: ty.Any ) -> None: if not self._enabled: return if not isinstance(leaf, FileLeaf): return if not isinstance(action, fileactions.Open): return path = leaf.object if not leaf.is_dir(): path = os.path.dirname(path) # check is path is excluded if any(map(path.startswith, __kupfer_settings__["exclude"])): return subprocess.run(["zoxide", "add", path], check=False) def _on_setting_changed(self, settings, key, value): if key == "record_enabled": self._enabled = bool(value) _RECORDER = LaunchRecorder() def initialize_plugin(plugin_name: str) -> None: _RECORDER.connect() def finalize_plugin(plugin_name: str) -> None: _RECORDER.disconnect() def _get_dirs( exclude: list[str], min_score: int, existing: bool, max_items: int ) -> ty.Iterator[str]: """Load folders with score from zoxide.""" cmd = ["zoxide", "query", "--list", "--score"] if not existing: cmd.append("--all") with subprocess.Popen(cmd, stdout=subprocess.PIPE) as proc: stdout, _stderr = proc.communicate() lines = stdout.splitlines() for rownum, line in enumerate(lines): if rownum > max_items: return line = line.strip() # noqa: PLW2901 score, _dummy, dirpath = line.partition(b" ") if not dirpath: continue if float(score) < min_score: return path = dirpath.decode() # zoxide query not support multiple --exclude; so filter it here if any(map(path.startswith, exclude)): continue yield path class ZoxideDirSource(Source, FilesystemWatchMixin): source_scan_interval: int = 3600 rank_adjust = 20 def __init__(self): super().__init__(name=_("Zoxide Directories")) self.monitor = None def initialize(self): zoxide_home = config.get_data_dirs("", "zoxide") self.monitor = self.monitor_directories(*zoxide_home) __kupfer_settings__.connect( "plugin-setting-changed", self._on_setting_changed ) def monitor_include_file(self, gfile): return gfile and gfile.get_basename() == "zo.db" def get_items(self): for dirname in _get_dirs( __kupfer_settings__["exclude"], __kupfer_settings__["min_score"], __kupfer_settings__["existing"], __kupfer_settings__["max_items"], ): yield FileLeaf(dirname) def _on_setting_changed(self, settings, key, value): if key in ("exclude", "min_score"): self.mark_for_update() def get_gicon(self): return icons.ComposedIconSmall("folder", "emblem-favorite") kupfer-328/kupfer/plugin_support.py000066400000000000000000000264401500175051100176250ustar00rootroot00000000000000from __future__ import annotations import shutil import typing as ty from gi.repository import GObject from kupfer.core import plugins, settings from kupfer.support import fileutils, pretty if ty.TYPE_CHECKING: from gettext import gettext as _ from gettext import ngettext __all__ = [ "PluginSettings", "UserNamePassword", "check_any_command_available", "check_command_available", "check_dbus_connection", "check_keyring_support", "register_alternative", ] def _is_core_setting(key: str) -> bool: return key.startswith("kupfer_") SettingChangeCB = ty.Callable[[ty.Any, str, ty.Any], None] class PluginSettings(GObject.GObject, pretty.OutputMixin): # type:ignore """Allows plugins to have preferences by assigning an instance of this class to the plugin's __kupfer_settings__ attribute. Setting values are accessed by the getitem operator [] with the setting's 'key' attribute Signals: plugin-setting-changed: key, value """ __gtype_name__ = "PluginSettings" def __init__(self, *setdescs: dict[str, ty.Any]) -> None: """Create a settings collection by passing in dictionaries as arguments, where each dictionary must have the following keys: key type value (default value) label (localized label) the @key may be any string except strings starting with 'kupfer_', which are reserved """ GObject.GObject.__init__(self) self.setting_descriptions: dict[str, dict[str, ty.Any]] = {} self.setting_key_order: list[str] = [] self.signal_connection: int = -1 req_keys = {"key", "value", "type", "label"} for desc in setdescs: if not req_keys.issubset(list(desc.keys())): missing = req_keys.difference(list(desc.keys())) raise KeyError(f"Plugin setting missing keys: {missing}") if _is_core_setting(desc["key"]): raise KeyError(f"Reserved plugin setting key: {desc['key']!r}") self.setting_descriptions[desc["key"]] = desc.copy() self.setting_key_order.append(desc["key"]) def __iter__(self) -> ty.Iterator[str]: return iter(self.setting_key_order) def initialize(self, plugin_name: str) -> None: """Init by reading from global settings and setting up callbacks""" setctl = settings.get_settings_controller() for key in self: value_type = self.setting_descriptions[key]["type"] value = setctl.get_plugin_config(plugin_name, key, value_type) if value is not None: self[key] = value elif _is_core_setting(key): default = self.setting_descriptions[key]["value"] setctl.set_plugin_config(plugin_name, key, default, value_type) setctl.connect("value-changed", self._on_value_changed, plugin_name) # register for unload notification if not plugin_name.startswith("core."): plugins.register_plugin_unimport_hook( plugin_name, self._disconnect_all, plugin_name ) def __getitem__(self, key: str) -> ty.Any: return self.setting_descriptions[key]["value"] def __setitem__(self, key: str, value: ty.Any) -> None: value_type = self.setting_descriptions[key]["type"] self.setting_descriptions[key]["value"] = value_type(value) if not _is_core_setting(key): self.emit(f"plugin-setting-changed::{key}", key, value) def _on_value_changed( self, setctl: settings.SettingsController, section: str, key: str, value: ty.Any, plugin_name: str, ) -> None: """Preferences changed, update object""" if key in self and plugin_name in section: self[key] = value def get_value_type(self, key: str) -> ty.Type[ty.Any]: """Return type of setting @key""" return ty.cast( "ty.Type[ty.Any]", self.setting_descriptions[key]["type"] ) def get_label(self, key: str) -> str: """Return label for setting @key""" return ty.cast("str", self.setting_descriptions[key]["label"]) def get_alternatives(self, key: str) -> ty.Iterable[ty.Any] | None: """Return alternatives for setting @key (if any)""" return self.setting_descriptions[key].get("alternatives") def get_tooltip(self, key: str) -> str | None: """Return tooltip string for setting @key (if any)""" return self.setting_descriptions[key].get("tooltip") def get_parameter( self, key: str, name: str, default: ty.Any = None ) -> ty.Any: return self.setting_descriptions[key].get(name, default) def connect_settings_changed_cb( self, callback: SettingChangeCB, *args: ty.Any ) -> None: self.signal_connection = self.connect( "plugin-setting-changed", callback, *args ) def _disconnect_all(self, plugin_name: str) -> None: if self.signal_connection != -1: self.disconnect(self.signal_connection) # Arguments: Key, Value # Detailed by the key GObject.signal_new( "plugin-setting-changed", PluginSettings, GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.DETAILED, GObject.TYPE_BOOLEAN, (GObject.TYPE_STRING, GObject.TYPE_PYOBJECT), ) # Plugin convenience functions for dependencies # pylint: disable=too-few-public-methods class _DBusChecker: has_connection: bool | None = None @classmethod def check(cls) -> bool: if cls.has_connection is None: try: import dbus # pylint: disable=import-outside-toplevel dbus.Bus() cls.has_connection = True except (ImportError, dbus.DBusException): cls.has_connection = False assert cls.has_connection is not None return cls.has_connection def check_dbus_connection() -> None: """Check if a connection to the D-Bus daemon is available, else raise ImportError with an explanatory error message. For plugins that can not be used without contact with D-Bus; if this check is used, the plugin may use D-Bus and assume it is available in the Plugin's code. """ if not _DBusChecker.check(): raise ImportError(_("No D-Bus connection to desktop session")) # pylint: disable=too-few-public-methods class UserNamePassword: pass def check_keyring_support() -> None: """raise ImportError with because it is not supported.""" raise ImportError("Keyring is not supported") def check_keybinding_support() -> None: """Check if we can make global keybindings.""" from kupfer.ui import ( keybindings, # pylint: disable=import-outside-toplevel ) if not keybindings.is_available(): raise ImportError(_("Dependency '%s' is not available") % "Keybinder") def _plugin_configuration_error(plugin: str, err: ty.Any) -> None: pretty.print_error(__name__, err) def _is_valid_terminal(term_dict: dict[str, ty.Any]) -> bool: if len(term_dict["argv"]) < 1: return False exe = term_dict["argv"][0] return bool(fileutils.lookup_exec_path(exe)) _AVAILABLE_ALTERNATIVES: ty.Final[dict[str, dict[str, ty.Any]]] = { "terminal": { "filter": _is_valid_terminal, "required_keys": { "name": str, "argv": list, "exearg": str, "desktopid": str, "startup_notify": bool, }, }, "editor": { "filter": None, "required_keys": { "name": str, "argv": list, "terminal": bool, }, }, "icon_renderer": { "filter": None, "required_keys": { "name": str, "renderer": object, }, }, } _ALTERNATIVES: dict[str, dict[str, ty.Any]] = { "terminal": {}, "editor": {}, "icon_renderer": {}, } def register_alternative( caller: str, category_key: str, id_: str, **kwargs: ty.Any ) -> bool: """Register a new alternative for the category @category_key. @caller: Must be the caller's plugin id (Plugin __name__ variable) @id_ is a string identifier for the object to register @kwargs are the keyed arguments for the alternative constructor Returns True with success """ if category_key not in _AVAILABLE_ALTERNATIVES: _plugin_configuration_error( caller, f"Category '{category_key}' does not exist" ) return False full_id = f"{caller}.{id_}" kw_set = set(kwargs) alt = _AVAILABLE_ALTERNATIVES[category_key] req_set = set(alt["required_keys"]) if full_id in _ALTERNATIVES[category_key]: pretty.print_debug( __name__, f"Alternative {full_id} already defined in {category_key}", ) return False if not req_set.issubset(kw_set): _plugin_configuration_error( caller, f"Configuration error for alternative '{category_key}':" ) _plugin_configuration_error( caller, f"Missing keys: {req_set - kw_set}" ) return False _ALTERNATIVES[category_key][full_id] = kwargs pretty.print_debug( __name__, f"Registered alternative {category_key}: {full_id}" ) setctl = settings.get_settings_controller() setctl.update_alternatives( category_key, _ALTERNATIVES[category_key], alt["filter"] ) # register the alternative to be unloaded plugin_id = ".".join(caller.split(".")[2:]) if plugin_id and not plugin_id.startswith("core."): plugins.register_plugin_unimport_hook( plugin_id, _unregister_alternative, caller, category_key, full_id ) return True def _unregister_alternative( caller: str, category_key: str, full_id: str ) -> None: """Remove the alternative for category @category_key (this is done automatically at plugin unload) """ if category_key not in _AVAILABLE_ALTERNATIVES: _plugin_configuration_error( caller, f"Category '{category_key}' does not exist" ) return alt = _AVAILABLE_ALTERNATIVES[category_key] try: del _ALTERNATIVES[category_key][full_id] except KeyError: _plugin_configuration_error( caller, f"Alternative '{full_id}' does not exist" ) return pretty.print_debug( __name__, f"Unregistered alternative {category_key}: {full_id}" ) setctl = settings.get_settings_controller() setctl.update_alternatives( category_key, _ALTERNATIVES[category_key], alt["filter"] ) def check_command_available(*cmd: str) -> None: """Check if the commands is available in system, throw ImportError when not""" missing = [f'"{c}"' for c in cmd if not shutil.which(c)] if not missing: return raise ImportError( ngettext( "Command %(msg)s is not available.", "Commands %(msg)s are not available.", len(missing), ) % {"msg": ", ".join(missing)} ) def check_any_command_available(*cmd: str) -> None: """Check if any of command is available in system, throw ImportError when not""" for c in cmd: if shutil.which(c): return raise ImportError( _("None of commands %(msg)s is available.") % {"msg": ", ".join(f'"{c}"' for c in cmd)} ) kupfer-328/kupfer/puid.py000066400000000000000000000123631500175051100154730ustar00rootroot00000000000000"""Persistent Globally Unique Indentifiers for KupferObjects. Some objects are assigned identifiers by reference, some are assigned identifiers containing the whole object data (SerializedObject). SerializedObject is a saved representation of a KupferObject, i.e. a data model user-level object. We unpickle SerializedObjects in an especially conservative way: new module loading is always refused; this way, we avoid loading parts of the program that we didn't wish to activate. """ from __future__ import annotations import contextlib import pickle import typing as ty from kupfer.core import actioncompat, qfurl from kupfer.core.sources import get_source_controller from kupfer.obj import Action, AnySource, Leaf, Source from kupfer.support import conspickle, pretty __all__ = ( "SerializedObject", "get_unique_id", "is_reference", "resolve_action_id", "resolve_unique_id", ) _SERIALIZABLE_ATTRIBUTE = "serializable" class SerializedObject: # treat the serializable attribute as a version number, defined on the class def __init__(self, obj: Leaf) -> None: self.version = getattr(obj, _SERIALIZABLE_ATTRIBUTE) self.data = pickle.dumps(obj, pickle.HIGHEST_PROTOCOL) def __hash__(self) -> int: return hash(self.data) def __eq__(self, other: object) -> bool: return ( isinstance(other, type(self)) and self.data == other.data and self.version == other.version ) def reconstruct(self) -> Leaf: obj = conspickle.ConservativeUnpickler.loads(self.data) if self.version != getattr(obj, _SERIALIZABLE_ATTRIBUTE): raise ValueError(f"Version mismatch for reconstructed {obj}") assert isinstance(obj, Leaf) return obj PuID = ty.Union[str, SerializedObject] # pylint: disable=invalid-name def get_unique_id(obj: ty.Any) -> PuID | None: """Return unique id for object: if obj has attribute qf_id - return URI to locate object in Kupfer catalog (as str); if object is serializable return SerializedObject for `obj`; otherwise return string representation of object. Return None if obj is None or create SerializedObject failed. """ if obj is None: return None if hasattr(obj, "qf_id"): return str(qfurl.Qfurl(obj)) if getattr(obj, _SERIALIZABLE_ATTRIBUTE, None) is not None: try: return SerializedObject(obj) except pickle.PicklingError as exc: pretty.print_error(__name__, type(exc).__name__, exc) return None return repr(obj) def is_reference(puid: ty.Any) -> bool: """Return True if @puid is a reference-type ID""" return not isinstance(puid, SerializedObject) # A Context manager to block recursion when seeking inside a # catalog; we have a stack (@_EXCLUDING) of the sources we # are visiting, and nested context with the _exclusion # context manager _EXCLUDING: ty.Final[list[AnySource]] = [] @contextlib.contextmanager def _exclusion(src): try: _EXCLUDING.append(src) yield finally: _EXCLUDING.pop() def _is_currently_excluding(src: ty.Any) -> bool: return src is not None and src in _EXCLUDING def _find_obj_in_catalog( puid: str, catalog: ty.Collection[Source] ) -> Leaf | None: if puid.startswith(qfurl.QFURL_SCHEME): qfu = qfurl.Qfurl(url=puid) return qfu.resolve_in_catalog(catalog) for src in catalog: if _is_currently_excluding(src): continue with _exclusion(src): for obj in src.get_leaves() or []: if repr(obj) == puid: return obj return None def resolve_unique_id( puid: ty.Any, excluding: AnySource | None = None ) -> Leaf | Action | None: """Resolve unique id @puid. The caller (if a Source) should pass itself as @excluding, so that recursion into itself is avoided. """ if excluding is not None: with _exclusion(excluding): return resolve_unique_id(puid, None) if puid is None: return None if isinstance(puid, SerializedObject): try: return puid.reconstruct() except Exception as exc: pretty.print_debug(__name__, type(exc).__name__, exc) return None sctl = get_source_controller() if (obj := _find_obj_in_catalog(puid, sctl.firstlevel)) is not None: return obj other_sources = sctl.get_sources().copy() - set(sctl.firstlevel) return _find_obj_in_catalog(puid, other_sources) def resolve_action_id( puid: ty.Any, for_item: Leaf | None = None ) -> Action | None: if puid is None: return None if isinstance(puid, SerializedObject): act = resolve_unique_id(puid) assert act is None or isinstance(act, Action) return act sctr = get_source_controller() if for_item is not None: for action in actioncompat.actions_for_item(for_item, sctr): if get_unique_id(action) == puid: return action get_action_id = repr for actions in sctr.action_decorators.values(): for action in actions: if get_action_id(action) == puid: return action pretty.print_debug(__name__, f"Unable to resolve {puid} ({for_item})") return None kupfer-328/kupfer/runtimehelper.py000066400000000000000000000035371500175051100174200ustar00rootroot00000000000000from __future__ import annotations import typing as ty from gi.repository import Gio from kupfer.obj import FileLeaf from kupfer.support import scheduler if ty.TYPE_CHECKING: from kupfer.core.commandexec import ExecutionToken __all__ = ("AsyncFileResult", "register_async_file_result") # pylint: disable=too-few-public-methods class AsyncFileResult: """Expect a given file path to be created, and when (probably) done, post the file as a late result.""" def __init__( self, ctx: ExecutionToken, filepath: str, timeout: int = 0 ) -> None: self.ctx = ctx gfile = Gio.File.new_for_path(filepath) self.monitor = gfile.monitor_file(Gio.FileMonitorFlags.NONE) self.callback_id = self.monitor.connect("changed", self._on_changed) self._cancel_timer = None if timeout: self._cancel_timer = scheduler.Timer(True) self._cancel_timer.set(timeout, self._cancel) def _cancel(self, *_args: ty.Any) -> None: """Stop waiting for file.""" self.monitor.disconnect(self.callback_id) self.monitor.cancel() self.monitor = None if self._cancel_timer: self._cancel_timer.invalidate() def _on_changed( self, monitor: Gio.FileMonitor, gfile1: Gio.File, gfile2: Gio.File | None, event: Gio.FileMonitorEvent, ) -> None: if event == Gio.FileMonitorEvent.CHANGES_DONE_HINT: self.ctx.register_late_result(FileLeaf(gfile1.get_path())) self._cancel() def register_async_file_result( ctx: ExecutionToken, filepath: str, timeout: int = 600 ) -> AsyncFileResult: """Register that `filepath` may appear soon. `ctx` is the action's execution context token. `timeout` is maximum time to wait for file. """ return AsyncFileResult(ctx, filepath, timeout) kupfer-328/kupfer/support/000077500000000000000000000000001500175051100156675ustar00rootroot00000000000000kupfer-328/kupfer/support/__init__.py000066400000000000000000000004411500175051100177770ustar00rootroot00000000000000""" Support object/functions that are independent from other parts of Kupfer. """ from __future__ import annotations from kupfer.support import desktop_parse __all__ = ("argv_for_commandline",) def argv_for_commandline(cli: str) -> list[str]: return desktop_parse.parse_argv(cli) kupfer-328/kupfer/support/conspickle.py000066400000000000000000000050211500175051100203710ustar00rootroot00000000000000import fnmatch import io import pickle import sys import typing as ty __all__ = ("BasicUnpickler", "ConservativeUnpickler") # pylint: disable=too-few-public-methods class UniversalSet: def __contains__(self, item: ty.Any) -> bool: return True class ConservativeUnpickler(pickle.Unpickler): """An Unpickler that refuses to import new modules >>> import pickle >>> import kupfer.objects >>> ConservativeUnpickler.loads(pickle.dumps(kupfer.objects.FileLeaf("A"))) >>> ConservativeUnpickler.loads(pickle.dumps(eval)) Traceback (most recent call last): ... UnpicklingError: Refusing unsafe __builtin__.eval >>> import sys >>> import kupfer.obj.base >>> pdata = pickle.dumps(kupfer.obj.base.Leaf(1, "A")) >>> del sys.modules["kupfer.obj.base"] >>> ConservativeUnpickler.loads(pdata) Traceback (most recent call last): ... UnpicklingError: Refusing to load module kupfer.obj.base """ safe_modules: ty.ClassVar[dict[str, ty.Any]] = { "builtins": {"set", "sum", "object"}, "copy_reg": {"_reconstructor"}, "kupfer.*": UniversalSet(), } @classmethod def is_safe_symbol(cls, module: str, name: str) -> bool: for pattern, modules in cls.safe_modules.items(): if fnmatch.fnmatchcase(module, pattern): return name in modules return False def find_class(self, module: str, name: str) -> ty.Any: if module not in sys.modules: raise pickle.UnpicklingError(f"Refusing to load module {module}") if not self.is_safe_symbol(module, name): raise pickle.UnpicklingError(f"Refusing unsafe {module}.{name}") return pickle.Unpickler.find_class(self, module, name) @classmethod def loads(cls, pickledata: bytes) -> ty.Any: unpickler = cls(io.BytesIO(pickledata)) return unpickler.load() class BasicUnpickler(ConservativeUnpickler): """An Unpickler that can only unpickle persistend ids and select builtins >>> import pickle >>> import kupfer.objects >>> BasicUnpickler.loads(pickle.dumps(kupfer.objects.FileLeaf("A"))) Traceback (most recent call last): ... UnpicklingError: Refusing unsafe kupfer.obj.objects.FileLeaf """ safe_modules: ty.ClassVar[dict[str, set[str]]] = { "__builtin__": {"object"}, "copy_reg": {"_reconstructor"}, "kupfer.puid": {"SerializedObject"}, } if __name__ == "__main__": import doctest doctest.testmod() kupfer-328/kupfer/support/datatools.py000066400000000000000000000126671500175051100202470ustar00rootroot00000000000000""" This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ from __future__ import annotations import functools import inspect import typing as ty from collections import OrderedDict __all__ = ("LruCache", "evaluate_once", "simple_cache") K = ty.TypeVar("K") V = ty.TypeVar("V") VD = ty.TypeVar("VD") def _get_point_of_create(offset: int = 2) -> str: """Find information about function caller with `offset` in tracestack.""" for frame in inspect.stack()[offset:]: if "kupfer" in frame.filename: return f"{frame.filename}:{frame.lineno}" return "?" _sentinel = object() class LruCache(ty.Generic[K, V]): """Least-recently-used cache mapping of size *maxsize*. *name* is optional cache name for debug purpose. If not given, is place when cache is created (filename:lineno). """ def __init__(self, maxsize: int, name: str | None = None) -> None: super().__init__() self._data: OrderedDict[K, V] = OrderedDict() self._maxsize = maxsize self._name = name or _get_point_of_create() self._hit = 0 self._miss = 0 self._inserts = 0 def __len__(self) -> int: return len(self._data) def __setitem__(self, key: K, value: V) -> None: self._inserts += 1 # set add item on the end of dict data = self._data if key in self._data: # check is item already in dict by trying to move it to the end data.move_to_end(key, last=True) else: # item not found in dict so add it data[key] = value if len(data) > self._maxsize: # remove the first item (was inserted longest time ago) data.popitem(last=False) def __getitem__(self, key: K) -> V: # try to get item from dict, if not found KeyError is raised try: value = self._data[key] except KeyError: self._miss += 1 raise self._hit += 1 # found, so move it to the end self._data.move_to_end(key, last=True) return value def get(self, key: K, default: V | VD | None = None) -> V | VD | None: try: return self[key] except KeyError: return default def keys(self) -> ty.KeysView[K]: return self._data.keys() def values(self) -> ty.ValuesView[V]: return self._data.values() def items(self) -> ty.ItemsView[K, V]: return self._data.items() def clear(self) -> None: self._data.clear() def __str__(self) -> str: return ( f"" ) def get_or_insert(self, key: K, creator: ty.Callable[[], V]) -> V: """Get value from cache. If not exists - create with with `creator` function and insert into cache.""" try: val = self._data[key] except KeyError: self._miss += 1 self._inserts += 1 val = self._data[key] = creator() else: self._hit += 1 return val RT = ty.TypeVar("RT") # return type class simple_cache(ty.Generic[RT]): # pylint: disable=invalid-name # noqa:N801 """Function wrapper that remember (cache) one result and return it if no arguments changed. Wrapper properties: *cache_current_args* remembered (last) arguments *cache_current_value* remembered (last) function result *cache_hit* number of result returned from cache *cache_miss* number of wrapped function calls Usage:: @SimpleCache def function(args): ... """ cache_current_value: RT cache_current_args: ty.Any cache_hit: int cache_miss: int def __init__(self, func: ty.Callable[..., RT]): """Create SimpleCache for *func* function.""" functools.update_wrapper(self, func) self.func = func self.cache_clear() self.name = _get_point_of_create() def __call__(self, *args: ty.Any, **kwargs: ty.Any) -> RT: if self.cache_current_args == (args, kwargs): self.cache_hit += 1 return self.cache_current_value result = self.func(*args, **kwargs) self.cache_current_args = (args, kwargs) self.cache_current_value = result self.cache_miss += 1 return result def cache_clear(self) -> None: """Clear cache and stats.""" self.cache_current_value = None # type: ignore self.cache_current_args = None self.cache_hit = 0 self.cache_miss = 0 def __str__(self) -> str: return ( f"" ) def evaluate_once(func: ty.Callable[..., RT]) -> ty.Callable[..., RT]: """Decorator that run wrapped function once and always return computed value. No thread safe.""" @functools.wraps(func) def wrapper(*args, **kwargs): result = getattr(wrapper, "cached_value", _sentinel) if result is not _sentinel: return result result = func(*args, **kwargs) wrapper.cached_value = result # type: ignore return result return wrapper kupfer-328/kupfer/support/datatools_test.py000066400000000000000000000040521500175051100212730ustar00rootroot00000000000000# Distributed under terms of the GPLv3 license. """ Test for datatools module. """ import unittest from kupfer.support import datatools as d class TestLruCache(unittest.TestCase): def test_insers(self): cache: d.LruCache[int, int] = d.LruCache(10) for i in range(5): cache[i] = i self.assertEqual(len(cache), 5) self.assertEqual(list(cache.keys()), [0, 1, 2, 3, 4]) for i in range(10): cache[i] = i self.assertEqual(len(cache), 10) self.assertEqual(list(cache.keys()), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) for i in range(20): cache[i] = i self.assertEqual(len(cache), 10) self.assertEqual( list(cache.keys()), [10, 11, 12, 13, 14, 15, 16, 17, 18, 19] ) for i in range(10, 16): cache[i] = i self.assertEqual(len(cache), 10) self.assertEqual( list(cache.keys()), [16, 17, 18, 19, 10, 11, 12, 13, 14, 15] ) for i in range(16, 20): self.assertEqual(cache[i], i) self.assertEqual( list(cache.keys()), [10, 11, 12, 13, 14, 15, 16, 17, 18, 19] ) def test_get_or_insert(self): cache: d.LruCache[int, int] = d.LruCache(10) # pylint: disable=too-few-public-methods class Creator: def __init__(self): self.cntr = 0 def call(self): self.cntr += 1 return self.cntr creator = Creator() val = cache.get_or_insert(0, creator.call) self.assertEqual(val, 1) val = cache.get_or_insert(0, creator.call) self.assertEqual(val, 1) val = cache.get_or_insert(1, creator.call) self.assertEqual(val, 2) val = cache.get_or_insert(2, creator.call) self.assertEqual(val, 3) val = cache.get_or_insert(1, creator.call) self.assertEqual(val, 2) val = cache.get_or_insert(0, creator.call) self.assertEqual(val, 1) self.assertEqual(creator.cntr, 3) kupfer-328/kupfer/support/desktop_parse.py000066400000000000000000000114271500175051100211110ustar00rootroot00000000000000""" Implementation of unescaping and unquoting of the Exec= key in the Desktop Entry Specification (As of March 2011, version 1.1-draft) http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s06.html http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.1.html#exec-variables The unescaping we are doing is only one way.. so we unescape according to the rules, but we accept everything, if validly quoted or not. """ from __future__ import annotations import shlex import typing as ty from kupfer.support import itertools as kitertools __all__ = ("parse_argv", "parse_unesc_argv") # This is the "string" type encoding escapes # this is unescaped before we process anything.. _ESCAPE_TABLE = { r"\s": " ", r"\n": "\n", r"\t": "\t", r"\r": "\r", "\\\\": "\\", } # quoted are those chars that need a backslash in front # (inside a double-quoted section, that is) # not in use # quoted = r""" " ` $ \ """.split() # quoted_table = { # r"\"": '"', # r"\`": "`", # r"\$": "$", # "\\\\": "\\", # } # reserved are those that need to be inside quotes # note that all the quoted are also reserved, of course # We don't use these at all # reserved = r""" " ' \ > < ~ | & ; $ * ? # ( ) ` """.split() # reserved.extend([' ', '\t', '\n']) def _two_part_unescaper(string: str, reptable: dict[str, str]) -> str: """Scan @s two characters at a time and replace using @reptable""" if not string: return string def repfunc(instr: str) -> str | None: return reptable.get(instr) return kitertools.two_part_mapper(string, repfunc) T = ty.TypeVar("T", str, bytes) def _custom_shlex_split( string: T, comments: bool = False, posix: bool = True ) -> list[T]: """Wrapping shlex.split.""" ustring: str if isinstance(string, str): ustring = string elif isinstance(string, bytes): ustring = string.decode("UTF-8", "replace") else: raise TypeError lex = shlex.shlex(ustring, posix=posix) lex.whitespace_split = True if not comments: lex.commenters = "" try: lex_output = tuple(lex) except ValueError: lex_output = (ustring,) ## extra-unescape ` and $ that are not handled by shlex quoted_shlex = {r"\`": "`", r"\$": "$"} output = (_two_part_unescaper(x, quoted_shlex) for x in lex_output) if isinstance(string, str): return list(output) return list(map(str.encode, output)) def _unescape(string: str) -> str: """Primary unescape of control sequences""" return _two_part_unescaper(string, _ESCAPE_TABLE) def parse_argv(instr: str) -> list[str]: r"""Parse quoted @instr into an argv This is according to the spec >>> parse_argv('env "VAR=is good" ./program') ['env', 'VAR=is good', './program'] >>> parse_argv('env "VAR=\\\\ \\$ @ x" ./program') ['env', 'VAR=\\ $ @ x', './program'] >>> parse_argv('"\\$" "\\`" "\\""') ['$', '`', '"'] >>> parse_argv('/usr/bin/x-prog -q %F') ['/usr/bin/x-prog', '-q', '%F'] >>> parse_argv('env LANG=en_US.UTF-8 freeciv-gtk2') ['env', 'LANG=en_US.UTF-8', 'freeciv-gtk2'] >>> parse_argv('emacsclient -a "" -c %f') ['emacsclient', '-a', '', '-c', '%f'] == Below this we need quirks mode == The following style is common but not supported in spec >>> parse_argv('env VAR="is broken" ./program') ['env', 'VAR=is broken', './program'] The following is just completely broken >>> parse_argv('./program unquoted\\\\argument') ['./program', 'unquoted\\argument'] The following is just completely broken >>> parse_argv('./program No\\ Space') ['./program', 'No Space'] The following is just insanely broken >>> parse_argv("'/opt'/now/'This is broken/'") ['/opt/now/This is broken/'] This is broken #>>> parse_argv('\\$') #['$'] #>>> parse_argv('\\$ \\` \\"') #['$', '`', '"'] Unmatched quote, normal mode (just testing that it does not raise) >>> parse_argv('"hi there') ['"hi there'] Unmatched quote, quirks mode (just testing that it does not raise) >>> parse_argv('A\\\\BC "hi there') ['A\\\\BC "hi there'] """ return _custom_shlex_split(instr) def parse_unesc_argv(instr: str) -> list[str]: r"""Parse quoted @instr into an argv after unescaping it >>> parse_unesc_argv(r'stuff "C:\\\\suck\\\\start.exe"') ['stuff', 'C:\\suck\\start.exe'] == Below this we need quirks mode == >>> parse_unesc_argv(r'stuff C:\\\\suck\\\\start.exe') ['stuff', 'C:\\suck\\start.exe'] >>> parse_unesc_argv("'/usr'/bin/gnome-terminal -x gvim 'Insanely Broken'Yes") ['/usr/bin/gnome-terminal', '-x', 'gvim', 'Insanely BrokenYes'] """ return _custom_shlex_split(_unescape(instr)) if __name__ == "__main__": import doctest doctest.testmod() kupfer-328/kupfer/support/desktop_parse_test.py000066400000000000000000000010441500175051100221420ustar00rootroot00000000000000# pylint: disable=protected-access """ This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ import unittest from kupfer.support import desktop_parse class TestUnescape(unittest.TestCase): def test1(self): self.assertEqual( desktop_parse._unescape(r'"This \\$ \\\\ \s\\\\"'), '"This \\$ \\\\ \\\\"', ) self.assertEqual(desktop_parse._unescape(r"\t\s\\\\"), "\t \\\\") kupfer-328/kupfer/support/fileutils.py000066400000000000000000000123451500175051100202460ustar00rootroot00000000000000"""File-related support functions. This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ from __future__ import annotations import itertools import os import tempfile import typing as ty from os import path as os_path from pathlib import Path from kupfer.support import pretty __all__ = ( "get_destfile", "get_destfile_in_directory", "get_destpath_in_directory", "get_dirlist", "get_safe_tempfile", "is_directory_writable", "is_file_writable", "lookup_exec_path", ) FilterFunc = ty.Callable[[str], bool] def get_dirlist( folder: str, max_depth: int = 0, include: FilterFunc | None = None, exclude: FilterFunc | None = None, ) -> ty.Iterator[str]: """Return a list of absolute paths in folder include, exclude: a function returning a boolean def include(filename): return ShouldInclude """ h_include: FilterFunc = include or (lambda _x: True) h_exclude: FilterFunc = exclude or (lambda _x: False) def accept_file(file): return h_include(file) and not h_exclude(file) for dirname, dirnames, fnames in os.walk(folder): # skip deep directories depth = len(os.path.relpath(dirname, folder).split(os.path.sep)) - 1 if depth >= max_depth: # this stop processing subfolders dirnames.clear() continue excl_dir = [] for directory in dirnames: if accept_file(directory): yield os_path.join(dirname, directory) else: excl_dir.append(directory) yield from ( os_path.join(dirname, file) for file in fnames if accept_file(file) ) # do not process excluded dirs for directory in reversed(excl_dir): dirnames.remove(directory) def is_directory_writable(dpath: str | Path) -> bool: """If directory path @dpath is a valid destination to write new files?""" if isinstance(dpath, str): dpath = Path(dpath) if not dpath.is_dir(): return False return os.access(dpath, os.R_OK | os.W_OK | os.X_OK) def is_file_writable(dpath: str | Path) -> bool: """If @dpath is a valid, writable file UNUSED """ if isinstance(dpath, str): dpath = Path(dpath) if not dpath.is_file(): return False return os.access(dpath, os.R_OK | os.W_OK) def get_destpath_in_directory( directory: str, filename: str, extension: str | None = None ) -> str: """Find a good destpath for a file named @filename in path @directory Try naming the file as filename first, before trying numbered versions if the previous already exist. If @extension, it is used as the extension. Else the filename is split and the last extension is used """ # find a nonexisting destname if extension: basename = filename + extension root, ext = filename, extension else: basename = filename root, ext = os_path.splitext(filename) ctr = itertools.count(1) destpath = Path(directory, basename) while destpath.exists(): num = next(ctr) basename = f"{root}-{num}{ext}" destpath = Path(directory, basename) return str(destpath) def get_destfile_in_directory( directory: str, filename: str, extension: str | None = None ) -> tuple[ty.BinaryIO | None, str | None]: """Find a good destination for a file named @filename in path @directory. Like get_destpath_in_directory, but returns an open file object, opened atomically to avoid race conditions. Return (fileobj, filepath) """ # retry if it fails for _retry in range(3): destpath = get_destpath_in_directory(directory, filename, extension) try: fileno = os.open( destpath, os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0o666 ) except OSError as exc: pretty.print_error(__name__, exc) else: return (os.fdopen(fileno, "wb"), destpath) return (None, None) def get_destfile( destpath: str | Path, ) -> tuple[ty.BinaryIO | None, str | None]: """Open file object for full file path. Return the same object like get_destfile_in_directory. Return (fileobj, filepath). """ # retry if it fails for _retry in range(3): try: fileno = os.open( destpath, os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0o666 ) except OSError as exc: # noqa: PERF203 pretty.print_error(__name__, exc) else: return (os.fdopen(fileno, "wb"), str(destpath)) return (None, None) def get_safe_tempfile() -> tuple[ty.BinaryIO, str]: """Return (fileobj, filepath) pointing to an open temporary file""" fileno, path = tempfile.mkstemp() return (os.fdopen(fileno, "wb"), path) def lookup_exec_path(exename: str) -> str | None: """Return path for @exename in $PATH or None""" env_path = os.environ.get("PATH") or os.defpath for execdir in env_path.split(os.pathsep): exepath = Path(execdir, exename) if os.access(exepath, os.R_OK | os.X_OK) and exepath.is_file(): return str(exepath) return None kupfer-328/kupfer/support/itertools.py000066400000000000000000000115231500175051100202670ustar00rootroot00000000000000""" Support function for iterators This file is a part of the program kupfer, which is released under GNU General Public License v3 (or any later version), see the main program file, and COPYING for details. """ from __future__ import annotations import itertools import typing as ty __all__ = ( "SavedIterable", "as_list", "peekfirst", "two_part_mapper", "unique_iterator", ) def two_part_mapper( instr: str, repfunc: ty.Callable[[str], str | None] ) -> str: """Scan @instr two characters at a time and replace using @repfunc. If @repfunc return not None - use origin character. """ if not instr: return instr def _inner(): sit = zip(instr, instr[1:]) for cur, nex in sit: key = cur + nex if (rep := repfunc(key)) is not None: yield rep # skip a step in the iter try: next(sit) except StopIteration: return else: yield cur yield instr[-1] return "".join(_inner()) T = ty.TypeVar("T") def peekfirst( seq: ty.Iterable[T], ) -> tuple[T | None, ty.Iterable[T]]: """This function will return (firstitem, iter) where firstitem is the first item of `seq` or None if empty, and iter an equivalent copy of `seq` """ seq = iter(seq) for itm in seq: old_iter = itertools.chain((itm,), seq) return (itm, old_iter) return (None, seq) class SavedIterable(ty.Generic[T]): """Wrap an iterable and cache it. The SavedIterable can be accessed streamingly, while still being incrementally cached. Later attempts to iterate it will access the whole of the sequence. When it has been cached to its full extent once, it reduces to a thin wrapper of a sequence iterator. The SavedIterable will pickle into a list. >>> s = SavedIterable(range(5)) >>> next(iter(s)) 0 >>> list(s) [0, 1, 2, 3, 4] >>> iter(s) # doctest: +ELLIPSIS >>> import pickle >>> pickle.loads(pickle.dumps(s)) [0, 1, 2, 3, 4] >>> u = SavedIterable(list(range(5))) >>> one, two = iter(u), iter(u) >>> next(one), next(two) (0, 0) >>> list(two) [1, 2, 3, 4] >>> list(one) [1, 2, 3, 4] >>> SavedIterable(list(range(3))) [0, 1, 2] """ def __new__(cls, iterable: ty.Iterable[T]) -> ty.Any: if isinstance(iterable, list): return iterable return object.__new__(cls) def __init__(self, iterable: ty.Iterable[T]) -> None: # parent iterator self._iterator: ty.Iterator[T] | None = iter(iterable) # cached data self._data: list[T] = [] def __iter__(self) -> ty.Iterator[T]: if self._iterator is None: # iterator was exhausted, so we return data from cache return iter(self._data) return self._incremental_caching_iter() def _incremental_caching_iter(self) -> ty.Iterator[T]: """Get next item from local cache, if no more items is in cache, try to load from origin iterator.""" indices = itertools.count() while True: idx = next(indices) try: yield self._data[idx] except IndexError: pass else: continue if self._iterator is None: return try: x = next(self._iterator) self._data.append(x) yield x except StopIteration: self._iterator = None def __reduce__(self) -> tuple[ty.Any, ...]: # pickle into a list with __reduce__ # (callable, args, state, listitems) return (list, (), None, iter(self)) K = ty.TypeVar("K") def unique_iterator( seq: ty.Iterable[T], key: ty.Callable[[T], K] | None = None, ) -> ty.Iterator[T]: """Yield items of `seq` with set semantics; no duplicates. If `key` is given, value of key(object) is used for detecting duplicates. >>> list(unique_iterator([1, 2, 3, 3, 5, 1])) [1, 2, 3, 5] >>> list(unique_iterator([1, -2, 3, -3, -5, 2], key=abs)) [1, -2, 3, -5] """ if key is None: coll: set[T] = set() # itertools is ~10% faster for obj in itertools.filterfalse(coll.__contains__, seq): yield obj coll.add(obj) else: collk: set[K] = set() for obj in seq: if (value := key(obj)) not in collk: yield obj collk.add(value) def as_list(seq: ty.Iterable[T]) -> ty.Collection[T]: """Return a list out of @seq, or seq if it is a list""" if isinstance(seq, (list, tuple)): return seq return list(seq) if __name__ == "__main__": import doctest doctest.testmod() kupfer-328/kupfer/support/itertools_test.py000066400000000000000000000036511500175051100213310ustar00rootroot00000000000000import unittest from kupfer.support import itertools as kit class TestTwoPartMapper(unittest.TestCase): def test1(self): def repfunc(string): print(string) self.assertEqual(len(string), 2) if string[0] == string[1]: return string.upper() return string # no changes self.assertEqual( kit.two_part_mapper("abbcdedeeffg123", repfunc), "abbcdedeeffg123" ) self.assertEqual( kit.two_part_mapper("abbbcdedeeffg123", repfunc), "abBBcdedEEFFg123", ) def test2(self): mapping = { "aa": "01", "bb": "23", "cc": "34", } def repfunc(string): return mapping.get(string) self.assertEqual( kit.two_part_mapper("abaabcdecccfag1aa", repfunc), "ab01bcde34cfag101", ) self.assertEqual( kit.two_part_mapper("abbbcdedeeffg123", repfunc), "a23bcdedeeffg123", ) self.assertEqual( kit.two_part_mapper("aaaaaaaaaaaaaaaa", repfunc), "0101010101010101", ) self.assertEqual( kit.two_part_mapper("aabaabaabaab", repfunc), "01b01b01b01b" ) self.assertEqual( kit.two_part_mapper("baabaabaabaab", repfunc), "b01b01b01b01b" ) self.assertEqual( kit.two_part_mapper("baaabaaabaaabbaabb", repfunc), "b01ab01ab01a230123", ) class TestPeekfirst(unittest.TestCase): def test1(self): first, tail = kit.peekfirst([]) self.assertIsNone(first) self.assertTrue(hasattr(tail, "__next__")) self.assertEqual([], list(tail)) first, tail = kit.peekfirst([1, 2, 3, 4, 5]) self.assertEqual(first, 1) self.assertTrue(hasattr(tail, "__next__")) self.assertEqual([1, 2, 3, 4, 5], list(tail)) kupfer-328/kupfer/support/kupferstring.py000066400000000000000000000064431500175051100207730ustar00rootroot00000000000000from __future__ import annotations import locale import typing as ty from functools import cmp_to_key from unicodedata import category, normalize from kupfer.support.datatools import evaluate_once __all__ = ("get_encoding", "locale_sort", "tofolded", "tolocale", "tounicode") def _folditems(): _folding_table = { # general non-decomposing characters # FIXME: This is not complete "ł": "l", "œ": "oe", "ð": "d", "þ": "th", # germano-scandinavic canonical transliterations "ü": "ue", "å": "aa", "ä": "ae", "æ": "ae", "ö": "oe", "ø": "oe", } for char, rep in _folding_table.items(): yield (ord(char.upper()), rep.upper()) yield (ord(char), rep) yield ord("ß"), "ss" yield ord("ẞ"), "SS" _FOLDING_TABLE = dict(_folditems()) def tounicode(utf8str: ty.Union[str, bytes, None]) -> str | None: """Return `unicode` from UTF-8 encoded @utf8str This is to use the same error handling etc everywhere """ if isinstance(utf8str, str) or utf8str is None: return utf8str return utf8str.decode("UTF-8", "replace") if utf8str is not None else "" # not in use # def toutf8(ustr: ty.AnyStr) -> bytes: # """Return UTF-8 `str` from unicode @ustr # This is to use the same error handling etc everywhere # if ustr is `str`, just return it # """ # if isinstance(ustr, bytes): # return ustr # return ustr.encode("UTF-8") @evaluate_once def get_encoding() -> str: return locale.getpreferredencoding(do_setlocale=False) def fromlocale(lstr: bytes) -> str: """Return a unicode string from locale bytestring @lstr""" assert isinstance(lstr, bytes) return lstr.decode(get_encoding(), "replace") def tolocale(ustr: str) -> bytes: """Return a locale-encoded bytestring from unicode @ustr""" assert isinstance(ustr, str) return ustr.encode(get_encoding()) def tofolded(ustr: str) -> str: """Fold @ustr Return a unicode string where composed characters are replaced by their base, and extended latin characters are replaced by similar basic latin characters. >>> tofolded(u"Wyłącz") 'Wylacz' >>> tofolded(u"naïveté") 'naivete' >>> tofolded(u"Groß") 'Gross' Characters from other scripts are not transliterated. >>> print(tofolded(u"Ἑλλάς")) Ελλας """ srcstr = normalize("NFKD", ustr.translate(_FOLDING_TABLE)) return "".join(c for c in srcstr if category(c) != "Mn") _SortItem = ty.TypeVar("_SortItem") def locale_sort( seq: ty.Iterable[_SortItem], key: ty.Callable[[_SortItem], ty.Any] = str ) -> list[_SortItem]: """Return @seq of objects with @key function as a list sorted in locale lexical order >>> locale.setlocale(locale.LC_ALL, "C") 'C' >>> locale_sort("abcABC") ['A', 'B', 'C', 'a', 'b', 'c'] >>> locale.setlocale(locale.LC_ALL, "en_US.UTF-8") 'en_US.UTF-8' >>> locale_sort("abcABC") ['a', 'A', 'b', 'B', 'c', 'C'] """ def locale_cmp(val1, val2): return locale.strcoll(key(val1), key(val2)) seq = seq if isinstance(seq, list) else list(seq) seq.sort(key=cmp_to_key(locale_cmp)) return seq if __name__ == "__main__": import doctest doctest.testmod() kupfer-328/kupfer/support/pretty.py000066400000000000000000000111621500175051100175710ustar00rootroot00000000000000from __future__ import annotations import sys import traceback import typing as ty from time import time as timestamp if ty.TYPE_CHECKING: from kupfer.support.types import ExecInfo __all__ = ( "OutputMixin", "print_debug", "print_error", "print_exc", "print_info", "timing_start", "timing_step", ) DEBUG = False COLORS = True _COLOR_INFO = "\033[96m" _COLOR_WARNING = "\033[93m" _COLOR_FAIL = "\033[91m" _COLOR_STD = "\033[0m" class OutputMixin: """A mixin class providing prefixed output standard output and DEBUG output.""" def _output_category(self) -> str: return f"[{type(self).__module__}] {type(self).__name__}:" def _output_core( self, prefix: str, sep: str, end: str, stream: ty.TextIO | None, *items: ty.Any, ) -> None: category = self._output_category() pitems = [ item if isinstance(item, (str, int, float)) else repr(item) for item in items ] print(f"{prefix}{category}", *pitems, sep=sep, end=end, file=stream) def output_info( self, *items: ty.Any, sep: str = " ", end: str = "\n", **kwargs: ty.Any ) -> None: """Output given items using @sep as separator, ending the line with @end""" if COLORS: self._output_core( f"{_COLOR_INFO}INF{_COLOR_STD} ", sep, end, sys.stdout, *items ) else: self._output_core("INF ", sep, end, sys.stdout, *items) def output_exc(self, exc_info: ExecInfo | None = None) -> None: """Output current exception, or use @exc_info if given""" etype, value, tback = exc_info or sys.exc_info() assert etype if DEBUG: if COLORS: self._output_core( f"{_COLOR_FAIL}EXC{_COLOR_STD} ", "", "\n", sys.stderr, ) else: self._output_core("EXC ", "", "\n", sys.stderr) traceback.print_exception(etype, value, tback, file=sys.stderr) return msg = f"{etype.__name__}: {value}" if COLORS: self._output_core( f"{_COLOR_FAIL}EXC{_COLOR_STD} ", " ", "\n", sys.stderr, msg, ) else: self._output_core("EXC ", " ", "\n", sys.stderr, msg) def output_debug( self, *items: ty.Any, sep: str = " ", end: str = "\n", **kwargs: ty.Any ) -> None: if DEBUG: self._output_core("DBG ", sep, end, sys.stderr, *items) def output_error( self, *items: ty.Any, sep: str = " ", end: str = "\n", **kwargs: ty.Any ) -> None: if COLORS: self._output_core( f"{_COLOR_WARNING}ERR{_COLOR_STD} ", sep, end, sys.stderr, *items, ) else: self._output_core("ERR ", sep, end, sys.stderr, *items) class _StaticOutput(OutputMixin): current_calling_module: str | None = None def _output_category(self) -> str: return f"[{self.current_calling_module}]:" def print_info( self, modulename: str, *args: ty.Any, **kwargs: ty.Any ) -> None: self.current_calling_module = modulename self.output_info(*args, **kwargs) def print_error( self, modulename: str, *args: ty.Any, **kwargs: ty.Any ) -> None: self.current_calling_module = modulename self.output_error(*args, **kwargs) def print_exc( self, modulename: str, *args: ty.Any, **kwargs: ty.Any ) -> None: self.current_calling_module = modulename self.output_exc(*args, **kwargs) def print_debug( self, modulename: str, *args: ty.Any, **kwargs: ty.Any ) -> None: if DEBUG: self.current_calling_module = modulename self.output_debug(*args, **kwargs) _StaticOutputInst = _StaticOutput() print_info = _StaticOutputInst.print_info print_debug = _StaticOutputInst.print_debug print_error = _StaticOutputInst.print_error print_exc = _StaticOutputInst.print_exc def timing_start() -> float | None: """In debug get current timestamp; return None otherwise""" if DEBUG: return timestamp() return None def timing_step( modulename: str, start: float | None, label: str, *args: str ) -> float | None: """In debug printtime from `start`.""" if DEBUG and start: cts = timestamp() print_debug(modulename, label, f"in {cts - start:.6f} s", *args) return cts return None kupfer-328/kupfer/support/scheduler.py000066400000000000000000000075521500175051100202300ustar00rootroot00000000000000from __future__ import annotations import typing as ty from gi.repository import GLib, GObject from kupfer.support import pretty, weaklib __all__ = ("Scheduler", "Timer", "get_scheduler") def get_scheduler() -> Scheduler: """Get the shared instance""" return Scheduler.instance() class Scheduler(GObject.GObject, pretty.OutputMixin): # type:ignore __gtype_name__ = "Scheduler" _instance: Scheduler | None = None @classmethod def instance(cls) -> Scheduler: if cls._instance is None: cls._instance = Scheduler() return cls._instance def __init__(self) -> None: super().__init__() self._finished = False def load(self) -> None: self.output_debug("Loading") self.emit("load") self.emit("loaded") self.output_debug("Loaded") def display(self) -> None: self.output_debug("Display") self.emit("display") GLib.idle_add(self._after_display) def _after_display(self) -> None: self.output_debug("After Display") self.emit("after-display") @property def finished(self) -> bool: return self._finished def finish(self) -> None: self._finished = True self.emit("finish") GObject.signal_new( "load", Scheduler, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, () ) GObject.signal_new( "loaded", Scheduler, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, () ) GObject.signal_new( "display", Scheduler, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (), ) GObject.signal_new( "after-display", Scheduler, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (), ) GObject.signal_new( "finish", Scheduler, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, () ) TimerCallback = ty.Callable[..., None] class Timer: def __init__(self, call_at_finish: bool = False) -> None: self._current_timer = -1 self._call_at_finish = call_at_finish self._current_callback: ty.Callable[[], None] | None = None weaklib.gobject_connect_weakly( get_scheduler(), "finish", self._on_finish ) def set( self, timeout_seconds: float, callback: TimerCallback, *arguments: ty.Any, ) -> None: """Setup timer to call @timeout_seconds in the future. If the timer was previously set, it is postponed """ self.invalidate() self._current_callback = lambda: callback(*arguments) self._current_timer = GLib.timeout_add_seconds( timeout_seconds, self._call ) def set_ms( self, timeout_milliseconds: int, callback: TimerCallback, *arguments: ty.Any, ) -> None: """Setup timer to call @timeout_milliseconds in the future. If the timer was previously set, it is postponed """ self.invalidate() self._current_callback = lambda: callback(*arguments) self._current_timer = GLib.timeout_add( timeout_milliseconds, self._call ) def set_idle(self, callback: TimerCallback, *arguments: ty.Any) -> None: self.invalidate() self._current_callback = lambda: callback(*arguments) self._current_timer = GLib.idle_add(self._call) def _call(self, timer: ty.Any = None) -> None: assert self._current_callback self._current_timer = -1 self._current_callback() def invalidate(self) -> None: if self._current_timer > 0: GLib.source_remove(self._current_timer) self._current_timer = -1 def is_valid(self) -> bool: """If Timer is currently set""" return self._current_timer > 0 def _on_finish(self, _scheduler: ty.Any) -> None: if self._call_at_finish and self.is_valid(): self._call() else: self.invalidate() kupfer-328/kupfer/support/system.py000066400000000000000000000012251500175051100175650ustar00rootroot00000000000000#! /usr/bin/env python3 # Distributed under terms of the GPLv3 license. """ System related functions """ import os.path import socket import sys from kupfer.support import datatools, pretty __all__ = ("get_application_filename", "get_homedir", "get_hostname") @datatools.evaluate_once def get_hostname() -> str: """Get cached host name""" try: return socket.gethostname() except Exception: pretty.print_exc(__name__) return "" @datatools.evaluate_once def get_homedir() -> str: return os.path.expanduser("~") @datatools.evaluate_once def get_application_filename() -> str: return os.path.basename(sys.argv[0]) kupfer-328/kupfer/support/task.py000066400000000000000000000103101500175051100171760ustar00rootroot00000000000000from __future__ import annotations import sys import threading import time import typing as ty from gi.repository import GLib from kupfer.support import pretty, scheduler if ty.TYPE_CHECKING: from kupfer.support.types import ExecInfo __all__ = ("Task", "TaskRunner", "ThreadTask") TaskCallback = ty.Callable[[ty.Any], None] class Task: """Represent a task that can be done in the background The finish_callback received in Task.start(..) must be stored, and regardless if the task exits with an error, or completes successfully, the callback *must* be called. The finish callback must pass the Task instance itself as the only and first argument: finish_callback(self) """ def __init__(self, name: str | None = None) -> None: self.name = name def __repr__(self) -> str: name = repr(getattr(self, "name", None)) return f"<{type(self).__module__}.{type(self).__name__} name={name}>" def start(self, finish_callback: TaskCallback) -> None: raise NotImplementedError class ThreadTask(Task): """Run in a thread. `wait_sec` (when >0) specify time when we wait for result. After this time `thread_finish`, `finish_callback` and `thread_finally` are not called. We can't simply kill background thread but we can ignore its result and log errors (if any). """ def __init__(self, name: str | None = None, wait_sec: int = 0): Task.__init__(self, name) self._finish_callback: TaskCallback | None = None # what long we wait for result; after this time _finish_callback is not # called self.wait_sec = wait_sec self.thread_started_ts: float = 0 def thread_do(self) -> None: """Override this to run what should be done in the thread""" raise NotImplementedError def thread_finish(self) -> None: """This finish function runs in the main thread after thread completion, and can be used to communicate with the GUI. """ def thread_finally(self, exc_info: ExecInfo | None) -> None: """Always run at thread finish""" if exc_info is not None: _etype, value, tback = exc_info if value: raise value.with_traceback(tback) def _thread_finally(self, exc_info: ExecInfo | None) -> None: try: self.thread_finally(exc_info) finally: if self._finish_callback: self._finish_callback(self) def _log_error(self, exc_info: ExecInfo | None) -> None: if exc_info: pretty.print_exc(__name__, exc_info) def _run_thread(self) -> None: exc_info = None overdue = False try: self.thread_do() overdue = self.wait_sec > 0 and ( time.monotonic() - self.thread_started_ts > self.wait_sec ) if not overdue: GLib.idle_add(self.thread_finish) except Exception: exc_info = sys.exc_info() finally: if overdue: GLib.idle_add(self._log_error, exc_info) else: GLib.idle_add(self._thread_finally, exc_info) def start(self, finish_callback: TaskCallback) -> None: self._finish_callback = finish_callback self.thread_started_ts = time.monotonic() thread = threading.Thread(target=self._run_thread) thread.start() class TaskRunner(pretty.OutputMixin): """Run Tasks in the idle Loop""" def __init__(self, end_on_finish: bool) -> None: self.tasks: set[Task] = set() self.end_on_finish = end_on_finish scheduler.get_scheduler().connect("finish", self._on_finish) def _task_finished(self, task): self.output_debug("Task finished", task) self.tasks.remove(task) def add_task(self, task: Task) -> None: """Register @task to be run""" self.tasks.add(task) task.start(self._task_finished) def _on_finish(self, _sched: ty.Any) -> None: if self.end_on_finish: self.tasks.clear() return if self.tasks: self.output_info("Uncompleted tasks:") for task in self.tasks: self.output_info(task) kupfer-328/kupfer/support/textutils.py000066400000000000000000000070141500175051100203100ustar00rootroot00000000000000from __future__ import annotations import itertools from contextlib import suppress __all__ = ("extract_title_body", "parse_time_interval") def _unicode_truncate(ustr: str, length: int, encoding: str = "UTF-8") -> str: """Truncate @ustr to specific encoded byte length""" bstr = ustr.encode(encoding)[:length] return bstr.decode(encoding, "ignore") def _split_first_line(text: str) -> tuple[str, str]: """Take first non-empty line of @text and rest""" lines, *rest = text.lstrip().split("\n", maxsplit=1) return lines, rest[0] if rest else "" def _split_first_words(text: str, maxlen: int) -> tuple[str, str]: text = text.lstrip() first_text = _unicode_truncate(text, maxlen) words = first_text.split() if len(words) > 3: # noqa: PLR2004 first_words = " ".join(words[:-2]) if text.startswith(first_words): first_text = first_words rest_text = text[len(first_text) :] return first_text, rest_text def extract_title_body(text: str, maxtitlelen: int = 60) -> tuple[str, str]: """Prepare @text: Return a (title, body) tuple @text: A user-submitted paragraph or otherwise snippet of text. We try to detect an obvious title and then return the title and the following body. Otherwise we extract a title from the first words, and return the full text as body. @maxtitlelen: A unitless measure of approximate length of title. The default value yields a resulting title of approximately 60 ascii characters, or 20 asian characters. >>> extract_title_body("Short Text") ('Short Text', '') >>> title, body = extract_title_body(u"執筆方針については、項目名の付け方、" ... "フォーマットや表記上の諸問題に関して多くの方針が存在している。") >>> print(title) 執筆方針については、項目名の付け方、フォ >>> print(body) # doctest: +ELLIPSIS 執筆方針については、項目名の付け方、フォ...して多くの方針が存在している。 """ # if you don't make real tests, it's not not worth doing it at all. if not text.strip(): return text, "" firstline, rest = _split_first_line(text) if len(firstline.encode("UTF-8")) <= maxtitlelen: return firstline, rest # We use the UTF-8 encoding and truncate due to it: # this is a good heuristic for ascii vs "wide characters" # it results in taking fewer characters if they are asian, which # is exactly what we want firstline, rest = _split_first_words(text, maxtitlelen) if rest.strip(): return firstline, text return text, "" def parse_time_interval(tstr: str) -> int: """Parse a time interval in `tstr`, return whole number of seconds. >>> parse_time_interval("2") 2 >>> parse_time_interval("1h 2m 5s") 3725 >>> parse_time_interval("2 min") 120 """ weights = { "s": 1, "sec": 1, "m": 60, "min": 60, "h": 3600, "hours": 3600, } with suppress(ValueError): return int(tstr) total = 0 amount = 0 # Split the string in runs of digits and runs of characters for isdigit, group in itertools.groupby(tstr, str.isdigit): if not (part := "".join(group).strip()): continue if isdigit: amount = int(part) else: total += amount * weights.get(part.lower(), 0) amount = 0 return total if __name__ == "__main__": import doctest doctest.testmod() kupfer-328/kupfer/support/types.py000066400000000000000000000003471500175051100174110ustar00rootroot00000000000000""" Various, common types for typechecing """ import types import typing as ty ExecInfo = ty.Union[ tuple[ ty.Type[BaseException], BaseException, ty.Optional[types.TracebackType] ], tuple[None, None, None], ] kupfer-328/kupfer/support/validators.py000066400000000000000000000157351500175051100204240ustar00rootroot00000000000000from __future__ import annotations import re import typing as ty import urllib.parse from contextlib import suppress __all__ = ("is_url", "is_valid_email", "is_valid_file_path", "validate_netloc") def _validate_port(port: str) -> bool: if not port: return False with suppress(ValueError): return 0 <= int(port) <= 65535 # noqa: PLR2004 return False def _is_ipv4(string: str) -> bool: if len(octets := string.split(".")) == 4: # noqa: PLR2004 with suppress(ValueError): return all(0 <= int(o) <= 255 for o in octets) # noqa: PLR2004 return False def _is_ipv6(netloc: str) -> bool: # quick and not perfect ipv6 address validation if netloc[0] != "[" or netloc[-1] != "]": return False netloc = netloc[1:-1] if not (2 <= len(netloc) <= 39): # noqa: PLR2004 return False parts = netloc.split(":") if not (3 <= len(parts) <= 8): # noqa: PLR2004 return False return all(re.match(r"[0-9a-fA-F]{1,4}", part) for part in parts if part) def _is_valid_domain(domain: str) -> bool: if not domain: return False domain_re = ( # hostname r"[a-z\u00a1-\uffff0-9](?:[a-z\u00a1-\uffff0-9-]{0,61}" r"[a-z\u00a1-\uffff0-9])?" # domain r"(?:\.(?!-)[a-z\u00a1-\uffff0-9-]{1,63}(? bool: return bool( re.match( r"[a-z\u00a1-\uffff0-9](?:[a-z\u00a1-\uffff0-9-]{0,61}" r"[a-z\u00a1-\uffff0-9])?", name, re.IGNORECASE, ) ) def validate_netloc(netloc: str) -> bool: """Check if `netloc` is valid netlocation. Accepted forms [[:]@][:port] based on django.validator https://github.com/django/django/blob/main/django/core/validators.py """ if not netloc: return False # netlock may contain user:pass if "@" in netloc: user_pass, _s, netloc = netloc.partition("@") if user_pass and not re.match(r"[^\s:@/]+(?::[^\s:@/]*)?", user_pass): return False host = netloc # is there domain:port? if re.match(r".+:\d{1,5}$", netloc): # check is port valid host, _s, port = netloc.rpartition(":") if not _validate_port(port): return False if not host: return False return ( host == "localhost" or _is_ipv4(host) or _is_valid_domain(host) or _is_ipv6(host) ) def _guess_schema(netloc: str) -> str: """Guess schema for network location `netloc`.""" if netloc.startswith("ftp.") or "@ftp." in netloc: return "ftp" # assume localhost is http if "localhost" in netloc or re.match(r"^127\.\d+\.\d+\.\d+$", netloc): return "http" return "https" def _is_http_domain(netloc: str) -> bool: # noqa: PLR0911 """Guess is `netloc` is some kind of real domain. It's not accurate""" if netloc == "localhost": return True parts = netloc.split(".") if not all(parts): return False len_parts = len(parts) if len_parts == 1: return False if len_parts > 2: # noqa: PLR2004 return True if "localhost" in parts: return True lpart = parts[-1] if len(lpart) == 2: # natonal code (mostly) # noqa: PLR2004 return True return lpart in ("com", "org", "net", "gov", "local") # from https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml # schemes that not require / not have netloc. Skipped exotic/historic. _schema_wo_netloc = { "android", "admin", # unofficial, gnome "apt", "bitcoin", "bitcoincash", "callto", "dab", "dvb", "ethereum", "file", "fm", "gg", "gtalk", "ipfs", "ipns", "jabber", "lastfm", "magnet", "mailto", "maps", "market", "message", "nntp", "news", "skype", "sms", "steam", } def is_url(text: str) -> str | None: # noqa: PLR0911 """If `text` is an URL, return a cleaned-up URL, else return `None` Ref: https://en.wikipedia.org/wiki/Uniform_Resource_Identifier https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml https://en.wikipedia.org/wiki/List_of_URI_schemes """ text = text.strip() # quick check is text contain valid for url characters if not re.match( r"^[a-z\u00a1-\uffff0-9-:/?#\[\]@!$&;()*+.,;=~_%-]+$", text, re.IGNORECASE, ): return None url = urllib.parse.urlparse(text) netloc = url.netloc scheme = url.scheme path = url.path if scheme and netloc: # if we have schema and valid domain - it's ok if validate_netloc(netloc): return text # accept also non-fqdn hostname if _is_valid_hostname(netloc): return text return None if scheme and path: # this is valid for mailto:, news: and other urls that not have netloc if scheme in _schema_wo_netloc: return text # spacial case for mail: replace mail: -> mailto: if scheme == "mail": return f"mailto{text[4:]}" if not netloc: # if there is no schema and no '//' on begin of netloc urlparse # put this in path value. Also when for address like 'abc:a@kks' 'abc' # is in schema and rest in path. # try to fix this: if scheme and "://" not in text: netloc, _d, path = text.partition("/") schema = "" elif path: netloc, _d, path = path.partition("/") # valid netloc if ( netloc and validate_netloc(netloc) and (path or url.query or _is_http_domain(netloc)) ): schema = _guess_schema(netloc) return f"{schema}://{text}" return None def is_valid_email(text: str) -> bool: """Check if `text` is valid email address.""" if not text: return False local_part, _dummy, domain = text.partition("@") if not _is_valid_domain(domain): return False re_local_part = r"[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+" return bool(re.match(re_local_part, local_part)) _UNPRINTABLE: ty.Final[str] = ( "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0e\x0f" "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a" "\x1b\x1c\x1d\x1e\x1f\x7f" ) _MAX_PATH_LEN: ty.Final[int] = 256 def is_valid_file_path(path: str | None) -> bool: """Not perfect path validation""" if not path: return False if len(path) > _MAX_PATH_LEN: return False if re.match(r"^[a-z]+://", path) or path.startswith("//"): return False return not any(c in _UNPRINTABLE for c in path) kupfer-328/kupfer/support/validators_test.py000066400000000000000000000201701500175051100214500ustar00rootroot00000000000000# pylint:disable=protected-access # type:ignore """ Tests for validators. """ import unittest from kupfer.support import validators as v class TestValidateNetloc(unittest.TestCase): def test_ipv4(self): self.assertTrue(v.validate_netloc("127.0.0.1")) self.assertTrue(v.validate_netloc("0.0.0.0")) self.assertTrue(v.validate_netloc("255.255.255.255")) self.assertTrue(v.validate_netloc("@127.0.0.1")) self.assertTrue(v.validate_netloc("username@127.0.0.1")) self.assertTrue(v.validate_netloc("username:pass@127.0.0.1")) self.assertTrue(v.validate_netloc("127.0.0.1:123")) self.assertTrue(v.validate_netloc("@127.0.0.1:2314")) self.assertTrue(v.validate_netloc("username@127.0.0.1:21")) self.assertTrue(v.validate_netloc("username:pass@127.0.0.1:3")) def test_ipv4_neg(self): self.assertFalse(v.validate_netloc("127.0.")) self.assertFalse(v.validate_netloc("127")) self.assertFalse(v.validate_netloc("276.0.0.0")) self.assertFalse(v.validate_netloc("255.255.255.255.244")) self.assertFalse(v.validate_netloc(":pass@127.0.0.1")) self.assertFalse(v.validate_netloc("@127.0.0.1:66666")) def test_ipv6(self): self.assertTrue(v.validate_netloc("[2001:db8:1::ab9:C:102]")) self.assertTrue(v.validate_netloc("[2001:db8:]")) self.assertTrue(v.validate_netloc("[::1]")) self.assertTrue(v.validate_netloc("[1:db8::1234:5678]")) self.assertTrue(v.validate_netloc("[::]")) self.assertTrue(v.validate_netloc("@[2001:db8:1::ab9:C:102]:12")) self.assertTrue(v.validate_netloc("user@[2001:db8:]:12")) self.assertTrue(v.validate_netloc("user:pass@[::1]:2131")) self.assertTrue(v.validate_netloc("[1:db8::1234:5678]:21312")) self.assertTrue(v.validate_netloc("[::]:1")) def test_ipv6_neg(self): # url need ipv6 address in [ ] self.assertFalse(v.validate_netloc("2001:db8:1::ab9:C:102")) self.assertFalse(v.validate_netloc("[2001]")) self.assertFalse(v.validate_netloc("[2:2:3:4:4:5:5:5:5:6]")) self.assertFalse( v.validate_netloc("[aaaa:bbbb:aaaa:bbbb:aaaa:bbbb:aaaa:bbbb:]") ) self.assertFalse( v.validate_netloc("[aaaa:bbbb:aaaa:bbbb:aaaa:bbbb::aaaa:bbbb]") ) self.assertFalse( v.validate_netloc("[aaaa:zbbb:aaaa:bbbb:aaaa:bbbb::azaa:bbbb]") ) def test_hostname(self): self.assertTrue(v.validate_netloc("localhost")) self.assertTrue(v.validate_netloc("localhost:123")) self.assertTrue(v.validate_netloc("user@localhost")) self.assertTrue(v.validate_netloc("user:pass@localhost:123")) self.assertTrue(v.validate_netloc("www.abc.com")) self.assertTrue(v.validate_netloc("www.abc.com.")) self.assertTrue(v.validate_netloc("www.abc-bc.com")) self.assertTrue(v.validate_netloc("www.ąśłóę.com")) self.assertTrue(v.validate_netloc("www.abc.com.pl")) self.assertTrue(v.validate_netloc("www.abc.com.pl:1234")) self.assertTrue(v.validate_netloc("user@www.abc.com.pl:1234")) self.assertTrue(v.validate_netloc("user:pass@www.abc.com.pl:1234")) def test_hostname_neg(self): self.assertTrue(v.validate_netloc("www.ab-c.com")) self.assertTrue(v.validate_netloc("www.abc--abc.com")) self.assertFalse(v.validate_netloc("anc*test.31231.com")) self.assertFalse(v.validate_netloc(".31231.com")) self.assertFalse( v.validate_netloc( ".123456789012345678901234567890123456789012345678901234567890.com" ) ) self.assertFalse(v.validate_netloc(".31231-.com")) self.assertFalse(v.validate_netloc("test@")) class TestIsUrl(unittest.TestCase): def test_is_http_domain(self): self.assertTrue(v._is_http_domain("www.com")) self.assertTrue(v._is_http_domain("www.abc.com")) self.assertTrue(v._is_http_domain("www.abc.io")) self.assertTrue(v._is_http_domain("test.pl")) self.assertTrue(v._is_http_domain("test.com")) self.assertTrue(v._is_http_domain("localhost")) self.assertTrue(v._is_http_domain("ftp.localhost")) self.assertTrue(v._is_http_domain("abc.local")) self.assertTrue(v._is_http_domain("abc.local")) self.assertTrue(v._is_http_domain("abc.home.arpa")) self.assertFalse(v._is_http_domain("abcd")) self.assertFalse(v._is_http_domain("abc.xxxxxxxx")) self.assertFalse(v._is_http_domain("abc..local")) self.assertFalse(v._is_http_domain("abc.local.")) self.assertFalse(v._is_http_domain(".abc.local")) def test_valid_http(self): self.assertEqual("https://www.abc.com", v.is_url("www.abc.com")) self.assertEqual("http://www.abc.com", v.is_url("http://www.abc.com")) self.assertEqual("http://abc.com", v.is_url("http://abc.com")) self.assertEqual( "https://abc.com/abc?test", v.is_url("abc.com/abc?test") ) self.assertEqual("http://localhost", v.is_url("localhost")) self.assertEqual( "https://localhost/test", v.is_url("https://localhost/test") ) self.assertEqual( "https://john.doe@www.example.com:123/forum/questions/" "?tag=networking&order=newest#top", v.is_url( "https://john.doe@www.example.com:123/forum/questions/" "?tag=networking&order=newest#top" ), ) self.assertEqual( "https://example.com/tests/file%20name.pdf", v.is_url("https://example.com/tests/file%20name.pdf"), ) def test_valid_mail(self): self.assertEqual( "mailto:user@example.com", v.is_url("mailto:user@example.com"), ) # "mail:" is invalid schema for email, but still valid url... # special case: fix to mailto self.assertEqual( "mailto:user@example.com", v.is_url("mail:user@example.com"), ) def test_valid_other(self): self.assertEqual( "ftp://abc:123@localhost/test", v.is_url("ftp://abc:123@localhost/test"), ) self.assertEqual( "ftp://abc:123@ftp.localhost/test", v.is_url("abc:123@ftp.localhost/test"), ) self.assertEqual( "sftp://sftp.localhost/", v.is_url("sftp://sftp.localhost/"), ) self.assertEqual( "sftp://test@localhost", v.is_url("sftp://test@localhost"), ) self.assertEqual( "sftp://test@sftp.localhost/", v.is_url("sftp://test@sftp.localhost/"), ) self.assertEqual( "ldap://[2001:db8::7]/c=GB?objectClass?one", v.is_url( "ldap://[2001:db8::7]/c=GB?objectClass?one", ), ) self.assertEqual( "news:comp.infosystems.www.servers.unix", v.is_url("news:comp.infosystems.www.servers.unix"), ) self.assertEqual( "telnet://192.0.2.16:80/", v.is_url( "telnet://192.0.2.16:80/", ), ) def test_valid_http_neg(self): self.assertIsNone(v.is_url("www.abc")) self.assertIsNone(v.is_url("abcdds")) self.assertIsNone(v.is_url("http daldkal alkl")) self.assertIsNone(v.is_url("com.")) def test_short_netloc(self): self.assertEqual("sftp://localhost", v.is_url("sftp://localhost")) self.assertEqual("sftp://test", v.is_url("sftp://test")) def test_invalid(self): self.assertIsNone(v.is_url("http://kla alsdalk")) self.assertIsNone(v.is_url("http://www.^abc")) self.assertIsNone(v.is_url("http://www.abc|dsl")) class TestIsEmail(unittest.TestCase): def test_is_valid_email(self): self.assertTrue(v.is_valid_email("test@ldldl.com")) self.assertTrue(v.is_valid_email("test1w123@ldldl.com.pl")) self.assertFalse(v.is_valid_email("test@")) self.assertFalse(v.is_valid_email("@ldldl.com.pl")) self.assertFalse(v.is_valid_email("ldldl.com.pl")) kupfer-328/kupfer/support/weaklib.py000066400000000000000000000101451500175051100176600ustar00rootroot00000000000000""" This module is a part of the program Kupfer, see the main program file for more information. """ from __future__ import annotations import sys import typing as ty import weakref if ty.TYPE_CHECKING: from gi.repository import GObject __all__ = ( "DbusWeakCallback", "GobjectWeakCallback", "WeakCallback", "gobject_connect_weakly", ) MCallback = ty.Callable[..., None] class WeakCallback: """A Weak Callback object that will keep a reference to the connecting object with weakref semantics. This allows object A to pass a callback method to object S, without object S keeping A alive. """ def __init__(self, mcallback: MCallback) -> None: """Create a new Weak Callback calling the method @mcallback""" # pylint: disable=no-member obj = mcallback.__self__ # type: ignore # pylint: disable=no-member attr = mcallback.__func__.__name__ # type: ignore self.wref = weakref.ref(obj, self.object_deleted) self.callback_attr = attr self.token = None def __call__(self, *args: ty.Any, **kwargs: ty.Any) -> None: if obj := self.wref(): attr = getattr(obj, self.callback_attr) attr(*args, **kwargs) else: self.default_callback(*args, **kwargs) def default_callback(self, *args: ty.Any, **kwargs: ty.Any) -> None: """Called instead of callback when expired""" def object_deleted(self, wref: weakref.ReferenceType[ty.Any]) -> None: """Called when callback expires""" class DbusWeakCallback(WeakCallback): """ Will use @token if set as follows: token.remove() """ def object_deleted(self, wref: weakref.ReferenceType[ty.Any]) -> None: # App is shutting down try: if sys.is_finalizing(): return except AttributeError: if sys is None: return if self.token: self.token.remove() self.token = None def dbus_signal_connect_weakly( bus: ty.Any, signal: str, mcallback: MCallback, **kwargs: ty.Any ) -> None: """ Connect method @mcallback to dbus signal using a weak callback Connect to @signal on @bus, passing on all keyword arguments """ weak_cb = DbusWeakCallback(mcallback) weak_cb.token = bus.add_signal_receiver(weak_cb, signal, **kwargs) class GobjectWeakCallback(WeakCallback): """ Will use @token if set as follows: sender.disconnect(token) """ __senders: ty.ClassVar[dict[ty.Any, GObject]] = {} def object_deleted(self, wref: weakref.ReferenceType[GObject]) -> None: # App is shutting down try: if sys.is_finalizing(): return except AttributeError: if sys is None: return sender = self.__senders.pop(self.token, None) if sender is not None: sender.disconnect(self.token) @classmethod def _connect( cls, sender: GObject, signal: str, mcallback: MCallback, *user_args: ty.Any, ) -> None: # We save references to the sender in a class variable, # this is the only way to have it accessible when obj expires. wcb = cls(mcallback) wcb.token = sender.connect(signal, wcb, *user_args) cls.__senders[wcb.token] = sender def gobject_connect_weakly( sender: GObject, signal: str, mcallback: MCallback, *user_args: ty.Any ) -> None: """Connect weakly to GObject @sender's @signal, with a callback method @mcallback >>> import gi >>> gi.require_version("Gtk", "3.0") >>> from gi.repository import Gtk >>> btn = Gtk.Button.new() >>> class Handler (object): ... def handle(self): pass ... def __del__(self): print("deleted") ... >>> h = Handler() >>> gobject_connect_weakly(btn, "clicked", h.handle) >>> del h deleted >>> """ # pylint: disable=protected-access GobjectWeakCallback._connect( # noqa: SLF001 sender, signal, mcallback, *user_args ) if __name__ == "__main__": import doctest doctest.testmod() kupfer-328/kupfer/ui/000077500000000000000000000000001500175051100145705ustar00rootroot00000000000000kupfer-328/kupfer/ui/__init__.py000066400000000000000000000000001500175051100166670ustar00rootroot00000000000000kupfer-328/kupfer/ui/_support.py000066400000000000000000000047521500175051100170250ustar00rootroot00000000000000#! /usr/bin/env python3 """ UI support functions """ from gi.repository import Gtk from kupfer.support import datatools _escape_table = { ord("&"): "&", ord("<"): "<", ord(">"): ">", } def escape_markup_str(mstr: str) -> str: """Use a simple homegrown replace table to replace &, <, > with entities in @mstr """ return mstr.translate(_escape_table) @datatools.evaluate_once def text_direction_is_ltr() -> bool: """Check is system is configured as left-to-right.""" return Gtk.Widget.get_default_direction() != Gtk.TextDirection.RTL # type: ignore def normalize_display_name(name: str) -> str: # NOT IN USE if name[-2] == ":": return name + ".0" return name # # NOT IN USE # def make_rounded_rect(cr, x, y, width, height, radius): # """ # Draws a rounded rectangle with corners of @radius # """ # MPI = math.pi # cr.save() # cr.move_to(radius, 0) # cr.line_to(width-radius,0) # cr.arc(width-radius, radius, radius, 3*MPI/2, 2*MPI) # cr.line_to(width, height-radius) # cr.arc(width-radius, height-radius, radius, 0, MPI/2) # cr.line_to(radius, height) # cr.arc(radius, height-radius, radius, MPI/2, MPI) # cr.line_to(0, radius) # cr.arc(radius, radius, radius, MPI, 3*MPI/2) # cr.close_path() # cr.restore() # # not in use # def get_glyph_pixbuf( # text: str, # size: int, # center_vert: bool = True, # color: tuple[int, int, int] | None = None, # ) -> GdkPixbuf.Pixbuf: # """Return pixbuf for @text # if @center_vert, then center completely vertically # """ # margin = size * 0.1 # ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, size, size) # cctx = cairo.Context(ims) # cctx.move_to(margin, size - margin) # cctx.set_font_size(size / 2) # if color is None: # cctx.set_source_rgba(0, 0, 0, 1) # else: # cctx.set_source_rgb(*color) # cctx.text_path(text) # x1, y1, x2, y2 = cctx.path_extents() # skew_horiz = ((size - x2) - x1) / 2.0 # skew_vert = ((size - y2) - y1) / 2.0 # if not center_vert: # skew_vert = skew_vert * 0.2 - margin * 0.5 # cctx.new_path() # cctx.move_to(margin + skew_horiz, size - margin + skew_vert) # cctx.text_path(text) # cctx.fill() # ims.flush() # pngfile = io.BytesIO() # ims.write_to_png(pngfile) # loader = GdkPixbuf.PixbufLoader() # loader.write(pngfile.getvalue()) # loader.close() # return loader.get_pixbuf() kupfer-328/kupfer/ui/_widgets.py000066400000000000000000000373571500175051100167660ustar00rootroot00000000000000# Distributed under terms of the GPLv3 license. """ Custom widgets used mostly in Preferences Dialog """ from __future__ import annotations import os import re import traceback import typing as ty from gi.repository import Gio, GLib, Gtk from kupfer import icons, launch, plugin_support from kupfer.core import plugins, settings from kupfer.obj import KupferObject, Source if ty.TYPE_CHECKING: from gettext import gettext as _ from kupfer.support import types as kty # pylint: disable=too-few-public-methods class DirsSelectWidget(Gtk.Bin): # type: ignore """Widgets with list of folders and buttons to add/remove folder into.""" def __init__( self, plugin_id: str, setting: str, plugin_settings: plugin_support.PluginSettings, ): """Create widgets. Args: `plugin_id`: plugin id `setting`: name of parameter `plugin_support`: object PluginSettings for given plugin """ super().__init__() self.plugin_id = plugin_id self.setting = setting self.plugin_settings = plugin_settings self.model = Gtk.ListStore.new([str, Gio.Icon, str]) self.view = Gtk.TreeView.new_with_model(self.model) # pylint: disable=no-member self.btn_add = Gtk.Button.new_from_icon_name( "add", Gtk.IconSize.BUTTON ) self.btn_add.always_show_image = True self.btn_add.set_label(_("Add")) # pylint: disable=no-member self.btn_del = Gtk.Button.new_from_icon_name( "remove", Gtk.IconSize.BUTTON ) self.btn_del.always_show_image = True self.btn_del.set_label(_("Remove")) self._configure_model() self._create_layout() if dirs := plugin_settings[setting]: self._add_dirs(dirs) self.view.connect("cursor-changed", self._on_cursor_changed) self.btn_del.connect("clicked", self._on_del_clicked) self.btn_add.connect("clicked", self._on_add_clicked) def _configure_model(self): view = self.view view.set_headers_visible(False) view.set_property("enable-search", False) view.get_selection().set_mode(Gtk.SelectionMode.BROWSE) icon_cell = Gtk.CellRendererPixbuf() icon_col = Gtk.TreeViewColumn("icon", icon_cell) icon_col.add_attribute(icon_cell, "gicon", 1) cell = Gtk.CellRendererText() setctl = settings.get_settings_controller() cell.set_property("ellipsize", setctl.get_ellipsize_mode()) col = Gtk.TreeViewColumn("name", cell) col.add_attribute(cell, "text", 2) view.append_column(icon_col) view.append_column(col) view.show() def _create_layout(self): box = Gtk.VBox() box.set_spacing(3) scrollwin = Gtk.ScrolledWindow() # pylint: disable=no-member scrollwin.set_shadow_type(type=Gtk.ShadowType.IN) scrollwin.set_hexpand(True) scrollwin.set_size_request(50, 100) # pylint: disable=no-member scrollwin.add(self.view) box.pack_start(scrollwin, True, True, 0) # buttons bbox = Gtk.HButtonBox() bbox.set_property("layout-style", Gtk.ButtonBoxStyle.END) bbox.pack_start(self.btn_del, False, False, 0) bbox.pack_start(self.btn_add, False, False, 0) box.pack_end(bbox, True, True, 0) box.set_hexpand(True) self.add(box) def _add_dirs(self, dirs: list[str]) -> None: for directory in map(os.path.expanduser, dirs): dispname = launch.get_display_path_for_bytestring(directory) gicon = icons.get_gicon_for_file(directory) self.model.append((directory, gicon, dispname)) def _on_cursor_changed(self, table: Gtk.TreeView) -> None: curpath, _curcol = table.get_cursor() self.btn_del.set_sensitive(bool(curpath)) def _on_del_clicked(self, widget: Gtk.Widget) -> None: curpath, _curcol = self.view.get_cursor() if curpath: rowiter = self.model.get_iter(curpath) self.model.remove(rowiter) self._save() def _on_add_clicked(self, widget: Gtk.Widget) -> None: # TRANS: File Chooser Title chooser_dialog = Gtk.FileChooserDialog( title=_("Choose a Directory"), action=Gtk.FileChooserAction.SELECT_FOLDER, buttons=( Gtk.STOCK_CANCEL, Gtk.ResponseType.REJECT, Gtk.STOCK_OK, Gtk.ResponseType.ACCEPT, ), ) chooser_dialog.set_select_multiple(True) # pylint: disable=no-member if chooser_dialog.run() == Gtk.ResponseType.ACCEPT: # pylint: disable=no-member have = self.current_dirs() new_dirs = [ directory for directory in chooser_dialog.get_filenames() if directory not in have ] self._add_dirs(new_dirs) self._save() chooser_dialog.hide() def current_dirs(self) -> list[str]: return [os.path.normpath(row[0]) for row in self.model] def _save(self) -> None: setctl = settings.get_settings_controller() setctl.set_plugin_config( self.plugin_id, self.setting, self.current_dirs(), list ) # pylint: disable=too-few-public-methods class FileDirSelectWidget(Gtk.Bin): # type: ignore """Widgets with entry and buttons that allow to select file or directory.""" def __init__( self, plugin_id: str, setting: str, plugin_settings: plugin_support.PluginSettings, kind: str, ): """Create widgets. Args: `plugin_id`: plugin id `setting`: name of parameter `plugin_support`: object PluginSettings for given plugin `kind`: what user can select via dialog: 'choose_file' or 'choose_directory' """ assert kind in ("choose_directory", "choose_file") super().__init__() self.plugin_id = plugin_id self.setting = setting self.plugin_settings = plugin_settings self.kind = kind self.entry = Gtk.Entry() self.btn_add = Gtk.Button.new_from_icon_name( "fileopen", Gtk.IconSize.BUTTON, # pylint: disable=no-member ) self.btn_add.always_show_image = True self.btn_add.set_label(_("Select")) self.btn_clear = Gtk.Button.new_from_icon_name( "editclear", Gtk.IconSize.BUTTON, # pylint: disable=no-member ) self.btn_clear.always_show_image = True self.btn_clear.set_label(_("Clear")) self._create_layout() self.entry.set_text(plugin_settings[setting]) self.btn_clear.connect("clicked", self._on_del_clicked) self.btn_add.connect("clicked", self._on_add_clicked) self.entry.connect("changed", self._on_change) def _create_layout(self): box = Gtk.VBox() box.set_spacing(3) box.pack_start(self.entry, True, True, 0) # buttons bbox = Gtk.HButtonBox() bbox.set_property("layout-style", Gtk.ButtonBoxStyle.END) bbox.pack_start(self.btn_clear, False, False, 0) bbox.pack_start(self.btn_add, False, False, 0) box.pack_end(bbox, True, True, 0) box.set_hexpand(True) self.add(box) def _on_change(self, widget: Gtk.Widget) -> None: setctl = settings.get_settings_controller() setctl.set_plugin_config( self.plugin_id, self.setting, widget.get_text(), str ) def _on_del_clicked(self, widget: Gtk.Widget) -> None: self.entry.set_text("") def _on_add_clicked(self, widget: Gtk.Widget) -> None: # TRANS: File Chooser Title if self.kind == "choose_directory": title = _("Choose a Directory") action = Gtk.FileChooserAction.SELECT_FOLDER else: title = _("Choose a File") action = Gtk.FileChooserAction.OPEN chooser_dialog = Gtk.FileChooserDialog( title=title, action=action, buttons=( Gtk.STOCK_CANCEL, Gtk.ResponseType.REJECT, Gtk.STOCK_OK, Gtk.ResponseType.ACCEPT, ), ) chooser_dialog.set_select_multiple(False) if fname := self.entry.get_text(): fname = os.path.expanduser(fname) chooser_dialog.set_filename(fname) # pylint: disable=no-member # pylint: disable=no-member if chooser_dialog.run() == Gtk.ResponseType.ACCEPT: # pylint: disable=no-member fname = chooser_dialog.get_filename() fname = os.path.normpath(fname) self.entry.set_text(fname) chooser_dialog.hide() # pylint: disable=too-few-public-methods class ObjectsInfoWidget(Gtk.Bin): # type: ignore """Widget with list of `objs` (sources, actions): name, description.""" def __init__( self, plugin_id: str, objs: ty.Iterable[str], ) -> None: super().__init__() setctl = settings.get_settings_controller() small_icon_size = setctl.get_config_int( "Appearance", "icon_small_size" ) box = Gtk.Grid() box.set_row_spacing(6) box.set_column_spacing(12) for row, item in enumerate(objs): plugin_type = plugins.get_plugin_attribute(plugin_id, item) if not plugin_type: continue obj: KupferObject = plugin_type() # object icon image = Gtk.Image() image.set_property("gicon", obj.get_icon()) image.set_property("pixel-size", small_icon_size) image.set_alignment(0, 0) # pylint: disable=no-member box.attach(image, 0, row, 1, 1) ibox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 3) # name and description ibox.pack_start(self._create_label(obj), False, True, 0) box.attach(ibox, 1, row, 1, 1) # Display information for application content-sources. # only sources have leaf representation if isinstance(obj, Source): _valid, leaf_repr = obj.get_valid_leaf_repr() if leaf_repr is not None: hbox = self._create_leaves_info(leaf_repr, small_icon_size) ibox.pack_start(hbox, True, True, 0) self.add(box) def _create_label(self, obj: KupferObject) -> Gtk.Label: name_label = GLib.markup_escape_text(str(obj)) # name if desc := GLib.markup_escape_text(obj.get_description() or ""): name_label = f"{name_label}\n{desc}" label = Gtk.Label() label.set_alignment(0, 0) # pylint: disable=no-member label.set_markup(name_label) label.set_line_wrap(True) # pylint: disable=no-member label.set_selectable(True) return label def _create_leaves_info( self, leaf_repr: KupferObject, small_icon_size: int ) -> Gtk.Box: hbox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 6) image = Gtk.Image() image.set_property("gicon", leaf_repr.get_icon()) image.set_property("pixel-size", small_icon_size // 2) hbox.pack_start(Gtk.Label.new(_("Content of")), False, True, 0) hbox.pack_start(image, False, True, 0) hbox.pack_start(Gtk.Label.new(str(leaf_repr)), False, True, 0) return hbox # pylint: disable=too-few-public-methods class PluginAboutWidget(Gtk.Bin): # type: ignore """Widget with basic information about plugin.""" def __init__(self, plugin_id: str, info: dict[str, ty.Any]) -> None: super().__init__() box = Gtk.Box.new(Gtk.Orientation.VERTICAL, 12) ver, description, author = plugins.get_plugin_attributes( plugin_id, ( plugins.PluginAttr.VERSION, plugins.PluginAttr.DESCRIPTION, plugins.PluginAttr.AUTHOR, ), ) infobox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 6) # TRANS: Plugin info fields for field, val in ( (_("Description"), description), (_("Author"), author), (_("Version"), ver), ): if sbox := self._create_title_val_label_box(field, val): infobox.pack_start(sbox, False, True, 0) box.pack_start(infobox, False, True, 0) errormsg = None # Check for plugin load exception if (exc_info := plugins.get_plugin_error(plugin_id)) is not None: errstr = _format_exc_info(exc_info) errormsg = "".join( ( "", _("Plugin could not be read due to an error:"), "\n\n", GLib.markup_escape_text(errstr), ) ) elif not plugins.is_plugin_loaded(plugin_id): errormsg = ( "" + GLib.markup_escape_text(_("Plugin is disabled")) + "" ) if errormsg: label = Gtk.Label() label.set_markup(errormsg) label.set_alignment(0, 0) # pylint: disable=no-member label.set_line_wrap(True) # pylint: disable=no-member label.set_selectable(True) box.pack_start(label, False, True, 0) self.add(box) def _create_title_val_label_box( self, title: str, value: str ) -> Gtk.Box | None: if not value: return None sbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 3) for label_text in (f"{title}", GLib.markup_escape_text(value)): label = Gtk.Label() label.set_markup(label_text) label.set_alignment(0, 0) # pylint: disable=no-member label.set_line_wrap(True) # pylint: disable=no-member label.set_selectable(True) sbox.pack_start(label, False, True, 0) return sbox def _format_exc_info(exc_info: kty.ExecInfo) -> str: """Format ExecInfo to presentable form.""" etype, error, _tb = exc_info import_error_pat = r"No module named ([^\s]+)" errmsg = str(error) if re.match(import_error_pat, errmsg): # TRANS: Error message when Plugin needs a Python module to load import_error_localized = _("Python module '%s' is needed") % "\\1" return re.sub( import_error_pat, import_error_localized, errmsg, count=1 ) if etype and issubclass(etype, ImportError): return errmsg return "".join(traceback.format_exception(*exc_info)) def new_label_header( parent: Gtk.Box | None, markup: str, tooltip: str | None = None ) -> Gtk.Label: """Return "header" label with `markup` text and optional `tooltip`. Add it to `parent` box if given. Return new label object.""" markup = GLib.markup_escape_text(markup) return new_label( parent, f"{markup}", selectable=False, tooltip=tooltip ) def new_label( # pylint: disable=keyword-arg-before-vararg parent: Gtk.Box | None = None, /, *markup: str, selectable: bool = True, tooltip: str | None = None, ) -> Gtk.Label: """Create new label with `markup` text (concatenated). Set optional parameters: `selectable` (default True), `tooltip`. If `parent` box is given, add label to box. Return widget object.""" text = "".join(markup) label = Gtk.Label() label.set_alignment(0, 0.5) # pylint: disable=no-member label.set_markup(text) label.set_line_wrap(True) # pylint: disable=no-member label.set_selectable(selectable) if tooltip: label.set_tooltip_text(tooltip) if parent: parent.pack_start(label, False, True, 0) return label kupfer-328/kupfer/ui/about.py000066400000000000000000000035371500175051100162640ustar00rootroot00000000000000#! /usr/bin/env python3 """ About dialog. """ from __future__ import annotations import typing as ty from gi.repository import Gtk from kupfer import version if ty.TYPE_CHECKING: from kupfer.ui.uievents import GUIEnvironmentContext # pylint: disable=too-few-public-methods class _AboutDialog: _instance: _AboutDialog | None = None @classmethod def instance(cls) -> _AboutDialog: if cls._instance is None: cls._instance = _AboutDialog() assert cls._instance return cls._instance def __init__(self): self._dlg = abdlg = Gtk.AboutDialog() abdlg.set_program_name(version.PROGRAM_NAME) abdlg.set_icon_name(version.ICON_NAME) abdlg.set_logo_icon_name(version.ICON_NAME) abdlg.set_version(version.VERSION) abdlg.set_comments(version.SHORT_DESCRIPTION) abdlg.set_copyright(version.COPYRIGHT) abdlg.set_website(version.WEBSITE) abdlg.set_license(version.LICENSE) abdlg.set_authors(version.AUTHORS) if version.DOCUMENTERS: abdlg.set_documenters(version.DOCUMENTERS) if version.TRANSLATOR_CREDITS: abdlg.set_translator_credits(version.TRANSLATOR_CREDITS) if version.ARTISTS: abdlg.set_artists(version.ARTISTS) abdlg.connect("response", self._on_response) def show(self, ctxenv: GUIEnvironmentContext | None = None) -> None: if ctxenv: ctxenv.present_window(self._dlg) else: self._dlg.present() def _on_response(self, dialog: Gtk.Dialog, response_id: ty.Any) -> bool: dialog.destroy() _AboutDialog._instance = None return True def show_about_dialog( ctxenv: GUIEnvironmentContext | None = None, ) -> None: """Create an about dialog and show it.""" dlg = _AboutDialog.instance() dlg.show() kupfer-328/kupfer/ui/accelerators.py000066400000000000000000000022611500175051100176120ustar00rootroot00000000000000import typing as ty if ty.TYPE_CHECKING: from gettext import gettext as _ ACCELERATOR_NAMES: ty.Final = { # TRANS: Names of accelerators in the interface "activate": _("Alternate Activate"), # TRANS: The "Comma Trick"/"Put Selection on Stack" allows the # TRANS: user to select many objects to be used for one action "comma_trick": _("Comma Trick"), # TRANS: "Compose Command" makes one object out of the selected # TRANS: object + action (+iobject) "compose_action": _("Compose Command"), "mark_as_default": _("Mark Default Action"), "erase_affinity_for_first_pane": _("Forget Object"), "reset_all": _("Reset All"), "select_quit": _("Select Quit"), "select_selected_file": _("Select Selected File"), "select_selected_text": _("Select Selected Text"), "select_clipboard_file": _("Select Clipboard File"), "select_clipboard_text": _("Select Clipboard Text"), "show_help": _("Show Help"), "show_preferences": _("Show Preferences"), "switch_to_source": _("Switch to 1st Pane"), "switch_to_2": _("Switch to 2nd Pane"), "switch_to_3": _("Switch to 3rd Pane"), "toggle_text_mode_quick": _("Toggle Text Mode"), } kupfer-328/kupfer/ui/browser.py000066400000000000000000000700471500175051100166350ustar00rootroot00000000000000from __future__ import annotations import signal import sys import typing as ty from contextlib import suppress import cairo from gi.repository import Gdk, GLib, Gtk try: from gi.repository import AyatanaAppIndicator3 as AppIndicator3 except ImportError: AppIndicator3 = None import kupfer.config import kupfer.environment from kupfer import version from kupfer.core import commandexec, settings from kupfer.core.datactrl import DataController from kupfer.support import pretty, scheduler from kupfer.ui import ( about, keybindings, kupferhelp, listen, preferences, uievents, ) from kupfer.ui._support import text_direction_is_ltr from kupfer.ui.interface import Interface if ty.TYPE_CHECKING: from gettext import gettext as _ _KUPFER_CSS: ty.Final = b""" #kupfer { border: 2px solid alpha(black, 0.3); border-radius: 10px; } .matchview { border-radius: 0.6em; } #kupfer-preedit { padding: 0 0 0 0; } #kupfer-preedit.hidden { border-width: 0 0 0 0; padding: 0 0 0 0 ; margin: 0 0 0 0; outline-width: 0; min-height: 0; min-width: 0; } #kupfer-object-pane { } #kupfer-action-pane { } #kupfer-indirect-object-pane { } #kupfer-list { } #kupfer-list-view { } *:selected.matchview { background: alpha(@theme_selected_bg_color, 0.5); border: 2px solid alpha(black, 0.3) } """ WINDOW_BORDER_WIDTH: ty.Final = 8 class WindowController(pretty.OutputMixin): """ This is the fundamental Window (and App) Controller """ def __init__(self): self._window: Gtk.Window = None self._current_screen_handler = 0 self._interface: Interface = None # type: ignore self._statusicon = None self._statusicon_ai = None self._window_hide_timer = scheduler.Timer() def _initialize(self, data_controller: DataController) -> None: self._window = Gtk.Window( type=Gtk.WindowType.TOPLEVEL, border_width=WINDOW_BORDER_WIDTH, decorated=False, name="kupfer", ) # screen = self._window.get_screen() # pylint: disable=no-member # if (visual := screen.get_rgba_visual()) and screen.is_composited(): # self._window.set_visual(visual) # pylint: disable=no-member self._window.connect("realize", self._on_window_realize) self._window.connect( "configure-event", self._on_window_configure_event ) self._window.add_events( # pylint: disable=no-member Gdk.EventMask.BUTTON_PRESS_MASK ) data_controller.connect("launched-action", self._on_launch_action) data_controller.connect("command-result", self._on_command_result) self._interface = Interface(data_controller, self._window) self._interface.connect("launched-action", self._on_launch_action) self._interface.connect("cancelled", self._on_cancelled) self._window.connect("map-event", self._on_window_map_event) self._setup_window() # Accept drops self._window.drag_dest_set( # pylint: disable=no-member Gtk.DestDefaults.ALL, [], Gdk.DragAction.COPY ) self._window.drag_dest_add_uri_targets() # pylint: disable=no-member self._window.drag_dest_add_text_targets() # pylint: disable=no-member self._window.connect("drag-data-received", self._on_drag_data_received) signal.signal(signal.SIGINT, self._on_sigterm) signal.signal(signal.SIGTERM, self._on_sigterm) signal.signal(signal.SIGHUP, self._on_sigterm) def _on_window_map_event(self, *_args: ty.Any) -> None: self._interface.update_third() def _on_window_realize(self, widget: Gtk.Widget) -> None: # Load css style_provider = Gtk.CssProvider() style_provider.load_from_data(_KUPFER_CSS) Gtk.StyleContext.add_provider_for_screen( # pylint: disable=no-member widget.get_screen(), style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION, ) def _on_window_configure_event( self, widget: Gtk.Widget, event: Gdk.EventConfigure ) -> None: """Set main window rounded shape.""" width, height = widget.get_size() radius = 10 width_radius = width - radius height_radius = height - radius surface = cairo.ImageSurface( # pylint: disable=no-member cairo.FORMAT_ARGB32, # pylint: disable=no-member width, height, ) ctx = cairo.Context(surface) # pylint: disable=no-member ctx.set_source_rgba(0.0, 0.0, 255.0, 128.0) ctx.set_operator(cairo.OPERATOR_SOURCE) # pylint: disable=no-member ctx.move_to(radius, 0) ctx.line_to(width_radius, 0) ctx.arc(width_radius, radius, radius, 4.71, 6.28) ctx.line_to(width, height_radius) ctx.arc(width_radius, height_radius, radius, 0, 1.57) ctx.line_to(radius, height) ctx.arc(radius, height_radius, radius, 1.57, 3.14) ctx.line_to(0, radius) ctx.arc(radius, radius, radius, 3.14, 4.71) ctx.close_path() ctx.fill() reg = Gdk.cairo_region_create_from_surface(surface) widget.shape_combine_region(reg) def _show_statusicon(self) -> None: """Create (if not exists) and show status icon.""" if not self._statusicon: status = Gtk.StatusIcon.new_from_icon_name(version.ICON_NAME) status.set_tooltip_text(version.PROGRAM_NAME) status.connect( "popup-menu", self._on_popup_menu, self._setup_menu() ) status.connect("activate", self._on_statusicon_activate) self._statusicon = status with suppress(AttributeError): self._statusicon.set_visible(True) def _on_showstatusicon_changed( self, setctl: settings.SettingsController, section: str, key: str, value: ty.Any, ) -> None: """Callback from SettingsController - show / hide status icon on settings changed.""" if value: self._show_statusicon() elif self._statusicon: # hide try: self._statusicon.set_visible(False) except AttributeError: self._statusicon = None def _show_statusicon_ai(self) -> None: """Show (create if not exists) status icon using AyatanaAppIndicator3.""" if AppIndicator3 is None: return if not self._statusicon_ai: indicator = AppIndicator3.Indicator.new( version.PROGRAM_NAME, version.ICON_NAME, AppIndicator3.IndicatorCategory.APPLICATION_STATUS, ) indicator.set_menu(self._setup_menu()) self._statusicon_ai = indicator self._statusicon_ai.set_status(AppIndicator3.IndicatorStatus.ACTIVE) def _showstatusicon_ai_changed( self, setctl: settings.SettingsController, section: str, key: str, value: ty.Any, ) -> None: """Show/Hide AppIndicator3 status icon on preferences change.""" if AppIndicator3 is None: return if value: self._show_statusicon_ai() elif self._statusicon_ai: # hide self._statusicon_ai.set_status( AppIndicator3.IndicatorStatus.PASSIVE ) def _setup_menu(self, context_menu: bool = False) -> Gtk.Menu: menu = Gtk.Menu() menu.set_name("kupfer-menu") def submenu_callback( menuitem: Gtk.MenuItem, callback: ty.Callable[[], None] ) -> bool: callback() return True def add_menu_item( icon: str | None, callback: ty.Callable[..., None], label: str | None = None, with_ctx: bool = True, ) -> None: def mitem_handler( menuitem: Gtk.MenuItem, callback: ty.Callable[..., None] ) -> bool: if with_ctx: ui_ctx = uievents.gui_context_from_widget( Gtk.get_current_event_time(), menuitem ) callback(ui_ctx) else: callback() if context_menu: self.put_away() return True if label and not icon: mitem = Gtk.MenuItem(label=label) else: mitem = Gtk.ImageMenuItem.new_from_stock(icon) mitem.connect("activate", mitem_handler, callback) menu.append(mitem) if context_menu: add_menu_item(Gtk.STOCK_CLOSE, self.put_away, with_ctx=False) else: add_menu_item(None, self._on_activate, _("Show Main Interface")) menu.append(Gtk.SeparatorMenuItem()) if context_menu: for name, func in self._interface.get_context_actions(): mitem = Gtk.MenuItem(label=name) mitem.connect("activate", submenu_callback, func) menu.append(mitem) menu.append(Gtk.SeparatorMenuItem()) add_menu_item(Gtk.STOCK_PREFERENCES, preferences.show_preferences) add_menu_item(Gtk.STOCK_HELP, kupferhelp.show_help) add_menu_item(Gtk.STOCK_ABOUT, about.show_about_dialog) menu.append(Gtk.SeparatorMenuItem()) add_menu_item(Gtk.STOCK_QUIT, self._on_quit, with_ctx=False) menu.show_all() return menu def _setup_window(self) -> None: """Returns window.""" self._window.connect("delete-event", self._on_close_window) self._window.connect("focus-out-event", self._on_lost_focus) self._window.connect( "button-press-event", self._on_window_frame_clicked ) widget = self._interface.get_widget() widget.show() # Build the window frame with its top bar topbar = Gtk.HBox() vbox = Gtk.VBox() vbox.pack_start(topbar, False, False, 0) vbox.pack_start(widget, True, True, 0) vbox.show() self._window.add(vbox) # pylint: disable=no-member title = Gtk.Label.new("") button = Gtk.Label.new("") l_programname = version.PROGRAM_NAME.lower() # The text on the general+context menu button btext = f"{l_programname} ⚙" button.set_markup(btext) button_box = Gtk.EventBox() button_box.set_visible_window(False) button_adj = Gtk.Alignment.new(0.5, 0.5, 0, 0) button_adj.set_padding(0, 2, 0, 3) button_adj.add(button) button_box.add(button_adj) button_box.connect("button-press-event", self._on_context_menu_clicked) button_box.connect( "enter-notify-event", self._on_button_enter, button, btext ) button_box.connect( "leave-notify-event", self._on_button_leave, button, btext ) button.set_name("kupfer-menu-button") title_align = Gtk.Alignment.new(0, 0.5, 0, 0) title_align.add(title) topbar.pack_start(title_align, True, True, 0) topbar.pack_start(button_box, False, False, 0) topbar.show_all() self._window.set_title(version.PROGRAM_NAME) self._window.set_icon_name(version.ICON_NAME) self._window.set_type_hint( # pylint: disable=no-member self._create_window_type_hint() ) self._window.set_property("skip-taskbar-hint", True) self._window.set_keep_above(True) # pylint: disable=no-member if (pos := self._create_window_position()) != Gtk.WindowPosition.NONE: self._window.set_position(pos) # pylint: disable=no-member if not text_direction_is_ltr(): self._window.set_gravity( # pylint: disable=no-member Gdk.GRAVITY_NORTH_EAST ) # Setting not resizable changes from utility window # on metacity self._window.set_resizable(False) def _create_window_type_hint(self) -> Gdk.WindowTypeHint: """Create window type hints according to WINDOW_TYPE_HINT env setting.""" type_hint = Gdk.WindowTypeHint.UTILITY hint_name = kupfer.config.get_kupfer_env("WINDOW_TYPE_HINT").upper() if not hint_name: return type_hint if ( hint_enum := getattr(Gdk.WindowTypeHint, hint_name, None) ) is not None: return hint_enum self.output_error("No such Window Type Hint", hint_name) self.output_error("Existing type hints:") for name in dir(Gdk.WindowTypeHint): if name.upper() == name: self.output_error(name) return type_hint def _create_window_position(self) -> Gtk.WindowPosition: """Create window position according to WINDOW_POSITION env setting.""" value = Gtk.WindowPosition.NONE hint_name = kupfer.config.get_kupfer_env("WINDOW_POSITION").upper() if not hint_name: return value if hint_enum := getattr(Gtk.WindowPosition, hint_name, None): return hint_enum self.output_error("No such Window Position", hint_name) self.output_error("Existing values:") for name in dir(Gtk.WindowPosition): if name.upper() == name: self.output_error(name) return value def _on_window_frame_clicked( self, widget: Gtk.Widget, event: Gdk.EventButton ) -> None: """Start drag when the window is clicked""" widget.begin_move_drag( event.button, int(event.x_root), int(event.y_root), event.time ) def _on_context_menu_clicked( self, widget: Gtk.Widget, event: Gdk.EventButton ) -> bool: """The context menu label was clicked""" menu = self._setup_menu(True) menu.set_screen(self._window.get_screen()) # pylint: disable=no-member menu.popup(None, None, None, None, event.button, event.time) return True def _on_button_enter( self, widget: Gtk.Widget, event: Gdk.EventCrossing, button: Gtk.Widget, udata: str, ) -> None: """Pointer enters context menu button""" button.set_markup(f"{udata}") def _on_button_leave( self, widget: Gtk.Widget, event: Gdk.EventCrossing, button: Gtk.Widget, udata: str, ) -> None: """Pointer leaves context menu button""" button.set_markup(udata) def _on_popup_menu( self, status_icon: Gtk.StatusIcon, button: int, activate_time: float, menu: Gtk.Menu, ) -> None: """When the StatusIcon is right-clicked.""" menu.popup( None, None, Gtk.StatusIcon.position_menu, status_icon, button, activate_time, ) def _on_launch_action(self, sender: ty.Any, *_args: ty.Any) -> None: """Callback for launch-action event: hide window. Separate window hide from the action being done. This is to solve a window focus bug when we switch windows using an action. """ self._interface.did_launch() self._window_hide_timer.set_ms(100, self.put_away) def _on_command_result( self, sender: DataController, result_type: int, ui_ctx: uievents.GUIEnvironmentContext, ) -> None: """Callback for command-result event: update window.""" result_type = commandexec.ExecResult(result_type) # handle "refresh" result if result_type == commandexec.ExecResult.REFRESH: self.output_debug("refresh leaves list") self._interface.reset_current() self._interface.did_launch() return self._interface.did_get_result() if ui_ctx: self._on_present( sender, ui_ctx.get_display(), ui_ctx.get_timestamp() ) else: self._on_present(sender, "", Gtk.get_current_event_time()) def _on_lost_focus( self, window: Gtk.Window, event: Gdk.EventFocus ) -> None: """Hide window on lost focus.""" if not kupfer.config.has_capability("HIDE_ON_FOCUS_OUT"): return # Close at unfocus. # Since focus-out-event is triggered even when we click inside the # window, we'll do some additional math to make sure that # that window won't close if the mouse pointer is over it. _gdkwindow, x, y, _mods = ( window.get_screen().get_root_window().get_pointer() ) w_x, w_y = window.get_position() w_w, w_h = window.get_size() if not (w_x <= x <= w_x + w_w and w_y <= y <= w_y + w_h): self._window_hide_timer.set_ms(50, self.put_away) def _on_monitors_changed(self, *_ignored: ty.Any) -> None: """Center window on monitor changed.""" self._center_window() def _window_put_on_screen(self, screen: Gdk.Screen) -> None: """Move window to `screen`.""" if self._current_screen_handler: scr = self._window.get_screen() # pylint: disable=no-member scr.disconnect(self._current_screen_handler) self._window.set_screen(screen) # pylint: disable=no-member self._current_screen_handler = screen.connect( "monitors-changed", self._on_monitors_changed ) def _center_window(self, displayname: str | None = None) -> None: """Center Window on the monitor the pointer is currently on""" # pylint: disable=no-member if not displayname and self._window.has_screen(): display = self._window.get_display() else: display = uievents.GUIEnvironmentContext.ensure_display_open( displayname ) screen, x, y, _mod = display.get_pointer() self._window_put_on_screen(screen) monitor_nr = screen.get_monitor_at_point(x, y) geo = screen.get_monitor_geometry(monitor_nr) wid, hei = self._window.get_size() midx = geo.x + geo.width / 2 - wid / 2 midy = geo.y + geo.height / 2 - hei / 2 self._window.move(midx, midy) uievents.try_close_unused_displays(screen) def _should_recenter_window(self) -> bool: """Return True if the mouse pointer and the window are on different monitors.""" # Check if the GtkWindow was realized yet if not self._window.get_realized(): return True # pylint: disable=no-member display = self._window.get_screen().get_display() screen, x, y, _modifiers = display.get_pointer() mon_cur = screen.get_monitor_at_point(x, y) mon_win = screen.get_monitor_at_window(self._window.get_window()) return mon_cur != mon_win # type: ignore def _on_activate(self, sender: ty.Any = None) -> None: """Activate (show) main windows.""" # pylint: disable=no-member dispname = self._window.get_screen().make_display_name() self._on_present(sender, dispname, Gtk.get_current_event_time()) def _on_present( self, sender: ty.Any, display: str | None, timestamp: int ) -> None: """Present on @display, where None means default display""" self._window_hide_timer.invalidate() display = display or Gdk.Display.get_default().get_name() # Center window before first show if not self._window.get_realized(): self._center_window(display) self._window.stick() # pylint: disable=no-member self._window.present_with_time(timestamp) # pylint: disable=no-member self._window.get_window().focus(timestamp=timestamp) self._interface.focus() # Center after present if we are moving between monitors if self._should_recenter_window(): self._center_window(display) def put_away(self) -> None: """Hide main window.""" self._interface.put_away() self._window.hide() def _on_cancelled(self, _obj: Interface) -> None: self.put_away() def _on_show_hide( self, sender: ty.Any, display: str, timestamp: int ) -> None: """Toggle activate/put-away.""" if self._window.get_property("visible"): self.put_away() else: self._on_present(sender, display, timestamp) # refresh current match (if has qf_id) self._interface.re_search_kpfer() def _on_statusicon_activate(self, sender: Gtk.StatusIcon) -> None: """GtkStatusIcon callback""" self._on_show_hide(sender, "", Gtk.get_current_event_time()) def _on_key_binding( self, keyobj: keybindings.KeyboundObject, keybinding_number: int, display: str, timestamp: int, ) -> None: """Keybinding activation callback""" if keybinding_number == keybindings.KEYBINDING_TARGET_DEFAULT: self._on_show_hide(keyobj, display, timestamp) elif keybinding_number == keybindings.KEYBINDING_TARGET_MAGIC: self._on_present(keyobj, display, timestamp) self._interface.select_selected_text() self._interface.select_selected_file() def _on_drag_data_received( self, widget: Gtk.Widget, context: ty.Any, x: int, y: int, data_: Gtk.SelectionData, info: ty.Any, time: int, ) -> None: if uris := data_.get_uris(): self._interface.put_files(uris, paths=False) else: self._interface.put_text(data_.get_text()) def _on_put_text( self, sender: Gtk.Widget, text: str, display: str, timestamp: int ) -> None: """We got a search text from dbus""" self._on_present(sender, display, timestamp) self._interface.put_text(text) def _on_put_files( self, sender: ty.Any, fileuris: ty.Iterable[str], display: str, timestamp: int, ) -> None: self._on_present(sender, display, timestamp) self._interface.put_files(fileuris, paths=True) def _on_find_object( self, sender: ty.Any, qpfer: str, display: str, timestamp: int ) -> None: self._on_present(sender, display, timestamp) self._interface.find_object(qpfer) def _on_execute_file( self, sender: ty.Any, filepath: str, display: str, timestamp: int, ) -> None: self._interface.execute_file(filepath, display, timestamp) def _on_close_window(self, window: Gtk.Widget, event: ty.Any) -> bool: """Callback for main window delete-event.""" self.put_away() return True def _on_sigterm(self, signal_: int, _frame: ty.Any) -> None: self.output_info("Caught signal", signal_, "exiting..") self._on_quit() def _on_early_interrupt(self, _signal: int, _frame: ty.Any) -> None: sys.exit(1) def save_data(self) -> None: """Save state before quit""" sch = scheduler.get_scheduler() sch.finish() self._interface.save_config() def _on_quit(self, sender: Gtk.Widget | None = None) -> None: Gtk.main_quit() def _quit_now(self) -> None: """Quit immediately (state save should already be done)""" raise SystemExit def _on_session_save(self, *_args: ty.Any) -> bool: """Old-style session save callback. Return True on successful.""" # No quit, only save self.output_info("Saving for logout...") self.save_data() return True def _on_session_die(self, *_args: ty.Any) -> None: """Session callback on session end: quit now, without saving, since we already do that on Session save! """ self._quit_now() def _lazy_setup(self, activate: bool = False) -> None: """Do all setup that can be done after showing main interface. Connect to desktop services (keybinding callback, session logout callbacks etc). When `activate`, call _on_activate at the end (show main window). """ # pylint: disable=import-outside-toplevel from kupfer.ui import session self.output_debug("in lazy_setup") setctl = settings.get_settings_controller() if setctl.get_show_status_icon(): self._show_statusicon() if setctl.get_show_status_icon_ai(): self._show_statusicon_ai() setctl.connect( "value-changed::kupfer.showstatusicon", self._on_showstatusicon_changed, ) setctl.connect( "value-changed::kupfer.showstatusicon_ai", self._showstatusicon_ai_changed, ) if keystr := setctl.get_keybinding(): succ = keybindings.bind_key(keystr) self.output_info( f"Trying to register {keystr} to spawn kupfer.. " + ("success" if succ else "failed") ) if magickeystr := setctl.get_magic_keybinding(): succ = keybindings.bind_key( magickeystr, keybindings.KEYBINDING_TARGET_MAGIC ) self.output_debug( f"Trying to register {magickeystr} to spawn kupfer.. " + ("success" if succ else "failed") ) keyobj = keybindings.get_keybound_object() keyobj.connect("keybinding", self._on_key_binding) client = session.SessionClient() client.connect("save-yourself", self._on_session_save) client.connect("die", self._on_session_die) self._interface.lazy_setup() if activate: self._on_activate() self.output_debug("finished lazy_setup") def main(self, quiet: bool = False) -> None: """Start WindowController, present its window (if not @quiet)""" signal.signal(signal.SIGINT, self._on_early_interrupt) kserv1 = None kserv2 = None try: # NOTE: For a *very short* time we will use both APIs TODO: off one kserv1 = listen.Service() kserv2 = listen.ServiceNew() except listen.AlreadyRunningError: self.output_info("An instance is already running, exiting...") self._quit_now() except listen.NoConnectionError: pass if kserv1: keyobj = keybindings.get_keybound_object() keyobj.connect( "bound-key-changed", lambda _x, y, z: kserv1.BoundKeyChanged(y, z), ) kserv1.connect("relay-keys", keyobj.relayed_keys) # Load data data_controller = DataController.instance() sch = scheduler.get_scheduler() sch.load() # Now create UI and display self._initialize(data_controller) sch.display() for kserv in (kserv1, kserv2): if kserv: kserv.connect("present", self._on_present) kserv.connect("show-hide", self._on_show_hide) kserv.connect("put-text", self._on_put_text) kserv.connect("put-files", self._on_put_files) kserv.connect("find-object", self._on_find_object) kserv.connect("execute-file", self._on_execute_file) kserv.connect("quit", self._on_quit) GLib.idle_add(self._lazy_setup, not quiet) def do_main_iterations(max_events=0): # use sentinel form of iter for idx, _pending in enumerate(iter(Gtk.events_pending, False)): if max_events and idx > max_events: break Gtk.main_iteration() try: Gtk.main() # put away window *before exiting further* self.put_away() do_main_iterations(10) finally: self.save_data() # tear down but keep hanging for kserv in (kserv1, kserv2): if kserv: kserv.unregister() keybindings.bind_key(None, keybindings.KEYBINDING_TARGET_DEFAULT) keybindings.bind_key(None, keybindings.KEYBINDING_TARGET_MAGIC) do_main_iterations(100) # if we are still waiting, print a message if Gtk.events_pending(): self.output_info("Waiting for tasks to finish...") do_main_iterations() kupfer-328/kupfer/ui/credentials_dialog.py000066400000000000000000000042721500175051100207630ustar00rootroot00000000000000from __future__ import annotations from gi.repository import Gtk from kupfer import config, version class _CredentialsDialogController: def __init__( self, username: str | None, password: str | None, infotext: str | None = None, ): """Load ui from data file""" builder = Gtk.Builder() builder.set_translation_domain(version.PACKAGE_NAME) ui_file = config.get_data_file("credentials_dialog.ui") builder.add_from_file(ui_file) builder.connect_signals(self) # pylint: disable=no-member self.window = builder.get_object("credentials_dialog") self.entry_user = builder.get_object("entry_username") self.entry_pass = builder.get_object("entry_password") if infotext: hbox_information = builder.get_object("hbox_information") label_information = builder.get_object("label_information") label_information.set_text(infotext) hbox_information.show() self.entry_user.set_text(username or "") self.entry_pass.set_text(password or "") def on_button_ok_clicked(self, widget: Gtk.Widget) -> None: self.window.response(Gtk.ResponseType.ACCEPT) self.window.hide() def on_button_cancel_clicked(self, widget: Gtk.Widget) -> None: self.window.response(Gtk.ResponseType.CANCEL) self.window.hide() def show(self) -> bool: return self.window.run() # type: ignore @property def username(self) -> str: return self.entry_user.get_text() # type:ignore @property def password(self) -> str: return self.entry_pass.get_text() # type:ignore def ask_user_credentials( user: str | None = None, password: str | None = None, infotext: str | None = None, ) -> tuple[str, str] | None: """Ask user for username and password. @user, @password - initial values @return: (user, password) when user press "change" None when user press "cancel" button""" dialog = _CredentialsDialogController(user, password, infotext) result = None if dialog.show() == Gtk.ResponseType.ACCEPT: result = dialog.username, dialog.password return result kupfer-328/kupfer/ui/getdata_dialog.py000066400000000000000000000055471500175051100201050ustar00rootroot00000000000000from __future__ import annotations from gi.repository import Gdk, Gtk from kupfer import config, version __all__ = ["GetDataDialog", "ask_for_text"] class GetDataDialog: def __init__( self, title: str, message: str = "", screen: Gdk.Screen | None = None, parent: Gtk.Window | None = None, ): """ screen: Screen to use parent: Parent toplevel window """ builder = Gtk.Builder() builder.set_translation_domain(version.PACKAGE_NAME) builder.add_from_file(config.get_data_file("getdata_dialog.ui")) builder.connect_signals(self) # pylint: disable=no-member self.window = builder.get_object("dialoggetdata") self._box_fields = builder.get_object("box_fields") builder.get_object("label_title").set_text(title) if message: builder.get_object("label_message").set_text(message) else: builder.get_object("label_message").hide() if screen: self.window.set_screen(screen) if parent: self.window.set_transient_for(parent) self._text = None self._fields: dict[str, Gtk.Widget] = {} self._result: dict[str, str] | None = None def add_field(self, name: str, label: str, value: str) -> None: """Add text entry to dialog with `label` and `value`. `name` is internal name of value returned by dialog.""" row = len(self._fields) wlabel = Gtk.Label() wlabel.set_alignment(0, 0.5) # pylint: disable=no-member wlabel.set_markup(label) wlabel.set_selectable(False) self._box_fields.attach(wlabel, 0, row, 1, 1) widget = Gtk.Entry() widget.set_text(value) widget.set_hexpand(True) widget.set_activates_default(True) self._box_fields.attach(widget, 1, row, 1, 1) self._fields[name] = widget def run(self) -> dict[str, str] | None: """Run dialog, return key codes or None when user press cancel""" self._box_fields.show_all() self.window.set_keep_above(True) self.window.run() self.window.destroy() return self._result def on_buttonok_activate(self, _widget: Gtk.Widget) -> bool: self._result = {n: w.get_text() for n, w in self._fields.items()} self.window.hide() return True def on_buttonclose_activate(self, _widget: Gtk.Widget) -> bool: self.window.hide() return True def ask_for_text( title: str, message: str, label: str = "", value: str = "", screen: Gdk.Screen | None = None, parent: Gtk.Window | None = None, ) -> str | None: dlg = GetDataDialog( title, message, screen=screen, parent=parent, ) dlg.add_field("text", label, value) res = dlg.run() return res["text"] if res else None kupfer-328/kupfer/ui/getkey_dialog.py000066400000000000000000000126551500175051100177620ustar00rootroot00000000000000from __future__ import annotations import typing as ty from gi.repository import Gdk, Gtk from kupfer import config, version CheckCallback = ty.Callable[[str], bool] class _GetKeyDialogController: """Get Key for binding dialog controller.""" def __init__( self, check_callback: CheckCallback | None = None, previous_key: str | None = None, screen: Gdk.Screen | None = None, parent: Gtk.Window | None = None, show_clear: bool = True, ): """ check_callback: optional function to check is entered key is valid. previous_key - optional previous keybinding, press equal act like cancel screen: Screen to use parent: Parent toplevel window show_clear: Show the “clear” button """ builder = Gtk.Builder() builder.set_translation_domain(version.PACKAGE_NAME) builder.add_from_file(config.get_data_file("getkey_dialog.ui")) builder.connect_signals(self) # pylint: disable=no-member self.window = builder.get_object("dialoggetkey") # self.labelkey = builder.get_object("labelkey") self.imagekeybindingaux = builder.get_object("imagekeybindingaux") self.labelkeybindingaux = builder.get_object("labelkeybindingaux") self.labelaccelerator = builder.get_object("labelaccelerator") if not show_clear: buttonclear = builder.get_object("buttonclear") buttonclear.hide() self.imagekeybindingaux.hide() self.labelkeybindingaux.hide() self._key: str | None = None self._check_callback = check_callback self._previous_key = previous_key self._press_time = None if screen: self.window.set_screen(screen) if parent: self.window.set_transient_for(parent) self.window.connect("focus-in-event", self._on_window_focus_in) self.window.connect("focus-out-event", self._on_window_focus_out) def run(self) -> str | None: """Run dialog, return key codes or None when user press cancel""" self.window.set_keep_above(True) self.window.run() self.window.destroy() return self._key def _return(self, key: str | None) -> None: "Finish dialog with @key as result" self._key = key self.window.hide() def on_buttoncancel_activate(self, _widget: Gtk.Widget) -> bool: self._return_cancel() return True def on_buttonclear_activate(self, _widget: Gtk.Widget) -> bool: self._return_clear() return True def _return_cancel(self) -> None: self._return(None) def _return_clear(self) -> None: self._return("") def _translate_keyboard_event( self, widget: Gtk.Widget, event: Gdk.EventKey ) -> tuple[int, int]: keymap = Gdk.Keymap.get_for_display(widget.get_display()) # translate keys properly ( _wasmapped, keyval, _egroup, _level, consumed, ) = keymap.translate_keyboard_state( event.hardware_keycode, event.get_state(), event.group ) modifiers = Gtk.accelerator_get_default_mod_mask() & ~consumed state = event.get_state() & modifiers return keyval, state def _update_accelerator_label(self, keyval: int, state: int) -> None: accel_label = Gtk.accelerator_get_label(keyval, state) self.labelaccelerator.set_text(accel_label) def on_dialoggetkey_key_press_event( self, widget: Gtk.Widget, event: Gdk.EventKey ) -> None: self.imagekeybindingaux.hide() self.labelkeybindingaux.hide() self._press_time = event.time keyval, state = self._translate_keyboard_event(widget, event) state = Gdk.ModifierType(state) keyname = Gtk.accelerator_name(keyval, state) if keyname == "Escape": self._return_cancel() elif keyname == "BackSpace": self._return_clear() self._update_accelerator_label(keyval, state) def on_dialoggetkey_key_release_event( self, widget: Gtk.Widget, event: Gdk.EventKey ) -> None: if not self._press_time: return keyval, state = self._translate_keyboard_event(widget, event) self._update_accelerator_label(0, 0) state = Gdk.ModifierType(state) if Gtk.accelerator_valid(keyval, state): key = Gtk.accelerator_name(keyval, state) if self._previous_key is not None and key == self._previous_key: self._return_cancel() return if self._check_callback is None or self._check_callback(key): self._return(key) else: self.imagekeybindingaux.show() self.labelkeybindingaux.show() def _on_window_focus_in( self, _window: Gtk.Window, _event: Gdk.EventFocus ) -> None: pass def _on_window_focus_out( self, _window: Gtk.Window, _event: Gdk.EventFocus ) -> None: pass def ask_for_key( check_callback: CheckCallback | None = None, previous_key: str | None = None, screen: Gdk.Screen | None = None, parent: Gtk.Window | None = None, show_clear: bool = True, ) -> str | None: dlg = _GetKeyDialogController( check_callback, previous_key, screen=screen, parent=parent, show_clear=show_clear, ) return dlg.run() kupfer-328/kupfer/ui/interface.py000066400000000000000000001265121500175051100171110ustar00rootroot00000000000000#! /usr/bin/env python3 """ UI Interface controller """ from __future__ import annotations import functools import textwrap import typing as ty from gi.repository import Gdk, Gio, GObject, Gtk from kupfer import interface from kupfer.core import actionaccel, settings from kupfer.core.datactrl import DataController, PaneMode, PaneSel from kupfer.obj import Action, AnySource, FileLeaf, Leaf from kupfer.support import pretty, scheduler from kupfer.ui import ( accelerators, getkey_dialog, kupferhelp, preferences, uievents, uiutils, ) from kupfer.ui._support import escape_markup_str, text_direction_is_ltr from kupfer.ui.search import ActionSearch, LeafSearch, Search, State if ty.TYPE_CHECKING: from gettext import gettext as _ from kupfer.core.search import Rankable _SLOW_INPUT_INTERVAL: ty.Final = 2 _KEY_PRESS_INTERVAL: ty.Final = 0.3 _KEY_PRESS_REPEAT_THRESHOLD: ty.Final = 0.02 # accelerator is any function with no parameters; result is ignored AccelFunc = ty.Callable[[], ty.Any] # pylint: disable=too-few-public-methods @ty.runtime_checkable class KeyCallback(ty.Protocol): """Key press callback interface.""" def __call__(self, shift_mask: int, mod_mask: int, /) -> bool: ... _MAX_STRING_LEN: ty.Final[int] = 27 def _trunc_long_str(instr: ty.Any) -> str: "truncate long object names" ustr = str(instr) return ( ustr[: _MAX_STRING_LEN - 2] + "…" if len(ustr) > _MAX_STRING_LEN else ustr ) def _get_accel(key: str, acf: AccelFunc) -> tuple[str, AccelFunc]: """Return name, method pair for @key""" if name := accelerators.ACCELERATOR_NAMES.get(key): return name, acf raise RuntimeError(f"Missing accelerator: {key}") def _translate_keys(event: Gdk.EventKey) -> tuple[int, int, bool]: event_state = event.get_state() # translate keys properly ( _was_bound, keyv, _egroup, _level, consumed, ) = Gdk.Keymap.get_default().translate_keyboard_state( event.hardware_keycode, event_state, event.group ) all_modifiers = Gtk.accelerator_get_default_mod_mask() shift_mask = (event_state & all_modifiers) == Gdk.ModifierType.SHIFT_MASK event_state &= all_modifiers & ~consumed return event_state, keyv, shift_mask # pylint: disable=too-many-public-methods,too-many-instance-attributes class Interface(GObject.GObject, pretty.OutputMixin): # type:ignore """Controller object that controls the input and the state (current active) search object/widget. Signals: * cancelled: def callback(controller) escape was typed NOTE: some methods are get by getattr and call! """ __gtype_name__ = "Interface" def __init__(self, controller: DataController, window: Gtk.Window) -> None: """ @controller: DataController @window: toplevel window """ GObject.GObject.__init__(self) self.search = LeafSearch() self.search.set_name("kupfer-object-pane") self.action = ActionSearch() self.action.set_name("kupfer-action-pane") self.third = LeafSearch() self.third.set_name("kupfer-indirect-object-pane") self.current: Search | None = None self._widget: Gtk.Widget | None = None self._ui_transition_timer = scheduler.Timer() self._panel_two_is_visible = True self._pane_three_is_visible = False self._is_text_mode = False self._latest_input_timer = scheduler.Timer() self._reset_to_toplevel = False self._reset_when_back = False self._preedit_text = "" self._create_widgets(window) self._data_ctrl = controller self._data_ctrl.connect("search-result", self._on_search_result) self._data_ctrl.connect("source-changed", self._on_source_changed) self._data_ctrl.connect("pane-reset", self._on_pane_reset) self._data_ctrl.connect("mode-changed", self._on_mode_changed) self._data_ctrl.connect( "object-stack-changed", self._on_object_stack_changed ) # Setup keyval mapping self._prepare_key_book() self._action_accel_config = actionaccel.AccelConfig() self.search.reset() def _create_widgets(self, window: Gtk.Window) -> None: setctl = settings.get_settings_controller() self._entry = Gtk.Entry() self._preedit = Gtk.Entry() ## make sure we lose the preedit focus ring self._preedit.set_name("kupfer-preedit") self._preedit.set_has_frame(False) self._preedit.set_width_chars(0) self._preedit.set_alignment(1) self._label = Gtk.Label() self._label.set_width_chars(50) self._label.set_max_width_chars(50) self._label.set_single_line_mode(True) self._label.set_ellipsize(setctl.get_ellipsize_mode()) self._label.set_name("kupfer-description") self._switch_to_source_init() self._entry.connect("realize", self._on_entry_realized) self._entry.connect("changed", self._on_entry_changed) self._preedit.connect("insert-text", self._on_preedit_insert_text) self._preedit.connect("draw", self._on_preedit_draw) self._preedit.connect("preedit-changed", self._on_preedit_im_changed) for widget in (self._entry, self._preedit): widget.connect("activate", self._on_activate, None) widget.connect("key-press-event", self._on_entry_key_press) widget.connect("key-release-event", self._on_entry_key_release) widget.connect("copy-clipboard", self._on_entry_copy_clipboard) widget.connect("cut-clipboard", self._on_entry_cut_clipboard) widget.connect("paste-clipboard", self._on_entry_paste_clipboard) # set up panewidget => self signals # as well as window => panewidgets for widget_owner in (self.search, self.action, self.third): widget = widget_owner.widget() widget_owner.connect("activate", self._on_activate) widget_owner.connect("cursor-changed", self._on_selection_changed) widget.connect("button-press-event", self._on_pane_button_press) # window signals window.connect("configure-event", widget_owner.window_config) window.connect("hide", widget_owner.window_hidden) def _prepare_key_book(self) -> None: keys = ( "Up", "Down", "Right", "Left", "Tab", "ISO_Left_Tab", "BackSpace", "Escape", "Delete", "space", "Page_Up", "Page_Down", "Home", "End", "Return", ) self._key_book = key_book = {k: Gdk.keyval_from_name(k) for k in keys} if not text_direction_is_ltr(): # for RTL languages, simply swap the meaning of Left and Right # (for keybindings!) key_book["Left"], key_book["Right"] = ( key_book["Right"], key_book["Left"], ) self._key_book_cbs: dict[int, KeyCallback] = { key_book["Escape"]: self._on_escape_key_press, key_book["Up"]: self._on_up_key_press, key_book["Page_Up"]: self._on_page_up_key_press, key_book["Down"]: self._on_down_key_press, key_book["Page_Down"]: self._on_page_down_key_press, key_book["Right"]: self._on_right_key_press, key_book["BackSpace"]: self._on_backspace_key_press, key_book["Left"]: self._on_back_key_press, key_book["Tab"]: functools.partial( self._on_tab_key_press, reverse=False ), key_book["ISO_Left_Tab"]: functools.partial( self._on_tab_key_press, reverse=True ), key_book["Home"]: self._on_home_key_press, } def get_widget(self) -> Gtk.Widget: """Return a Widget containing the whole Interface. Create if not exist.""" if self._widget: return self._widget box = Gtk.HBox() box.pack_start(self.search.widget(), True, True, 3) box.pack_start(self.action.widget(), True, True, 3) box.pack_start(self.third.widget(), True, True, 3) vbox = Gtk.VBox() vbox.pack_start(box, True, True, 0) label_align = Gtk.Alignment.new(0.5, 1, 0, 0) label_align.set_property("top-padding", 3) label_align.add(self._label) vbox.pack_start(label_align, False, False, 0) vbox.pack_start(self._entry, False, False, 0) vbox.show_all() self.third.hide() self._widget = vbox return vbox def lazy_setup(self) -> None: def validate(keystr): keyv, mod = Gtk.accelerator_parse(keystr) return ( mod == 0 and keyv != 0 and Gtk.accelerator_valid( keyv, Gdk.ModifierType.MOD1_MASK, # pylint: disable=no-member ) ) self._action_accel_config.load(validate) self.action.action_accel_config = self._action_accel_config self.action.lazy_setup() self.output_debug("Finished lazy_setup") def save_config(self) -> None: self._action_accel_config.store() self.output_debug("Finished save_config") def _on_entry_realized(self, widget: Gtk.Widget) -> None: self._update_text_mode() def _on_entry_key_release(self, entry, event): return def _process_accels(self, keyv: int, event_state: int) -> bool: setctl = settings.get_settings_controller() # process accelerators for action, accel in setctl.get_accelerators().items(): akeyv, amodf = Gtk.accelerator_parse(accel) if akeyv and akeyv == keyv and amodf == event_state: if action_method := getattr(self, action, None): action_method() else: pretty.print_error(__name__, f"Action invalid '{action}'") return True # look for action accelerators if event_state == self.action.accel_modifier: keystr = Gtk.accelerator_name(keyv, 0) if self._action_accelerator(keystr): return True return False def _on_entry_key_press( # noqa: PLR0911 self, entry: Gtk.Entry, event: Gdk.EventKey ) -> bool: """Intercept arrow keys and manipulate table without losing focus from entry field.""" assert self.current is not None direct_text_key: int = Gdk.keyval_from_name("period") init_text_keys = list( map(Gdk.keyval_from_name, ("slash", "equal", "question")) ) init_text_keys.append(direct_text_key) # translate keys properly event_state, keyv, shift_mask = _translate_keys(event) self._reset_input_timer() # process accelerators if self._process_accels(keyv, event_state): return True if self._preedit_text: return False key_book = self._key_book use_command_keys = ( settings.get_settings_controller().get_use_command_keys() ) has_selection = self.current.get_match_state() == State.MATCH if not self._is_text_mode and use_command_keys: # translate extra commands to normal commands here # and remember skipped chars if keyv == key_book["space"]: keyv = key_book["Up" if shift_mask else "Down"] elif keyv == ord("/") and has_selection: keyv = key_book["Right"] elif keyv == ord(",") and has_selection: if self.comma_trick(): return True elif keyv in init_text_keys and self._try_enable_text_mode(): # swallow if it is the direct key return keyv == direct_text_key if self._is_text_mode and keyv in ( key_book["Left"], key_book["Right"], key_book["Home"], key_book["End"], ): # pass these through in text mode # except on → at the end of the input cursor_position = self._entry.get_property("cursor-position") if ( keyv != key_book["Right"] or cursor_position == 0 or cursor_position != self._entry.get_text_length() ): return False if key_cb := self._key_book_cbs.get(keyv): self._reset_to_toplevel = False # pylint: disable=no-member return key_cb( shift_mask, event_state == Gdk.ModifierType.MOD1_MASK ) return False def _on_entry_copy_clipboard(self, entry: Gtk.Entry) -> bool: """Copy current selection to clipboard. Delegate to text entry when in text mode.""" if self._is_text_mode or not self.current: return False if selection := self.current.get_current(): clip = Gtk.Clipboard.get_for_display( entry.get_display(), Gdk.SELECTION_CLIPBOARD ) return interface.copy_to_clipboard(selection, clip) return False def _on_entry_cut_clipboard(self, entry: Gtk.Entry) -> bool: if self._on_entry_copy_clipboard(entry): self.reset_current() self._reset() return False def _entry_paste_data_received( self, clipboard: Gtk.Clipboard, targets: ty.Iterable[str], _extra: ty.Any, entry: Gtk.Widget, ) -> None: uri_target = Gdk.Atom.intern("text/uri-list", False) ### check if we can insert files if uri_target in targets: # paste as files sdata = clipboard.wait_for_contents(uri_target) self.reset_current() self._reset() self.put_files(sdata.get_uris(), paths=False) ## done else: # enable text mode and reemit to paste text self._try_enable_text_mode() if self._is_text_mode: entry.emit("paste-clipboard") def _on_entry_paste_clipboard(self, entry: Gtk.Widget) -> None: if not self._is_text_mode: self._reset() ## when not in text mode, ## stop signal emission so we can handle it clipboard = Gtk.Clipboard.get_for_display( entry.get_display(), Gdk.SELECTION_CLIPBOARD ) clipboard.request_targets(self._entry_paste_data_received, entry) entry.emit_stop_by_name("paste-clipboard") def _reset_text(self) -> None: """Reset text in entry.""" self._entry.set_text("") def _reset(self) -> None: """Reset text and hide table.""" self._reset_text() if self.current: self.current.hide_table() def reset_current(self, populate: bool = False) -> None: """Reset the source or action view. Corresponds to backspace. """ assert self.current if self.current.get_match_state() is State.WAIT: self._toggle_text_mode(False) if self.current is self.action or populate: self._populate_search() else: self.current.reset() def reset_all(self) -> None: """Reset all panes and focus the first. This is accelerator handler.""" self.switch_to_source() while self._browse_up(): pass self._toggle_text_mode(False) self._data_ctrl.object_stack_clear_all() self.reset_current() self._reset() def _populate_search(self) -> None: """Do a blanket search/empty search to populate current pane""" pane = self._pane_for_widget(self.current) self._data_ctrl.search(pane, interactive=True) def soft_reset(self, pane: PaneSel | None = None) -> None: """Reset `pane` or current pane context/source softly (without visible update), and unset _reset_to_toplevel marker. """ pane = pane or self._pane_for_widget(self.current) if newsrc := self._data_ctrl.soft_reset(pane): assert self.current self.current.set_source(newsrc) self._reset_to_toplevel = False def _delete_from_stack(self) -> None: """Delete item from stack; related do backspace key press.""" pane = self._pane_for_widget(self.current) if self._data_ctrl.get_object_stack(pane): self._data_ctrl.object_stack_pop(pane) self._reset_text() return self._on_back_key_press() def _relax_search_terms(self) -> None: if self._is_text_mode: return assert self.current self._reset_text() self.current.relax_match() def _get_can_enter_text_mode(self) -> bool: """We can enter text mode if the data backend allows, and the text entry is ready for input (empty) """ pane = self._pane_for_widget(self.current) val = self._data_ctrl.get_can_enter_text_mode(pane) entry_text = self._entry.get_text() return val and not entry_text def _try_enable_text_mode(self) -> bool: """Perform a soft reset if possible and then try enabling text mode""" if self._reset_to_toplevel: self.soft_reset() if self._get_can_enter_text_mode(): return self._toggle_text_mode(True) return False def _toggle_text_mode(self, val: bool) -> bool: """Toggle text mode on/off per @val, and return the subsequent on/off state. """ val = val and self._get_can_enter_text_mode() self._is_text_mode = val self._update_text_mode() self._reset() return val def toggle_text_mode_quick(self) -> None: """Toggle text mode or not, if we can or not, without reset. NOTE: accelerator """ self._is_text_mode = not self._is_text_mode if self._is_text_mode and self.current: self.current.hide_table() self._update_text_mode() def _disable_text_mode_quick(self) -> None: """Toggle text mode or not, if we can or not, without reset""" if self._is_text_mode: self._is_text_mode = False self._update_text_mode() def _update_text_mode(self) -> None: """update appearance to whether text mode enabled or not""" if self._is_text_mode: self._entry.show() self._entry.grab_focus() self._entry.set_position(-1) self._preedit.hide() self._preedit.set_width_chars(0) else: self._entry.hide() self._update_active() def _switch_to_source_init(self) -> None: """Initial switch to source.""" self.current = self.search self._update_active() if self._is_text_mode: self.toggle_text_mode_quick() def switch_to_source(self) -> None: """Switch to first (leaves) pane. NOTE: accelerator """ self._switch_current_to(0) def switch_to_2(self) -> None: """Switch to second (action) pane. NOTE: accelerator """ self._switch_current_to(1) def switch_to_3(self) -> None: """Switch to third (leaves) pane. NOTE: accelerator """ self._switch_current_to(2) def focus(self) -> None: """Called when the interface is focus (after being away).""" if self._reset_when_back: self._reset_when_back = False self._toggle_text_mode(False) # preserve text mode, but switch to source if we are not in it if not self._is_text_mode: self.switch_to_source() # Check that items are still valid when "coming back" self._data_ctrl.validate() def did_launch(self) -> None: """Called to notify that 'activate' was successful. Request reset on get focus again.""" self._reset_when_back = True def did_get_result(self) -> None: """called when a command result has come in.""" self._reset_when_back = False def put_away(self) -> None: """Called when the interface is hidden""" self._relax_search_terms() self._reset_to_toplevel = True # no hide / show pane three on put away -> focus anymore def select_selected_file(self) -> None: """Find & select selected file in browser. Note: accelerator. """ # Add optional lookup data to narrow the search self._data_ctrl.find_object("qpfer:selectedfile#any.FileLeaf") def select_clipboard_file(self) -> None: """Find & select leaf representing file in clipboard. Note: accelerator. """ # Add optional lookup data to narrow the search self._data_ctrl.find_object("qpfer:clipboardfile#any.FileLeaf") def select_selected_text(self) -> None: """Find & select leaf representing selected text. Note: accelerator. """ self._data_ctrl.find_object("qpfer:selectedtext#any.TextLeaf") def select_clipboard_text(self) -> None: """Find & select leaf representing text in clipboard. Note: accelerator. """ # Add optional lookup data to narrow the search self._data_ctrl.find_object("qpfer:clipboardtext#any.TextLeaf") def select_quit(self) -> None: """Find & select quit leaf. Note: accelerator. """ self._data_ctrl.reset() self._data_ctrl.find_object("qpfer:quit") def show_help(self) -> None: """Show help. Note: accelerator. """ kupferhelp.show_help(self._make_gui_ctx()) self.emit("launched-action") def show_preferences(self) -> None: """Show preferences window. Note: accelerator. """ self._data_ctrl.reset() preferences.show_preferences(self._make_gui_ctx()) self.emit("launched-action") def compose_action(self) -> None: """Compose action from current stack. NOTE: accelerator """ self._data_ctrl.compose_selection() def mark_as_default(self) -> bool: """Mark current action as default for selected leaf. NOTE: accelerator """ if self.action.get_match_state() != State.MATCH: return False self._data_ctrl.mark_as_default(PaneSel.ACTION) return True def erase_affinity_for_first_pane(self) -> bool: """ NOTE: accelerator """ if self.search.get_match_state() != State.MATCH: return False self._data_ctrl.erase_object_affinity(PaneSel.SOURCE) return True def comma_trick(self) -> bool: """Comma trick - add current leaf to stack. NOTE: accelerator """ assert self.current if self.current.get_match_state() != State.MATCH: return False cur = self.current.get_current() curpane = self._pane_for_widget(self.current) if cur and self._data_ctrl.object_stack_push(curpane, cur): self._relax_search_terms() if self._is_text_mode: self._reset_text() return True return False def _action_accelerator(self, keystr: str) -> bool: """Find & launch accelerator action for `keystr` accelerator name.. Return False if it was not possible to handle or the action was not used, return True if it was acted upon """ if self.search.get_match_state() != State.MATCH: return False self.output_debug("Looking for action accelerator for", keystr) success, activate = self.action.select_action_by_accel(keystr) if success: if activate: self._disable_text_mode_quick() self.activate() else: self.switch_to_3() else: self.output_debug("No action found for", keystr) return False return True def _assign_action_accelerator(self) -> None: if self.action.get_match_state() != State.MATCH: raise RuntimeError("No Action Selected") def is_good_keystr(k: str) -> bool: keyv, mods = Gtk.accelerator_parse(k) return keyv != 0 and mods in (0, self.action.accel_modifier) widget = self.get_widget() keystr = getkey_dialog.ask_for_key( is_good_keystr, screen=widget.get_screen(), parent=widget.get_toplevel(), ) if keystr is None: # Was cancelled return action = self.action.get_current() # Remove the modifiers keyv, _mods = Gtk.accelerator_parse(keystr) keystr = Gtk.accelerator_name(keyv, 0) assert keystr self._action_accel_config.set(action, keystr) def get_context_actions(self) -> ty.Iterable[tuple[str, AccelFunc]]: """Get a list of (name, function) currently active context actions.""" assert self.current has_match = self.current.get_match_state() == State.MATCH if has_match: yield _get_accel("compose_action", self.compose_action) yield _get_accel("select_selected_text", self.select_selected_text) if self._get_can_enter_text_mode(): yield _get_accel( "toggle_text_mode_quick", self.toggle_text_mode_quick ) if self.action.get_match_state() == State.MATCH: smatch = self.search.get_current() amatch = self.action.get_current() label = _('Assign Accelerator to "%(action)s"') % { "action": _trunc_long_str(amatch) } w_label = textwrap.wrap(label, width=40, subsequent_indent=" ") yield ("\n".join(w_label), self._assign_action_accelerator) label = _('Make "%(action)s" Default for "%(object)s"') % { "action": _trunc_long_str(amatch), "object": _trunc_long_str(smatch), } w_label = textwrap.wrap(label, width=40, subsequent_indent=" ") yield ("\n".join(w_label), self.mark_as_default) if has_match: if self._data_ctrl.get_object_has_affinity(PaneSel.SOURCE): # TRANS: Removing learned and/or configured bonus search score yield ( _('Forget About "%s"') % _trunc_long_str(self.search.get_current()), self.erase_affinity_for_first_pane, ) yield _get_accel("reset_all", self.reset_all) def _on_pane_reset( self, _controller: ty.Any, pane: int, # real PaneSel, item: Rankable | None, ) -> None: pane = PaneSel(pane) wid = self._widget_for_pane(pane) if not item: wid.reset() return wid.set_match_plain(item) if wid is self.search: self._reset() self._toggle_text_mode(False) self.switch_to_source() def _on_source_changed( self, _sender: ty.Any, pane: int, # real PaneSel, source: AnySource, at_root: bool, select: ty.Any, ) -> None: """Notification about a new data source, (represented object for the `self.search object`.""" pane = PaneSel(pane) wid = self._widget_for_pane(pane) wid.set_source(source) wid.reset() if pane == PaneSel.SOURCE: self.switch_to_source() self.action.reset() if wid is self.current: self._toggle_text_mode(False) self._reset_to_toplevel = False # when `select` try to show selected item even on root if not at_root or select: self.reset_current(populate=True) wid.show_table_quirk() if select: wid.set_match_leaf(select) def update_third(self) -> None: """Show or hide third panel according to _pane_three_is_visible state.""" if self._pane_three_is_visible: self._ui_transition_timer.set_ms(200, self._show_third_pane, True) else: self._show_third_pane(False) def _on_mode_changed( self, _ctr: ty.Any, mode: int, _ignored: ty.Any ) -> None: """Show / hide third panel on mode changed.""" if mode == PaneMode.SOURCE_ACTION_OBJECT: # use a delay before showing the third pane, # but set internal variable to "shown" already now self._pane_three_is_visible = True self._show_second_pane(True) self._ui_transition_timer.set_ms(200, self._show_third_pane, True) elif mode == PaneMode.ACTION_OBJECT: self._pane_three_is_visible = True self._show_second_pane(False) self._ui_transition_timer.set_ms(200, self._show_third_pane, True) else: self._pane_three_is_visible = False self._show_second_pane(True) self._show_third_pane(False) def _show_second_pane(self, show: bool) -> None: """Set visibility of second panel to `show`.""" self._panel_two_is_visible = show self.action.set_visible(show) def _show_third_pane(self, show: bool) -> None: """Set visibility of third panel to `show`.""" self._ui_transition_timer.invalidate() self.third.set_visible(show) def _update_active(self) -> None: for panewidget in (self.action, self.search, self.third): if panewidget is not self.current: panewidget.set_state(Gtk.StateType.NORMAL) panewidget.match_view.inject_preedit(None) assert self.current if self._is_text_mode: # or self._key_repeat_active: self.current.set_state(Gtk.StateType.ACTIVE) else: self.current.set_state(Gtk.StateType.SELECTED) self.current.match_view.inject_preedit(self._preedit) self._description_changed() def _switch_current(self, reverse: bool = False) -> None: # Only allow switch if we have match if self._pane_three_is_visible: curidx = self._pane_for_widget(self.current).value - 1 newidx = (curidx - 1 if reverse else curidx + 1) % 3 else: # for 2 panels simple switch to other one newidx = 0 if self.current == self.action else 1 self._switch_current_to(newidx) def _switch_current_to(self, index: int) -> bool: """Switch selected pane. index: index (0, 1, or 2) of the pane to select. In ACTION_OBJECT mode second panel is hidden. """ order: ( tuple[LeafSearch, ActionSearch, LeafSearch] | tuple[LeafSearch, ActionSearch] | tuple[LeafSearch, LeafSearch] ) if not self._panel_two_is_visible: order = (self.search, self.third) elif self._pane_three_is_visible: order = (self.search, self.action, self.third) else: order = (self.search, self.action) if not (0 <= index <= len(order)): return False pane_before = order[max(index - 1, 0)] new_focus = order[index] no_match_ok = index == 0 # Only allow switch if we have match in the pane before if ( self.current and (no_match_ok or pane_before.get_match_state() is State.MATCH) and new_focus is not self.current ): self.current.hide_table() self.current = new_focus # Use toggle_text_mode to reset self._toggle_text_mode(False) pane = self._pane_for_widget(new_focus) self._update_active() if self._data_ctrl.get_should_enter_text_mode(pane): self.toggle_text_mode_quick() return True def _browse_up(self) -> bool: pane = self._pane_for_widget(self.current) return self._data_ctrl.browse_up(pane) def _browse_down(self, alternate: bool = False) -> None: pane = self._pane_for_widget(self.current) self._data_ctrl.browse_down(pane, alternate=alternate) def _make_gui_ctx(self) -> uievents.GUIEnvironmentContext: event_time = Gtk.get_current_event_time() return uievents.gui_context_from_widget(event_time, self._widget) def _on_activate(self, _pane_owner: ty.Any, _current: ty.Any) -> None: self._data_ctrl.activate(ui_ctx=self._make_gui_ctx()) def activate(self) -> None: """Activate current selection (Run action). NOTE: accelerator """ self._on_activate(None, None) def execute_file( self, filepath: str, display: str, event_time: int, ) -> None: """Execute a .kfcom file""" def _handle_error(exc_info): _etype, exc, _tb = exc_info if not uiutils.show_notification(str(exc), icon_name="kupfer"): raise exc ctxenv = uievents.gui_context_from_keyevent(event_time, display) self._data_ctrl.execute_file(filepath, ctxenv, _handle_error) def _on_search_result( self, _sender: ty.Any, pane: int, # real PaneSel matchrankable: Rankable | None, matches: ty.Iterable[Rankable], key: str | None, ) -> None: pane = PaneSel(pane) # NOTE: "Always-matching" search. # If we receive an empty match, we ignore it, to retain the previous # results. The user is not served by being met by empty results. if key and len(key) > 1 and matchrankable is None: # with typos or so, reset quicker self._latest_input_timer.set( _SLOW_INPUT_INTERVAL / 2, self._relax_search_terms ) return wid = self._widget_for_pane(pane) wid.update_match(key, matchrankable, matches) def _widget_for_pane(self, pane: PaneSel) -> Search: # we have only 3 panels, so this is better than lookup in dict if pane == PaneSel.SOURCE: return self.search if pane == PaneSel.ACTION: return self.action if pane == PaneSel.OBJECT: return self.third raise ValueError(f"invalid pane value {pane}") def _pane_for_widget(self, widget: GObject.GObject) -> PaneSel: # we have only 3 panels, so this is better than lookup in dict if widget == self.search: return PaneSel.SOURCE if widget == self.action: return PaneSel.ACTION if widget == self.third: return PaneSel.OBJECT raise ValueError("invalid widget") def _on_object_stack_changed( self, controller: DataController, pane: int, # real PaneSel ) -> None: """Stack of objects (for comma trick) changed in @pane.""" pane = PaneSel(pane) wid = self._widget_for_pane(pane) wid.set_object_stack(controller.get_object_stack(pane)) def _on_pane_button_press( self, widget: Gtk.Widget, event: Gdk.EventButton ) -> bool: """mouse clicked on a pane widget - activate it.""" # activate on double-click # pylint: disable=no-member,protected-access if event.type == Gdk.EventType._2BUTTON_PRESS: # noqa:SLF001 self.activate() return True return False def _on_selection_changed( self, pane_owner: Search, match: Leaf | Action | None ) -> None: pane = self._pane_for_widget(pane_owner) self._data_ctrl.select(pane, match) if pane_owner is not self.current: return self._description_changed() def _description_changed(self) -> None: assert self.current match = self.current.get_current() if desc := match and match.get_description(): desc = escape_markup_str(desc) self._label.set_tooltip_markup(desc) self._label.set_has_tooltip(True) # show only first line of description first_line = desc.split("\n", 1)[0] self._label.set_markup(f"{first_line}") else: # Use invisible WORD JOINER instead of empty, to maintain vertical size self._label.set_markup("\N{WORD JOINER}") self._label.set_has_tooltip(False) def put_text(self, text: str) -> None: """Put @text into the interface to search, to use for "queries" from other sources.""" self._try_enable_text_mode() self._entry.set_text(text) self._entry.set_position(-1) def put_files(self, fileuris: ty.Iterable[str], paths: bool) -> None: # don't consume iterable # self.output_debug("put-files:", list(fileuris)) if paths: objs = (Gio.File.new_for_path(U).get_path() for U in fileuris) else: objs = (Gio.File.new_for_uri(U).get_path() for U in fileuris) if leaves := list(map(FileLeaf, filter(None, objs))): self._data_ctrl.insert_objects( PaneSel.SOURCE, ty.cast("list[Leaf]", leaves) ) def _reset_input_timer(self) -> None: # if input is slow/new, we reset self._latest_input_timer.set( _SLOW_INPUT_INTERVAL, self._relax_search_terms ) def _on_preedit_im_changed( self, _editable: ty.Any, preedit_string: str ) -> None: """This is called whenever the input method changes its own preedit box. We take this opportunity to expand it.""" if preedit_string: assert self.current self.current.match_view.expand_preedit(self._preedit) self._reset_input_timer() self._preedit_text = preedit_string def _on_preedit_insert_text( self, editable: Gtk.Entry, text: str, byte_length: int, position: int ) -> bool: # New text about to be inserted in preedit if text: self._entry.insert_text(text, -1) self._entry.set_position(-1) self._reset_input_timer() self._update_active() GObject.signal_stop_emission_by_name(editable, "insert-text") return False def _on_preedit_draw(self, widget: Gtk.Widget, _cr: ty.Any) -> bool: # draw nothing if hidden return widget.get_width_chars() == 0 # type: ignore def _on_entry_changed(self, editable: Gtk.Entry) -> None: """The entry changed callback. if text is blank, start search. Otherwise cancel search.""" text = editable.get_text() # draw character count as icon editable.set_icon_from_pixbuf(Gtk.EntryIconPosition.SECONDARY, None) # cancel search and return if empty if not text: self._data_ctrl.cancel_search() # See if it was a deleting key press curr_evt = Gtk.get_current_event() if ( curr_evt and curr_evt.type == Gdk.EventType.KEY_PRESS and curr_evt.keyval in (self._key_book["Delete"], self._key_book["BackSpace"]) ): self._delete_from_stack() return # start search for updated query pane = self._pane_for_widget(self.current) if not self._is_text_mode and self._reset_to_toplevel: self.soft_reset(pane) self._data_ctrl.search( pane, key=text, context=text, text_mode=self._is_text_mode ) def _on_up_key_press(self, shift_mask: int, mod_mask: int) -> bool: assert self.current self.current.go_up() return True def _on_down_key_press(self, shift_mask: int, mod_mask: int) -> bool: assert self.current if shift_mask and self.current == self.search: self.current.hide_table() self._switch_current() if ( not self.current.get_current() and self.current.get_match_state() is State.WAIT ): self._populate_search() self.current.go_down() return True def _on_page_up_key_press(self, shift_mask: int, mod_mask: int) -> bool: assert self.current self.current.go_page_up() return True def _on_page_down_key_press(self, shift_mask: int, mod_mask: int) -> bool: assert self.current if ( not self.current.get_current() and self.current.get_match_state() is State.WAIT ): self._populate_search() self.current.go_page_down() return True def _on_right_key_press(self, shift_mask: int, mod_mask: int) -> bool: # MOD1_MASK is alt/option self._browse_down(alternate=bool(mod_mask)) return True def _on_backspace_key_press(self, shift_mask: int, mod_mask: int) -> bool: if not self._entry.get_text(): # not has_input self._delete_from_stack() elif not self._is_text_mode: self._entry.delete_text(self._entry.get_text_length() - 1, -1) else: return False return True def _on_tab_key_press( self, shift_mask: int, mod_mask: int, reverse: bool ) -> bool: self._switch_current(reverse=reverse) return True def _on_home_key_press(self, shift_mask: int, mod_mask: int) -> bool: assert self.current self.current.go_first() return True def _on_back_key_press( self, shift_mask: int = 0, mod_mask: int = 0 ) -> bool: # leftarrow (or backspace without object stack) # delete/go up through stource stack assert self.current if self.current.is_showing_result(): self.reset_current(populate=True) elif not self._browse_up(): self._reset() self.reset_current() self._reset_to_toplevel = True self._reset_text() return True def _on_escape_key_press(self, shift_mask: int, mod_mask: int) -> bool: """Handle escape if first pane is reset, cancel (put away) self.""" assert self.current if self.current.has_result(): if self.current.is_showing_result(): self.reset_current(populate=True) else: self.reset_current() else: if self._is_text_mode: self._toggle_text_mode(False) elif not self.current.get_table_visible(): pane = self._pane_for_widget(self.current) self._data_ctrl.object_stack_clear(pane) self.emit("cancelled") self._reset_to_toplevel = True self.current.hide_table() self._reset_text() return True def re_search_kpfer(self) -> None: """Try to re-search current selected KupferObject if it has qf_id. For leaves like selected text this update leaf to current selected not previously selected.""" if (obj := self.search.get_current()) and ( qf_id := getattr(obj, "qf_id", None) ): pretty.print_debug(__name__, f"re-search qpfer '{qf_id}'") self._data_ctrl.find_object(f"qpfer:{qf_id}") def find_object(self, qpfer: str) -> None: self._data_ctrl.find_object(qpfer) GObject.type_register(Interface) GObject.signal_new( "cancelled", Interface, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (), ) # Send only when the interface itself launched an action directly GObject.signal_new( "launched-action", Interface, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (), ) kupfer-328/kupfer/ui/keybindings.py000066400000000000000000000115041500175051100174510ustar00rootroot00000000000000from __future__ import annotations import typing as ty import gi from gi.repository import GObject from kupfer import environment from kupfer.support import pretty Keybinder: ty.Any = None # pylint: disable=invalid-name if environment.allows_keybinder(): try: gi.require_version("Keybinder", "3.0") # pylint: disable=ungrouped-imports from gi.repository import Keybinder # type:ignore Keybinder.init() except (ValueError, ImportError): pretty.print_debug(__name__, "Keybinder 3.0 not available in gi") Keybinder = None else: pretty.print_debug(__name__, "Keybinder disabled") KeybindingTarget = int KEYBINDING_TARGET_DEFAULT = 1 KEYBINDING_TARGET_MAGIC = 2 KEYRANGE_RESERVED = (3, 0x1000) # range for custom keybingings KEYRANGE_TRIGGERS = (0x1000, 0x2000) def get_keybound_object(): """Get the shared instance""" return KeyboundObject.instance() class KeyboundObject(GObject.GObject): # type:ignore """Keybinder object signals: keybinding (target, event_time) keybinding signal is triggered when the key bound for @target is triggered. """ __gtype_name__ = "KeyboundObject" _instance: KeyboundObject | None = None @classmethod def instance(cls) -> KeyboundObject: if cls._instance is None: cls._instance = KeyboundObject() return cls._instance def keybinding(self, target: int) -> None: assert Keybinder time = Keybinder.get_current_event_time() self.emit("keybinding", target, "", time) def emit_bound_key_changed(self, keystring: str, is_bound: bool) -> None: self.emit("bound-key-changed", keystring, is_bound) def relayed_keys( self, _sender: ty.Any, keystring: str, display: str, timestamp: float, ) -> None: for target, key in _CURRENTLY_BOUND.items(): if keystring == key: self.emit("keybinding", target, display, timestamp) # Arguments: Target, Display, Timestamp GObject.signal_new( "keybinding", KeyboundObject, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_INT, GObject.TYPE_STRING, GObject.TYPE_UINT), ) # Arguments: Keystring, Boolean GObject.signal_new( "bound-key-changed", KeyboundObject, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, ( GObject.TYPE_STRING, GObject.TYPE_BOOLEAN, ), ) _CURRENTLY_BOUND: dict[int, str | None] = {} def is_available(): """Return True if keybindings are available.""" if Keybinder is None: return False try: return Keybinder.supported() except AttributeError: return True def get_all_bound_keys() -> list[str]: """Return all currently bounded keys.""" return list(filter(None, _CURRENTLY_BOUND.values())) def get_current_event_time() -> int: "Return current event time as given by keybinder" if Keybinder is None: return 0 return int(Keybinder.get_current_event_time()) def _register_bound_key(keystr: str | None, target: int) -> None: _CURRENTLY_BOUND[target] = keystr def _get_currently_bound_key( target: KeybindingTarget = KEYBINDING_TARGET_DEFAULT, ) -> str | None: return _CURRENTLY_BOUND.get(target) def bind_key( keystr: str | None, keybinding_target: KeybindingTarget = KEYBINDING_TARGET_DEFAULT, ) -> bool: """Bind @keystr, unbinding any previous key for @keybinding_target. If @keystr is a false value, any previous key will be unbound.""" if Keybinder is None: return False if not _is_sane_keybinding(keystr): pretty.print_error(__name__, "Refusing to bind key", repr(keystr)) return False succ = True if keystr: def callback(keystr: str) -> bool: get_keybound_object().keybinding(keybinding_target) return False try: succ = Keybinder.bind(keystr, callback) pretty.print_debug(__name__, "binding", repr(keystr)) get_keybound_object().emit_bound_key_changed(keystr, True) except KeyError as exc: pretty.print_error(__name__, exc) succ = False if succ: old_keystr = _get_currently_bound_key(keybinding_target) if old_keystr and old_keystr != keystr: Keybinder.unbind(old_keystr) pretty.print_debug(__name__, "unbinding", repr(old_keystr)) get_keybound_object().emit_bound_key_changed(old_keystr, False) _register_bound_key(keystr, keybinding_target) return succ def _is_sane_keybinding(keystr: str | None) -> bool: """Refuse keys that we absolutely do not want to bind""" if keystr is None: return True if len(keystr) == 1 and keystr.isalnum(): return False return keystr not in ("Return", "space", "BackSpace", "Escape") kupfer-328/kupfer/ui/kupferhelp.py000066400000000000000000000007071500175051100173130ustar00rootroot00000000000000#! /usr/bin/env python3 """ Show application help. """ from __future__ import annotations import typing as ty from kupfer import launch, version if ty.TYPE_CHECKING: from kupfer.ui.uievents import GUIEnvironmentContext def show_help(ctxenv: GUIEnvironmentContext | None = None) -> None: """Show Kupfer help pages, if possible""" if not launch.show_help_url(f"help:{version.PACKAGE_NAME}"): launch.show_url(version.HELP_WEBSITE) kupfer-328/kupfer/ui/listen.py000066400000000000000000000272001500175051100164410ustar00rootroot00000000000000# pylint: disable=invalid-name # ruff: noqa: N802 """ This module has a singleton Service for dbus callbacks, and ensures there is only one unique service in the Session """ from __future__ import annotations import typing as ty from gi.repository import GObject try: import dbus from dbus.mainloop.glib import DBusGMainLoop DBusGMainLoop(set_as_default=True) import dbus.service from dbus.gi_service import ExportedGObject dbus.mainloop.glib.threads_init() # if dbus unavailable print the exception here # but further actions (register) will fail without warning _SESSION_BUS = dbus.Bus() except (ImportError, dbus.exceptions.DBusException) as exc: _SESSION_BUS = None print(exc) from kupfer.ui import uievents class AlreadyRunningError(Exception): """Service already available on the bus Exception""" class NoConnectionError(Exception): """Not possible to establish connection for callbacks""" _SERVER_NAME: ty.Final = "se.kaizer.kupfer" _INTERFACE_NAME: ty.Final = "se.kaizer.kupfer.Listener" _OBJECT_NAME: ty.Final = "/interface" _SERVER_NAME_NEW: ty.Final = "io.github.kupferlauncher" _INTERFACE_NAME_NEW: ty.Final = "io.github.kupferlauncher.Listener" _OBJECT_NAME_NEW: ty.Final = "/io/github/kupferlauncher" class Service(ExportedGObject): # type:ignore def __init__(self): """Create a new Kupfer service on the Session Bus Raises NoConnectionError, AlreadyRunningError """ if not _SESSION_BUS: raise NoConnectionError if _SESSION_BUS.name_has_owner(_SERVER_NAME): raise AlreadyRunningError bus_name = dbus.service.BusName(_SERVER_NAME, bus=_SESSION_BUS) super().__init__( conn=_SESSION_BUS, object_path=_OBJECT_NAME, bus_name=bus_name ) def unregister(self): if _SESSION_BUS: _SESSION_BUS.release_name(_SERVER_NAME) @dbus.service.method(_INTERFACE_NAME) def Present(self): self.PresentOnDisplay("", "") @dbus.service.method(_INTERFACE_NAME, in_signature="ay", byte_arrays=True) def PresentWithStartup(self, notify_id): self.PresentOnDisplay("", notify_id) @dbus.service.method( _INTERFACE_NAME, in_signature="ayay", byte_arrays=True ) def PresentOnDisplay(self, display, notify_id): with uievents.using_startup_notify_id(notify_id) as time: self.emit("present", display, time) @dbus.service.method(_INTERFACE_NAME) def ShowHide(self): self.emit("show-hide", "", 0) @dbus.service.method(_INTERFACE_NAME, in_signature="s") def PutText(self, text): self.PutTextOnDisplay(text, "", "") @dbus.service.method( _INTERFACE_NAME, in_signature="sayay", byte_arrays=True ) def PutTextOnDisplay(self, text, display, notify_id): with uievents.using_startup_notify_id(notify_id) as time: self.emit("put-text", text, display, time) @dbus.service.method(_INTERFACE_NAME, in_signature="as") def PutFiles(self, fileuris): self.PutFilesOnDisplay(fileuris, "", "") @dbus.service.method( _INTERFACE_NAME, in_signature="asayay", byte_arrays=True ) def PutFilesOnDisplay(self, fileuris, display, notify_id): # files sent with dbus-send from kupfer have a custom comma # escape that we have to unescape here fileuris[:] = [f.replace("%%kupfercomma%%", ",") for f in fileuris] with uievents.using_startup_notify_id(notify_id) as time: self.emit("put-files", fileuris, display, time) @dbus.service.method(_INTERFACE_NAME, in_signature="s") def FindObject(self, qpfer): self.FindObjectOnDisplay(qpfer, "", "") @dbus.service.method(_INTERFACE_NAME, in_signature="sss") def FindObjectOnDisplay(self, qpfer, display, notify_id): with uievents.using_startup_notify_id(notify_id) as time: self.emit("find-object", qpfer, display, time) @dbus.service.method(_INTERFACE_NAME, in_signature="s") def ExecuteFile(self, filepath): self.ExecuteFileOnDisplay(filepath, "", "") @dbus.service.method( _INTERFACE_NAME, in_signature="sayay", byte_arrays=True ) def ExecuteFileOnDisplay(self, filepath, display, notify_id): with uievents.using_startup_notify_id(notify_id) as time: self.emit("execute-file", filepath, display, time) @dbus.service.method( _INTERFACE_NAME, in_signature="sayay", byte_arrays=True ) def RelayKeysFromDisplay(self, keystring, display, notify_id): with uievents.using_startup_notify_id(notify_id) as time: self.emit("relay-keys", keystring, display, time) @dbus.service.method( _INTERFACE_NAME, in_signature=None, out_signature="as", byte_arrays=True, ) def GetBoundKeys(self): # pylint: disable=import-outside-toplevel from kupfer.ui import keybindings return keybindings.get_all_bound_keys() @dbus.service.signal(_INTERFACE_NAME, signature="sb") def BoundKeyChanged(self, keystr, is_bound): pass @dbus.service.method(_INTERFACE_NAME) def Quit(self): self.emit("quit") # Signature: displayname, timestamp GObject.signal_new( "present", Service, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_STRING, GObject.TYPE_UINT), ) # Signature: displayname, timestamp GObject.signal_new( "show-hide", Service, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_STRING, GObject.TYPE_UINT), ) # Signature: text, displayname, timestamp GObject.signal_new( "put-text", Service, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_UINT), ) # Signature: filearray, displayname, timestamp GObject.signal_new( "put-files", Service, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_PYOBJECT, GObject.TYPE_STRING, GObject.TYPE_UINT), ) # Signature: string, displayname, timestamp GObject.signal_new( "find-object", Service, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_UINT), ) # Signature: fileuri, displayname, timestamp GObject.signal_new( "execute-file", Service, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_UINT), ) # Signature: () GObject.signal_new( "quit", Service, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, () ) # Signature: keystring, displayname, timestamp GObject.signal_new( "relay-keys", Service, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_UINT), ) class ServiceNew(ExportedGObject): # type: ignore def __init__(self): """Create a new Kupfer service on the Session Bus Raises NoConnectionError, AlreadyRunningError """ if not _SESSION_BUS: raise NoConnectionError if _SESSION_BUS.name_has_owner(_SERVER_NAME_NEW): raise AlreadyRunningError bus_name = dbus.service.BusName(_SERVER_NAME_NEW, bus=_SESSION_BUS) super().__init__( conn=_SESSION_BUS, object_path=_OBJECT_NAME_NEW, bus_name=bus_name ) def unregister(self): if _SESSION_BUS: _SESSION_BUS.release_name(_SERVER_NAME) @dbus.service.method(_INTERFACE_NAME_NEW) def Present(self): self.PresentOnDisplay("", "") @dbus.service.method(_INTERFACE_NAME_NEW, in_signature="ss") def PresentOnDisplay(self, display, notify_id): with uievents.using_startup_notify_id(notify_id) as time: self.emit("present", display, time) @dbus.service.method(_INTERFACE_NAME_NEW) def ShowHide(self): self.ShowHideOnDisplay("", "") @dbus.service.method(_INTERFACE_NAME_NEW, in_signature="ss") def ShowHideOnDisplay(self, display, notify_id): with uievents.using_startup_notify_id(notify_id) as time: self.emit("show-hide", display, time) @dbus.service.method(_INTERFACE_NAME_NEW, in_signature="s") def PutText(self, text): self.PutTextOnDisplay(text, "", "") @dbus.service.method(_INTERFACE_NAME_NEW, in_signature="sss") def PutTextOnDisplay(self, text, display, notify_id): with uievents.using_startup_notify_id(notify_id) as time: self.emit("put-text", text, display, time) @dbus.service.method(_INTERFACE_NAME_NEW, in_signature="as") def PutFiles(self, fileuris): self.PutFilesOnDisplay(fileuris, "", "") @dbus.service.method(_INTERFACE_NAME_NEW, in_signature="asss") def PutFilesOnDisplay(self, fileuris, display, notify_id): # files sent with dbus-send from kupfer have a custom comma # escape that we have to unescape here fileuris[:] = [f.replace("%%kupfercomma%%", ",") for f in fileuris] with uievents.using_startup_notify_id(notify_id) as time: self.emit("put-files", fileuris, display, time) @dbus.service.method(_INTERFACE_NAME_NEW, in_signature="s") def FindObject(self, qpfer): self.FindObjectOnDisplay(qpfer, "", "") @dbus.service.method(_INTERFACE_NAME_NEW, in_signature="sss") def FindObjectOnDisplay(self, qpfer, display, notify_id): with uievents.using_startup_notify_id(notify_id) as time: self.emit("find-object", qpfer, display, time) @dbus.service.method(_INTERFACE_NAME_NEW, in_signature="s") def ExecuteFile(self, filepath): self.ExecuteFileOnDisplay(filepath, "", "") @dbus.service.method(_INTERFACE_NAME_NEW, in_signature="sss") def ExecuteFileOnDisplay(self, filepath, display, notify_id): with uievents.using_startup_notify_id(notify_id) as time: self.emit("execute-file", filepath, display, time) @dbus.service.method(_INTERFACE_NAME_NEW) def Quit(self): self.emit("quit") # Signature: displayname, timestamp GObject.signal_new( "present", ServiceNew, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_STRING, GObject.TYPE_UINT), ) # Signature: displayname, timestamp GObject.signal_new( "show-hide", ServiceNew, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_STRING, GObject.TYPE_UINT), ) # Signature: text, displayname, timestamp GObject.signal_new( "put-text", ServiceNew, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_UINT), ) # Signature: filearray, displayname, timestamp GObject.signal_new( "put-files", ServiceNew, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_PYOBJECT, GObject.TYPE_STRING, GObject.TYPE_UINT), ) # Signature: string, displayname, timestamp GObject.signal_new( "find-object", ServiceNew, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_UINT), ) # Signature: fileuri, displayname, timestamp GObject.signal_new( "execute-file", ServiceNew, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_UINT), ) # Signature: () GObject.signal_new( "quit", ServiceNew, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, () ) # Note ServiceNew has the same signals, but doesn't actually implement them # all (yet). Needs new design for wayland keyrelay. # Signature: keystring, displayname, timestamp GObject.signal_new( "relay-keys", ServiceNew, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_UINT), ) kupfer-328/kupfer/ui/preferences.py000066400000000000000000001413201500175051100174440ustar00rootroot00000000000000from __future__ import annotations import operator import os import typing as ty from contextlib import suppress from pathlib import Path import gi from gi.repository import Gdk, Gio, GLib, GObject, Gtk, Pango from xdg import BaseDirectory as xdgBase from xdg import DesktopEntry from xdg import Exceptions as xdgExc from kupfer import config, icons, launch, plugin_support, version from kupfer.core import plugins, relevance, settings, sources from kupfer.support import kupferstring, pretty, scheduler from kupfer.ui import _widgets as widgets from kupfer.ui import accelerators, getkey_dialog, keybindings, kupferhelp from kupfer.ui.credentials_dialog import ask_user_credentials if ty.TYPE_CHECKING: from gettext import gettext as _ from kupfer.ui.uievents import GUIEnvironmentContext # index in GtkNotebook _PLUGIN_LIST_PAGE: ty.Final = 2 # List icon pixel size _LIST_ICON_SIZE: ty.Final = 18 _KEYBINDING_TARGETS: ty.Final[dict[str, int]] = { "keybinding": keybindings.KEYBINDING_TARGET_DEFAULT, "magickeybinding": keybindings.KEYBINDING_TARGET_MAGIC, } _KUPFER_DESKTOP: ty.Final = "kupfer.desktop" _AUTOSTART_KEY: ty.Final = "X-GNOME-Autostart-enabled" _HIDDEN_KEY: ty.Final = "Hidden" def _set_combobox(value: ty.Any, combobox: Gtk.ComboBoxText) -> None: """Set activate the alternative in the combobox with text value.""" value = str(value) col = combobox.get_entry_text_column() for row in combobox.get_model(): if row[col] == value: combobox.set_active_iter(row.iter) return def _set_combobox_id(id_: ty.Any, combobox: Gtk.ComboBox) -> None: """Set activate the alternative in the combobox with id.""" if id_: combobox.set_active_id(str(id_)) def _make_combobox_model(combobox: Gtk.ComboBox) -> None: # List store with columns (Name, ID) combobox_store = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING) combobox.set_model(combobox_store) combobox_cell = Gtk.CellRendererText() combobox.pack_start(combobox_cell, True) combobox.add_attribute(combobox_cell, "text", 0) def _create_plugin_change_cb( plugin_id: str, key: str, value_type: ty.Type[ty.Any], get_attr: str, no_false_values: bool = False, ) -> ty.Callable[[Gtk.Widget], None]: """Callback factory for the plugin parameter configuration. Callback load value from widget calling `get_attr` method and update setting in SettingsController. When `no_false_values`, ignore empty/0 values. """ def callback(widget: Gtk.Widget) -> None: value = getattr(widget, get_attr)() if no_false_values and not value: return setctl = settings.get_settings_controller() setctl.set_plugin_config(plugin_id, key, value, value_type) return callback def _create_plugin_credentials_cb( plugin_id: str, key: str ) -> ty.Callable[[Gtk.Widget], None]: """Create callback for credentials widget.""" # TODO: check, not used / not working probably def callback(widget): setctl = settings.get_settings_controller() val_type = plugin_support.UserNamePassword # pylint: disable=no-member backend_name = ( plugin_support.UserNamePassword.get_backend_name() # type:ignore ) assert backend_name # pylint: disable=no-member if ( plugin_support.UserNamePassword.is_backend_encrypted() # type:ignore ): information = ( _("Using encrypted password storage: %s") % backend_name ) else: information = _("Using password storage: %s") % backend_name upass = ( setctl.get_plugin_config(plugin_id, key, val_type) or plugin_support.UserNamePassword() ) # pylint: disable=no-member user_password = ask_user_credentials( upass.username, upass.password, information, ) if user_password: # pylint: disable=no-member upass.username, upass.password = user_password # type:ignore # TODO: fix setctl.set_plugin_config( plugin_id, key, upass, # type:ignore val_type, ) return callback def _make_plugin_sett_widget_str( plugin_id: str, setting: str, plugin_settings: plugin_support.PluginSettings, ) -> tuple[Gtk.Widget, bool]: """Create widgets for str-like plugin setting. Usually this setting is simple Entry, but this may be changed by parameters: - alternatives: create combobox - multiline: create TextView - helper (choose_directory, choose_file): text + buttons for select directory/file. Returns: (widget, ). Information about size of widget is used to better place of label. """ wid = None multiline = False if alternatives := plugin_settings.get_alternatives(setting): wid = _make_plugin_sett_widget_combo( plugin_id, setting, plugin_settings, alternatives ) elif plugin_settings.get_parameter(setting, "multiline"): wid = _make_plugin_sett_widget_multiline( plugin_id, setting, plugin_settings ) multiline = True elif helper := plugin_settings.get_parameter(setting, "helper"): if helper in ("choose_directory", "choose_file"): wid = widgets.FileDirSelectWidget( plugin_id, setting, plugin_settings, helper ) multiline = True else: pretty.print_error("unknown helper", helper) if not wid: wid = Gtk.Entry() wid.set_text(plugin_settings[setting]) wid.set_hexpand(True) wid.set_size_request(100, 10) wid.connect( "changed", _create_plugin_change_cb( plugin_id, setting, str, "get_text", no_false_values=True, ), ) return wid, multiline def _make_plugin_sett_widget_combo( plugin_id: str, setting: str, plugin_settings: plugin_support.PluginSettings, alternatives: ty.Iterable[str], ) -> Gtk.Widget: """Create combobox widget for str-like plugin settings with alternatives.""" wid = Gtk.ComboBoxText.new() wid.set_vexpand(False) val = plugin_settings[setting] active_index = -1 for idx, text in enumerate(alternatives): id_ = text if isinstance(text, (tuple, list)): id_, text = text # noqa: PLW2901 wid.append(id=id_, text=text) if id_ == val: active_index = idx if active_index < 0: wid.prepend_text(val) active_index = 0 wid.set_active(active_index) wid.connect( "changed", _create_plugin_change_cb(plugin_id, setting, str, "get_active_id"), ) return wid def _make_plugin_sett_widget_multiline( plugin_id: str, setting: str, plugin_settings: plugin_support.PluginSettings, ) -> Gtk.Widget: """Create widget for str-like plugin settings with multiline enabled.""" wid = Gtk.ScrolledWindow() wid.set_shadow_type(type=Gtk.ShadowType.IN) # pylint: disable=no-member wid.set_hexpand(True) # wid.set_vexpand(True) wid.set_size_request(50, 75) tview = Gtk.TextView() tview.set_border_width(6) # pylint: disable=no-member buf = tview.get_buffer() buf.set_text(plugin_settings[setting]) # we must use non-plain callback to get content of TextView. def callback(widget: Gtk.TextBuffer) -> None: start, end = buf.get_bounds() value = buf.get_text(start, end, True) setctl = settings.get_settings_controller() setctl.set_plugin_config(plugin_id, setting, value, str) buf.connect("changed", callback) wid.add(tview) # pylint: disable=no-member return wid def _make_plugin_sett_widget_bool( label: str, plugin_id: str, setting: str, plugin_settings: plugin_support.PluginSettings, ) -> Gtk.Widget: """Create combobox widget for plugin settings with type `bool`.""" wid = Gtk.CheckButton.new_with_label(label) wid.set_active(plugin_settings[setting]) wid.connect( "toggled", _create_plugin_change_cb(plugin_id, setting, bool, "get_active"), ) return wid def _make_plugin_sett_widget_int( plugin_id: str, setting: str, plugin_settings: plugin_support.PluginSettings, ) -> Gtk.Widget: """Make spinner button widget for plugin settings with type `int`.""" wid = Gtk.SpinButton() wid.set_increments(1, 1) min_val, max_val = 0, 1000 if val := plugin_settings.get_parameter(setting, "min"): min_val = int(val) if val := plugin_settings.get_parameter(setting, "max"): max_val = int(val) assert max_val > min_val wid.set_range(min_val, max_val) wid.set_value(plugin_settings[setting]) wid.set_vexpand(False) wid.connect( "changed", _create_plugin_change_cb( plugin_id, setting, int, "get_text", no_false_values=True, ), ) return wid def _make_plugin_sett_widget_list( plugin_id: str, setting: str, plugin_settings: plugin_support.PluginSettings, ) -> Gtk.Widget | None: """Create widget for list-like plugin settings.""" # TODO: plain (text) multiline helper = plugin_settings.get_parameter(setting, "helper") if helper == "choose_directory": return widgets.DirsSelectWidget(plugin_id, setting, plugin_settings) pretty.print_error("unknown helper", helper) return None def _is_good_keystr(keystr: str) -> bool: """Check is `keystr` is acceptable key for global keybindings.""" # Reject single letters so you can't bind 'A' etc if keystr is None: return False if label := Gtk.accelerator_get_label(*Gtk.accelerator_parse(keystr)): return not (len(label) == 1 and label.isalnum()) return False def _create_conf_keys_list() -> tuple[Gtk.TreeView, Gtk.ListStore]: columns = (_("Command"), _("Shortcut"), None) column_types = (str, str, str) keybind_store = Gtk.ListStore.new(column_types) keybind_table = Gtk.TreeView.new_with_model(keybind_store) for idx, col_header in enumerate(columns): renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn(col_header, renderer, text=idx) column.set_visible(col_header is not None) keybind_table.append_column(column) keybind_table.set_property("enable-search", False) keybind_table.set_headers_visible(True) keybind_table.show() return keybind_table, keybind_store # pylint: disable=too-many-instance-attributes,too-many-public-methods class PreferencesWindowController(pretty.OutputMixin): _instance: PreferencesWindowController | None = None _col_plugin_id = 0 _col_enabled = 1 _col_icon_name = 2 _col_text = 3 @classmethod def instance(cls) -> PreferencesWindowController: if cls._instance is None: cls._instance = PreferencesWindowController() return cls._instance def __init__(self): """Load ui from data file""" builder = Gtk.Builder() builder.set_translation_domain(version.PACKAGE_NAME) self.window: Gtk.Window = None if ui_file := config.get_data_file("preferences.ui"): builder.add_from_file(ui_file) else: return self.window = builder.get_object("preferenceswindow") self.window.set_position(Gtk.WindowPosition.CENTER) self.window.connect("delete-event", self._on_wnd_delete_event) self._plugin_sidebar = builder.get_object("plugin_about_parent") self._preferences_notebook = builder.get_object("preferences_notebook") self._btn_remove_dir = builder.get_object("buttonremovedirectory") self._plugins_filter = builder.get_object("entry_plugins_filter") self._sources_list_ctrl = _SourceListController( builder.get_object("source_list_parent") ) builder.get_object("checkautostart").set_active( self._is_autostart_enabled() ) setctl = settings.get_settings_controller() _set_combobox( setctl.get_config_int("Appearance", "icon_large_size"), builder.get_object("icons_large_size"), ) _set_combobox( setctl.get_config_int("Appearance", "icon_small_size"), builder.get_object("icons_small_size"), ) builder.get_object("checkusecommandkeys").set_active( setctl.get_use_command_keys() ) builder.get_object("radio_actionaccelalt").set_active( setctl.get_action_accelerator_modifer() != "ctrl" ) builder.get_object("radio_actionaccelctrl").set_active( setctl.get_action_accelerator_modifer() == "ctrl" ) self._init_checkstatus(setctl, builder) # Make alternative comboboxes self._terminal_combobox = builder.get_object("terminal_combobox") _make_combobox_model(self._terminal_combobox) self._update_alternative_combobox("terminal", self._terminal_combobox) self._editor_combobox = builder.get_object("editor_combobox") _make_combobox_model(self._editor_combobox) self._update_alternative_combobox("editor", self._editor_combobox) self._icons_combobox = builder.get_object("icons_combobox") _make_combobox_model(self._icons_combobox) self._update_alternative_combobox( "icon_renderer", self._icons_combobox ) _set_combobox_id( setctl.get_config_int("Appearance", "ellipsize_mode"), builder.get_object("ellipsize_mode"), ) # Plugin List self._init_plugin_lists(builder.get_object("plugin_list_parent")) # Directory List self._init_indexed_folders_widgets( builder.get_object("directory_list_parent") ) self._load_indexed_folders_settings() # global keybindings list self._keybind_table, self._keybind_store = _create_conf_keys_list() builder.get_object("keybindings_list_parent").add(self._keybind_table) self._keybind_table.connect( "row-activated", self.on_keybindings_row_activate ) builder.get_object("button_reset_keys").set_sensitive( keybindings.is_available() ) self._keybind_table.set_sensitive(keybindings.is_available()) # kupfer interface (accelerators) keybindings list self._init_keybindings(builder.get_object("gkeybindings_list_parent")) self._show_keybindings(setctl) self._show_gkeybindings(setctl) # Connect to signals at the last point builder.connect_signals(self) # pylint: disable=no-member setctl.connect("alternatives-changed", self._on_alternatives_changed) def _init_checkstatus( self, setctl: settings.SettingsController, builder: Gtk.Builder ) -> None: checkstatusicon_gtk = builder.get_object("checkstatusicon_gtk") checkstatusicon_gtk.set_label( checkstatusicon_gtk.get_label() + " (GtkStatusIcon)" ) checkstatusicon_gtk.set_active(setctl.get_show_status_icon()) checkstatusicon_ai = builder.get_object("checkstatusicon_ai") checkstatusicon_ai.set_label( checkstatusicon_ai.get_label() + " (AppIndicator)" ) if _supports_app_indicator(): checkstatusicon_ai.set_active(setctl.get_show_status_icon_ai()) else: checkstatusicon_ai.set_sensitive(False) def _init_plugin_lists(self, parent: Gtk.Widget) -> None: # setup plugin list table # cols: ("plugin_id", "enabled", "icon-name", "text") self._plugins_store = Gtk.ListStore.new((str, bool, str, str)) self._plugins_table = table = Gtk.TreeView.new_with_model( self._plugins_store ) table.set_headers_visible(False) table.set_property("enable-search", False) table.connect("cursor-changed", self._on_plugins_sel_changed) table.get_selection().set_mode(Gtk.SelectionMode.BROWSE) checkcell = Gtk.CellRendererToggle() checkcol = Gtk.TreeViewColumn("item", checkcell) checkcol.add_attribute(checkcell, "active", self._col_enabled) checkcell.connect("toggled", self._on_plugin_enable_toggled) icon_cell = Gtk.CellRendererPixbuf() icon_cell.set_property("height", _LIST_ICON_SIZE) icon_cell.set_property("width", _LIST_ICON_SIZE) icon_col = Gtk.TreeViewColumn("icon", icon_cell) icon_col.add_attribute(icon_cell, "icon-name", self._col_icon_name) cell = Gtk.CellRendererText() col = Gtk.TreeViewColumn("item", cell) col.add_attribute(cell, "text", self._col_text) table.append_column(checkcol) # hide icon for now # self.table.append_column(icon_col) table.append_column(col) self.plugin_list_timer = scheduler.Timer() self.plugin_info = kupferstring.locale_sort( plugins.get_plugin_info(), key=operator.itemgetter("localized_name"), ) self._refresh_plugin_list() self.output_debug(f"Standard Plugins: {len(self._plugins_store)}") table.show() parent.add(self._plugins_table) def _init_indexed_folders_widgets(self, parent: Gtk.Widget) -> None: """Setup indexed folders list & model.""" self._indexed_folders_store = Gtk.ListStore.new([str, Gio.Icon, str]) self._indexed_folders_table = table = Gtk.TreeView.new_with_model( self._indexed_folders_store ) table.set_headers_visible(False) table.set_property("enable-search", False) table.connect("cursor-changed", self._on_indexed_folders_sel_changed) table.get_selection().set_mode(Gtk.SelectionMode.BROWSE) icon_cell = Gtk.CellRendererPixbuf() icon_col = Gtk.TreeViewColumn("icon", icon_cell) icon_col.add_attribute(icon_cell, "gicon", 1) cell = Gtk.CellRendererText() cell.set_property("ellipsize", Pango.EllipsizeMode.END) col = Gtk.TreeViewColumn("name", cell) col.add_attribute(cell, "text", 2) table.append_column(icon_col) table.append_column(col) table.show() parent.add(self._indexed_folders_table) def _init_keybindings(self, parent: Gtk.Widget) -> None: self.gkeybind_table, self.gkeybind_store = _create_conf_keys_list() parent.add(self.gkeybind_table) self.gkeybind_table.connect( "row-activated", self.on_gkeybindings_row_activate ) # Requires GTK 3.22 with suppress(AttributeError): parent.set_propagate_natural_height(True) def _show_keybindings(self, setctl: settings.SettingsController) -> None: names = ( # TRANS: Names of global keyboard shortcuts (_("Show Main Interface"), "keybinding"), (_("Show with Selection"), "magickeybinding"), ) self._keybind_store.clear() for name, binding in sorted(names): accel = setctl.get_global_keybinding(binding) label = Gtk.accelerator_get_label(*Gtk.accelerator_parse(accel)) self._keybind_store.append((name, label, binding)) def _show_gkeybindings(self, setctl: settings.SettingsController) -> None: names = accelerators.ACCELERATOR_NAMES self.gkeybind_store.clear() for binding in sorted(names, key=lambda k: names[k]): accel = setctl.get_accelerator(binding) or "" label = Gtk.accelerator_get_label(*Gtk.accelerator_parse(accel)) self.gkeybind_store.append((names[binding], label, binding)) def _load_indexed_folders_settings(self) -> None: """Load indexed folders.""" setctl = settings.get_settings_controller() for directory in setctl.get_directories(): self._add_indexed_directory(directory, store=False) def _add_indexed_directory( self, directory: str, store: bool = False ) -> None: """Add directory to list indexed folders. When `store` update list in SettingController.""" have = [ os.path.normpath(row[0]) for row in self._indexed_folders_store ] if directory in have: self.output_debug("Ignoring duplicate directory: ", directory) return have.append(directory) directory = os.path.expanduser(directory) dispname = launch.get_display_path_for_bytestring(directory) gicon = icons.get_gicon_for_file(directory) self._indexed_folders_store.append((directory, gicon, dispname)) if store: setctl = settings.get_settings_controller() setctl.set_directories(have) def _remove_indexed_folder( self, rowiter: Gtk.TreeIter, store: bool = True ) -> None: """Remove directory from list indexed folders by `rowiter`. When `store` update list in SettingController.""" self._indexed_folders_store.remove(rowiter) if store: have = [ os.path.normpath(row[0]) for row in self._indexed_folders_store ] setctl = settings.get_settings_controller() setctl.set_directories(have) def on_preferenceswindow_key_press_event( self, widget: Gtk.Widget, event: Gdk.EventKey ) -> bool: if event.keyval == Gdk.keyval_from_name("Escape"): self._hide() return True return False def on_checkstatusicon_gtk_toggled(self, widget: Gtk.Widget) -> None: """Toggle status icon checkbox callback.""" setctl = settings.get_settings_controller() setctl.set_show_status_icon(widget.get_active()) def on_checkstatusicon_ai_toggled(self, widget: Gtk.Widget) -> None: """Toggle AppIndicator3 status icon checkbox callback.""" setctl = settings.get_settings_controller() setctl.set_show_status_icon_ai(widget.get_active()) def _is_autostart_enabled(self) -> bool: """Get state of autostart settings.""" autostart_dir = xdgBase.save_config_path("autostart") autostart_file = Path(autostart_dir, _KUPFER_DESKTOP) if not autostart_file.exists(): return False try: dfile = DesktopEntry.DesktopEntry(str(autostart_file)) except xdgExc.ParsingError as exception: pretty.print_error(__name__, exception) return False return ( dfile.hasKey(_AUTOSTART_KEY) and dfile.get(_AUTOSTART_KEY, type="boolean") ) and ( not dfile.hasKey(_HIDDEN_KEY) or not dfile.get(_HIDDEN_KEY, type="boolean") ) def on_checkautostart_toggled(self, widget: Gtk.Widget) -> None: """Change autostart settings on toggle autostart checkbox.""" autostart_dir = xdgBase.save_config_path("autostart") autostart_file = Path(autostart_dir, _KUPFER_DESKTOP) if not autostart_file.exists(): desktop_files = list( xdgBase.load_data_paths("applications", _KUPFER_DESKTOP) ) if not desktop_files: self.output_error("Installed kupfer desktop file not found!") return desktop_file_path = desktop_files[0] # Read installed file and modify it try: dfile = DesktopEntry.DesktopEntry(desktop_file_path) except xdgExc.ParsingError as exception: pretty.print_error(__name__, exception) return executable = dfile.getExec() ## append no-splash if "--no-splash" not in executable: executable += " --no-splash" dfile.set("Exec", executable) else: try: dfile = DesktopEntry.DesktopEntry(str(autostart_file)) except xdgExc.ParsingError as exception: pretty.print_error(__name__, exception) return activestr = str(bool(widget.get_active())).lower() not_activestr = str(not bool(widget.get_active())).lower() self.output_debug("Setting autostart to", activestr) dfile.set(_AUTOSTART_KEY, activestr) dfile.set(_HIDDEN_KEY, not_activestr) ## remove the format specifiers executable = dfile.getExec().replace("%F", "") dfile.set("Exec", executable) dfile.write(filename=str(autostart_file)) def on_helpbutton_clicked(self, widget: Gtk.Widget) -> None: kupferhelp.show_help() def on_closebutton_clicked(self, widget: Gtk.Widget) -> None: self._hide() def _refresh_plugin_list(self, us_filter: str | None = None) -> None: """List plugins that pass text filter @us_filter or list all if None""" self._plugins_store.clear() setctl = settings.get_settings_controller() if us_filter: self.plugin_list_timer.set_ms(300, self._show_focus_topmost_plugin) else: self.plugin_list_timer.invalidate() for info in self.plugin_info: plugin_id = info["name"] if setctl.get_plugin_is_hidden(plugin_id): continue name = info["localized_name"] if us_filter: name_score = relevance.score(name, us_filter) folded_name = kupferstring.tofolded(name) fold_name_score = relevance.score(folded_name, us_filter) desc_score = relevance.score(info["description"], us_filter) if not name_score and not fold_name_score and desc_score < 0.9: # noqa:PLR2004 continue enabled = setctl.get_plugin_enabled(plugin_id) self._plugins_store.append( (plugin_id, enabled, "kupfer-object", str(name)) ) def _show_focus_topmost_plugin(self) -> None: try: first_row = next(iter(self._plugins_store)) except StopIteration: return plugin_id = first_row[0] self.show_focus_plugin(plugin_id, 0) def _on_plugin_enable_toggled( self, cell: Gtk.CellRendererToggle, path: str ) -> None: plugin_id = self._get_plugin_id(path) pathit = self._plugins_store.get_iter(path) plugin_is_enabled = not self._plugins_store.get_value( pathit, self._col_enabled ) self._plugins_store.set_value( pathit, self._col_enabled, plugin_is_enabled ) setctl = settings.get_settings_controller() setctl.set_plugin_enabled(plugin_id, plugin_is_enabled) self._plugin_sidebar_update(plugin_id) def _get_plugin_id(self, path: str | Gtk.TreePath) -> str: """Find plugin id by tree `path`.""" pathit = self._plugins_store.get_iter(path) plugin_id: str = self._plugins_store.get_value( pathit, self._col_plugin_id ) return plugin_id def _table_path_for_plugin_id(self, plugin_id: str) -> Gtk.TreePath: """Find the tree path of @plugin_id""" for row in self._plugins_store: if plugin_id == row[self._col_plugin_id]: return row.path raise ValueError(f"No such plugin {plugin_id}") def _get_plugin_info(self, plugin_id: str) -> dict[str, ty.Any] | None: """Get dict with plugin information for `plugin_id`.""" for info in self.plugin_info: if info["name"] == plugin_id: return info return None def _on_plugins_sel_changed(self, table: Gtk.TreeView) -> None: curpath, _curcol = table.get_cursor() if not curpath: return plugin_id = self._get_plugin_id(curpath) self._plugin_sidebar_update(plugin_id) def _plugin_sidebar_update(self, plugin_id: str) -> None: """Update content of plugin sidebar panel. Remove old panel if exist. Create new widgets with information and settings. """ # remove old panel if exists if oldch := self._plugin_sidebar.get_child(): self._plugin_sidebar.remove(oldch) oldch.destroy() info = self._get_plugin_info(plugin_id) if not info: return about = Gtk.Box.new(Gtk.Orientation.VERTICAL, 12) # title label = Gtk.Label() label.set_alignment(0, 0) # pylint: disable=no-member title = GLib.markup_escape_text(info["localized_name"]) label.set_markup(f"{title}") label.set_line_wrap(True) # pylint: disable=no-member label.set_selectable(True) about.pack_start(label, False, True, 0) # about section about_widg = widgets.PluginAboutWidget(plugin_id, info) about.pack_start(about_widg, False, True, 0) # objects info section if objects := self._make_plugin_objects_widget(plugin_id): about.pack_start(objects, False, True, 0) # settings if psettings_wid := self._make_plugin_settings_widget(plugin_id): about.pack_start(psettings_wid, True, True, 0) # create new panel vport = Gtk.Viewport() vport.set_shadow_type(Gtk.ShadowType.NONE) # pylint: disable=no-member vport.add(about) # pylint: disable=no-member self._plugin_sidebar.add(vport) self._plugin_sidebar.show_all() def _make_plugin_objects_widget(self, plugin_id: str) -> Gtk.Widget | None: srcs, actions, text_sources = plugins.get_plugin_attributes( plugin_id, ( plugins.PluginAttr.SOURCES, plugins.PluginAttr.ACTION_DECORATORS, plugins.PluginAttr.TEXT_SOURCES, ), ) if not actions and not srcs and not text_sources: return None vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 6) if srcs := list(srcs or ()) + list(text_sources or ()): # TRANS: Plugin contents header widgets.new_label_header(vbox, _("Sources")) swid = widgets.ObjectsInfoWidget(plugin_id, srcs) vbox.pack_start(swid, True, True, 0) if actions: # pylint: disable=using-constant-test # TRANS: Plugin contents header widgets.new_label_header(vbox, _("Actions")) awid = widgets.ObjectsInfoWidget(plugin_id, actions) vbox.pack_start(awid, True, True, 0) return vbox # pylint: disable=too-many-locals def _make_plugin_settings_widget( self, plugin_id: str ) -> Gtk.Widget | None: plugin_settings: plugin_support.PluginSettings | None plugin_settings = plugins.get_plugin_attribute( plugin_id, plugins.PluginAttr.SETTINGS ) if not plugin_settings: return None box = Gtk.Grid() box.set_row_spacing(6) box.set_column_spacing(12) label = widgets.new_label_header(None, _("Configuration")) box.attach(label, 0, 0, 2, 1) for row, setting in enumerate(plugin_settings, 1): label = plugin_settings.get_label(setting) typ = plugin_settings.get_value_type(setting) tooltip = plugin_settings.get_tooltip(setting) if issubclass(typ, plugin_support.UserNamePassword): wid = Gtk.Button(label or _("Set username and password")) wid.set_tooltip_text(tooltip) wid.connect( "clicked", _create_plugin_credentials_cb(plugin_id, setting), ) box.attach(wid, 0, row, 2, 1) continue if issubclass(typ, bool): wid = _make_plugin_sett_widget_bool( label, plugin_id, setting, plugin_settings ) wid.set_tooltip_text(tooltip) box.attach(wid, 0, row, 2, 1) continue wid = None multiline = False if issubclass(typ, str): wid, multiline = _make_plugin_sett_widget_str( plugin_id, setting, plugin_settings ) box.attach(wid, 1, row, 1, 1) elif issubclass(typ, int): wid = _make_plugin_sett_widget_int( plugin_id, setting, plugin_settings ) box.attach(wid, 1, row, 1, 1) elif issubclass(typ, list): if wid := _make_plugin_sett_widget_list( plugin_id, setting, plugin_settings ): multiline = True box.attach(wid, 1, row, 1, 1) wid.set_tooltip_text(tooltip) label_wid = widgets.new_label( None, label, selectable=False, tooltip=tooltip ) box.attach(label_wid, 0, row, 1, 1) # on multiline widgets put label on top if multiline: label_wid.set_alignment(0, 0) # pylint: disable=no-member label_wid.set_padding(0, 4) # pylint: disable=no-member else: label_wid.set_alignment(0, 0.5) # pylint: disable=no-member label_wid.set_padding(0, 0) # pylint: disable=no-member box.show_all() # pylint: disable=no-member return box def on_buttonadddirectory_clicked(self, widget: Gtk.Widget) -> None: """Choose folder for indexed folders - callback.""" # TRANS: File Chooser Title chooser_dialog = Gtk.FileChooserDialog( title=_("Choose a Directory"), action=Gtk.FileChooserAction.SELECT_FOLDER, buttons=( Gtk.STOCK_CANCEL, Gtk.ResponseType.REJECT, Gtk.STOCK_OK, Gtk.ResponseType.ACCEPT, ), ) chooser_dialog.set_select_multiple(True) # pylint: disable=no-member if chooser_dialog.run() == Gtk.ResponseType.ACCEPT: # pylint: disable=no-member for selected_dir in chooser_dialog.get_filenames(): self._add_indexed_directory(selected_dir, store=True) chooser_dialog.hide() def on_buttonremovedirectory_clicked(self, widget: Gtk.Widget) -> None: """Fromove folder from indexed folders - callback.""" curpath, _curcol = self._indexed_folders_table.get_cursor() if curpath: pathit = self._indexed_folders_store.get_iter(curpath) self._remove_indexed_folder(pathit, store=True) def on_entry_plugins_filter_changed(self, widget: Gtk.Widget) -> None: """Filter plugins list on filter entry changed - callback.""" s_filter = widget.get_text() us_filter = s_filter.lower() self._refresh_plugin_list(us_filter) def on_entry_plugins_filter_icon_press( self, entry: Gtk.Entry, icon_pos: ty.Any, event: ty.Any ) -> None: """Clear plugins filter, refresh list - callback.""" entry.set_text("") def on_keybindings_row_activate( self, treeview: Gtk.TreeView, path: Gtk.TreePath, view_column: Gtk.TreeViewColumn, ) -> None: """Change keybinding (ask user for new keybinding) on activate row of keybindings list - callback.""" def bind_key_func(target): def bind_key(keystr): return keybindings.bind_key(keystr, target) return bind_key pathit = self._keybind_store.get_iter(path) keybind_id = self._keybind_store.get_value(pathit, 2) setctl = settings.get_settings_controller() curr_key = setctl.get_global_keybinding(keybind_id) bind_func = bind_key_func(_KEYBINDING_TARGETS[keybind_id]) keystr = getkey_dialog.ask_for_key( bind_func, curr_key, screen=treeview.get_screen(), parent=treeview.get_toplevel(), ) if keystr == "": keybindings.bind_key(None, _KEYBINDING_TARGETS[keybind_id]) setctl.set_global_keybinding(keybind_id, keystr) self._keybind_store.set_value(pathit, 1, "") elif keystr is not None: setctl.set_global_keybinding(keybind_id, keystr) label = Gtk.accelerator_get_label(*Gtk.accelerator_parse(keystr)) self._keybind_store.set_value(pathit, 1, label) def on_gkeybindings_row_activate( self, treeview: Gtk.TreeView, path: Gtk.TreePath, view_column: Gtk.TreeViewColumn, ) -> None: """Ask user for new global keybinding on activate row of global keybindings list.""" pathit = self.gkeybind_store.get_iter(path) keybind_id = self.gkeybind_store.get_value(pathit, 2) setctl = settings.get_settings_controller() curr_key = setctl.get_accelerator(keybind_id) keystr = getkey_dialog.ask_for_key( _is_good_keystr, previous_key=curr_key, screen=treeview.get_screen(), parent=treeview.get_toplevel(), ) if keystr is not None: setctl.set_accelerator(keybind_id, keystr) label = Gtk.accelerator_get_label(*Gtk.accelerator_parse(keystr)) self.gkeybind_store.set_value(pathit, 1, label) def on_button_reset_keys_clicked(self, button: Gtk.Button) -> None: """Reset keybindings to defaults after confirmation.""" if self._ask_user_for_reset_keybinding(): setctl = settings.get_settings_controller() setctl.reset_keybindings() self._show_keybindings(setctl) # Unbind all before re-binding for target in _KEYBINDING_TARGETS.values(): keybindings.bind_key(None, target) for keybind_id, target in _KEYBINDING_TARGETS.items(): keystr = setctl.get_global_keybinding(keybind_id) keybindings.bind_key(keystr, target) def on_button_reset_gkeys_clicked(self, button: Gtk.Button) -> None: """Reset global keybindings to defaults after confirmation.""" if self._ask_user_for_reset_keybinding(): setctl = settings.get_settings_controller() setctl.reset_accelerators() self._show_gkeybindings(setctl) def on_checkusecommandkeys_toggled(self, widget: Gtk.Widget) -> None: """Change 'use single keystroke commands...' setting - callback.""" setctl = settings.get_settings_controller() setctl.set_use_command_keys(widget.get_active()) def on_radio_action_accel_alt(self, widget: Gtk.RadioButton) -> None: """Change 'Action accelerators use alt' setting - callback.""" if widget.get_active(): setctl = settings.get_settings_controller() setctl.set_action_accelerator_modifier("alt") def on_radio_action_accel_ctrl(self, widget: Gtk.RadioButton) -> None: """Change 'Action accelerators use ctrl' setting - callback.""" if widget.get_active(): setctl = settings.get_settings_controller() setctl.set_action_accelerator_modifier("ctrl") def _on_indexed_folders_sel_changed(self, table: Gtk.TreeView) -> None: curpath, _curcol = table.get_cursor() if not curpath or not self._indexed_folders_store: self._btn_remove_dir.set_sensitive(False) return self._btn_remove_dir.set_sensitive(True) def on_terminal_combobox_changed(self, widget: Gtk.ComboBox) -> None: """Change terminal setting - callback.""" setctl = settings.get_settings_controller() if itr := widget.get_active_iter(): term_id = widget.get_model().get_value(itr, 1) setctl.set_preferred_tool("terminal", term_id) def on_editor_combobox_changed(self, widget: Gtk.ComboBox) -> None: """Change editor setting - callback.""" setctl = settings.get_settings_controller() if itr := widget.get_active_iter(): editor_id = widget.get_model().get_value(itr, 1) setctl.set_preferred_tool("editor", editor_id) def on_icons_combobox_changed(self, widget: Gtk.ComboBox) -> None: """Change 'icons set' setting - callback.""" setctl = settings.get_settings_controller() if itr := widget.get_active_iter(): term_id = widget.get_model().get_value(itr, 1) setctl.set_preferred_tool("icon_renderer", term_id) def on_icons_large_size_changed(self, widget: Gtk.ComboBoxText) -> None: """Change 'large icon size' setting - callback.""" if widget.get_active_iter(): val = widget.get_active_text() setctl = settings.get_settings_controller() setctl.set_large_icon_size(val) def on_icons_small_size_changed(self, widget: Gtk.ComboBoxText) -> None: """Change 'small icon size' setting - callback.""" if widget.get_active_iter(): val = widget.get_active_text() setctl = settings.get_settings_controller() setctl.set_small_icon_size(val) def on_ellipsize_mode_changed(self, widget: Gtk.ComboBox) -> None: """Change 'Text ellipsization' setting - callback.""" setctl = settings.get_settings_controller() if itr := widget.get_active_iter(): mode = widget.get_model().get_value(itr, 1) setctl.set_config("Appearance", "ellipsize_mode", mode) def _update_alternative_combobox( self, category_key: str, combobox: Gtk.ComboBox ) -> None: """ Alternatives changed """ combobox_store = combobox.get_model() combobox_store.clear() setctl = settings.get_settings_controller() term_id = setctl.get_preferred_tool(category_key) # fill in the available alternatives alternatives = kupferstring.locale_sort( setctl.get_valid_alternative_ids(category_key), key=operator.itemgetter(1), ) term_iter = None for id_, name in alternatives: _it = combobox_store.append((name, id_)) if id_ == term_id: term_iter = _it # Update selection term_iter = term_iter or combobox_store.get_iter_first() combobox.set_sensitive(len(combobox_store) > 1) if term_iter: combobox.set_active_iter(term_iter) def _on_alternatives_changed( self, setctl: settings.SettingsController, category_key: str ) -> None: """Update alternatives comboboxes after settings changed.""" if category_key == "terminal": self._update_alternative_combobox( category_key, self._terminal_combobox ) elif category_key == "editor": self._update_alternative_combobox( category_key, self._editor_combobox ) elif category_key == "icon_renderer": self._update_alternative_combobox( category_key, self._icons_combobox ) def on_preferences_notebook_switch_page( self, notebook: Gtk.Notebook, page: Gtk.Widget, page_num: int ) -> None: ## focus the search box on the plugin tab if page_num == _PLUGIN_LIST_PAGE: GLib.idle_add(self._plugins_filter.grab_focus) def show(self, timestamp: int) -> None: assert self.window self.window.present_with_time(timestamp) def show_on_screen(self, timestamp: int, screen: Gdk.Screen) -> None: assert self.window self.window.set_screen(screen) self.show(timestamp) ## focus the search box on the plugin tab if self._preferences_notebook.get_current_page() == _PLUGIN_LIST_PAGE: self._plugins_filter.grab_focus() def show_focus_plugin(self, plugin_id: str, timestamp: int) -> None: """Open and show information about plugin `plugin_id`.""" assert self.window try: table_path = self._table_path_for_plugin_id(plugin_id) except ValueError: self._plugins_filter.set_text("") self._refresh_plugin_list() table_path = self._table_path_for_plugin_id(plugin_id) self._plugins_table.set_cursor(table_path) self._plugins_table.scroll_to_cell(table_path) self._preferences_notebook.set_current_page(_PLUGIN_LIST_PAGE) self.window.present_with_time(timestamp) def _hide(self) -> None: assert self.window # close window instead of hide # self.window.hide() self.window.close() def _on_wnd_delete_event(self, *ignored: ty.Any) -> bool: # remove instance on close window # self._hide() self.window.destroy() PreferencesWindowController._instance = None return False def _ask_user_for_reset_keybinding(self) -> bool: """Request user confirmation of resetting keybinding.""" dlg = Gtk.MessageDialog( self.window, Gtk.DialogFlags.MODAL, Gtk.MessageType.QUESTION ) dlg.set_markup(_("Reset all shortcuts to default values?")) dlg.add_buttons( Gtk.STOCK_CANCEL, Gtk.ResponseType.CLOSE, _("Reset"), Gtk.ResponseType.ACCEPT, ) # pylint: disable=no-member result: bool = dlg.run() == Gtk.ResponseType.ACCEPT dlg.destroy() return result get_preferences_window_controller = PreferencesWindowController.instance # pylint: disable=too-few-public-methods class _SourceListController: """Controller for sources list.""" def __init__(self, parent_widget): # setup plugin list table column_types = (GObject.TYPE_PYOBJECT, str, bool, Gio.Icon, str) columns = ("source", "plugin_id", "toplevel", "icon", "text") self.store = Gtk.ListStore(*column_types) self.table = Gtk.TreeView.new_with_model(self.store) self.table.set_headers_visible(False) self.table.set_property("enable-search", False) # self.table.connect("cursor-changed", self.plugin_table_cursor_changed) self.table.get_selection().set_mode(Gtk.SelectionMode.NONE) checkcell = Gtk.CellRendererToggle() checkcol = Gtk.TreeViewColumn("item", checkcell) checkcol.add_attribute(checkcell, "active", columns.index("toplevel")) checkcell.connect("toggled", self.on_checktoplevel_enabled) icon_cell = Gtk.CellRendererPixbuf() icon_cell.set_property("height", _LIST_ICON_SIZE) icon_cell.set_property("width", _LIST_ICON_SIZE) icon_col = Gtk.TreeViewColumn("icon", icon_cell) icon_col.add_attribute(icon_cell, "gicon", columns.index("icon")) cell = Gtk.CellRendererText() col = Gtk.TreeViewColumn("item", cell) col.add_attribute(cell, "text", columns.index("text")) self.table.append_column(checkcol) self.table.append_column(icon_col) self.table.append_column(col) self._refresh() self.table.show() parent_widget.add(self.table) setctl = settings.get_settings_controller() setctl.connect("plugin-enabled-changed", self._refresh) def _refresh(self, *ignored: ty.Any) -> None: self.store.clear() setctl = settings.get_settings_controller() srcctl = sources.get_source_controller() srcs = sorted(srcctl.get_sources(), key=str) for src in srcs: plugin_id = srcctl.get_plugin_id_for_object(src) if not plugin_id or setctl.get_plugin_is_hidden(plugin_id): continue if not src.get_valid_leaf_repr()[0]: continue gicon = src.get_icon() toplevel = setctl.get_source_is_toplevel(plugin_id, src) name = str(src) self.store.append((src, plugin_id, toplevel, gicon, name)) def on_checktoplevel_enabled( self, cell: Gtk.CellRendererToggle, path: str ) -> None: pathit = self.store.get_iter(path) is_toplevel = not self.store.get_value(pathit, 2) plugin_id = self.store.get_value(pathit, 1) src = self.store.get_value(pathit, 0) srcctl = sources.get_source_controller() srcctl.set_toplevel(src, is_toplevel) setctl = settings.get_settings_controller() setctl.set_source_is_toplevel(plugin_id, src, is_toplevel) self.store.set_value(pathit, 2, is_toplevel) def _supports_app_indicator() -> bool: try: gi.require_version("AyatanaAppIndicator3", "0.1") except ValueError: return False return True def _get_time(ctxenv: GUIEnvironmentContext | None) -> int: if ctxenv: return ctxenv.get_timestamp() return int(Gtk.get_current_event_time()) def show_preferences(ctxenv: GUIEnvironmentContext) -> None: win = get_preferences_window_controller() if ctxenv: win.show_on_screen(ctxenv.get_timestamp(), ctxenv.get_screen()) else: win.show(_get_time(ctxenv)) def show_plugin_info( plugin_id: str, ctxenv: GUIEnvironmentContext | None = None ) -> None: prefs = get_preferences_window_controller() prefs.show_focus_plugin(plugin_id, _get_time(ctxenv)) kupfer-328/kupfer/ui/progress_dialog.py000066400000000000000000000053421500175051100203310ustar00rootroot00000000000000# note: not used from __future__ import annotations import functools import typing as ty # NOTE: was glib; changed to gio.repo.GLib from gi.repository import GLib, Gtk from kupfer import config, version T = ty.TypeVar("T") def idle_call(func: ty.Callable[..., T]) -> ty.Callable[..., T]: @functools.wraps(func) def idle_wrapper(*args): GLib.idle_add(func, *args) # pylint: disable=no-member return idle_wrapper _HEADER_MARKUP = '%s' class ProgressDialogController: def __init__( self, title: str, header: str | None = None, max_value: int = 100 ): """Create a new progress dialog @header: first line of dialog The methods show, hide and update are all wrapped to be safe to call from any thread. """ self.aborted = False self._max_value = float(max_value) ui_file = config.get_data_file("progress_dialog.ui") self._construct_dialog(ui_file, title, header) @idle_call def _construct_dialog(self, ui_file: str, title: str, header: str) -> None: builder = Gtk.Builder() builder.set_translation_domain(version.PACKAGE_NAME) builder.add_from_file(ui_file) builder.connect_signals(self) # pylint: disable=no-member self._window = builder.get_object("window_progress") self._button_abort = builder.get_object("button_abort") self._progressbar = builder.get_object("progressbar") self._label_info = builder.get_object("label_info") label_header = builder.get_object("label_header") if header: label_header.set_markup( _HEADER_MARKUP % GLib.markup_escape_text(header) ) else: label_header.hide() self._window.set_title(title) self.update(0, "", "") def on_button_abort_clicked(self, widget: Gtk.Button) -> None: self.aborted = True self._button_abort.set_sensitive(False) @idle_call def show(self) -> None: self._window.present() @idle_call def hide(self) -> None: self._window.hide() @idle_call def update(self, value: float, label: str, text: str) -> bool: """Update dialog information. @value: value to set for progress bar @label: current action (displayed in emphasized style) @text: current information (normal style) @return true when abort button was pressed """ self._progressbar.set_fraction(min(value / self._max_value, 1.0)) self._label_info.set_markup( "" + GLib.markup_escape_text(label) + "" + GLib.markup_escape_text(text) ) return self.aborted kupfer-328/kupfer/ui/search.py000066400000000000000000001111301500175051100164040ustar00rootroot00000000000000#! /usr/bin/env python3 from __future__ import annotations import enum import itertools import typing as ty from gi.repository import Gdk, GdkPixbuf, GLib, GObject, Gtk import kupfer.config import kupfer.environment from kupfer import icons from kupfer.core import actionaccel, learn, relevance, search, settings from kupfer.obj import Action, AnySource, KupferObject, Leaf from kupfer.support import pretty from kupfer.ui._support import escape_markup_str, text_direction_is_ltr if ty.TYPE_CHECKING: from gettext import gettext as _ from kupfer.core.search import Rankable def _format_match(match: str) -> str: """Function used to format matched text in label.""" return f"{escape_markup_str(match)}" # State Constants class State(enum.IntEnum): WAIT = 1 MATCH = 2 NO_MATCH = 3 _PREEDIT_HIDDEN_CLASS: ty.Final = "hidden" _WINDOW_BORDER_WIDTH: ty.Final = 8 # columns position _ICON_COL: ty.Final = 1 _NAME_COL: ty.Final = 2 _FAV_COL: ty.Final = 3 _INFO_COL: ty.Final = 4 _RANK_COL: ty.Final = 5 _MIN_ICON_SIZE_TO_SHOW: ty.Final[int] = 8 class _LeafModel: """A base for a tree view with a magic load-on-demand feature. self.set_base will set its base iterator and self.populate(num) will load @num items into the model Attributes: icon_size """ def __init__( self, aux_info_callback: ty.Callable[[search.RankableObject], str] ) -> None: """First column is always the object -- returned by get_object it needs not be specified in columns.""" self.icon_size = 32 columns = (GObject.TYPE_OBJECT, str, str, str, str) self._store = Gtk.ListStore(GObject.TYPE_PYOBJECT, *columns) self._base: ty.Iterator[Rankable] | None = None self._setup_columns() self._aux_info_callback = aux_info_callback def __len__(self) -> int: return len(self._store) def _setup_columns(self): # Name and description column # Expands to the rest of the space name_cell = Gtk.CellRendererText() setctl = settings.get_settings_controller() name_cell.set_property("ellipsize", setctl.get_ellipsize_mode()) name_col = Gtk.TreeViewColumn("item", name_cell) name_col.set_expand(True) name_col.add_attribute(name_cell, "markup", _NAME_COL) fav_cell = Gtk.CellRendererText() fav_col = Gtk.TreeViewColumn("fav", fav_cell) fav_col.add_attribute(fav_cell, "text", _FAV_COL) info_cell = Gtk.CellRendererText() info_col = Gtk.TreeViewColumn("info", info_cell) info_col.add_attribute(info_cell, "text", _INFO_COL) nbr_cell = Gtk.CellRendererText() nbr_col = Gtk.TreeViewColumn("rank", nbr_cell) nbr_cell.set_property("width-chars", 3) nbr_col.add_attribute(nbr_cell, "text", _RANK_COL) icon_cell = Gtk.CellRendererPixbuf() icon_col = Gtk.TreeViewColumn("icon", icon_cell) icon_col.add_attribute(icon_cell, "pixbuf", _ICON_COL) self.columns = [icon_col, name_col, fav_col, info_col] # show rank only in debug mode if pretty.DEBUG: self.columns.append(nbr_col) def get_object(self, path: ty.Iterable[int] | None) -> Rankable | None: """Get object for given `path`.""" if path is None: return None store_iter = self._store.get_iter(path) return self._store.get_value(store_iter, 0) # type: ignore def get_store(self) -> Gtk.ListStore: """Get list store.""" return self._store def clear(self) -> None: """Clear the model and reset its base""" self._store.clear() self._base = None def set_base(self, baseiter: ty.Iterable[Rankable]) -> None: """Set base iterator that provide items for model.""" self._base = iter(baseiter) def populate(self, num: int | None = None) -> KupferObject | None: """Populate model with num items from its base and return first item inserted. If num is none, insert everything. """ if not self._base: return None iterator: ty.Iterator[Rankable] = self._base if num: iterator = itertools.islice(self._base, num) append = self._store.append build_row = self._build_row try: first_rank = next(iterator) append(build_row(first_rank)) first = first_rank.object except StopIteration: return None for item in iterator: append(build_row(item)) # first.object is a leaf return first def _build_row( self, rankable: Rankable ) -> tuple[Rankable, GdkPixbuf.Pixbuf | None, str, str, str, str]: """Use the UI description functions get_* to initialize `rankable` into the model. Return (rankable, icon, markup, fav, info, rank_str). """ leaf, rank = rankable.object, rankable.rank assert isinstance(leaf, (Leaf, Action)) return ( rankable, self._get_icon(leaf), self._get_label_markup(leaf), self._get_fav(leaf), self._get_aux_info(leaf), self._get_rank_str(rank), ) def _iter_store(self) -> ty.Iterator[tuple[Rankable, Gtk.TreeIter]]: """Iterate over item in tree store and yield rankable object and iterator""" siter = self._store.get_iter_first() while siter: yield self._store.get(siter, 0)[0], siter siter = self._store.iter_next(siter) def add_first(self, rankable: Rankable) -> None: """Add rankable on top the list. Remove previous object when already exists. """ # first check is object already exists for row_rankable, siter in self._iter_store(): if row_rankable.object == rankable.object: # object already on list; remove it self._store.remove(siter) break self._store.prepend(self._build_row(rankable)) def find(self, obj: search.RankableObject) -> int: """Find @obj in store and return it row number""" for row, (row_rankable, _siter) in enumerate(self._iter_store()): if row_rankable.object == obj: return row return -1 def _get_icon( self, leaf: search.RankableObject ) -> GdkPixbuf.Pixbuf | None: """Get icon from `leaf` to show in row.""" if (size := self.icon_size) > _MIN_ICON_SIZE_TO_SHOW: return leaf.get_thumbnail(size, size) or leaf.get_pixbuf(size) return None def _get_label_markup(self, leaf: search.RankableObject) -> str: """Get `rankable` description to show in row.""" # Here we use the items real name. # Previously we used the alias that was matched, but it can be too # confusing or ugly name = escape_markup_str(str(leaf)) if desc := escape_markup_str(leaf.get_description() or ""): return f"{name}\n{desc}" return name def _get_fav(self, leaf: search.RankableObject) -> str: """Get star if `leaf` is favourite.""" if learn.is_favorite(leaf): return "\N{BLACK STAR}" return "" def _get_aux_info(self, leaf: search.RankableObject) -> str: """Show additional information about leaves using aux_info_callback. For objects: Show arrow if it has content. For actions: Show accelerator. """ if self._aux_info_callback is not None: return self._aux_info_callback(leaf) return "" def _get_rank_str(self, rank: float | None) -> str: # Display rank empty instead of 0 since it looks better return str(int(rank)) if rank else "" def _dim_icon(icon: GdkPixbuf.Pixbuf | None) -> GdkPixbuf.Pixbuf | None: if not icon: return None dim_icon = icon.copy() dim_icon.fill(0) icon.composite( dim_icon, 0, 0, icon.get_width(), icon.get_height(), 0, 0, 1.0, 1.0, GdkPixbuf.InterpType.NEAREST, 127, ) return dim_icon _LABEL_CHAR_WIDTH: ty.Final = 25 _PREEDIT_CHAR_WIDTH: ty.Final = 5 # pylint: disable=too-many-instance-attributes class MatchViewOwner(pretty.OutputMixin): """Owner of the widget for displaying name, icon and name underlining (if applicable) of the current match.""" def __init__(self) -> None: # object attributes self._match_state: State = State.WAIT self.object_stack: list[Leaf] = [] # finally build widget self._build_widget() self._cur_icon: GdkPixbuf.Pixbuf | None = None self._cur_text: str | None = None self._cur_match: str | None = None self._icon_size: int = 0 self._read_icon_size() def _on_icon_size_changed( self, setctl: settings.SettingsController, section: str | None, key: str | None, value: ty.Any, ) -> None: self._icon_size = setctl.get_config_int( "Appearance", "icon_large_size" ) def _read_icon_size(self, *_args: ty.Any) -> None: setctl = settings.get_settings_controller() setctl.connect( "value-changed::appearance.icon_large_size", self._on_icon_size_changed, ) self._on_icon_size_changed(setctl, None, None, None) def _build_widget(self) -> None: """Core initialization method that builds the widget.""" self._label = label = Gtk.Label.new("") label.set_single_line_mode(True) label.set_width_chars(_LABEL_CHAR_WIDTH) label.set_max_width_chars(_LABEL_CHAR_WIDTH) setctl = settings.get_settings_controller() label.set_ellipsize(setctl.get_ellipsize_mode()) self._icon_view = Gtk.Image() # infobox: icon and match name icon_align = Gtk.Alignment.new(0.5, 0.5, 0, 0) icon_align.set_property("top-padding", 5) icon_align.add(self._icon_view) infobox = Gtk.HBox() infobox.pack_start(icon_align, True, True, 0) box = Gtk.VBox() box.pack_start(infobox, True, False, 0) self._editbox = Gtk.HBox() self._editbox.pack_start(self._label, True, True, 0) box.pack_start(self._editbox, False, False, 3) event_box = Gtk.EventBox() event_box.add(box) event_box.get_style_context().add_class("matchview") event_box.show_all() self._child = event_box def widget(self) -> Gtk.Widget: """Return the corresponding Widget""" return self._child # pylint: disable=too-many-locals def _render_composed_icon( self, base: GdkPixbuf.Pixbuf, pixbufs: list[GdkPixbuf.Pixbuf], small_size: int, ) -> GdkPixbuf.Pixbuf: """Render the main selection + a string of objects on the stack. Scale the main image into the upper portion, leaving a clear strip at the bottom where we line up the small icons. @base: main selection pixbuf @pixbufs: icons of the object stack, in final (small) size @small_size: the size of the small icons """ size = self._icon_size assert size base_scale = min( (size - small_size) * 1.0 / base.get_height(), size * 1.0 / base.get_width(), ) new_sz_x = int(base_scale * base.get_width()) new_sz_y = int(base_scale * base.get_height()) if not base.get_has_alpha(): base = base.add_alpha(False, 0, 0, 0) destbuf = base.scale_simple(size, size, GdkPixbuf.InterpType.NEAREST) destbuf.fill(0x00000000) # Align in the middle of the area offset_x = (size - new_sz_x) / 2 offset_y = ((size - small_size) - new_sz_y) / 2 base.composite( destbuf, offset_x, offset_y, new_sz_x, new_sz_y, offset_x, offset_y, base_scale, base_scale, GdkPixbuf.InterpType.BILINEAR, 255, ) # @fr is the scale compared to the destination pixbuf frac = small_size * 1.0 / size dest_y = offset_y = int((1 - frac) * size) n_small = size // small_size for idx, pbuf in enumerate(pixbufs[-n_small:]): dest_x = offset_x = int(frac * size) * idx pbuf.copy_area( 0, 0, small_size, small_size, destbuf, dest_x, dest_y ) return destbuf def update_match(self) -> None: """Update interface to display the currently selected match.""" # update icon if icon := self._cur_icon: if self._match_state is State.NO_MATCH: icon = _dim_icon(icon) if icon and self.object_stack: small_size = small_max = 16 pixbufs = [ o.get_pixbuf(small_size) for o in self.object_stack[-small_max:] ] icon = self._render_composed_icon(icon, pixbufs, small_size) self._icon_view.set_from_pixbuf(icon) else: self._icon_view.clear() self._icon_view.set_pixel_size(self._icon_size) if not self._cur_text: self._label.set_text("") return if not self._cur_match: if self._match_state is not State.MATCH: # Allow markup in the text string if we have no match self._label.set_markup(self._cur_text) else: self._label.set_text(self._cur_text) return # update the text label markup = relevance.format_common_substrings( str(self._cur_text), # text str(self._cur_match).lower(), # key, format_clean=escape_markup_str, format_match=_format_match, ) self._label.set_markup(markup) def set_object( self, text: str | None, icon: GdkPixbuf.Pixbuf | None, update: bool = True, ) -> None: self._cur_text = text self._cur_icon = icon if update: self.update_match() def set_match( self, match: str | None = None, state: State | None = None, update: bool = True, ) -> None: self._cur_match = match if state: self._match_state = state elif match is not None: self._match_state = State.MATCH else: self._match_state = State.NO_MATCH if update: self.update_match() def set_match_state( self, text: str | None, icon: GdkPixbuf.Pixbuf | None, match: str | None = None, state: State | None = None, update: bool = True, ) -> None: self.set_object(text, icon, update=False) self.set_match(match, state, update=False) if update: self.update_match() def set_match_text(self, text: str | None, update: bool = True) -> None: self._cur_match = text if update: self.update_match() def expand_preedit(self, preedit: Gtk.Entry) -> None: new_label_width = _LABEL_CHAR_WIDTH - _PREEDIT_CHAR_WIDTH self._label.set_width_chars(new_label_width) preedit.set_width_chars(_PREEDIT_CHAR_WIDTH) preedit.get_style_context().remove_class(_PREEDIT_HIDDEN_CLASS) def shrink_preedit(self, preedit: Gtk.Entry) -> None: self._label.set_width_chars(_LABEL_CHAR_WIDTH) preedit.set_width_chars(0) preedit.get_style_context().add_class(_PREEDIT_HIDDEN_CLASS) def inject_preedit(self, preedit: Gtk.Entry | None) -> None: """@preedit: Widget to be injected or None""" if not preedit: self._label.set_width_chars(_LABEL_CHAR_WIDTH) self._label.set_alignment(0.5, 0.5) return if old_parent := preedit.get_parent(): old_parent.remove(preedit) self.shrink_preedit(preedit) self._editbox.pack_start(preedit, False, True, 0) # selectedc = self.style.dark[Gtk.StateType.SELECTED] # preedit.modify_bg(Gtk.StateType.SELECTED, selectedc) preedit.show() preedit.grab_focus() # number rows to skip when press PgUp/PgDown _PAGE_STEP: ty.Final = 7 _SHOW_MORE: ty.Final = 10 # pylint: disable=too-many-public-methods class Search(GObject.GObject, pretty.OutputMixin): # type:ignore """Owner of a widget for displaying search results (using match view), keeping current search result list and its display. Signals * cursor-changed: def callback(widget, selection) called with new selected (represented) object or None * activate: def callback(widget, selection) called with activated leaf, when the widget is activated by double-click in table * table-event: def callback(widget, table, event) called when the user types in the table """ # minimal length of list is MULT * icon size small LIST_MIN_MULT = 8 __gtype_name__ = "Search" def __init__(self): GObject.GObject.__init__(self) # object attributes self._model = _LeafModel(self._get_aux_info) self._match = None self._match_state = State.WAIT self._text: str | None = "" self._source: AnySource | None = None self._old_win_position: tuple[int, int] | None = None self._old_win_size: tuple[int, int] | None = None self._has_search_result = False self._initialized = False self._icon_size: int = 0 self._icon_size_small: int = 0 # finally build widget self._build_widget() self._read_icon_size() self._setup_empty() def _get_aux_info(self, leaf: KupferObject) -> str: # Return content for the aux info column return "" def set_name(self, name: str) -> None: """Set the `name` of the Search's widget.""" self._child.set_name(name) def set_state(self, state: Gtk.StateType) -> None: self._child.set_state(state) def show(self) -> None: self._child.show() def hide(self) -> None: self._child.hide() def set_visible(self, flag: bool) -> None: if flag: self.show() else: self.hide() def _on_icon_size_changed( self, setctl: settings.SettingsController, section: str | None, key: str | None, value: ty.Any, ) -> None: self._icon_size = setctl.get_config_int( "Appearance", "icon_large_size" ) self._icon_size_small = setctl.get_config_int( "Appearance", "icon_small_size" ) self._model.icon_size = self._icon_size_small def _read_icon_size(self, *args: ty.Any) -> None: setctl = settings.get_settings_controller() setctl.connect( "value-changed::appearance.icon_large_size", self._on_icon_size_changed, ) setctl.connect( "value-changed::appearance.icon_small_size", self._on_icon_size_changed, ) self._on_icon_size_changed(setctl, None, None, None) def _build_widget(self) -> None: """ Core initialization method that builds the widget """ self.match_view = MatchViewOwner() self._table = table = Gtk.TreeView.new_with_model( self._model.get_store() ) table.set_name("kupfer-list-view") table.set_headers_visible(False) table.set_property("enable-search", False) table.set_has_tooltip(True) table.set_tooltip_column(2) for col in self._model.columns: table.append_column(col) table.connect("row-activated", self._on_row_activated) table.connect("cursor-changed", self._on_cursor_changed) scroller = Gtk.ScrolledWindow() scroller.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) scroller.add(table) # pylint: disable=no-member vscroll = scroller.get_vscrollbar() vscroll.connect("change-value", self._on_table_scroll_changed) self._list_window = Gtk.Window.new(Gtk.WindowType.POPUP) self._list_window.set_name("kupfer-list") self._list_window.add(scroller) scroller.show_all() # pylint: disable=no-member self._child = self.match_view.widget() def widget(self) -> Gtk.Widget: """Return the corresponding Widget.""" return self._child def get_current(self) -> KupferObject | None: """return current selection""" return self._match def set_object_stack(self, stack: list[Leaf]) -> None: self.match_view.object_stack = stack self.match_view.update_match() def set_source(self, source: AnySource) -> None: """Set current source (to get icon, name etc)""" self._source = source def get_match_state(self) -> State: return self._match_state def get_match_text(self) -> str | None: return self._text def get_table_visible(self) -> bool: return self._list_window.get_property("visible") # type: ignore def hide_table(self) -> None: if self.get_table_visible(): self._list_window.hide() def _reposition_list_window( self, ) -> None: # pylint: disable=too-many-locals widget = self.widget() window = widget.get_toplevel() win_size = window.get_size() if not win_size: return win_pos = window.get_position() # do nothing if position and size not changed if ( self._old_win_position == win_pos and self._old_win_size == win_size ): return ssize = widget.translate_coordinates(window, 0, 0) if not ssize: return pos_x, pos_y = win_pos self_x = ssize[0] self_width = widget.size_request().width self_end = self_x + self_width sub_y = pos_y + win_size[1] self._table.size_request() setctl = settings.get_settings_controller() subwin_height = setctl.get_config_int("Appearance", "list_height") if subwin_height < self._icon_size_small * self.LIST_MIN_MULT: subwin_height = self.LIST_MIN_MULT * self._icon_size_small subwin_width = self_width * 2 + _WINDOW_BORDER_WIDTH if self_end < subwin_width: # Place snugly to left sub_x = pos_x + self_x else: # Place aligned with right side of window sub_x = pos_x + self_end - subwin_width self._list_window.move(sub_x, sub_y) self._list_window.resize(subwin_width, subwin_height) self._list_window.set_transient_for(window) self._list_window.set_property("focus-on-map", False) self._old_win_position = win_pos self._old_win_size = win_size def _show_table(self) -> None: # pylint: disable=too-many-locals self._reposition_list_window() self._list_window.show() def show_table(self) -> None: self.go_down(True) def show_table_quirk(self) -> None: "Show table after being hidden in the same event" # KWin bugs out if we hide and show the table during the same gtk event # issue #47 if kupfer.environment.is_kwin(): GLib.idle_add(self.show_table) else: self.show_table() def _on_table_scroll_changed( self, scrollbar: Gtk.Scrollbar, _scroll_type: ty.Any, value: int ) -> None: """When the scrollbar changes due to user interaction""" # page size: size of currently visible area adj = scrollbar.get_adjustment() upper = adj.get_property("upper") page_size = adj.get_property("page-size") if value + page_size >= upper: self._populate(_SHOW_MORE) # table methods def _table_set_cursor_at_row(self, row: int) -> None: self._table.set_cursor((row,)) # scroll with minimal delay GLib.timeout_add(100, lambda: self._table.scroll_to_cell((row,))) def _table_current_row(self) -> int | None: path, _col = self._table.get_cursor() return path[0] if path else None def go_up(self, rows_count: int = 1) -> None: """Upwards in the table""" # go up, simply. close table if we go up from row 0 path, _col = self._table.get_cursor() if not path: return if (row := path[0]) >= 1: self._table_set_cursor_at_row(row - min(rows_count, row)) else: self.hide_table() def go_down( self, force: bool = False, rows_count: int = 1, show_table: bool = True ) -> None: """Down in the table.""" table_visible = self.get_table_visible() # if no data is loaded (frex viewing catalog), load # if too little data is loaded, try load more if len(self._model) <= 1: self._populate(_SHOW_MORE) if len(self._model) >= 1: path, _col = self._table.get_cursor() if path: row = path[0] if len(self._model) - rows_count <= row: self._populate(_SHOW_MORE) # go down only if table is visible if table_visible and ( step := min(len(self._model) - row - 1, rows_count) ): self._table_set_cursor_at_row(row + step) else: self._table_set_cursor_at_row(0) if show_table: self._show_table() if force and show_table: self._show_table() def go_page_up(self) -> None: """move list one page up""" self.go_up(_PAGE_STEP) def go_page_down(self) -> None: """move list one page down""" self.go_down(rows_count=_PAGE_STEP) def go_first(self) -> None: """Rewind to first item""" if self.get_table_visible(): self._table_set_cursor_at_row(0) def window_config( self, widget: Gtk.Widget, event: Gdk.EventConfigure ) -> None: """When the window moves""" if self.get_table_visible(): self._reposition_list_window() def window_hidden(self, window: Gtk.Widget) -> None: """Window changed hid""" self.hide_table() def _on_row_activated( self, treeview: Gtk.TreeView, path: ty.Any, col: ty.Any ) -> None: obj = self.get_current() self.emit("activate", obj) def _on_cursor_changed(self, treeview: Gtk.TreeView) -> None: path, _col = treeview.get_cursor() match = self._model.get_object(path) self._set_match(match) def _set_match(self, rankable: Rankable | None = None) -> None: """Set the currently selected (represented) object, either as @rankable or KupferObject @obj Emits cursor-changed """ self._match = rankable.object if rankable else None self.emit("cursor-changed", self._match) if self._match: match_text = rankable.value if rankable else None self._match_state = State.MATCH icon_size = self._icon_size pbuf = self._match.get_thumbnail( icon_size * 4 // 3, icon_size ) or self._match.get_pixbuf(icon_size) self.match_view.set_match_state( match_text, pbuf, match=self._text, state=self._match_state ) def set_match_plain(self, obj: Rankable) -> None: """Set match to object @obj, without search or matches""" self._text = None self._set_match(obj) self._model.add_first(obj) self._table_set_cursor_at_row(0) def set_match_leaf(self, leaf: Leaf) -> None: """Set match to @leaf if it is on list""" if len(self._model) == 0: return while True: # try find if (row := self._model.find(leaf)) >= 0: self._show_table() self._table_set_cursor_at_row(row) return # if not found try to load more items if not self._populate(_SHOW_MORE): # stop when no more leaves return def relax_match(self) -> None: """Remove match text highlight""" self.match_view.set_match_text(None) self._text = None def has_result(self) -> bool: """A search with explicit search term is active""" return self._has_search_result def is_showing_result(self) -> bool: """Showing search result: A search with explicit search term is active, and the result list is shown. """ return self._has_search_result and self.get_table_visible() def update_match( self, key: str | None, matchrankable: Rankable | None, matches: ty.Iterable[Rankable], ) -> None: """ @matchrankable: Rankable first match or None @matches: Iterable to rest of matches """ self._has_search_result = bool(key) self._model.clear() self._text = key if not matchrankable: self._set_match(None) self._handle_no_matches(empty=not key) return self._set_match(matchrankable) self._model.set_base(iter(matches)) if not self._model and self.get_table_visible(): self.go_down() def reset(self) -> None: self._has_search_result = False self._initialized = True self._model.clear() self._setup_empty() def _setup_empty(self) -> None: self._match_state = State.NO_MATCH self.match_view.set_match_state("No match", None, state=State.NO_MATCH) self.relax_match() def _populate(self, num: int) -> KupferObject | None: """populate model with num items""" return self._model.populate(num) def _handle_no_matches(self, empty: bool = False) -> None: """if @empty, there were no matches to find""" assert hasattr(self, "_get_nomatch_name_icon") name, icon = self._get_nomatch_name_icon( # pylint: disable=no-member empty=empty ) self._match_state = State.NO_MATCH self.match_view.set_match_state(name, icon, state=State.NO_MATCH) # Take care of GObject things to set up the Search class GObject.type_register(Search) GObject.signal_new( "activate", Search, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_PYOBJECT,), ) GObject.signal_new( "cursor-changed", Search, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (GObject.TYPE_PYOBJECT,), ) class LeafSearch(Search): """Customize for leaves search""" def __init__(self): super().__init__() if text_direction_is_ltr(): self._aux_info_str = "\N{BLACK RIGHT-POINTING SMALL TRIANGLE} " else: self._aux_info_str = "\N{BLACK LEFT-POINTING SMALL TRIANGLE} " def _get_aux_info(self, leaf: KupferObject) -> str: if hasattr(leaf, "has_content") and leaf.has_content(): return self._aux_info_str return "" def _get_pbuf(self, src: AnySource) -> GdkPixbuf.Pixbuf: icon_size = self._icon_size return src.get_thumbnail( icon_size * 4 // 3, icon_size ) or src.get_pixbuf(icon_size) def _get_nomatch_name_icon( self, empty: bool ) -> tuple[str, GdkPixbuf.Pixbuf]: if empty and self._source: return ( f"{escape_markup_str(self._source.get_empty_text())}", self._get_pbuf(self._source), ) if self._source: assert self._text return ( _('No matches in %(src)s for "%(query)s"') % { "src": f"{escape_markup_str(str(self._source))}", "query": escape_markup_str(self._text), }, self._get_pbuf(self._source), ) return _("No matches"), icons.get_icon_for_name( "kupfer-object", self._icon_size ) def _setup_empty(self) -> None: if self._source: icon = self._get_pbuf(self._source) msg = self._source.get_search_text() else: icon = None msg = _("Type to search") title = f"{msg}" self._set_match(None) self._match_state = State.WAIT self.match_view.set_match_state(title, icon, state=State.WAIT) def _accel_for_action( action: Action, action_accel_config: actionaccel.AccelConfig | None ) -> str | None: if action_accel_config is None: return None if (config_accel := action_accel_config.get(action)) is not None: return config_accel return action.action_accelerator class ActionSearch(Search): """Customization for Actions Attributes: accel_modifier """ def __init__(self) -> None: super().__init__() self.action_accel_config: actionaccel.AccelConfig | None = None # pylint: disable=no-member self.accel_modifier: Gdk.ModifierType = Gdk.ModifierType.MOD1_MASK def lazy_setup(self) -> None: setctl = settings.get_settings_controller() setctl.connect( "value-changed::kupfer.action_accelerator_modifer", self._on_modifier_changed, ) self._read_accel_modifier(setctl.get_action_accelerator_modifer()) def _on_modifier_changed( self, setctl: settings.SettingsController, section: ty.Any, key: ty.Any, value: str, ) -> None: self._read_accel_modifier(value) def _read_accel_modifier(self, value: str) -> None: if value == "alt": # pylint: disable=no-member self.accel_modifier = Gdk.ModifierType.MOD1_MASK elif value == "ctrl": # pylint: disable=no-member self.accel_modifier = Gdk.ModifierType.CONTROL_MASK else: pretty.print_error("Unknown modifier key", value) def _get_aux_info(self, leaf: Action) -> str: # type:ignore if not self.action_accel_config: return "" if accel := _accel_for_action(leaf, self.action_accel_config): keyv, mods = Gtk.accelerator_parse(accel) if mods != 0: self.output_error("Ignoring action accelerator mod", mods) return Gtk.accelerator_get_label( # type:ignore keyv, self.accel_modifier ) return "" def _get_nomatch_name_icon( self, empty: bool = False ) -> tuple[str, GdkPixbuf.Pixbuf | None]: # don't look up icons too early if not self._initialized: return ("", None) if self._text: msg = _('No action matches "%s"') % escape_markup_str(self._text) title = f"{msg}" else: title = "" return title, icons.get_icon_for_name( "kupfer-execute", self._icon_size ) def _setup_empty(self) -> None: self._handle_no_matches() self.hide_table() def select_action_by_accel(self, accel: str) -> tuple[bool, bool]: """Find and select the next action with accelerator key @accel. When exists two or more actions with the same accelerator, select next and not execute it. This allow to iterate between action by pressing accelerator key. Return pair of bool success, can activate """ if self.get_match_state() == State.NO_MATCH: return False, False idx = self._table_current_row() or 0 self._populate(1) if not self._model: return False, False start_row = idx # keep info about first found action with given accelerator (idx, action) matched_action = None while True: self._populate(1) idx = (idx + 1) % len(self._model) cur = self._model.get_object((idx,)) assert cur and isinstance(cur.object, Action) action: Action = cur.object self.output_debug("Looking at action", action) if _accel_for_action(action, self.action_accel_config) == accel: if matched_action is None: matched_action = (idx, action) else: # found another action with the same accelerator # select first action and exit (do not execute action) self._table_set_cursor_at_row(matched_action[0]) return True, False if idx == start_row: break if matched_action: idx, action = matched_action self._table_set_cursor_at_row(idx) return True, not action.requires_object() return False, False kupfer-328/kupfer/ui/session.py000066400000000000000000000142311500175051100166260ustar00rootroot00000000000000""" session sets up the program as a client to the current desktop session and enables notifications on session close, to be able to save state before being killed; the module API does not depend on the session API used """ from __future__ import annotations import os import time import typing as ty import dbus from gi.repository import GObject from kupfer import version from kupfer.support import pretty class SessionClient(GObject.GObject, pretty.OutputMixin): # type:ignore """Session handling controller signals: save-yourself: Program should save state die: Program should quit immediately """ __gtype_name__ = "SessionClient" def __init__(self): """Set up program as client to current Session""" GObject.GObject.__init__(self) self._session_ended = False self._client_id = None succ = False try: succ = self._connect_session_manager() except dbus.DBusException as exc: self.output_error(exc) if not succ: # try to bind to xfce session manager try: succ = self._connect_xfce_session_manager() except dbus.DBusException as exc: self.output_error(exc) self._enabled = succ or self._connect_gnomeui() # unset autostart id so that it is not transferred os.putenv("DESKTOP_AUTOSTART_ID", "") if not self.enabled: self.output_info( "Warning: Not able to connect to current " "desktop session, please Quit before logout to save " "kupfer's data." ) def _connect_gnomeui(self) -> bool: return False def _connect_session_manager(self) -> bool: bus = dbus.SessionBus() proxy_obj = bus.get_object( "org.freedesktop.DBus", "/org/freedesktop/DBus" ) dbus_iface = dbus.Interface(proxy_obj, "org.freedesktop.DBus") iface_name = service_name = "org.gnome.SessionManager" obj_name = "/org/gnome/SessionManager" if not dbus_iface.NameHasOwner(service_name): self.output_debug("D-Bus name", service_name, "not found") return False try: obj = bus.get_object(service_name, obj_name) except dbus.DBusException as exc: pretty.print_error(__name__, exc) return False smanager = dbus.Interface(obj, iface_name) app_id = version.PACKAGE_NAME startup_id = os.getenv("DESKTOP_AUTOSTART_ID") or "" self._client_id = smanager.RegisterClient(app_id, startup_id) self._session_ended = False self.output_debug( "Connected to session as client", self._client_id, startup_id ) private_iface_name = "org.gnome.SessionManager.ClientPrivate" bus.add_signal_receiver( self._on_query_end_session, "QueryEndSession", dbus_interface=private_iface_name, ) bus.add_signal_receiver( self._on_end_session_signal, "EndSession", dbus_interface=private_iface_name, ) bus.add_signal_receiver( self._on_stop_signal, "Stop", dbus_interface=private_iface_name ) return True def _connect_xfce_session_manager(self) -> bool: bus = dbus.SessionBus() proxy_obj = bus.get_object( "org.freedesktop.DBus", "/org/freedesktop/DBus" ) dbus_iface = dbus.Interface(proxy_obj, "org.freedesktop.DBus") service_name = "org.xfce.SessionManager" obj_name = "/org/xfce/SessionManager" if not dbus_iface.NameHasOwner(service_name): self.output_debug("D-Bus name", service_name, "not found") return False try: bus.get_object(service_name, obj_name) except dbus.DBusException as exc: pretty.print_error(__name__, exc) return False private_iface_name = "org.xfce.Session.Manager" bus.add_signal_receiver( self._on_xfce_session_state_changed, "StateChanged", dbus_interface=private_iface_name, ) return True def _get_response_obj(self) -> ty.Any: """Return D-Bus session object for ClientPrivate Interface""" service_name = "org.gnome.SessionManager" obj_name = self._client_id iface_name = "org.gnome.SessionManager.ClientPrivate" try: bus = dbus.Bus() obj = bus.get_object(service_name, obj_name) except dbus.DBusException as exc: pretty.print_error(__name__, exc) return None return dbus.Interface(obj, iface_name) def _on_query_end_session(self, flags: str) -> None: self.output_debug("Query end", flags) if smanager := self._get_response_obj(): smanager.EndSessionResponse(True, "Always OK") def _on_end_session_signal(self, flags: str) -> None: self.output_debug("Session end", flags) if not self._session_ended: self._session_ended = True self.emit("save-yourself") if smanager := self._get_response_obj(): smanager.EndSessionResponse(True, "Always OK") def _on_xfce_session_state_changed( self, old_value: int, new_value: int ) -> None: self.output_debug( "XFCE Session change", time.asctime(), old_value, new_value ) if new_value == 4: # noqa:PLR2004 self.emit("save-yourself") def _on_stop_signal(self) -> None: self.output_debug("Session stop") self.emit("die") # def _session_save(self, obj: ty.Any, *args: ty.Any) -> None: # self.emit("save-yourself") # def _session_die(self, obj: ty.Any, *args: ty.Any) -> None: # self.emit("die") @property def enabled(self) -> bool: """If a session connection is available""" return self._enabled GObject.signal_new( "save-yourself", SessionClient, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (), ) GObject.signal_new( "die", SessionClient, GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN, (), ) kupfer-328/kupfer/ui/uievents.py000066400000000000000000000123051500175051100170050ustar00rootroot00000000000000from __future__ import annotations import contextlib import os import typing as ty from dataclasses import dataclass from gi.repository import Gdk, Gtk from kupfer.support import pretty from kupfer.ui import keybindings def try_close_unused_displays(screen: Gdk.Screen) -> None: """Try to close inactive displays. `screen` is current GdkScreen. Take all GtkWindow that are hidden, and move to the current screen. If no windows remain then we close the display, but we never close the default display. """ skip_displays = [ d.get_name() for d in (screen.get_display(), Gdk.Display.get_default()) if d ] if not skip_displays: pretty.print_error(__name__, "empty skip_displays") return dmgr = Gdk.DisplayManager.get() for disp in dmgr.list_displays(): dname = disp.get_name() if dname in skip_displays: continue pretty.print_debug(__name__, "Trying to close", dname) open_windows = 0 for window in Gtk.Window.list_toplevels(): # find windows on @disp if window.get_screen().get_display().get_name() != dname: continue if not window.get_property("visible"): pretty.print_debug( __name__, "Moving window", window.get_name() ) pretty.print_debug(__name__, "Moving", window.get_title()) window.set_screen(screen) else: pretty.print_debug(__name__, "Open window blocks close") open_windows += 1 if not open_windows: pretty.print_debug(__name__, "Closing display", dname) disp.close() class GUIEnvironmentContext: """Context object for action execution in the current GUI context""" def __init__( self, timestamp: int, screen: Gdk.Screen | None = None ) -> None: self._timestamp = timestamp self._screen: Gdk.Screen = screen or Gdk.Screen.get_default() def __repr__(self): return ( f"<{type(self).__name__} " f"time={self._timestamp!r} screen={self._screen!r}>" ) @classmethod def ensure_display_open(cls, display_name: str | None) -> Gdk.Display: """Get GdkDisplay for `display_name` or return default if `display_name` is None or invalid/unavailable.""" # NOTE: display parameter was not supported; added (k) if disp := Gdk.Display.open(display_name): return disp return Gdk.DisplayManager.get().get_default_display() def get_timestamp(self) -> int: return self._timestamp def get_startup_notification_id(self) -> str: """Get new notification id.""" return _make_startup_notification_id(self.get_timestamp()) def get_display(self) -> str: """Return the display name to show new windows on.""" return ty.cast("str", self._screen.make_display_name()) def get_screen(self) -> Gdk.Screen: return self._screen def present_window(self, window: Gtk.Window) -> None: """Show and present `window` on the current workspace, screen & display as appropriate.""" window.set_screen(self.get_screen()) window.present_with_time(self.get_timestamp()) def gui_context_from_widget( timestamp: int, widget: Gtk.Widget ) -> GUIEnvironmentContext: return GUIEnvironmentContext(timestamp, widget.get_screen()) def gui_context_from_timestamp(timestamp: int) -> GUIEnvironmentContext: return GUIEnvironmentContext(timestamp, None) def gui_context_from_keyevent( timestamp: int, display: str ) -> GUIEnvironmentContext: new_display = GUIEnvironmentContext.ensure_display_open(display) screen, *_dummy = new_display.get_pointer() return GUIEnvironmentContext(timestamp, screen) @dataclass class _InternalData: seq: int = 0 current_event_time: int = 0 def inc_seq(self) -> None: self.seq = self.seq + 1 _internal_data = _InternalData() def _make_startup_notification_id(time: int) -> str: _internal_data.inc_seq() return f"kupfer-%{os.getpid()}-{_internal_data.seq}_TIME{time}" def current_event_time() -> int: return int( Gtk.get_current_event_time() or keybindings.get_current_event_time() or _internal_data.current_event_time ) def _parse_notify_id(startup_notification_id: str) -> int: """Return timestamp or 0 from @startup_notification_id.""" if "_TIME" in startup_notification_id: _ign, bstime = startup_notification_id.split("_TIME", 1) with contextlib.suppress(ValueError): return abs(int(bstime)) return 0 @contextlib.contextmanager def using_startup_notify_id(notify_id: str) -> ty.Any: """Pass in a DESKTOP_STARTUP_ID with using_startup_notify_id(...) as time: pass The yelt object is the parsed timestamp """ if timestamp := _parse_notify_id(notify_id): Gdk.notify_startup_complete_with_id(notify_id) try: pretty.print_debug(__name__, "Using startup id", notify_id, timestamp) _internal_data.current_event_time = timestamp yield timestamp finally: _internal_data.current_event_time = Gdk.CURRENT_TIME kupfer-328/kupfer/ui/uiutils.py000066400000000000000000000207511500175051100166450ustar00rootroot00000000000000""" User Interface Utility Functions for Kupfer These helper functions can be called from plugins (are meant to serve this purpose), but care should be taken to only call UI functions from the main (default) thread. """ from __future__ import annotations import math import textwrap import typing as ty from gi.repository import Gdk, Gtk, Pango from kupfer import config, version from kupfer.support import pretty from kupfer.ui import uievents if ty.TYPE_CHECKING: from gettext import gettext as _ from kupfer.core import commandexec def _window_close_on_escape(widget: Gtk.Widget, event: Gdk.EventKey) -> bool: """Callback function for Window's key press event, will destroy window on escape""" if event.keyval == Gdk.keyval_from_name("Escape"): widget.close() return True return False def builder_get_objects_from_file( fname: str, attrs: ty.Iterable[str], autoconnect_to: ty.Any = None ) -> ty.Iterator[Gtk.Widget]: """Open @fname with Gtk.Builder and yield objects named @attrs @fname is sought in the data directories. If @autoconnect_to is not None, signals are autoconnected to this object, and a user_data object is passed as a namespace containing all @attrs """ builder = Gtk.Builder() builder.set_translation_domain(version.PACKAGE_NAME) ui_file = config.get_data_file(fname) builder.add_from_file(ui_file) # pylint: disable=too-few-public-methods class Namespace: pass names = Namespace() for attr in attrs: obj = builder.get_object(attr) setattr(names, attr, obj) yield obj if autoconnect_to: assert hasattr(autoconnect_to, "names") autoconnect_to.names = names builder.connect_signals(autoconnect_to) # pylint: disable=no-member class _ResultWindowBehavior: def __init__(self): # this is dynamic builder_get_objects_from_file.Namespace self.names: ty.Any = None def on_text_result_window_key_press_event( self, widget: Gtk.Widget, event: Gdk.EventKey ) -> bool: return _window_close_on_escape(widget, event) def on_close_button_clicked(self, widget: Gtk.Widget) -> bool: self.names.text_result_window.close() return True def on_copy_button_clicked(self, widget: Gtk.Widget) -> None: clip = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) textview = self.names.result_textview buf = textview.get_buffer() buf.select_range(*buf.get_bounds()) buf.copy_clipboard(clip) # pylint: disable=too-many-locals def _calculate_window_size( window: Gtk.Window, textview: Gtk.TextView ) -> tuple[int, int]: # Find the size of one (monospace) letter playout = textview.create_pango_layout("X") ink_r, _logical_r = playout.get_pixel_extents() # Fix Sizing: # We want to size the window so that the # TextView is displayed without scrollbars # initially, if it fits on screen. tw_sr = textview.get_size_request() oldwid, oldhei = tw_sr.width, tw_sr.height winwid, winhei = window.get_size() # max_hsize, max_vsize = window.get_default_size() tw_sr = textview.size_request() wid, hei = tw_sr.width, tw_sr.height # Set max window size to 100 columns x 60 lines max_hsize = ink_r.height * 60 max_vsize = ink_r.width * 100 vsize = int(min(hei + (winhei - oldhei) + 5, max_vsize)) hsize = int(min(wid + (winwid - oldwid) + 5, max_hsize)) return vsize, hsize def show_text_result( text: str, title: str | None = None, ctx: commandexec.ExecutionToken | None = None, ) -> None: """Show @text in a result window. Use @title to set a window title """ window, textview = tuple( builder_get_objects_from_file( "result.ui", ("text_result_window", "result_textview"), autoconnect_to=_ResultWindowBehavior(), ) ) # Set up text buffer buf = Gtk.TextBuffer() buf.set_text(text) textview.set_buffer(buf) textview.set_wrap_mode(Gtk.WrapMode.NONE) textview.set_editable(True) if title: window.set_title(title) if ctx: ctx.environment.present_window(window) window.show_all() hsize, vsize = _calculate_window_size(window, textview) textview.set_wrap_mode(Gtk.WrapMode.WORD) window.resize(hsize, vsize) if ctx: ctx.environment.present_window(window) else: window.present_with_time(uievents.current_event_time()) def _wrap_paragraphs(text: str) -> str: """Return @text with linewrapped paragraphs""" return "\n\n".join(textwrap.fill(par) for par in text.split("\n\n")) def _set_font_size(label: Gtk.Label, fontsize: float = 48.0) -> None: label.modify_font(Pango.FontDescription.from_string(str(fontsize))) _MAX_LINE_WIDTH: ty.Final[int] = 100 def show_large_type( text: str, ctx: commandexec.ExecutionToken | None = None ) -> None: """Show @text, large, in a result window.""" text = text.strip() window = Gtk.Window() label = Gtk.Label() label.set_text(text) label.show() size = 72.0 _set_font_size(label, size) if ctx: screen = ctx.environment.get_screen() window.set_screen(screen) # pylint: disable=no-member else: screen = Gdk.Screen.get_default() assert screen maxwid = screen.get_width() - 50 maxhei = screen.get_height() - 100 l_sr = label.size_request() # pylint: disable=no-member wid, hei = l_sr.width, l_sr.height # If the text contains long lines, we try to # hard-wrap the text if (wid > maxwid or hei > maxhei) and any( len(L) > _MAX_LINE_WIDTH for L in text.splitlines() ): label.set_text(_wrap_paragraphs(text)) l_sr = label.size_request() # pylint: disable=no-member wid, hei = l_sr.width, l_sr.height if wid > maxwid or hei > maxhei: # Round size down to fit inside wscale = maxwid * 1.0 / wid hscale = maxhei * 1.0 / hei _set_font_size(label, math.floor(min(wscale, hscale) * size) or 1.0) window.add(label) # pylint: disable=no-member window.set_position(Gtk.WindowPosition.CENTER) # pylint: disable=no-member window.set_resizable(False) # pylint: disable=no-member window.set_decorated(False) window.set_property("border-width", 10) # pylint: disable=no-member window.modify_bg(Gtk.StateType.NORMAL, Gdk.color_parse("black")) # pylint: disable=no-member label.modify_fg(Gtk.StateType.NORMAL, Gdk.color_parse("white")) def _on_key_press(widget, event): widget.destroy() return True window.connect("key-press-event", _on_key_press) window.show_all() # pylint: disable=no-member if ctx: ctx.environment.present_window(window) else: window.present_with_time(uievents.current_event_time()) _SERVICE_NAME = "org.freedesktop.Notifications" _OBJECT_PATH = "/org/freedesktop/Notifications" _IFACE_NAME = "org.freedesktop.Notifications" def _get_notification_obj() -> ty.Any: """we will activate it over d-bus (start if not running)""" # pylint: disable=import-outside-toplevel import dbus try: bus = dbus.SessionBus() proxy_obj = bus.get_object(_SERVICE_NAME, _OBJECT_PATH) except dbus.DBusException as exc: pretty.print_debug(__name__, exc) return None return proxy_obj def show_notification( title: str, text: str = "", icon_name: str = "", nid: int = 0 ) -> int | None: """Show notification with `title` and optional `text` and `icon_name`. `nid` is id of then notification to replace; set 0 to get new notification id. Returns the id of the displayed notification. """ if not (notifications := _get_notification_obj()): return None hints = { "desktop-entry": version.DESKTOP_ID, } rid = notifications.Notify( "kupfer", nid, icon_name, title, text, (), hints, -1, dbus_interface=_IFACE_NAME, ) return int(rid) def confirm_dialog(msg: str, positive_btn: str) -> bool: """Request user confirmation.""" dlg = Gtk.MessageDialog( None, Gtk.DialogFlags.MODAL, Gtk.MessageType.QUESTION ) dlg.set_markup(msg) dlg.set_title(_("Kupfer")) dlg.add_buttons( Gtk.STOCK_CANCEL, Gtk.ResponseType.CLOSE, positive_btn, Gtk.ResponseType.ACCEPT, ) dlg.set_keep_above(True) # pylint: disable=no-member result: bool = dlg.run() == Gtk.ResponseType.ACCEPT dlg.destroy() return result kupfer-328/kupfer/version.py000066400000000000000000000051341500175051100162150ustar00rootroot00000000000000import typing as ty if ty.TYPE_CHECKING: from gettext import gettext as _ VERSION = "development version" PACKAGE_NAME = "kupfer" try: from kupfer import version_subst # type:ignore except ImportError: pass else: VERSION = version_subst.VERSION PACKAGE_NAME = version_subst.PACKAGE_NAME ICON_NAME = "kupfer" DESKTOP_ID = "kupfer" PROGRAM_NAME = _("Kupfer") AUTHORS = """Ulrik Sverdrup Karol Będkowski Francesco Marella Chmouel Boudjnah Horia V. Corcalciuc Grigory Javadyan Chris Parsons Fabian Carlström Jakh Daven Thomas Renard """.splitlines() PACKAGERS = """ Luca Falavigna (Debian, Ubuntu) Andrew from WebUpd8 (Ubuntu PPA ca 2017) Francesco Marella (Ubuntu PPA ca 2010) D. Can Celasun (Arch Linux AUR) """.splitlines() TRANSLATORS = """ Marek Černocký (cs) Petr Kovar (cs) Joe Hansen (da) Thibaud Roth (de) Mario Blättermann (de) Leandro Leites (es) Jesús Barbero Rodríguez (es) Jorge González (es) Daniel Mustieles (es) Oier Mees (eu) Iñaki Larrañaga Murgoitio (eu) Christophe Benz (fr) Marcos Lans (gl) Fran Diéguez (gl) Andrea Zagli (it) Francesco Marella (it) Martin Koelewijn (nl) Kjartan Maraas (no) Maciej Kwiatkowski (pl) Karol Będkowski (pl) Carlos Pais (pt) Andrej Žnidaršič (sl) Matej Urbančič (sl) M. Deran Delice (tr) lh (zh_CN) Aron Xu (zh_CN) Yinghua Wang (zh_CN) """.splitlines() ARTISTS = """ Nasser Alshammari (Kupfer Icon) GNOME Project https://www.gnome.org (Misc Icons) """.splitlines() AUTHORS += ARTISTS + PACKAGERS + TRANSLATORS DOCUMENTERS: list[str] = [] # TRANS: Don't translate literally! # TRANS: This should be a list of all translators of this language TRANSLATOR_CREDITS = _("translator-credits") WEBSITE = "https://kupferlauncher.github.io/" HELP_WEBSITE = "https://kupferlauncher.github.io/help/" SHORT_DESCRIPTION = _("A free software (GPLv3+) launcher") COPYRIGHT = """Copyright © 2007–2023 Ulrik Sverdrup with others""" LICENSE = _( """ 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 . """ ) # follows strings used elsewhere _("Could not find running Kupfer") kupfer-328/kupfer/version_subst.py.in000066400000000000000000000001411500175051100200330ustar00rootroot00000000000000VERSION = "@VERSION@" PACKAGE_NAME = "@PACKAGE@" LOCALEDIR = "@LOCALEDIR@" DATADIR = "@DATADIR@" kupfer-328/kupfer_dev.py000077500000000000000000000067301500175051100153740ustar00rootroot00000000000000#!/usr/bin/python3 """ kupfer A convenient command and access tool. This is launcher that load some useful libraries for development. Copyright 2007-2023 Ulrik Sverdrup and other Kupfer authors 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 . """ import sys try: import stackprinter stackprinter.set_excepthook( style="color", suppressed_paths=[r"*/site-packages/typeguard/"], ) except ImportError: try: from rich.traceback import install suppress_modules = [] try: import typeguard suppress_modules.append(typeguard) except ImportError: pass install(show_locals=True, suppress=suppress_modules) print("rich.traceback installed") except ImportError: pass try: import icecream icecream.install() icecream.ic.configureOutput(includeContext=True) import traceback def ic_stack(*args, **kwargs): stack = "".join(tbs.rstrip() for tbs in traceback.format_stack()[:-2]) ic(stack, *args, **kwargs) # type: ignore import inspect class ShiftedIceCreamDebugger(icecream.IceCreamDebugger): # type: ignore def format(self, *args): # one more frame back call_frame = inspect.currentframe().f_back.f_back # type: ignore return self._format(call_frame, *args) sic = ShiftedIceCreamDebugger() def ic_trace(func): def wrapper(*args, **kwargs): sic(func, args, kwargs) res = func(*args, **kwargs) sic(func, res) return res return wrapper import builtins builtins.ic_stack = ic_stack # type: ignore builtins.ic_trace = ic_trace # type: ignore except ImportError: # Graceful fallback if IceCream isn't installed. pass try: if "--debug" in sys.argv: from typeguard import install_import_hook install_import_hook("kupfer") print("WARN! typeguard hook installed") import typing typing.TYPE_CHECKING = True # type: ignore import typeguard._checkers as checkers checkers.check_protocol = None # agronholm/typeguard#465 except ImportError as err: print(err) try: from pympler import tracker except ImportError: tracker = None if __name__ == "__main__": from kupfer import main if tracker: tr = tracker.SummaryTracker() print("!!!!!!!!!!!!!! WARN !!!!!!!!!!!!!!") print( "Launching Kupfer by kupfer_dev.py is dedicated only for development. " "This may totally broke some plugins, and some parts may not not " "work as expected." ) print("Also Kupfer may run much slower.") print("Please install and run Kupfer as described in documentation.") print("!!!!!!!!!!!!!! WARN !!!!!!!!!!!!!!") main.main() if tracker: print("--- TRACKER start ---") tr.print_diff() print("--- TRACKER end ---") kupfer-328/po/000077500000000000000000000000001500175051100132755ustar00rootroot00000000000000kupfer-328/po/LINGUAS000066400000000000000000000001461500175051100143230ustar00rootroot00000000000000bs ca cs da de el en en_GB es eu fr gl hu it ko nb nl pl pt pt_BR ro ru sk sl sr sr@latin sv tr zh_CN kupfer-328/po/POTFILES.in000066400000000000000000000117041500175051100150550ustar00rootroot00000000000000# encoding: UTF-8 [type: gettext/glade]data/credentials_dialog.ui [type: gettext/glade]data/getkey_dialog.ui [type: gettext/glade]data/getdata_dialog.ui [type: gettext/glade]data/preferences.ui [type: gettext/glade]data/progress_dialog.ui [type: gettext/glade]data/result.ui auxdata/kupfer.desktop.in auxdata/kupfer-exec.desktop.in auxdata/kupfer-mimetypes.xml.in kupfer/__init__.py kupfer/config.py kupfer/core/__init__.py kupfer/core/_support.py kupfer/core/actionaccel.py kupfer/core/actioncompat.py kupfer/core/commandexec.py kupfer/core/datactrl.py kupfer/core/execfile.py kupfer/core/learn.py kupfer/core/panes.py kupfer/core/pluginload.py kupfer/core/plugins.py kupfer/core/qfurl.py kupfer/core/relevance.py kupfer/core/search.py kupfer/core/searcher.py kupfer/core/settings.py kupfer/core/sources.py kupfer/desktop_launch.py kupfer/environment.py kupfer/icons.py kupfer/interface.py kupfer/keyrelay.py kupfer/launch.py kupfer/main.py kupfer/obj/__init__.py kupfer/obj/actions.py kupfer/obj/apps.py kupfer/obj/base.py kupfer/obj/compose.py kupfer/obj/contacts.py kupfer/obj/exceptions.py kupfer/obj/fileactions.py kupfer/obj/files.py kupfer/obj/filesrc.py kupfer/obj/grouping.py kupfer/obj/helplib.py kupfer/obj/hosts.py kupfer/obj/objects.py kupfer/obj/representation.py kupfer/obj/sources.py kupfer/obj/special.py kupfer/plugin/__init__.py kupfer/plugin/_firefox_support.py kupfer/plugin/applications.py kupfer/plugin/apt_tools.py kupfer/plugin/archiveinside.py kupfer/plugin/archivemanager.py kupfer/plugin/aria2.py kupfer/plugin/audacious.py kupfer/plugin/brotab.py kupfer/plugin/calculator.py kupfer/plugin/chromium.py kupfer/plugin/chromium_support.py kupfer/plugin/clawsmail.py kupfer/plugin/clipboard.py kupfer/plugin/commands.py kupfer/plugin/core/__init__.py kupfer/plugin/core/alternatives.py kupfer/plugin/core/commands.py kupfer/plugin/core/contents.py kupfer/plugin/core/debug.py kupfer/plugin/core/internal.py kupfer/plugin/core/text.py kupfer/plugin/custom_terminal.py kupfer/plugin/darktheme.py kupfer/plugin/deepdirectories.py kupfer/plugin/defaultmail.py kupfer/plugin/devhelp.py kupfer/plugin/dictionary.py kupfer/plugin/documents.py kupfer/plugin/duckduckgo.py kupfer/plugin/favorites.py kupfer/plugin/fileactions.py kupfer/plugin/firefox.py kupfer/plugin/firefox_keywords.py kupfer/plugin/firefox_tags.py kupfer/plugin/glob.py kupfer/plugin/gtg.py kupfer/plugin/higherorder.py kupfer/plugin/image.py kupfer/plugin/instapaper.py kupfer/plugin/kupfer_actions.py kupfer/plugin/kupfer_plugins.py kupfer/plugin/librewolf.py kupfer/plugin/libvirt.py kupfer/plugin/locate.py kupfer/plugin/mediaplayers.py kupfer/plugin/nemo.py kupfer/plugin/nm.py kupfer/plugin/notes.py kupfer/plugin/pidgin.py kupfer/plugin/pinboard.py kupfer/plugin/qsicons/__init__.py kupfer/plugin/quickview.py kupfer/plugin/recoll.py kupfer/plugin/rhythmbox.py kupfer/plugin/rhythmbox_support.py kupfer/plugin/screen.py kupfer/plugin/screenshot.py kupfer/plugin/sendkeys.py kupfer/plugin/session_gnome.py kupfer/plugin/session_lxqt.py kupfer/plugin/session_support.py kupfer/plugin/session_xfce.py kupfer/plugin/shorten_links.py kupfer/plugin/show_qrcode.py kupfer/plugin/show_text.py kupfer/plugin/ssh_hosts.py kupfer/plugin/ssl_support.py kupfer/plugin/templates.py kupfer/plugin/textfiles.py kupfer/plugin/textutils.py kupfer/plugin/thunar.py kupfer/plugin/thunderbird.py kupfer/plugin/thunderbird_support.py kupfer/plugin/tmux.py kupfer/plugin/top.py kupfer/plugin/tracker1.py kupfer/plugin/tracker3.py kupfer/plugin/trash.py kupfer/plugin/triggers.py kupfer/plugin/urlactions.py kupfer/plugin/vim.py kupfer/plugin/virtualbox/__init__.py kupfer/plugin/virtualbox/constants.py kupfer/plugin/virtualbox/ose_support.py kupfer/plugin/virtualbox/vboxapi4_support.py kupfer/plugin/virtualbox/vboxapi_support.py kupfer/plugin/volumes.py kupfer/plugin/websearch.py kupfer/plugin/whatsapp.py kupfer/plugin/wikipedia.py kupfer/plugin/windows.py kupfer/plugin/zeal.py kupfer/plugin/zoxide.py kupfer/plugin_support.py kupfer/puid.py kupfer/runtimehelper.py kupfer/support/__init__.py kupfer/support/conspickle.py kupfer/support/datatools.py kupfer/support/datatools_test.py kupfer/support/desktop_parse.py kupfer/support/desktop_parse_test.py kupfer/support/fileutils.py kupfer/support/itertools.py kupfer/support/itertools_test.py kupfer/support/kupferstring.py kupfer/support/pretty.py kupfer/support/scheduler.py kupfer/support/system.py kupfer/support/task.py kupfer/support/textutils.py kupfer/support/types.py kupfer/support/validators.py kupfer/support/validators_test.py kupfer/support/weaklib.py kupfer/ui/__init__.py kupfer/ui/_support.py kupfer/ui/_widgets.py kupfer/ui/about.py kupfer/ui/accelerators.py kupfer/ui/browser.py kupfer/ui/credentials_dialog.py kupfer/ui/getdata_dialog.py kupfer/ui/getkey_dialog.py kupfer/ui/interface.py kupfer/ui/keybindings.py kupfer/ui/kupferhelp.py kupfer/ui/listen.py kupfer/ui/preferences.py kupfer/ui/progress_dialog.py kupfer/ui/search.py kupfer/ui/session.py kupfer/ui/uievents.py kupfer/ui/uiutils.py kupfer/version.py kupfer-328/po/POTFILES.skip000066400000000000000000000001421500175051100154070ustar00rootroot00000000000000contrib/icon_names.py contrib/nautilusselection.py contrib/runningapplications.py contrib/_ssl.py kupfer-328/po/bs.po000066400000000000000000001572041500175051100142520ustar00rootroot00000000000000# Bosnian translation for bosnianuniversetranslation # Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 # This file is distributed under the same license as the bosnianuniversetranslation package. # FIRST AUTHOR , 2014. # msgid "" msgstr "" "Project-Id-Version: bosnianuniversetranslation\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2015-01-09 14:13+0100\n" "Last-Translator: Samir Ribic \n" "Language-Team: Bosnian \n" "Language: bs\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: Launchpad (build 17341)\n" "X-Launchpad-Export-Date: 2015-02-17 06:20+0000\n" msgid "User credentials" msgstr "Korisničko uvjerenje" msgid "_User:" msgstr "_Korisnik:" msgid "_Password:" msgstr "_Lozinka:" msgid "_Change" msgstr "_Promijeni" msgid "Set Keyboard Shortcut" msgstr "Postavi prečicu na tastaturi" msgid "Please press desired key combination" msgstr "Molimo pritisnite željenu kombinaciju tipki" msgid "Keybinding could not be bound" msgstr "Tipke ne mogu biti povezane" msgid "Kupfer Preferences" msgstr "Postavke Kupfera" msgid "Start automatically on login" msgstr "Počni automatski pri logovanju" msgid "Start" msgstr "Počni" msgid "Show icon in notification area" msgstr "Prikazati ikonu u polju za notifikacije" msgid "Icon set:" msgstr "Skup ikona:" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" msgid "Terminal emulator:" msgstr "Imitator terminala:" msgid "Desktop Environment" msgstr "Desktop okruženje" msgid "General" msgstr "Opće" msgid "Global Keyboard Shortcuts" msgstr "Opće prečice tastature" msgid "Reset" msgstr "Resetujte" msgid "Browser Keyboard Shortcuts" msgstr "Pretraživačke prečice na tastaturi " msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "Koristite jednostruke komande tipki (Space, /, tačka, zarez itd.)" msgid "Keyboard" msgstr "Tastatura" msgid "Plugins" msgstr "Dodaci" msgid "Inclusion in Top Level Searches" msgstr "Uključivanje u Top Level pretrage" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "Markirani izvori imaju svoje objekte uključene u top level pretrage.\n" "Sadržaji nemarkiranih izvora su jedino dostupni lociranjem potkataloga." msgid "Indexed Folders" msgstr "Indeksirani folderi" msgid "Folders whose files are always available in the catalog." msgstr "Folderi čiji fajlovi su uvijek dostupni u katalogu." msgid "Catalog" msgstr "Katalog" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Pokretač programa" msgid "Convenient command and access tool for applications and documents" msgstr "Priručni alat komandi i dostupa za programe i dokumente" msgid "Execute in Kupfer" msgstr "Izvršite u Kupfer" msgid "Saved Kupfer Command" msgstr "Snimljena Kupfer komanda" #, python-format msgid "Could not to carry out '%s'" msgstr "Ne može iznijeti '%s'" #, python-format msgid "\"%s\" produced a result" msgstr "\"%s\" proizveden kao rezultat" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Nemam dozvolu za pokretanje \"%s\" (ne može se izvršiti)" #, python-format msgid "Command in \"%s\" is not available" msgstr "Komanda u \"%s\" nije dostupna" #, python-format msgid "Keyboard relay is active for display %s" msgstr "Oslanjanje na tastaturu je aktivno za prikaz %s" msgid "do not present main interface on launch" msgstr "ne predstavljaj glavno sučelje prilikom pokretanja" msgid "list available plugins" msgstr "izlistaj dostupne dodatke" msgid "enable debug info" msgstr "omogući degub informacije" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "pokkreni pomoć dodatka" msgid "show usage help" msgstr "prikaži pmoć pri upotrebi" msgid "show version information" msgstr "prikaži informacije o verziji" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Upotreba: kupfer [ OPCIJE | FAJL ...]" msgid "Available plugins:" msgstr "Dostupni dodaci:" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "Kucaj za pretragu" #, python-format msgid "%s is empty" msgstr "%s je prazan" msgid "Text" msgstr "Tekst" msgid "Run after Delay..." msgstr "Pokreni poslije odgode..." msgid "Perform command after a specified time interval" msgstr "Izvedi komandu nakod određenog vremenskog intervala" msgid "Multiple Objects" msgstr "Višestruki objekti" # translations. #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s objekat" msgstr[1] "%s objekta" msgstr[2] "%s objekata" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "nepoznato" msgid "Aim" msgstr "Cilj" msgid "Google Talk" msgstr "Google Talk" msgid "ICQ" msgstr "ICQ" msgid "MSN" msgstr "MSN" msgid "QQ" msgstr "QQ" msgid "Yahoo" msgstr "Yahoo" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "%s ne podržava ovu operaciju" msgid "Can not be used with multiple objects" msgstr "Ne može se koristiti sa višestrukim objektima" msgid "Open" msgstr "Otvori" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Nema predodređene aplikacije za %(file)s (%(type)s)" #, python-format msgid "Please use \"%s\"" msgstr "Molimo koristite \"%s\"" msgid "Set Default Application..." msgstr "Postavite predodređenu aplikaciju..." msgid "Open with default application" msgstr "Otvorite sa predodređenom aplikacijom" msgid "Reveal" msgstr "Otkrij" msgid "Open parent folder" msgstr "Otvori roditeljski folder" msgid "Open Terminal Here" msgstr "Otvori terminal ovdje" msgid "Open this location in a terminal" msgstr "Otvori ovu lokaciju u terminalu" msgid "Run in Terminal" msgstr "Pokreni u terminalu" msgid "Run (Execute)" msgstr "Pokreni(Izvrši)" msgid "Run this program in a Terminal" msgstr "Pokreni ovaj program u terminalu" msgid "Run this program" msgstr "Pokreni ovaj program" msgid "Go To" msgstr "Idi Na" msgid "Open URL" msgstr "Otvori URL" msgid "Open URL with default viewer" msgstr "Otvori URL sa predodređenim preglednikom" msgid "Launch" msgstr "Pokreni" msgid "Show application window" msgstr "Prikaži prozor aplikacije" msgid "Launch application" msgstr "Pokreni aplikaciju" msgid "Launch Again" msgstr "Pokreni ponovi" msgid "Launch another instance of this application" msgstr "Pokreni još jednu instancu ove aplikacije" msgid "Close" msgstr "Zatvori" msgid "Attempt to close all application windows" msgstr "Pokušaj zatvoriti sve aplikacijske prozore" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Pokreni" msgid "Perform command" msgstr "Izvrši komandu" msgid "(Empty Text)" msgstr "(Prazan Text)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "(%(num)d linija) \"%(text)s\"" msgstr[1] "(%(num)d linije) \"%(text)s\"" msgstr[2] "(%(num)d linija) \"%(text)s\"" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s i dr.." #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Rekurzivni izvor %(dir)s, (%(levels)d levels)" #, python-format msgid "Directory source %s" msgstr "Direktorij izvora %s" msgid "Home Folder" msgstr "Lični direktorij" msgid "Catalog Index" msgstr "Index kataloga" msgid "An index of all available sources" msgstr "Svi indexi svih dostupnih izvora" msgid "Root catalog" msgstr "Korijenski katalog" msgid "Please Configure Plugin" msgstr "Molimo konfigurirajte dodatak" #, python-format msgid "Plugin %s is not configured" msgstr "Dodatak %s nije konfiguriran" #, python-format msgid "Invalid user credentials for %s" msgstr "Nepravilno uvjerenje o korisniku za %s" msgid "Applications" msgstr "Aplikacije" msgid "All applications and preferences" msgstr "Sve aplikacije i postavke" msgid "Applications for Desktop Environment" msgstr "Aplikacije za Desktop okruženje" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "Otvori pomoću..." msgid "Open with any application" msgstr "Otvori pomoću bilo koje aplikacije" msgid "Set default application to open this file type" msgstr "Postavi predodređenu aplikaciju za otvaranje ovog tipa fajla" #, fuzzy msgid "Reset Associations" msgstr "URL Akcije" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "Duboke arhive" msgid "Allow browsing inside compressed archive files" msgstr "Dopusti pretraživanje unutra kompresovane arhive fajlova" #, python-format msgid "Content of %s" msgstr "Sadržaj iz %s" msgid "Archive Manager" msgstr "Upravitelj arhivama" msgid "Use Archive Manager actions" msgstr "Koristi akcije Upravitelja arhivama" msgid "Compressed archive type for 'Create Archive In'" msgstr "Kompresovana vrsta arhive za 'Create Archive In'" msgid "Extract Here" msgstr "Raspakuj ovdje" msgid "Extract compressed archive" msgstr "Raspakuj kompresovanu arhivu" msgid "Create Archive" msgstr "Napravi arhivu" msgid "Create a compressed archive from folder" msgstr "Napravi kompresovanu arhivu iz foldera" msgid "Create Archive In..." msgstr "Kreiraj arhivu u..." #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Arhiva" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "Kontroliraj Audacious reprodukciju i plejlistu" msgid "Include songs in top level" msgstr "Uključi pjesme u gornjem nivou" msgid "Enqueue" msgstr "Zakaži" msgid "Add track to the Audacious play queue" msgstr "Dodaj pjesmu u Audacious red čekanja" msgid "Dequeue" msgstr "Ukloni red čekanja" msgid "Remove track from the Audacious play queue" msgstr "Ukloni pjesmu sa Audacious reda čekanja" msgid "Play" msgstr "Reproduciraj" msgid "Jump to track in Audacious" msgstr "Idi na pjesmu u Audaciousu" msgid "Resume playback in Audacious" msgstr "Nastavi reproduciranje u Audaciousu" msgid "Pause" msgstr "Pauza" msgid "Pause playback in Audacious" msgstr "Pauziraj reproduciranje u Audaciousu" msgid "Next" msgstr "Sljedeći" msgid "Jump to next track in Audacious" msgstr "Idi na sljedeću pjesmu u Audaciousu" msgid "Previous" msgstr "Prethodna" msgid "Jump to previous track in Audacious" msgstr "Idi na prethodnu pjesmu u Audaciousu" msgid "Clear Queue" msgstr "Obriši zakazano" msgid "Clear the Audacious play queue" msgstr "Očisti red čekanja na izvođenje u Audacious" msgid "Shuffle" msgstr "Izmiješaj" msgid "Toggle shuffle in Audacious" msgstr "Miješanje žabice u Audaciousu" msgid "Repeat" msgstr "Ponovi" msgid "Toggle repeat in Audacious" msgstr "Ponavljanje žabice u Audaciousu" msgid "Show Playing" msgstr "Prikaži izvođenje" msgid "Tell which song is currently playing" msgstr "Reci koja je pjesma trenutno puštena" msgid "Playlist" msgstr "Lista pjesama" msgid "Calculator" msgstr "Kalkulator" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "Izračunaj" msgid "Clipboards" msgstr "Međuspremnici" msgid "Recent clipboards and clipboard proxy objects" msgstr "Skoriji međusprenminici i proxy objekti međuspremnika" msgid "Number of recent clipboards to remember" msgstr "Broj skorijih međuspremnika za pamćenje" msgid "Include selected text in clipboard history" msgstr "Uključi odabrani tekst u historiju međuspremnika" msgid "Copy selected text to primary clipboard" msgstr "Kopiraj odabrani tekst na pirmarni međuspremnik" msgid "Selected Text" msgstr "Odabrani tekst" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Odlagalište s %(num)d linijom \"%(desc)s\"" msgstr[1] "Odlagalište s %(num)d linije \"%(desc)s\"" msgstr[2] "Odlagalište s %(num)d linija \"%(desc)s\"" msgid "Clipboard Text" msgstr "Tekst međuspremnika" msgid "Clipboard File" msgstr "Datoteka u međuspremniku" msgid "Clipboard Files" msgstr "Datoteke u odlagalištu" msgid "Clear" msgstr "Očisti" msgid "Remove all recent clipboards" msgstr "Ukloni sve skorije međuspremnike" msgid "Shell Commands" msgstr "Komande školjke" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Pokreni programe komandnih linija. Akcije označene simbolom %s pokreni u " "podškoljci." msgid "Run (Get Output)" msgstr "Pokrene (Uzmi izlaz)" msgid "Run program and return its output" msgstr "Pokreni program i vrati njegov izlaz" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "Proslijedi komandi..." msgid "Run program with object as an additional parameter" msgstr "Pokreni program sa objektom kao dodatnim parametrom" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "Piši za naredbu..." msgid "Run program and supply text on the standard input" msgstr "Pokreni program i obezbijedi tekst na standardnom ulazu" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "Filter kroz Komandu..." msgid "Run command-line programs" msgstr "Pokreni programe komandne linije" msgid "GTK+" msgstr "GTK+" msgid "GNOME Terminal" msgstr "GNOME terminal" msgid "XFCE Terminal" msgstr "XFCE Terminal" msgid "LXTerminal" msgstr "LXTerminal" msgid "X Terminal" msgstr "X Terminal" msgid "Urxvt" msgstr "Urxvt" msgid "Konsole" msgstr "Konzola" msgid "Save As..." msgstr "Snimi kao..." #, fuzzy msgid "Restart Kupfer" msgstr "Ponovo pokreni uslugu" msgid "Quit" msgstr "Završi (Quit)" msgid "Quit Kupfer" msgstr "Završi Kupfer" msgid "About Kupfer" msgstr "O Kupferu" msgid "Show information about Kupfer authors and license" msgstr "Prikaži informacije o Kupferovim autorima i licenci" msgid "Kupfer Help" msgstr "Kupfer pomoć" msgid "Get help with Kupfer" msgstr "Nađi pomoć sa Kupferom" msgid "Show preferences window for Kupfer" msgstr "Prikaži prozor sa postavkama za Kupfer" msgid "Search Contents" msgstr "Pretraži sadržaj" msgid "Search inside this catalog" msgstr "Pretraži unutar ovog kataloga" msgid "Copy" msgstr "Kopiraj" msgid "Copy to clipboard" msgstr "Kopiraj na međuspremnik" msgid "Rescan" msgstr "Ponovo skeniraj" msgid "Force reindex of this source" msgstr "Nasilno ponovno indeksiraj ovaj izvor" msgid "Last Command" msgstr "Zadnja komanda" msgid "Internal Kupfer Objects" msgstr "Interni Kupfer Objekti" msgid "Last Result" msgstr "Posljednji Rezultat" msgid "Command Results" msgstr "Komandni rezultati" msgid "Custom Terminal" msgstr "Kastomizirani terminal" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Naredba" msgid "Execute flag" msgstr "Izvršna zastavica" msgid "Default Email Client" msgstr "Predodređeni e-mail klijent" msgid "Compose email using the system's default mailto: handler" msgstr "Sastavi e-mail koristeći predodređeni sistemski mailto: rukovatelj" #, fuzzy msgid "Compose Email To" msgstr "Sastavi e-poštu" msgid "Dictionary" msgstr "Rječnik" msgid "Look up word in dictionary" msgstr "Potraži riječ u rječniku" msgid "Look Up" msgstr "Potraži" msgid "Documents" msgstr "Dokumenti" msgid "Recently used documents and bookmarked folders" msgstr "Skoro korišteni dokumenti i spašeni folderi" msgid "Max recent document days" msgstr "Najskoriji dani dokumenta" msgid "Recent Items" msgstr "Skorašnje stavke" msgid "Recently used documents" msgstr "Skoro korišteni dokumenti" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "%s Dokumenti" #, python-format msgid "Recently used documents for %s" msgstr "Skoro korišteni dokumenti za %s" msgid "Places" msgstr "Mjesta" msgid "Bookmarked folders" msgstr "Zapamćeni folder" msgid "DuckDuckGo Search" msgstr "DuckDuckGo pretraga" msgid "Search the web securely with DuckDuckGo" msgstr "Pretraži sigurno web koristeći DuckDuckGo" msgid "Favorites" msgstr "Omiljeni" msgid "Mark commonly used items and store objects for later use" msgstr "Označi najviše korištene stavke i spasi objekte za kasniju upotrebu" msgid "Shelf of \"Favorite\" items" msgstr "Polica \"Omiljenih\" objekata" msgid "Add to Favorites" msgstr "Dodaj u Omiljene" msgid "Add item to favorites shelf" msgstr "Dodaj stavku u policu omiljenih" msgid "Remove from Favorites" msgstr "Ukloni iz omiljenih" msgid "Remove item from favorites shelf" msgstr "Ukloni stavku iz police omiljenih" msgid "File Actions" msgstr "Akcije fajla" msgid "More file actions" msgstr "Više akcija fajla" msgid "Move To..." msgstr "Pomjeri u..." msgid "Move file to new location" msgstr "Pomjeru fajl na novu lokaciju" msgid "Rename To..." msgstr "Preimenuj u..." msgid "Copy To..." msgstr "Kopiraj u..." msgid "Copy file to a chosen location" msgstr "Kopiraj fajl u odabranu lokaciju" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "Glom" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "Akcije višeg reda" msgid "Tools to work with commands as objects" msgstr "Alati za rad sa naredbama kao objektima" msgid "Select in Kupfer" msgstr "Odaberi u Kupfer-u" #, python-format msgid "Result of %s (%s)" msgstr "Rezultati %s (%s)" msgid "Run (Take Result)" msgstr "Pokreni (Uzmi rezultat)" msgid "Take the command result as a proxy object" msgstr "Uzmi rezultat naredbe kao proxy objekat" msgid "Run (Discard Result)" msgstr "Pokreni (Odbaci rezultat)" msgid "Image Tools" msgstr "Slikovni alati" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Alati za transformaciju slike" msgid "Scale..." msgstr "Povećaj/smanji ..." msgid "Scale image to fit inside given pixel measure(s)" msgstr "Skaliraj sliku da stane u zadanu mjeru tečaka" msgid "Rotate Clockwise" msgstr "Rotiraj u smjeru kazaljke na satu" msgid "Rotate Counter-Clockwise" msgstr "Rotiraj suprotno od smjera kazaljke na satu" msgid "Autorotate" msgstr "Sam rotiraj" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "Rotiraj JPEG (na mjestu) prema njegovim EXIF metapodacima" msgid "Kupfer Plugins" msgstr "Kupfer dodaci" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Pristupi Kupferovoj listi dodataka u Kupfer-u" msgid "Show Information" msgstr "Prikaži obavještenje" msgid "Show Source Code" msgstr "Prikaži izvorni kod" msgid "enabled" msgstr "omogućen" msgid "disabled" msgstr "onemogućen" msgid "Notes" msgstr "Bilješke" msgid "Gnote or Tomboy notes" msgstr "Gnote ili Tomboy zabilješke" msgid "Work with application" msgstr "Rad sa aplikacijom" msgid "Open with notes application" msgstr "Otvori sa aplikacijom bilješki" msgid "Append to Note..." msgstr "Dodaj u zabilješku..." msgid "Add text to existing note" msgstr "Dodaj tekst u postojeću zabilješku" msgid "Create Note" msgstr "Kreiraj Bilješku" msgid "Create a new note from this text" msgstr "Kreiraj novu bilješku od ovog teksta" msgid "Get Note Search Results..." msgstr "Uzmi rezultate pretrage bilješke..." msgid "Show search results for this query" msgstr "Prikaže rezultate pretrage za ovaj upit" #, python-format msgid "today, %s" msgstr "danas, %s" #, python-format msgid "yesterday, %s" msgstr "juče, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Zadnji ažuriran %s" msgid "Quicksilver Icons" msgstr "Quicksilver ikone" msgid "Quick Image Viewer" msgstr "Quicksilver preglednik slika" msgid "View Image" msgstr "Pogledaj sliku" msgid "GNU Screen" msgstr "GNU ekran" msgid "Active GNU Screen sessions" msgstr "Aktivne sesije GNU ekrana" msgid "Attached" msgstr "Zakačen" msgid "Detached" msgstr "Odvojeno" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "%(status)s sesija (%(pid)s) kreirana %(time)s" msgid "Screen Sessions" msgstr "Sesije ekrana" msgid "Attach" msgstr "Priloži" msgid "Send Keys" msgstr "Pošalji tipke" msgid "Send synthetic keyboard events using xautomation" msgstr "Pošlji sintetičke događaje na tastaturi koristeći xautomation" msgid "Paste to Foreground Window" msgstr "Zalijepi na prednji prozor" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "Kopiraj u spojnu ploču i pošalji Ctrl+V na prednji prozor" msgid "Send keys to foreground window" msgstr "Pošalji tipke na prednji prozor" msgid "Type Text" msgstr "Kucajte tekst" msgid "Type the text to foreground window" msgstr "Kucajte tekst u prednji prozor" msgid "GNOME Session Management" msgstr "GNOME Menadžment sesija" msgid "Special items and actions for GNOME environment" msgstr "Specijalne stavke i akcije za GNOME okruženje" msgid "Log Out..." msgstr "Odjavi se..." msgid "Log out or change user" msgstr "Odjavi se ili promijeni korisnika" msgid "Shut Down..." msgstr "Ugasi..." msgid "Shut down, restart or suspend computer" msgstr "Ugasi, restartuj ili obustavi računar" msgid "Lock Screen" msgstr "Zaključaj ekran" msgid "Enable screensaver and lock" msgstr "Omogući screensaver i zaključavanje" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "XFCE Menadžment sesija" msgid "Special items and actions for XFCE environment" msgstr "Specijalne stavke i akcije za XFCE okruženje" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "SSH Hosts" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "Dodaje SSH domaćine nađene u ~/.ssh/config." msgid "SSH host" msgstr "SSH domaćin" msgid "Connect" msgstr "Poveži" msgid "Connect to SSH host" msgstr "Poveži se sa SSH domaćinom" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "SSH domaćin specificiran u ~/.ssh/config" msgid "No D-Bus connection to desktop session" msgstr "Nema D-Bus veze u desktop sesiji" msgid "GNOME Keyring" msgstr "GNOME PrstenKljučeva" msgid "KWallet" msgstr "K‑novčanik" msgid "Unencrypted File" msgstr "Šifrovani fajl" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "Komanda u \"%s\" nije dostupna" msgid "Document Templates" msgstr "Predlosci dokumenta" msgid "Create new documents from your templates" msgstr "Kreirajte novi dokument od vaših predložaka" #, python-format msgid "%s template" msgstr "%s predložak" msgid "Empty File" msgstr "Prazna datoteka" msgid "New Folder" msgstr "Novi Direktorij" msgid "Create New Document..." msgstr "Kreiraj novi dokument..." msgid "Create a new document from template" msgstr "Kreiraj novi dokument od predloška" msgid "Create Document In..." msgstr "Kreiraj dokument u..." msgid "Textfiles" msgstr "Tekstualni fajlovi" msgid "Append To..." msgstr "Dodaj u..." msgid "Append..." msgstr "Dodaj..." msgid "Write To..." msgstr "Piši u..." msgid "Get Text Contents" msgstr "Uzmi tekstualne sadržaje" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "Akcije menadžera datoteka Thunar" msgid "Select in File Manager" msgstr "Odaberi u Menadžeru datoteka" msgid "Show Properties" msgstr "Prikaži karakteristike" msgid "Show information about file in file manager" msgstr "Prikaži informacije o menadžeru datoteka" msgid "Send To..." msgstr "Pošalji na..." msgid "Symlink In..." msgstr "Symlink u..." msgid "Create a symlink to file in a chosen location" msgstr "Kreiraj symlink na fajl u odabranoj lokaciji" msgid "Empty Trash" msgstr "Isprazni smeće" msgid "Thunar Send To Objects" msgstr "Thunar šalji u objekte" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Thunderbird/Icedove kontakti i akcije" msgid "Compose New Email" msgstr "Sastavi novi e-mail" msgid "Compose a new message in Thunderbird" msgstr "Sastavi novu poruku u Thunderbird-u" #, fuzzy msgid "Attach in Email To..." msgstr "Pošalje e-mail..." #, fuzzy msgid "Compose Email With" msgstr "Sastavi e-poštu" #, fuzzy msgid "Compose a new message using the text as body" msgstr "Sastavi novu poruku u Thunderbird-u" msgid "Thunderbird Address Book" msgstr "Thunderbird adresar" msgid "Contacts from Thunderbird Address Book" msgstr "Kontakti iz adresara Thunderbird-a" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Na vrhu" msgid "Show running tasks and allow sending signals to them" msgstr "Prikaži tekuće zadatke i dopusti slanje signala prema njima" msgid "Sort Order" msgstr "Sortiraj Red" msgid "Commandline" msgstr "Komandna linija" msgid "CPU usage (descending)" msgstr "Zauzetost procesora (opadajuće)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Zauzeće memorije (opadajuće)" msgid "Send Signal..." msgstr "Šalji signal..." msgid "Signals" msgstr "Signali" msgid "Running Tasks" msgstr "Tekući zadaci" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgid "Running tasks for current user" msgstr "Tekući zadaci za trenutnog korisnika" msgid "Trash" msgstr "Kanta" msgid "Access trash contents" msgstr "Pristupi sadržaju kante" msgid "Move to Trash" msgstr "Baci u smeće" msgid "Move this file to trash" msgstr "Premjesti ovaj fajl u kantu" msgid "Restore" msgstr "Obnovi" msgid "Move file back to original location" msgstr "Premjesti fajl natrag u originalnu lokaciju" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "Kanta je prazna" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "Smeće sadrži %(num)s datoteku" msgstr[1] "Smeće sadrži %(num)s datoteke" msgstr[2] "Smeće sadrži %(num)s datoteka" msgid "Triggers" msgstr "Okidači" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Dodijeli globalno povezivanje tipki (okidače) objektima kreiranim pomoću " "'Compose Command'." msgid "Add Trigger..." msgstr "Dodaj okidač..." msgid "Remove Trigger" msgstr "Ukloni okidač" msgid "URL Actions" msgstr "URL Akcije" msgid "Download and Open" msgstr "Skini i Otvori" msgid "Download To..." msgstr "Skini u..." msgid "Download URL to a chosen location" msgstr "Skini URL u odabranu lokaciju" msgid "Wikipedia" msgstr "Wikipedia" msgid "Search in Wikipedia" msgstr "Traži u Wikipedii" msgid "Wikipedia language" msgstr "Jezik Wikipedije" #. TRANS: Default wikipedia language code msgid "en" msgstr "eng" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Traži ovaj pojam u %s.wikipedia.org" msgid "Window List" msgstr "Lista Prozora" msgid "All windows on all workspaces" msgstr "Svi prozori na svim radnim prostorima" msgid "Activate" msgstr "Aktiviraj" msgid "Shade" msgstr "Sijenčenje" msgid "Unshade" msgstr "Bez sjenčenja" msgid "Minimize" msgstr "Minimiziraj" msgid "Unminimize" msgstr "Ne minimiziraj" msgid "Maximize" msgstr "Maksimiziraj" msgid "Unmaximize" msgstr "Ne maksimiziraj" msgid "Maximize Vertically" msgstr "Uvećaj vertikalno" msgid "Unmaximize Vertically" msgstr "Ne maksimiziraj vertikalno" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Prozor na %(wkspc)s" msgid "Frontmost Window" msgstr "Prozor ispred svih" msgid "Next Window" msgstr "Sljedeći prozor" msgid "Jump to this window's workspace and focus" msgstr "Skoči na radni prostor ovog prozora i fokusiraj" # translations. #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "%d prozor" msgstr[1] "%d prozora" msgstr[2] "%d prozora" msgid "Active workspace" msgstr "Aktivni radni prostori" msgid "Jump to this workspace" msgstr "Skoči na ovaj radni prostor" msgid "Workspaces" msgstr "Radni prostori" msgid "Volumes and Disks" msgstr "Volumeni i Diskovi" msgid "Mounted volumes and disks" msgstr "Montirani volumeni i diskovi" #, python-format msgid "Volume mounted at %s" msgstr "Volumen montiran na %s" msgid "Unmount" msgstr "Demontiraj" msgid "Unmount this volume" msgstr "Demontiraj ovaj volumen" msgid "Eject" msgstr "Izbaci" msgid "Unmount and eject this media" msgstr "Demontiraj i izbaci ovaj uređaj" msgid "Show Text" msgstr "Prikaži tekst" msgid "Display text in a window" msgstr "Prikaži tekst u prozoru" msgid "Large Type" msgstr "Veliki tip" msgid "Show Notification" msgstr "Prikaži obavijesti" msgid "Tracker" msgstr "Pratilac" msgid "Tracker desktop search integration" msgstr "Integracija desktop pretraga pratioca" msgid "Search in Tracker" msgstr "Traži u Pratiocu" msgid "Open Tracker Search Tool and search for this term" msgstr "Otvori Tracker Search Tool i traži ovaj pojam" msgid "Get Tracker Results..." msgstr "Uzmi rezultate Pratioca..." msgid "Show Tracker results for query" msgstr "Prikaži rezultate Pratioca za upit" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "Razultati za \"%s\"" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "Lociraj fajlove" msgid "Search filesystem using locate" msgstr "Pretraži filesystem koristeći locate" msgid "Ignore case distinctions when searching files" msgstr "Ignoriraj razliku između velikih i malih slova prilikom pretrage" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Firefox oznake" msgid "Index of Firefox bookmarks" msgstr "Index Firefox oznaka" #, fuzzy msgid "Firefox Keywords" msgstr "Firefox oznake" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "Pretražite web sa OpenSearch pretraživačem" msgid "Search With..." msgstr "Pretraži sa..." msgid "Search For..." msgstr "Traži..." #, fuzzy msgid "Search Terms" msgstr "Motori pretrage" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Molimo koristite \"%s\"" #, fuzzy msgid "Resume playback" msgstr "Nastavi reproduciranje u Audaciousu" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Sljedeći" #, fuzzy msgid "Skip to next track" msgstr "Idi na sljedeću pjesmu u Audaciousu" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Prethodna" #, fuzzy msgid "Skip to previous track" msgstr "Idi na prethodnu pjesmu u Audaciousu" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "Pristupi Pidgin Kontaktima" msgid "Show offline contacts" msgstr "Prikaži odjavljene kontakte" msgid "Open Chat" msgstr "Otvoreno ćaskanje" # translations. #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d znak)" msgstr[1] "%s (%d znaka)" msgstr[2] "%s (%d znakova)" msgid "Send Message..." msgstr "Pošalji poruku..." msgid "Available" msgstr "Dostupno" msgid "Away" msgstr "Odsutnost" msgid "Pidgin Contacts" msgstr "Pidgin kontakti" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Skraćeni linkovi" msgid "Create short aliases of long URLs" msgstr "Kreiraj kratke nadimke za duge URL-ove" msgid "Error" msgstr "Greška" msgid "Shorten With..." msgstr "Skraćena sa..." msgid "Services" msgstr "Servisi" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "Pusti i dodaj pjesme i pretraži muzičku biblioteku" msgid "Include artists in top level" msgstr "Uključi izvođače u gornjem nivou" msgid "Include albums in top level" msgstr "Uključi albume u gornjem nivou" msgid "Play tracks in Rhythmbox" msgstr "Pusti numere u ritam mašini" msgid "Add tracks to the play queue" msgstr "Dodaj numere u zakazane za puštanje" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "od %(artist)s sa albuma %(album)s" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "od %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Pjesme od %s" msgid "Albums" msgstr "Albumi" msgid "Music albums in Rhythmbox Library" msgstr "Muzički albumi u biblioteci ritam mašine" msgid "Artists" msgstr "Izvođači" msgid "Music artists in Rhythmbox Library" msgstr "Muzički izvođači u biblioteci ritam mašine" msgid "Songs" msgstr "Pjesme" msgid "Songs in Rhythmbox library" msgstr "Pjesme u biblioteci ritam mašine" msgid "Getting Things GNOME" msgstr "Getting Things GNOME" msgid "Browse and create new tasks in GTG" msgstr "Pretražuj i kreiraj nove zadatke u GTG-u" #, python-format msgid "due: %s" msgstr "zahvaljujući: %s" #, python-format msgid "start: %s" msgstr "počni: %s" #, python-format msgid "tags: %s" msgstr "oznake: %s" msgid "Open task in Getting Things GNOME!" msgstr "Otvori zadatak u Getting Things GNOME!" msgid "Delete" msgstr "Obriši" msgid "Permanently remove this task" msgstr "Zauvijek obriši ovaj zadatak" msgid "Mark Done" msgstr "Označi kao gotovo" msgid "Mark this task as done" msgstr "Označi zadatak kao izvršen" msgid "Dismiss" msgstr "Odbaci" msgid "Mark this task as not to be done anymore" msgstr "Označi ovaj zadatak kao da se ne treba raditi više" msgid "Create Task" msgstr "Kreiraj Zadatak" msgid "Create new task in Getting Things GNOME" msgstr "Kreiraj novi zadatak u Getting Things GNOME" msgid "Devhelp" msgstr "DevHelp" msgid "Search in Devhelp" msgstr "Traži u Devhelp-u" msgid "Empathy" msgstr "Empathy" msgid "Access to Empathy Contacts" msgstr "Pristupi Empathy kontaktima" msgid "Busy" msgstr "Zauzeto" msgid "Not Available" msgstr "Nedostup(an/na)" msgid "Invisible" msgstr "Nevidljiv" msgid "Offline" msgstr "Izvan mreže" msgid "Change Global Status To..." msgstr "Promijeni Globalni status u..." msgid "Empathy Contacts" msgstr "Empathy kontakti" msgid "Empathy Account Status" msgstr "Status Empathy naloga" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Alt Aktiviraj" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Trik zareza" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Sastavi komandu" msgid "Mark Default Action" msgstr "Markiraj predodređenu akciju" msgid "Forget Object" msgstr "Zaboravi objekt" msgid "Reset All" msgstr "Resetuj sve" msgid "Select Quit" msgstr "Odaberi Izlaz" msgid "Select Selected File" msgstr "Odaberi odabrani fajl" msgid "Select Selected Text" msgstr "Odaberi odabrani tekst" msgid "Show Help" msgstr "Pokaži pomoć" msgid "Show Preferences" msgstr "Prikaži Postavke" msgid "Switch to First Pane" msgstr "Prebaci na prvi panel" msgid "Toggle Text Mode" msgstr "Tekst mod žabice" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Nema poklapanja %(src)s sa \"%(query)s\"" msgid "No matches" msgstr "Nema poklapanja" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Nema poklapanja" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Napravi \"%(action)s\" predodređenim za \"%(object)s\"" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "Zaboravi na \"%s\"" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Prikaži glavno sučelje" msgid "Show with Selection" msgstr "Prikaži sa izborom" #. TRANS: Plugin info fields msgid "Description" msgstr "Opis" msgid "Author" msgstr "Autor" msgid "Version" msgstr "Verzija" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Python modul '%s' je potreban" msgid "Plugin could not be read due to an error:" msgstr "Dodatak se ne može pročitati zbog greške:" msgid "Content of" msgstr "Sadržaj" #. TRANS: Plugin contents header msgid "Sources" msgstr "Izvorni" #. TRANS: Plugin contents header msgid "Actions" msgstr "Radnje" #, python-format msgid "Using encrypted password storage: %s" msgstr "Koristim šifrovano spašavanje lozinki: %s" #, python-format msgid "Using password storage: %s" msgstr "Koristim spašavanje lozinski: %s" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Postavke" msgid "Set username and password" msgstr "Postavi korisničko ime i lozinku" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Odaberite direktorij" msgid "Reset all shortcuts to default values?" msgstr "Restujte sve prečice na predodređene vrijednosti?" msgid "Shortcut" msgstr "Prečica" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "" " Adem Jevric https://launchpad.net/~ajevric1\n" " Samir Ribić https://launchpad.net/~megaribi" msgid "A free software (GPLv3+) launcher" msgstr "Besplatni softver (GPLv3+) pokretač" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Ovaj program je besplatan: možete ga redistribuirati i/ili modificirati\n" "pod uvjetima GNU General Public Licence objavljene kao\n" "Free Software Foundation, ili verzije 3 Licence, ili\n" "(po vašem izboru) bili koje kasnije verzije.\n" "\n" "Ovaj program se redistribuira u nadi da će biti koristan,\n" "ali BEZ IKAKVE GARANCIJE; čak i bez podrazumijevane garancije\n" "PRODAJE ili VJEŽBE ZA ODREĐENU SVRHU. Pogledajte\n" "GNU General Public Licencu za više detalja.\n" "\n" "Trebalo bi da ste dobili kopiju GNU General Public Licence\n" "sa ovim programom. Ako niste, pogledajte .\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Ne mogu naći pokrenuti Kupfer" #~ msgid "Compose Email" #~ msgstr "Sastavi e-poštu" #~ msgid "Send in Email To..." #~ msgstr "Pošalje e-mail..." #~ msgid "Type to search %s" #~ msgstr "Kucaj za pretragu %s" #~ msgid "No action" #~ msgstr "Nema akcije." #~ msgid "GNOME Terminal Profiles" #~ msgstr "GNOME Profili terminala" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Lansiraj GNOME profile terminala" #~ msgid "Multihead Support" #~ msgstr "Višestruka podrška" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Računaj izraze koji počinju sa '='" #~ msgid "Epiphany Bookmarks" #~ msgstr "Zabilješke iz programa Epiphany" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Index epiphany bookmarka" #~ msgid "Include visited sites" #~ msgstr "Uključi posjećene stranice" #~ msgid "Firefox tag" #~ msgstr "Firefox oznaka" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Nastavi reproduciranje u ritam mašini" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Pauziraj reproduciranje u ritam mašini" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Idi na sljedeću numeru u ritam mašini" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Idi na prethodnu numeru u ritam mašini" #~ msgid "Search the Web" #~ msgstr "Pretražite web" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Skoro korišteni dokumenti u Abiwordu" #~ msgid "Abiword Recent Items" #~ msgstr "Skoro korištene stavke u Abiwodu" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "Sučelje sa APT menadžer paketom" #~ msgid "Installation method" #~ msgstr "Metod instalacije" #~ msgid "Show Package Information" #~ msgstr "Prikaži informacije paketa" #~ msgid "Install" #~ msgstr "Instaliraj" #~ msgid "Install package using the configured method" #~ msgstr "Instaliraj paket koristeći konfigurisanu metudu" #~ msgid "Packages matching \"%s\"" #~ msgstr "Podudarni paketi \"%s\"" #~ msgid "Search Package Name..." #~ msgstr "Pretraži ime paketa..." #~ msgid "Ascii & Unicode Icon Set" #~ msgstr "Ascii & Unicode skup ikona" #~ msgid "" #~ "Provides the Ascii and Unicode icon sets that use letters and symbols to " #~ "produce icons for the objects found in Kupfer." #~ msgstr "" #~ "Obezbjeđuje Ascii i Unicode skupove ikona koje koriste slova i simbole da " #~ "proizvedu ikone za objekte u Kupferu." #~ msgid "Ascii" #~ msgstr "Ascii" #~ msgid "Unicode" #~ msgstr "Unicode" #~ msgid "Chromium Bookmarks" #~ msgstr "Chromium oznake" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Indeks Chromium oznake" #~ msgid "Claws Mail" #~ msgstr "Claws pošta" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Kontakti Claws pošte i akcije" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Sastavi novu poruku u Claws Mail-u" #~ msgid "Receive All Email" #~ msgstr "Primi sve e-mailove" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "Primi nove poruke od svih naloga u Claws Mail-u" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Sastavi novu poruku u Claws Mail-u i zakači fajl" #~ msgid "Claws Mail Address Book" #~ msgstr "Claws Mail adresar" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Kontakti iz Claws Mail adresara" #~ msgid "Configure a custom terminal emulator" #~ msgstr "Konfiguriraj kastomizirani simulator terminala" #~ msgid "Custom Theme" #~ msgstr "Prilagođena tema" #~ msgid "Use a custom color theme" #~ msgstr "Koristi kastomiziranu šemu boja" #~ msgid "Theme:" #~ msgstr "Tema:" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Evolution kontakti" #~ msgid "Compose a new message in Evolution" #~ msgstr "Sastavi novu poruku u Evolution-u" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Sastavi novu poruku u Evolution-u i zakači fajl" #~ msgid "Evolution Address Book" #~ msgstr "Evolution adresar" #~ msgid "Filezilla" #~ msgstr "Filezilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Prikaži stranice i rukuj ftp adresama pomoću Filezilla-e" #~ msgid "Open Site with Filezilla" #~ msgstr "Otvori stranicu pomoću Filezilla-e" #~ msgid "Filezilla Sites" #~ msgstr "Filezilla stranice" #~ msgid "Sites from Filezilla" #~ msgstr "Stranice sa Filezilla-e" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Pristupi Gajim kontaktima" #~ msgid "Free for Chat" #~ msgstr "Slobodan za chat" #~ msgid "Gajim Contacts" #~ msgstr "Gajim kontakti" #~ msgid "Gajim Account Status" #~ msgstr "Statusi Gajim kontakata" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Učitaj kontakte i sastavi novi e-mail u Gmail-u" #~ msgid "Load contacts' pictures" #~ msgstr "Učitaj slike kontakata" #~ msgid "Load additional information" #~ msgstr "Učitaj dodatne informacije" #~ msgid "Work email" #~ msgstr "Poslovna el. pošta" #~ msgid "Home email" #~ msgstr "Lični e-mail" #~ msgid "Other email" #~ msgstr "Drugi e-mail" #~ msgid "Work address" #~ msgstr "Adresa na poslu" #~ msgid "Home address" #~ msgstr "Kućna adresa" #~ msgid "Other address" #~ msgstr "Druga adresa" #~ msgid "Car phone" #~ msgstr "Telefon u autu" #~ msgid "Fax" #~ msgstr "Faks" #~ msgid "Home phone" #~ msgstr "Kućni telefon" #~ msgid "Home fax" #~ msgstr "Kućni faks" #~ msgid "Internal phone" #~ msgstr "Interni telefon" #~ msgid "Mobile" #~ msgstr "Mobilno" #~ msgid "Other" #~ msgstr "Ostalo" #~ msgid "VOIP" #~ msgstr "VOIP" #~ msgid "Work phone" #~ msgstr "Radni telefon" #~ msgid "Work fax" #~ msgstr "Radni faks" #~ msgid "Compose Email in Gmail" #~ msgstr "Sastavi e-mail u Gmail-u" #~ msgid "Open web browser and compose new email in Gmail" #~ msgstr "Otvori web pretraživač i sastavi novi e-mail u Gmail-u" #~ msgid "Edit Contact in Gmail" #~ msgstr "Uredi kontakt u Gmail-u" #~ msgid "Open web browser and edit contact in Gmail" #~ msgstr "Otvori web pretraživač i uredi kontakt u Gmail-u" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Kontakti Google sevisa (Gmail)" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Prikaži albume i uploaduj fajlove u Picasa-u" #~ msgid "Users to show: (,-separated)" #~ msgstr "Korisnici za prikazati: (,-odvojeno)" #~ msgid "Load user and album icons" #~ msgstr "Učitaj ikone korisnika i albuma" #~ msgid "Uploading Pictures" #~ msgstr "Nabacujem slike" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Nabacujem slike u Picasa web album" #~ msgid "Creating album:" #~ msgstr "Kreiram album:" #~ msgid "Album created by Kupfer" #~ msgstr "Album kreiran od strane Kupfer-a" #~ msgid "File:" #~ msgstr "Fajl:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "%(num)d album" #~ msgstr[1] "%(num)d albuma" #~ msgstr[2] "%(num)d albuma" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "%(num)s slika" #~ msgstr[1] "%(num)s slike" #~ msgstr[2] "%(num)s slika" #~ msgid "Upload to Picasa Album..." #~ msgstr "Nakači na Picasa album..." #~ msgid "Upload files to Picasa album" #~ msgstr "Nakači fajlove na Picasa album" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Nakači na Picasa-u kao Novi album" #~ msgid "Create album from selected local directory" #~ msgstr "Kreiraj album iz odabranog lokalnog direktorija" #~ msgid "Picasa Albums" #~ msgstr "Picasa albumi" #~ msgid "User albums in Picasa" #~ msgstr "Korisnički albumi u Picasa-i" #~ msgid "Google Search" #~ msgstr "Google pretraga" #~ msgid "Search Google with results shown directly" #~ msgstr "Pretraži Google sa rezultatima prikazanim direktno" #~ msgid "Show More Results For \"%s\"" #~ msgstr "Prikaži još rezultata za \"%s\"" #~ msgid "%s total found" #~ msgstr "%s ukupno nađeno" #~ msgid "Gwibber" #~ msgstr "Gwibber" #~ msgid "" #~ "Microblogging with Gwibber. Allows sending and receiving messages from " #~ "social networks like Twitter, Identi.ca etc. Requires the package " #~ "'gwibber-service'." #~ msgstr "" #~ "Malo blogovanje sa Gwibber-om. Omogućava slanje i primanje poruka sa " #~ "socijlnih mreža kao što su Twitterm, Identi.ca itd. Zahtijeva paket " #~ "'gwibber-service'." #~ msgid "Maximum number of messages to show" #~ msgstr "Maksimalan broj poruka za prikazati" #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s na %(service)s" #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s na %(where)s" #~ msgid "Send Message" #~ msgstr "Pošalji poruku" #~ msgid "Send message to all Gwibber accounts" #~ msgstr "Pošalji poruku svim Gwibber nalozima" #~ msgid "Send Message To..." #~ msgstr "Pošalji poruku..." #~ msgid "Send message to a Gwibber account" #~ msgstr "Pošalji poruku Gwibber nalogu" #~ msgid "Send message to selected Gwibber account" #~ msgstr "Pošalji poruku odabranom Gwibber nalogu" #~ msgid "Reply..." #~ msgstr "Odgovaram..." #~ msgid "Delete Message" #~ msgstr "Obriši poruku" #~ msgid "Send Private Message..." #~ msgstr "Pošalji privatnu poruku..." #~ msgid "Send direct message to user" #~ msgstr "Pošalji direktnu poruku korisniku" #~ msgid "Retweet" #~ msgstr "Retweet-uj" #~ msgid "Retweet To..." #~ msgstr "Retweet-uj..." #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Retweeetuj poruku svim Gwibber nalozima" #~ msgid "Retweet message to a Gwibber account" #~ msgstr "Retweet-uj poruku Gwibber nalogu" #~ msgid "Open in Browser" #~ msgstr "Otvori u Pretraživaču" #~ msgid "Open message in default web browser" #~ msgstr "Otvori poruku u predodređenom web pretraživaču" #~ msgid "Gwibber Accounts" #~ msgstr "Gwibber nalozi" #~ msgid "Accounts configured in Gwibber" #~ msgstr "Nalozi konfigurirani u Gwibber-u" #~ msgid "Gwibber Messages" #~ msgstr "Gwibber poruke" #~ msgid "Recent messages received by Gwibber" #~ msgstr "Skorije poruke primljene preko Gwibber-a" #~ msgid "Gwibber Messages for %s" #~ msgstr "Gwibber poruke za %s" #~ msgid "Gwibber Streams" #~ msgstr "Gwibber streamovi" #~ msgid "Streams configured in Gwibber" #~ msgstr "Streamovi konfigurirani u Gwibber-u" #~ msgid "Gwibber Messages in %s" #~ msgstr "Gwibber poruke u %s" #~ msgid "Gwibber (Simple)" #~ msgstr "Gwibber(Jednostavno)" #~ msgid "Send updates via the microblogging client Gwibber" #~ msgstr "Šalji ažuriranja preko klijenta za mikroblogiranje Gwibber-a" #~ msgid "Send Update" #~ msgstr "Požalji ažuriranje" #~ msgid "Unable to activate Gwibber service" #~ msgstr "Ne može se aktivirati Gwibber servis" #~ msgid "OpenOffice / LibreOffice" #~ msgstr "OpenOffice / LibreOffice" #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Skoro korišteni dokumenti u OpenOffice / LibreOffice-u" #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "OpenOffice / LibreOffice skorije stavke" #~ msgid "Opera Mail" #~ msgstr "Opera Mail" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Opera Mail kontakti i akcije" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Sastavi novu poruku u Opera Mail-u" #~ msgid "Opera Mail Contacts" #~ msgstr "Opera Mail kontakti" #~ msgid "Contacts from Opera Mail" #~ msgstr "Kontakti iz Opera Mail-a" #~ msgid "Opera Bookmarks" #~ msgstr "Opera oznake" #~ msgid "Index of Opera bookmarks" #~ msgstr "Indey Opera oznaka" #~ msgid "PuTTY Sessions" #~ msgstr "PuTTY sesije" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Brzi pristup PuTTY sesijama" #~ msgid "Start Session" #~ msgstr "Pokreni sesiju" #~ msgid "reStructuredText" #~ msgstr "reStructuredText" #~ msgid "Render reStructuredText and show the result" #~ msgstr "Renderuj reStructuredText i prikaži rezultat" #~ msgid "View as HTML Document" #~ msgstr "Pogledaj kao HTML dokument" #~ msgid "System Services" #~ msgstr "Sistemski servisi" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "" #~ "Pokreni, zaustavi ili ponovo pokreni sistemske servise preko init skripti" #~ msgid "Sudo-like Command" #~ msgstr "Sudo-like komanda" #~ msgid "Start Service" #~ msgstr "Pokreni uslugu" #~ msgid "Stop Service" #~ msgstr "Zaustavi servis" #~ msgid "%s Service" #~ msgstr "%s servis" #~ msgid "Show QRCode" #~ msgstr "Prikaži QRCode" #~ msgid "Display text as QRCode in a window" #~ msgstr "Prikaži tekst kao QRCode u prozoru" #~ msgid "Access to Skype contacts" #~ msgstr "Pristupi Skype kontaktima" #~ msgid "Skype Me" #~ msgstr "Pozovi me na Skype" #~ msgid "Logged Out" #~ msgstr "Odlogovan" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Poziv" #~ msgid "Place a call to contact" #~ msgstr "Pozovi kontakt" #~ msgid "Skype Contacts" #~ msgstr "Skype kontakti" #~ msgid "Skype Statuses" #~ msgstr "Skype statusi" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Volumeni iz TrueCrypt historije" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "TrueCrypt volumen: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Montiraj volumen" #~ msgid "Mount in Truecrypt" #~ msgstr "Montiraj u TrueCrypt-u" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Pokušaj da montiraš fajl kao volumen TrueCrypt-a" #~ msgid "Dismount All Volumes" #~ msgstr "Demontiraj sve volumene" #~ msgid "TrueCrypt Volumes" #~ msgstr "TrueCrypt volumeni" #~ msgid "Terminal Server Client" #~ msgstr "Klijent terminalskog servera" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Sesije snimljene u Klijentu terminalskog servera" #~ msgid "TSClient sessions" #~ msgstr "TSClient sesije" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Snimljene sesije u Klijentu terminalskog servera" #~ msgid "Vim" #~ msgstr "Vim" #~ msgid "Recently used documents in Vim" #~ msgstr "Skoro korišteni dokumnti u Vim-u" #~ msgid "Vim Recent Documents" #~ msgstr "Skoriji Vim dokumenti" #~ msgid "Close (Save All)" #~ msgstr "Zatvori (Spasi sve)" #~ msgid "Send..." #~ msgstr "Pošalji..." #~ msgid "Send ex command" #~ msgstr "Pošalji bivšu komandu" #~ msgid "Insert in Vim..." #~ msgstr "Ubaci u Vim..." #~ msgid "Active Vim Sessions" #~ msgstr "Aktivne Vim sesije" #~ msgid "Vim Session %s" #~ msgstr "Vim sesija %s" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Vinagre oznake i akcije" #~ msgid "Start Vinagre Session" #~ msgstr "Počni Vinagre sesiju" #~ msgid "Vinagre Bookmarks" #~ msgstr "Vinagre oznake" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "Kontrolne VirtualBox virtualne mašine. Podržavaju i Sun VirtualBox i " #~ "Opijen Source izdanje." #~ msgid "Force use CLI interface" #~ msgstr "Forsiraj upotrebu CLI sučelja" #~ msgid "Power On" #~ msgstr "Uključen" #~ msgid "Power On Headless" #~ msgstr "Uključi bez glave" #~ msgid "Send Power Off Signal" #~ msgstr "Pošalje signal za gašenje" #~ msgid "Reboot" #~ msgstr "Ponovo pokreni" #~ msgid "Resume" #~ msgstr "Nastavi" #~ msgid "Save State" #~ msgstr "Snimi stanje" #~ msgid "Power Off" #~ msgstr "Ugasi" #~ msgid "VirtualBox Machines" #~ msgstr "VirtualBox mašine" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "Pristupi stranicama spašenim u Zim-u - Desktop Wiki-ju i Outliner-u" #~ msgid "Page names start with :colon" #~ msgstr "Ime stranice počinje sa :colon" #~ msgid "Default page name for quick notes" #~ msgstr "Predefinirano ime stranice za brze bilješke" #~ msgid "Note %x %X" #~ msgstr "Bilješka %x %X" #~ msgid "" #~ "Strftime tags can be used: %H - hour, %M - minutes, etc\n" #~ "Please check python documentation for details.\n" #~ "NOTE: comma will be replaced by _" #~ msgstr "" #~ "Stfrtime oznake mogu biti korištene: %H - sati, %M - minuta, itd.\n" #~ "Molimo provjerite python dokumentaciju za detalje.\n" #~ "PAZI: zarez (,) će biti zamijenjen sa _" #~ msgid "Default namespace for quick notes" #~ msgstr "Predodređeni namespace za brze biljške" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Zim stranica iz Sveske \"%s\"" #~ msgid "Create Zim Page" #~ msgstr "Kreiraj Zim Stranicu" #~ msgid "Create page in default notebook" #~ msgstr "Kreiraj stranicu u predodređenoj svesci" #~ msgid "Create Zim Page In..." #~ msgstr "Kreiraj Zim stranicu u..." #~ msgid "Insert QuickNote into Zim" #~ msgstr "Ubaci QuickNote u Zim" #~ msgid "Quick note selected text into Zim notebook" #~ msgstr "Izabran tekst Brze bilješke u Zim svesci" #~ msgid "Create Subpage..." #~ msgstr "Kreiraj podstranicu..." #~ msgid "Zim Notebooks" #~ msgstr "Zim Sveske" #~ msgid "Zim Pages" #~ msgstr "Zim Stranice" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Stranice snimljene u Zim Sveskama" kupfer-328/po/ca.po000066400000000000000000000770541500175051100142350ustar00rootroot00000000000000# Catalan translation for kupfer. # Copyright (C) 2012 gnome-software's COPYRIGHT HOLDER # This file is distributed under the same license as the gnome-calendar package. # # Jordi Mas i Hernandez , 2013. # # msgid "" msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2013-09-02 23:20+0200\n" "Last-Translator: Jordi Mas i Hernandez \n" "Language-Team: Softcatalà\n" "Language: ca\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Id-Version: gnome-software master\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgid "User credentials" msgstr "" msgid "_User:" msgstr "_Usuari:" msgid "_Password:" msgstr "_Contrasenya:" msgid "_Change" msgstr "_Canvia" msgid "Set Keyboard Shortcut" msgstr "Defineix la drecera de teclat" msgid "Please press desired key combination" msgstr "Premeu si us plau la combinació de tecles desitjada" msgid "Keybinding could not be bound" msgstr "" msgid "Kupfer Preferences" msgstr "Preferències del Kupfer" msgid "Start automatically on login" msgstr "" msgid "Start" msgstr "Inici" msgid "Show icon in notification area" msgstr "Mostra la icona a l'àrea de notificació" msgid "Icon set:" msgstr "Conjunt d'icones:" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" msgid "Terminal emulator:" msgstr "" msgid "Desktop Environment" msgstr "Entorn d'escriptori" msgid "General" msgstr "General" msgid "Global Keyboard Shortcuts" msgstr "Dreceres de teclat globals" msgid "Reset" msgstr "Reinicia" msgid "Browser Keyboard Shortcuts" msgstr "Navegador de dreceres de teclat" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "" msgid "Keyboard" msgstr "Teclat" msgid "Plugins" msgstr "Connectors" msgid "Inclusion in Top Level Searches" msgstr "" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" msgid "Indexed Folders" msgstr "" msgid "Folders whose files are always available in the catalog." msgstr "" msgid "Catalog" msgstr "Catàleg" msgid "Kupfer" msgstr "" msgid "Application Launcher" msgstr "Llançador d'aplicació" msgid "Convenient command and access tool for applications and documents" msgstr "" msgid "Execute in Kupfer" msgstr "" msgid "Saved Kupfer Command" msgstr "" #, python-format msgid "Could not to carry out '%s'" msgstr "" #, python-format msgid "\"%s\" produced a result" msgstr "" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "" #, python-format msgid "Command in \"%s\" is not available" msgstr "" #, python-format msgid "Keyboard relay is active for display %s" msgstr "" msgid "do not present main interface on launch" msgstr "" msgid "list available plugins" msgstr "" msgid "enable debug info" msgstr "activa la informació de depuració" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "" msgid "show usage help" msgstr "" msgid "show version information" msgstr "mostra la informació de la versió" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "" msgid "Available plugins:" msgstr "Connectors disponibles:" #, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" msgid "Type to search" msgstr "Teclegeu per cercar" #, python-format msgid "%s is empty" msgstr "" msgid "Text" msgstr "Text" msgid "Run after Delay..." msgstr "" msgid "Perform command after a specified time interval" msgstr "" msgid "Multiple Objects" msgstr "" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "" msgstr[1] "" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "" msgid "unknown" msgstr "desconegut" msgid "Aim" msgstr "" msgid "Google Talk" msgstr "Google Talk" msgid "ICQ" msgstr "ICQ" msgid "MSN" msgstr "MSN" msgid "QQ" msgstr "QQ" msgid "Yahoo" msgstr "Yahoo" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "" msgid "Can not be used with multiple objects" msgstr "" msgid "Open" msgstr "Obre" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "" #, python-format msgid "Please use \"%s\"" msgstr "" msgid "Set Default Application..." msgstr "" msgid "Open with default application" msgstr "" msgid "Reveal" msgstr "Mostra" msgid "Open parent folder" msgstr "" msgid "Open Terminal Here" msgstr "Obre un terminal aquí" msgid "Open this location in a terminal" msgstr "" msgid "Run in Terminal" msgstr "Executa en un terminal" msgid "Run (Execute)" msgstr "" msgid "Run this program in a Terminal" msgstr "" msgid "Run this program" msgstr "" msgid "Go To" msgstr "Vés a" msgid "Open URL" msgstr "Obre un URL" msgid "Open URL with default viewer" msgstr "" msgid "Launch" msgstr "Executa" msgid "Show application window" msgstr "" msgid "Launch application" msgstr "Executa l'aplicació" msgid "Launch Again" msgstr "" msgid "Launch another instance of this application" msgstr "" msgid "Close" msgstr "Tanca" msgid "Attempt to close all application windows" msgstr "" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "" msgid "Perform command" msgstr "" msgid "(Empty Text)" msgstr "" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "" msgstr[1] "" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "" #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "" #, python-format msgid "Directory source %s" msgstr "" msgid "Home Folder" msgstr "Carpeta personal" msgid "Catalog Index" msgstr "" msgid "An index of all available sources" msgstr "" msgid "Root catalog" msgstr "" msgid "Please Configure Plugin" msgstr "" #, python-format msgid "Plugin %s is not configured" msgstr "" #, python-format msgid "Invalid user credentials for %s" msgstr "" msgid "Applications" msgstr "Aplicacions" msgid "All applications and preferences" msgstr "" msgid "Applications for Desktop Environment" msgstr "" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "Obre amb..." msgid "Open with any application" msgstr "" msgid "Set default application to open this file type" msgstr "" #, fuzzy msgid "Reset Associations" msgstr "Accions" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "" msgid "Allow browsing inside compressed archive files" msgstr "" #, python-format msgid "Content of %s" msgstr "" msgid "Archive Manager" msgstr "Gestor d'arxius" msgid "Use Archive Manager actions" msgstr "" msgid "Compressed archive type for 'Create Archive In'" msgstr "" msgid "Extract Here" msgstr "Extreu aquí" msgid "Extract compressed archive" msgstr "" msgid "Create Archive" msgstr "Crea arxiu" msgid "Create a compressed archive from folder" msgstr "" msgid "Create Archive In..." msgstr "Crea arxiu..." #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Arxiu" msgid "Audacious" msgstr "" msgid "Control Audacious playback and playlist" msgstr "" msgid "Include songs in top level" msgstr "" msgid "Enqueue" msgstr "Afegeix a la cua" msgid "Add track to the Audacious play queue" msgstr "" msgid "Dequeue" msgstr "" msgid "Remove track from the Audacious play queue" msgstr "" msgid "Play" msgstr "Reprodueix" msgid "Jump to track in Audacious" msgstr "" msgid "Resume playback in Audacious" msgstr "" msgid "Pause" msgstr "Pausa" msgid "Pause playback in Audacious" msgstr "" msgid "Next" msgstr "Següent" msgid "Jump to next track in Audacious" msgstr "" msgid "Previous" msgstr "Anterior" msgid "Jump to previous track in Audacious" msgstr "" #, fuzzy msgid "Clear Queue" msgstr "Esborra" msgid "Clear the Audacious play queue" msgstr "" msgid "Shuffle" msgstr "Mescla" msgid "Toggle shuffle in Audacious" msgstr "" msgid "Repeat" msgstr "Repeteix" msgid "Toggle repeat in Audacious" msgstr "" msgid "Show Playing" msgstr "" msgid "Tell which song is currently playing" msgstr "" msgid "Playlist" msgstr "Llista de reproducció" msgid "Calculator" msgstr "Calculadora" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "Calcula" msgid "Clipboards" msgstr "Porta-retalls" msgid "Recent clipboards and clipboard proxy objects" msgstr "" msgid "Number of recent clipboards to remember" msgstr "" msgid "Include selected text in clipboard history" msgstr "" msgid "Copy selected text to primary clipboard" msgstr "" #, fuzzy msgid "Selected Text" msgstr "Seleccioneu el fitxer seleccionat" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "" msgstr[1] "" msgid "Clipboard Text" msgstr "Text del porta-retalls" #, fuzzy msgid "Clipboard File" msgstr "Text del porta-retalls" msgid "Clipboard Files" msgstr "" msgid "Clear" msgstr "Esborra" msgid "Remove all recent clipboards" msgstr "" #, fuzzy msgid "Shell Commands" msgstr "Ordre" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" msgid "Run (Get Output)" msgstr "" msgid "Run program and return its output" msgstr "" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "" msgid "Run program with object as an additional parameter" msgstr "" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "" msgid "Run program and supply text on the standard input" msgstr "" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "" msgid "Run command-line programs" msgstr "" msgid "GTK+" msgstr "GTK+" msgid "GNOME Terminal" msgstr "Terminal del GNOME" msgid "XFCE Terminal" msgstr "" #, fuzzy msgid "LXTerminal" msgstr "Terminal del GNOME" #, fuzzy msgid "X Terminal" msgstr "Terminal del GNOME" msgid "Urxvt" msgstr "" msgid "Konsole" msgstr "Konsole" msgid "Save As..." msgstr "Anomena i desa..." msgid "Restart Kupfer" msgstr "" msgid "Quit" msgstr "Surt" msgid "Quit Kupfer" msgstr "" msgid "About Kupfer" msgstr "" msgid "Show information about Kupfer authors and license" msgstr "" msgid "Kupfer Help" msgstr "" msgid "Get help with Kupfer" msgstr "" msgid "Show preferences window for Kupfer" msgstr "" #, fuzzy msgid "Search Contents" msgstr "Motors de cerca" msgid "Search inside this catalog" msgstr "" msgid "Copy" msgstr "Còpia" msgid "Copy to clipboard" msgstr "Copia-ho al porta-retalls" msgid "Rescan" msgstr "" msgid "Force reindex of this source" msgstr "" #, fuzzy msgid "Last Command" msgstr "Ordre" msgid "Internal Kupfer Objects" msgstr "" msgid "Last Result" msgstr "" msgid "Command Results" msgstr "" msgid "Custom Terminal" msgstr "" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Ordre" msgid "Execute flag" msgstr "" msgid "Default Email Client" msgstr "" msgid "Compose email using the system's default mailto: handler" msgstr "" #, fuzzy msgid "Compose Email To" msgstr "Adreça electrònica particular" msgid "Dictionary" msgstr "Diccionari" msgid "Look up word in dictionary" msgstr "" msgid "Look Up" msgstr "" msgid "Documents" msgstr "Documents" msgid "Recently used documents and bookmarked folders" msgstr "" msgid "Max recent document days" msgstr "" msgid "Recent Items" msgstr "" msgid "Recently used documents" msgstr "" #. TRANS: Recent Documents for application %s #, fuzzy, python-format msgid "%s Documents" msgstr "Documents" #, python-format msgid "Recently used documents for %s" msgstr "" msgid "Places" msgstr "Llocs" #, fuzzy msgid "Bookmarked folders" msgstr "Carpeta personal" msgid "DuckDuckGo Search" msgstr "" msgid "Search the web securely with DuckDuckGo" msgstr "" msgid "Favorites" msgstr "Preferits" msgid "Mark commonly used items and store objects for later use" msgstr "" msgid "Shelf of \"Favorite\" items" msgstr "" msgid "Add to Favorites" msgstr "Afegeix als preferits" msgid "Add item to favorites shelf" msgstr "" msgid "Remove from Favorites" msgstr "Suprimeix dels preferits" msgid "Remove item from favorites shelf" msgstr "" msgid "File Actions" msgstr "" msgid "More file actions" msgstr "" msgid "Move To..." msgstr "" msgid "Move file to new location" msgstr "" #, fuzzy msgid "Rename To..." msgstr "Envia a..." msgid "Copy To..." msgstr "Copia a..." msgid "Copy file to a chosen location" msgstr "" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "" msgid "Tools to work with commands as objects" msgstr "" msgid "Select in Kupfer" msgstr "" #, python-format msgid "Result of %s (%s)" msgstr "" msgid "Run (Take Result)" msgstr "" msgid "Take the command result as a proxy object" msgstr "" msgid "Run (Discard Result)" msgstr "" msgid "Image Tools" msgstr "" msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "" msgid "Scale..." msgstr "" msgid "Scale image to fit inside given pixel measure(s)" msgstr "" msgid "Rotate Clockwise" msgstr "Gira cap a la dreta" #, fuzzy msgid "Rotate Counter-Clockwise" msgstr "Gira cap a la dreta" msgid "Autorotate" msgstr "" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "" msgid "Kupfer Plugins" msgstr "" msgid "Access Kupfer's plugin list in Kupfer" msgstr "" #, fuzzy msgid "Show Information" msgstr "mostra la informació de la versió" msgid "Show Source Code" msgstr "" msgid "enabled" msgstr "habilitat" msgid "disabled" msgstr "inhabilitat" msgid "Notes" msgstr "Anotacions" msgid "Gnote or Tomboy notes" msgstr "" msgid "Work with application" msgstr "" msgid "Open with notes application" msgstr "" msgid "Append to Note..." msgstr "" msgid "Add text to existing note" msgstr "" #, fuzzy msgid "Create Note" msgstr "Crea arxiu" msgid "Create a new note from this text" msgstr "" msgid "Get Note Search Results..." msgstr "" msgid "Show search results for this query" msgstr "" #, python-format msgid "today, %s" msgstr "" #, python-format msgid "yesterday, %s" msgstr "" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "" msgid "Quicksilver Icons" msgstr "" msgid "Quick Image Viewer" msgstr "" msgid "View Image" msgstr "" msgid "GNU Screen" msgstr "" msgid "Active GNU Screen sessions" msgstr "" #, fuzzy msgid "Attached" msgstr "Adjunta" msgid "Detached" msgstr "" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "" msgid "Screen Sessions" msgstr "" msgid "Attach" msgstr "Adjunta" #, fuzzy msgid "Send Keys" msgstr "Envia el missatge" msgid "Send synthetic keyboard events using xautomation" msgstr "" msgid "Paste to Foreground Window" msgstr "" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "" msgid "Send keys to foreground window" msgstr "" #, fuzzy msgid "Type Text" msgstr "Text" msgid "Type the text to foreground window" msgstr "" msgid "GNOME Session Management" msgstr "" msgid "Special items and actions for GNOME environment" msgstr "" msgid "Log Out..." msgstr "" msgid "Log out or change user" msgstr "" msgid "Shut Down..." msgstr "" msgid "Shut down, restart or suspend computer" msgstr "" msgid "Lock Screen" msgstr "Bloca la pantalla" msgid "Enable screensaver and lock" msgstr "" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "" msgid "Special items and actions for XFCE environment" msgstr "" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "" msgid "SSH host" msgstr "" msgid "Connect" msgstr "Connecta" msgid "Connect to SSH host" msgstr "" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "" msgid "No D-Bus connection to desktop session" msgstr "" msgid "GNOME Keyring" msgstr "" msgid "KWallet" msgstr "" msgid "Unencrypted File" msgstr "" #, python-format msgid "Dependency '%s' is not available" msgstr "" msgid "Document Templates" msgstr "" msgid "Create new documents from your templates" msgstr "" #, python-format msgid "%s template" msgstr "" msgid "Empty File" msgstr "" msgid "New Folder" msgstr "Afegeix la carpeta" #, fuzzy msgid "Create New Document..." msgstr "Crea arxiu..." msgid "Create a new document from template" msgstr "" #, fuzzy msgid "Create Document In..." msgstr "Crea arxiu..." #, fuzzy msgid "Textfiles" msgstr "Text" msgid "Append To..." msgstr "" msgid "Append..." msgstr "" #, fuzzy msgid "Write To..." msgstr "Envia a..." msgid "Get Text Contents" msgstr "" msgid "Thunar" msgstr "" msgid "File manager Thunar actions" msgstr "" msgid "Select in File Manager" msgstr "" #, fuzzy msgid "Show Properties" msgstr "Mostra les preferències" msgid "Show information about file in file manager" msgstr "" msgid "Send To..." msgstr "Envia a..." msgid "Symlink In..." msgstr "" msgid "Create a symlink to file in a chosen location" msgstr "" msgid "Empty Trash" msgstr "Buida la paperera" msgid "Thunar Send To Objects" msgstr "" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "" msgid "Compose New Email" msgstr "" msgid "Compose a new message in Thunderbird" msgstr "" msgid "Attach in Email To..." msgstr "" #, fuzzy msgid "Compose Email With" msgstr "Adreça electrònica particular" msgid "Compose a new message using the text as body" msgstr "" #, fuzzy msgid "Thunderbird Address Book" msgstr "Thunderbird" msgid "Contacts from Thunderbird Address Book" msgstr "" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Part superior" msgid "Show running tasks and allow sending signals to them" msgstr "" msgid "Sort Order" msgstr "" #, fuzzy msgid "Commandline" msgstr "Ordre" msgid "CPU usage (descending)" msgstr "" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "" msgid "Send Signal..." msgstr "" msgid "Signals" msgstr "Senyals" msgid "Running Tasks" msgstr "" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "" msgid "Running tasks for current user" msgstr "" msgid "Trash" msgstr "Paperera" msgid "Access trash contents" msgstr "" msgid "Move to Trash" msgstr "Mou a la paperera" #, fuzzy msgid "Move this file to trash" msgstr "Mou a la paperera" msgid "Restore" msgstr "Restaura" msgid "Move file back to original location" msgstr "" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "" msgstr[1] "" msgid "Triggers" msgstr "Gallets" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" msgid "Add Trigger..." msgstr "" #, fuzzy msgid "Remove Trigger" msgstr "Gallets" #, fuzzy msgid "URL Actions" msgstr "Accions" msgid "Download and Open" msgstr "" #, fuzzy msgid "Download To..." msgstr "Envia a..." msgid "Download URL to a chosen location" msgstr "" msgid "Wikipedia" msgstr "Viquipèdia" msgid "Search in Wikipedia" msgstr "" msgid "Wikipedia language" msgstr "" #. TRANS: Default wikipedia language code msgid "en" msgstr "ca" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "" msgid "Window List" msgstr "Llista de finestres" msgid "All windows on all workspaces" msgstr "" msgid "Activate" msgstr "Activa" msgid "Shade" msgstr "Ombra" #, fuzzy msgid "Unshade" msgstr "Ombra" msgid "Minimize" msgstr "Minimitza" #, fuzzy msgid "Unminimize" msgstr "Minimitza" msgid "Maximize" msgstr "Maximitza" #, fuzzy msgid "Unmaximize" msgstr "Maximitza" msgid "Maximize Vertically" msgstr "Maximitza verticalment" #, fuzzy msgid "Unmaximize Vertically" msgstr "Maximitza verticalment" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "" msgid "Frontmost Window" msgstr "" msgid "Next Window" msgstr "Finestra següent" msgid "Jump to this window's workspace and focus" msgstr "" #, fuzzy, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "Finestra següent" msgstr[1] "Finestra següent" msgid "Active workspace" msgstr "" msgid "Jump to this workspace" msgstr "" msgid "Workspaces" msgstr "Espais de treball" msgid "Volumes and Disks" msgstr "" msgid "Mounted volumes and disks" msgstr "" #, python-format msgid "Volume mounted at %s" msgstr "" msgid "Unmount" msgstr "" msgid "Unmount this volume" msgstr "" msgid "Eject" msgstr "Expulsa" msgid "Unmount and eject this media" msgstr "" msgid "Show Text" msgstr "Mostra el text" msgid "Display text in a window" msgstr "" msgid "Large Type" msgstr "" #, fuzzy msgid "Show Notification" msgstr "Mostra la icona a l'àrea de notificació" msgid "Tracker" msgstr "Tracker" msgid "Tracker desktop search integration" msgstr "" msgid "Search in Tracker" msgstr "" msgid "Open Tracker Search Tool and search for this term" msgstr "" msgid "Get Tracker Results..." msgstr "" msgid "Show Tracker results for query" msgstr "" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "" msgid "Search filesystem using locate" msgstr "" msgid "Ignore case distinctions when searching files" msgstr "" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Adreces d'interès del Firefox" #, fuzzy msgid "Index of Firefox bookmarks" msgstr "Adreces d'interès del Firefox" #, fuzzy msgid "Firefox Keywords" msgstr "Adreces d'interès del Firefox" msgid "Search the web with Firefox keywords" msgstr "" #, fuzzy msgid "Search With..." msgstr "Obre amb..." msgid "Search For..." msgstr "" #, fuzzy msgid "Search Terms" msgstr "Motors de cerca" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, python-format msgid "Play/Pause (%s)" msgstr "" msgid "Resume playback" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Següent" msgid "Skip to next track" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Anterior" msgid "Skip to previous track" msgstr "" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "" msgid "Access to Pidgin Contacts" msgstr "" msgid "Show offline contacts" msgstr "Mostra els contactes fora de línia" #, fuzzy msgid "Open Chat" msgstr "Obre" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "" msgstr[1] "" msgid "Send Message..." msgstr "Envia el missatge..." msgid "Available" msgstr "Disponible" msgid "Away" msgstr "Absent" #, fuzzy msgid "Pidgin Contacts" msgstr "Contactes del Gajim" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "" msgid "Create short aliases of long URLs" msgstr "" msgid "Error" msgstr "Error" #, fuzzy msgid "Shorten With..." msgstr "Obre amb..." msgid "Services" msgstr "Serveis" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "" msgid "Include artists in top level" msgstr "" msgid "Include albums in top level" msgstr "" msgid "Play tracks in Rhythmbox" msgstr "" msgid "Add tracks to the play queue" msgstr "" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "per %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "" msgid "Albums" msgstr "Àlbums" msgid "Music albums in Rhythmbox Library" msgstr "" msgid "Artists" msgstr "Artistes" msgid "Music artists in Rhythmbox Library" msgstr "" msgid "Songs" msgstr "Cançons" msgid "Songs in Rhythmbox library" msgstr "" msgid "Getting Things GNOME" msgstr "" msgid "Browse and create new tasks in GTG" msgstr "" #, python-format msgid "due: %s" msgstr "" #, python-format msgid "start: %s" msgstr "" #, python-format msgid "tags: %s" msgstr "" msgid "Open task in Getting Things GNOME!" msgstr "" msgid "Delete" msgstr "Suprimeix" msgid "Permanently remove this task" msgstr "" msgid "Mark Done" msgstr "" msgid "Mark this task as done" msgstr "" msgid "Dismiss" msgstr "" msgid "Mark this task as not to be done anymore" msgstr "" #, fuzzy msgid "Create Task" msgstr "Crea arxiu" msgid "Create new task in Getting Things GNOME" msgstr "" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "" msgid "Empathy" msgstr "Empathy" msgid "Access to Empathy Contacts" msgstr "" msgid "Busy" msgstr "Ocupat" msgid "Not Available" msgstr "No és disponible" msgid "Invisible" msgstr "Invisible" msgid "Offline" msgstr "Fora de línia" msgid "Change Global Status To..." msgstr "" #, fuzzy msgid "Empathy Contacts" msgstr "Empathy" msgid "Empathy Account Status" msgstr "" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "" msgid "Mark Default Action" msgstr "" msgid "Forget Object" msgstr "Oblida l'objecte" msgid "Reset All" msgstr "Restableix-ho tot" msgid "Select Quit" msgstr "" msgid "Select Selected File" msgstr "Seleccioneu el fitxer seleccionat" msgid "Select Selected Text" msgstr "" msgid "Show Help" msgstr "Mostra l'ajuda" msgid "Show Preferences" msgstr "Mostra les preferències" msgid "Switch to First Pane" msgstr "" msgid "Toggle Text Mode" msgstr "" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "" msgid "No matches" msgstr "No hi ha cap coincidència" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "No hi ha cap coincidència" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "" msgid "Show with Selection" msgstr "" #. TRANS: Plugin info fields msgid "Description" msgstr "Descripció" msgid "Author" msgstr "Autor" msgid "Version" msgstr "Versió" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "" msgid "Plugin could not be read due to an error:" msgstr "" msgid "Content of" msgstr "" #. TRANS: Plugin contents header msgid "Sources" msgstr "Fonts" #. TRANS: Plugin contents header msgid "Actions" msgstr "Accions" #, python-format msgid "Using encrypted password storage: %s" msgstr "" #, python-format msgid "Using password storage: %s" msgstr "" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Configuració" msgid "Set username and password" msgstr "Defineix el nom d'usuari i contrasenya" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Escolliu un directori" msgid "Reset all shortcuts to default values?" msgstr "" msgid "Shortcut" msgstr "Drecera" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "Jordi Mas i Hernàndez , 2013" msgid "A free software (GPLv3+) launcher" msgstr "" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "" #, fuzzy #~ msgid "Compose Email" #~ msgstr "Adreça electrònica particular" #~ msgid "Type to search %s" #~ msgstr "Teclegeu per cercar %s" #~ msgid "No action" #~ msgstr "Cap acció" #, fuzzy #~ msgid "GNOME Terminal Profiles" #~ msgstr "Terminal del GNOME" #, fuzzy #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Terminal del GNOME" #~ msgid "Epiphany Bookmarks" #~ msgstr "Adreces d'interès de l'Epiphany" #, fuzzy #~ msgid "Firefox tag" #~ msgstr "Adreces d'interès del Firefox" #~ msgid "Search the Web" #~ msgstr "Cerca al web" #~ msgid "Abiword" #~ msgstr "Abiword" #, fuzzy #~ msgid "Show Package Information" #~ msgstr "mostra la informació de la versió" #~ msgid "Install" #~ msgstr "Instal·la" #~ msgid "Unicode" #~ msgstr "Unicode" #~ msgid "Theme:" #~ msgstr "Tema:" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Contactes de l'Evolution" #~ msgid "Gmail" #~ msgstr "Gmail" #, fuzzy #~ msgid "Load additional information" #~ msgstr "mostra la informació de la versió" #~ msgid "Work email" #~ msgstr "Correu electrònic de la feina" #~ msgid "Home email" #~ msgstr "Adreça electrònica particular" #~ msgid "Other email" #~ msgstr "Una altra adreça electrònica" #~ msgid "Work address" #~ msgstr "Adreça de la feina" #~ msgid "Home address" #~ msgstr "Adreça de casa" #~ msgid "Other address" #~ msgstr "Altres adreces" #~ msgid "Car phone" #~ msgstr "Telèfon del cotxe" #~ msgid "Fax" #~ msgstr "Fax" #~ msgid "Home phone" #~ msgstr "Telèfon fix" #~ msgid "Home fax" #~ msgstr "Fax de casa" #~ msgid "Mobile" #~ msgstr "Mòbil" #~ msgid "Other" #~ msgstr "Altres" #~ msgid "Work phone" #~ msgstr "Telèfon de la feina" #~ msgid "Work fax" #~ msgstr "Fax de la feina" #~ msgid "Uploading Pictures" #~ msgstr "S'estan pujant les fotografies" #~ msgid "File:" #~ msgstr "Fitxer:" #~ msgid "Send Message" #~ msgstr "Envia el missatge" #~ msgid "Send Message To..." #~ msgstr "Envia el missatge a..." #~ msgid "Reply..." #~ msgstr "Respon..." #~ msgid "Delete Message" #~ msgstr "Suprimeix el missatge" #~ msgid "Retweet" #~ msgstr "Repiula" #, fuzzy #~ msgid "Open in Browser" #~ msgstr "Obre un terminal aquí" #, fuzzy #~ msgid "Opera Bookmarks" #~ msgstr "Adreces d'interès de l'Epiphany" #, fuzzy #~ msgid "Start Service" #~ msgstr "Serveis" #, fuzzy #~ msgid "Stop Service" #~ msgstr "Serveis" #, fuzzy #~ msgid "%s Service" #~ msgstr "Serveis" #~ msgid "Call" #~ msgstr "Truca" #, fuzzy #~ msgid "Vim Recent Documents" #~ msgstr "Documents" #, fuzzy #~ msgid "Power On" #~ msgstr "Apaga" #~ msgid "Reboot" #~ msgstr "Reinicia" #~ msgid "Resume" #~ msgstr "Reprèn" #~ msgid "Save State" #~ msgstr "Desa l'estat" #~ msgid "Power Off" #~ msgstr "Apaga" kupfer-328/po/cs.po000066400000000000000000001644521500175051100142560ustar00rootroot00000000000000# Czech translation for kupfer. # Copyright (C) 2009, 2010 the author(s) of kupfer. # This file is distributed under the same license as the kupfer package. # # Lucas Lommer , 2010. # Petr Kovar , 2010. # Marek Černocký , 2009, 2010, 2011, 2012. # msgid "" msgstr "" "Project-Id-Version: kupfer master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2012-08-31 23:53+0200\n" "Last-Translator: Marek Černocký \n" "Language-Team: Czech \n" "Language: cs\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" msgid "User credentials" msgstr "Přístupové údaje uživatele" msgid "_User:" msgstr "_Uživatel:" msgid "_Password:" msgstr "_Heslo:" msgid "_Change" msgstr "_Změnit" msgid "Set Keyboard Shortcut" msgstr "Nastavit klávesové zkratky" msgid "Please press desired key combination" msgstr "Zmáčkněte prosím požadovanou kombinaci kláves" msgid "Keybinding could not be bound" msgstr "Nelze najít klávesovou zkratku" msgid "Kupfer Preferences" msgstr "Předvolby Kupfer" msgid "Start automatically on login" msgstr "Spouštět automaticky po přihlášení" msgid "Start" msgstr "Spuštění" msgid "Show icon in notification area" msgstr "Zobrazovat ikonu v oznamovací oblasti" msgid "Icon set:" msgstr "Sada ikon:" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" msgid "Terminal emulator:" msgstr "Emulátor terminálu:" msgid "Desktop Environment" msgstr "Pracovní prostředí" msgid "General" msgstr "Obecné" msgid "Global Keyboard Shortcuts" msgstr "Globální klávesové zkratky" msgid "Reset" msgstr "Vrátit původní" msgid "Browser Keyboard Shortcuts" msgstr "Klávesové zkratky prohlížeče" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "Použít jednoklávesové příkazy (mezerník, lomítko, tečka, čárka atd.)" msgid "Keyboard" msgstr "Klávesnice" msgid "Plugins" msgstr "Zásuvné moduly" msgid "Inclusion in Top Level Searches" msgstr "Zahrnout do nejvyšší úrovně hledání" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "Označené zdroje mají své objekty zahrnuty v nejvyšší úrovni hledání.\n" "Obsah neoznačených zdrojů je dostupny pouze při hledání v jeho podkatalogu." msgid "Indexed Folders" msgstr "Indexované složky" msgid "Folders whose files are always available in the catalog." msgstr "Složky, jejichž soubory jsou již dostupné v katalogu." msgid "Catalog" msgstr "Katalog" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Spouštěč aplikací" msgid "Convenient command and access tool for applications and documents" msgstr "" "Nástroj pro pohodlné provádění příkazů a přístup k aplikacím a dokumentům" msgid "Execute in Kupfer" msgstr "Spustit v aplikaci Kupfer" msgid "Saved Kupfer Command" msgstr "Uložený příkaz aplikace Kupfer" #, python-format msgid "Could not to carry out '%s'" msgstr "Nelze provést „%s“" #, python-format msgid "\"%s\" produced a result" msgstr "„%s“ vyprodukoval výsledek" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Nedostatečné oprávnění ke spuštění „%s“ (není spustitelný)" #, python-format msgid "Command in \"%s\" is not available" msgstr "Příkaz v „%s“ není dostupný" #, python-format msgid "Keyboard relay is active for display %s" msgstr "Zachytávání klávesnice je aktivní pro displej %s" msgid "do not present main interface on launch" msgstr "po spuštění nezobrazit hlavní rozhraní" msgid "list available plugins" msgstr "vypsat dostupné zásuvné moduly" msgid "enable debug info" msgstr "zapnout ladicí informace" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "spustit pomocníka zásuvného modulu" msgid "show usage help" msgstr "zobrazit nápovědu k použití" msgid "show version information" msgstr "zobrazit informace o verzi" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Použití: kupfer [PŘEPÍNAČE | SOUBOR … ]" msgid "Available plugins:" msgstr "Dostupné zásuvné moduly:" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "Pište co se má vyhledat" #, python-format msgid "%s is empty" msgstr "%s je prázdný" msgid "Text" msgstr "Text" msgid "Run after Delay..." msgstr "Spustit po chvíli…" msgid "Perform command after a specified time interval" msgstr "Provést příkaz po uplynutí zadané časové prodlevy" msgid "Multiple Objects" msgstr "Více objektů" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s objekt" msgstr[1] "%s objekty" msgstr[2] "%s objektů" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "neznámý" msgid "Aim" msgstr "Aim" msgid "Google Talk" msgstr "Google Talk" msgid "ICQ" msgstr "ICQ" msgid "MSN" msgstr "MSN" msgid "QQ" msgstr "QQ" msgid "Yahoo" msgstr "Yahoo" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "%s nepodporuje tuto operaci" msgid "Can not be used with multiple objects" msgstr "Nelze použít s více objekty naráz" msgid "Open" msgstr "Otevřít" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Není nastavená výchozí aplikace pro %(file)s (%(type)s)" #, python-format msgid "Please use \"%s\"" msgstr "Použijte prosím „%s“" msgid "Set Default Application..." msgstr "Nastavit výchozí aplikaci…" msgid "Open with default application" msgstr "Otevřít pomocí výchozí aplikace" msgid "Reveal" msgstr "Ukázat" msgid "Open parent folder" msgstr "Otevřít rodičovskou složku" msgid "Open Terminal Here" msgstr "Otevřít zde terminál" msgid "Open this location in a terminal" msgstr "Otevřít toto umístění v terminálu" msgid "Run in Terminal" msgstr "Spustit v terminálu" msgid "Run (Execute)" msgstr "Spustit (provést)" msgid "Run this program in a Terminal" msgstr "Spustit tento program v terminálu" msgid "Run this program" msgstr "Spustit tento program" msgid "Go To" msgstr "Přejít na" msgid "Open URL" msgstr "Otevřít URL" msgid "Open URL with default viewer" msgstr "Otevřít URL s výchozím prohlížečem" msgid "Launch" msgstr "Spustit" msgid "Show application window" msgstr "Zobrazit okno aplikace" msgid "Launch application" msgstr "Spustit aplikaci" msgid "Launch Again" msgstr "Spustit znovu" msgid "Launch another instance of this application" msgstr "Spustit další instanci této aplikace" msgid "Close" msgstr "Zavřít" msgid "Attempt to close all application windows" msgstr "Zkusit zavřít okna všech aplikací" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Spustit" msgid "Perform command" msgstr "Provést příkaz" msgid "(Empty Text)" msgstr "(Prázdný text)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "„%(text)s“" msgstr[1] "(%(num)d řádky) „%(text)s“" msgstr[2] "(%(num)d řádků) „%(text)s“" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s a další" #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Rekurzivní zdroj ze složky %(dir)s, (%(levels)d úrovní)" #, python-format msgid "Directory source %s" msgstr "Zdroj složka %s" msgid "Home Folder" msgstr "Domovská složka" msgid "Catalog Index" msgstr "Katalogový rejstřík" msgid "An index of all available sources" msgstr "Rejstřík ze všech dostupných zdrojů" msgid "Root catalog" msgstr "Kořenový katalog" msgid "Please Configure Plugin" msgstr "Nastavte prosím zásuvný modul" #, python-format msgid "Plugin %s is not configured" msgstr "Zásuvný modul %s není nastavený" #, python-format msgid "Invalid user credentials for %s" msgstr "Neplatné přístupové údaje uživatele pro %s" msgid "Applications" msgstr "Aplikace" msgid "All applications and preferences" msgstr "Všechny aplikace a předvolby" msgid "Applications for Desktop Environment" msgstr "Aplikace pro pracovní prostředí" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "Otevřít s…" msgid "Open with any application" msgstr "Otevřít pomocí nějaké aplikace" msgid "Set default application to open this file type" msgstr "Nastavit výchozí aplikaci na otevírání tohoto typu souboru" #, fuzzy msgid "Reset Associations" msgstr "Akce s URL" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "Do hloubky archivů" msgid "Allow browsing inside compressed archive files" msgstr "Umožňuje procházení uvnitř komprimovaných archivních souborů" #, python-format msgid "Content of %s" msgstr "Obsah archivu %s" msgid "Archive Manager" msgstr "Správa archivu" msgid "Use Archive Manager actions" msgstr "Použít akce správce archivu" msgid "Compressed archive type for 'Create Archive In'" msgstr "Typ komprimovaného archivu pro „Vytvořit archiv v“" msgid "Extract Here" msgstr "Rozbalit zde" msgid "Extract compressed archive" msgstr "Rozbalit komprimovaný archiv" msgid "Create Archive" msgstr "Vytvořit archiv" msgid "Create a compressed archive from folder" msgstr "Vytvořit komprimovaný archiv ze složky" msgid "Create Archive In..." msgstr "Vytvořit archiv v…" #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Archiv" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "Ovládat přehrávání a seznamy skladeb přehrávače Audacious" msgid "Include songs in top level" msgstr "Zahrnout skladby do nejvyšší úrovně" msgid "Enqueue" msgstr "Zařadit do fronty" msgid "Add track to the Audacious play queue" msgstr "Přidat skladbu do fronty přehrávaných skladeb v přehrávači Audacious" msgid "Dequeue" msgstr "Vyjmout z fronty" msgid "Remove track from the Audacious play queue" msgstr "Odstranit skladbu z fronty přehrávaných skladeb v přehrávači Audacious" msgid "Play" msgstr "Přehrát" msgid "Jump to track in Audacious" msgstr "Přeskočit na stopu v přehrávači Audacious" msgid "Resume playback in Audacious" msgstr "Pokračovat v přehrávání v přehrávači Audacious" msgid "Pause" msgstr "Pozastavit" msgid "Pause playback in Audacious" msgstr "Pozastavit přehrávání v přehrávači Audacious" msgid "Next" msgstr "Následující" msgid "Jump to next track in Audacious" msgstr "Přeskočit na následující stopu v přehrávači Audacious" msgid "Previous" msgstr "Předchozí" msgid "Jump to previous track in Audacious" msgstr "Přeskočit na předchozí stopu v přehrávači Audacious" msgid "Clear Queue" msgstr "Vymazat frontu" msgid "Clear the Audacious play queue" msgstr "Vymazat frontu přehrávaných skladeb v přehrávači Audacious" msgid "Shuffle" msgstr "Náhodně" msgid "Toggle shuffle in Audacious" msgstr "Zapnout/vypnout náhodné pořadí v přehrávači Audacious" msgid "Repeat" msgstr "Opakovat" msgid "Toggle repeat in Audacious" msgstr "Zapnout/vypnout opakování v přehrávači Audacious" msgid "Show Playing" msgstr "Zobrazit co se přehrává" msgid "Tell which song is currently playing" msgstr "Sdělit, která skladba se právě přehrává" msgid "Playlist" msgstr "Seznam skladeb" msgid "Calculator" msgstr "Kalkulačka" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "Vypočítat" msgid "Clipboards" msgstr "Schránky" msgid "Recent clipboards and clipboard proxy objects" msgstr "Nedávné objekty schránek a proxy schránky" msgid "Number of recent clipboards to remember" msgstr "Počet nedávných schránek k zapamatování" msgid "Include selected text in clipboard history" msgstr "Zahrnout vybraný text do historie schránky" msgid "Copy selected text to primary clipboard" msgstr "Kopírovat vybraný text do hlavní schránky" msgid "Selected Text" msgstr "Vybraný text" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Schránka „%(desc)s“" msgstr[1] "Schránka s %(num)d řádky „%(desc)s“" msgstr[2] "Schránka s %(num)d řádky „%(desc)s“" msgid "Clipboard Text" msgstr "Text schránky" msgid "Clipboard File" msgstr "Soubor schránky" msgid "Clipboard Files" msgstr "Soubory schránky" msgid "Clear" msgstr "Vyčistit" msgid "Remove all recent clipboards" msgstr "Odstranit všechny nedávné položky ze schránky" msgid "Shell Commands" msgstr "Příkazy shellu" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Spustit programy příkazové řádky. Akce označené symbolem %s poběží v " "podřízeném shellu." msgid "Run (Get Output)" msgstr "Spustit (získat výstup)" msgid "Run program and return its output" msgstr "Spustit program a vrátit jeho výstup" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "Předat do příkazu…" msgid "Run program with object as an additional parameter" msgstr "Spustit program s objektem, jako doplňujícím parametrem" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "Zapsat do příkazu…" msgid "Run program and supply text on the standard input" msgstr "Spustit program a poskytnout text na standardní vstup" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "Filtrovat přes příkaz…" msgid "Run command-line programs" msgstr "Spustit programy příkazové řádky" msgid "GTK+" msgstr "GTK+" msgid "GNOME Terminal" msgstr "Terminál GNOME" msgid "XFCE Terminal" msgstr "Terminál XFCE" msgid "LXTerminal" msgstr "LXTerminal" msgid "X Terminal" msgstr "Terminál X" msgid "Urxvt" msgstr "Urxvt" msgid "Konsole" msgstr "Konsole" msgid "Save As..." msgstr "Uložit jako…" #, fuzzy msgid "Restart Kupfer" msgstr "Restartovat službu" msgid "Quit" msgstr "Ukončit" msgid "Quit Kupfer" msgstr "Ukončit aplikaci Kupfer" msgid "About Kupfer" msgstr "O aplikaci Kupfer" msgid "Show information about Kupfer authors and license" msgstr "Zobrazit informace o autorech aplikace Kupfer a licenci" msgid "Kupfer Help" msgstr "Nápověda aplikace Kupfer" msgid "Get help with Kupfer" msgstr "Získat nápovědu k aplikaci Kupfer" msgid "Show preferences window for Kupfer" msgstr "Zobrazit okno s předvolbami pro Kupfer" msgid "Search Contents" msgstr "Prohledat obsah" msgid "Search inside this catalog" msgstr "Hledat v tomto katalogu" msgid "Copy" msgstr "Kopírovat" msgid "Copy to clipboard" msgstr "Kopírovat do schránky" msgid "Rescan" msgstr "Přeindexovat" msgid "Force reindex of this source" msgstr "Vynutit přeindexování tohoto zdroje" msgid "Last Command" msgstr "Poslední příkaz" msgid "Internal Kupfer Objects" msgstr "Interní objekty Kupfer" msgid "Last Result" msgstr "Poslední výsledek" msgid "Command Results" msgstr "Výsledky příkazu" msgid "Custom Terminal" msgstr "Vlastní terminál" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Příkaz" msgid "Execute flag" msgstr "Příznaky spuštění" msgid "Default Email Client" msgstr "Výchozí poštovní klient" msgid "Compose email using the system's default mailto: handler" msgstr "Napsat e-mail ve výchozím programu systému pro zpracován mailto:" #, fuzzy msgid "Compose Email To" msgstr "Napsat e-mail" msgid "Dictionary" msgstr "Slovník" msgid "Look up word in dictionary" msgstr "Vyhledat slovíčko ve slovníku" msgid "Look Up" msgstr "Vyhledat" msgid "Documents" msgstr "Dokumenty" msgid "Recently used documents and bookmarked folders" msgstr "Nedávno použité dokumenty a označené složky" msgid "Max recent document days" msgstr "Max. stáří nedávných dokumentů ve dnech" msgid "Recent Items" msgstr "Nedávné položky" msgid "Recently used documents" msgstr "Nedávno použité dokumenty" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "Dokumenty %s" #, python-format msgid "Recently used documents for %s" msgstr "Nedávno použité dokumenty pro %s" msgid "Places" msgstr "Místa" msgid "Bookmarked folders" msgstr "Označené složky" msgid "DuckDuckGo Search" msgstr "Vyhledávač DuckDuckGo" msgid "Search the web securely with DuckDuckGo" msgstr "Prohledat web bezpečně pomocí DuckDuckGo" msgid "Favorites" msgstr "Oblíbené" msgid "Mark commonly used items and store objects for later use" msgstr "Označit běžně používané položky a uchovat objekty pro pozdější použití" msgid "Shelf of \"Favorite\" items" msgstr "Seznam „oblíbených“ položek" msgid "Add to Favorites" msgstr "Přidat do oblíbených" msgid "Add item to favorites shelf" msgstr "Přidat položku do seznamu oblíbených" msgid "Remove from Favorites" msgstr "Odebrat z oblíbených" msgid "Remove item from favorites shelf" msgstr "Odebrat položku ze seznamu oblíbených" msgid "File Actions" msgstr "Akce se soubory" msgid "More file actions" msgstr "Více akcí se soubory" msgid "Move To..." msgstr "Přesunout do…" msgid "Move file to new location" msgstr "Přesunout tento soubor na nové místo" msgid "Rename To..." msgstr "Přejmenovat na…" msgid "Copy To..." msgstr "Kopírovat do…" msgid "Copy file to a chosen location" msgstr "Kopírovat soubor na vybrané místo" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "Glob" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "Akce nejvyšší úrovně" msgid "Tools to work with commands as objects" msgstr "Nástroj umožňující práci s příkazy jako s objekty" msgid "Select in Kupfer" msgstr "Vybrat v aplikaci Kupfer" #, python-format msgid "Result of %s (%s)" msgstr "Výsledky pro %s (%s)" msgid "Run (Take Result)" msgstr "Spustit (převzít výsledky)" msgid "Take the command result as a proxy object" msgstr "Převzít výsledek příkazu jako objekt proxy" msgid "Run (Discard Result)" msgstr "Spustit (zahodit výsledky)" msgid "Image Tools" msgstr "Nástroje na obrázky" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Nástroje pro transformaci obrázků" msgid "Scale..." msgstr "Změnit velikost…" msgid "Scale image to fit inside given pixel measure(s)" msgstr "" "Změnit velikost obrázku, aby odpovídal vnitřně daným rozměrům v pixelech" msgid "Rotate Clockwise" msgstr "Otočit ve směru hodinových ručiček" msgid "Rotate Counter-Clockwise" msgstr "Otočit proti směru hodinových ručiček" msgid "Autorotate" msgstr "Automaticky otočit" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "Otočit JPEG v souladu s jeho metadaty EXIF" msgid "Kupfer Plugins" msgstr "Zásuvné moduly Kupfer" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Přístup k seznamu zásuvných modulů Kupfer v aplikaci Kupfer" msgid "Show Information" msgstr "Zobrazit informace" msgid "Show Source Code" msgstr "Zobrazit zdrojový kód" msgid "enabled" msgstr "zapnutý" msgid "disabled" msgstr "vypnutý" msgid "Notes" msgstr "Poznámky" msgid "Gnote or Tomboy notes" msgstr "Poznámky v aplikacích Gnote nebo Tomboy" msgid "Work with application" msgstr "Pracovat s aplikací" msgid "Open with notes application" msgstr "Otevřít s aplikací pro práci s poznámkami" msgid "Append to Note..." msgstr "Připojit k poznámce…" msgid "Add text to existing note" msgstr "Přidat text do stávající poznámky" msgid "Create Note" msgstr "Vytvořit poznámku" msgid "Create a new note from this text" msgstr "Vytvořit novou poznámku z tohoto textu" msgid "Get Note Search Results..." msgstr "Získat výsledky hledávání poznámek…" msgid "Show search results for this query" msgstr "Zobrazit výsledky hledání pro tento dotaz" #, python-format msgid "today, %s" msgstr "dnes, %s" #, python-format msgid "yesterday, %s" msgstr "včera, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Naposledy aktualizováno %s" msgid "Quicksilver Icons" msgstr "Ikony Quicksilver" msgid "Quick Image Viewer" msgstr "Rychlé prohlížení obrázků" msgid "View Image" msgstr "Zobrazit obrázek" msgid "GNU Screen" msgstr "GNU Screen" msgid "Active GNU Screen sessions" msgstr "Aktivovat sezení GNU Screen" msgid "Attached" msgstr "Připojené" msgid "Detached" msgstr "Odpojené" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "%(status)s sezení (%(pid)s) vytvořené %(time)s" msgid "Screen Sessions" msgstr "Sezení obrazovky" msgid "Attach" msgstr "Připojit" msgid "Send Keys" msgstr "Poslat klávesy" msgid "Send synthetic keyboard events using xautomation" msgstr "Poslat pomocí xautomation uměle vyvolané události klávesnice" msgid "Paste to Foreground Window" msgstr "Vložit do okna na popředí" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "Kopírovat do schránky a poslat Ctrl+V do okna na popředí" msgid "Send keys to foreground window" msgstr "Poslat klávesy do okna na popředí" msgid "Type Text" msgstr "Psát text" msgid "Type the text to foreground window" msgstr "Psát text do okna na popředí" msgid "GNOME Session Management" msgstr "Správa sezení GNOME" msgid "Special items and actions for GNOME environment" msgstr "Speciální položky a akce pro pracovní prostředí GNOME" msgid "Log Out..." msgstr "Odhlásit se…" msgid "Log out or change user" msgstr "Odhlásit nebo změnit uživatele" msgid "Shut Down..." msgstr "Vypnout…" msgid "Shut down, restart or suspend computer" msgstr "Vypnout, restartovat nebo uspat počítač" msgid "Lock Screen" msgstr "Zamknout obrazovku" msgid "Enable screensaver and lock" msgstr "Povolit šetřič obrazovky a zamykání" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "Správa sezení XFCE" msgid "Special items and actions for XFCE environment" msgstr "Speciální položky a akce pro pracovní prostředí XFCE" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "Hostitelé SSH" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "Přidává hostitele SSH nalezené v ~/.ssh/config." msgid "SSH host" msgstr "Hostitel SSH" msgid "Connect" msgstr "Připojit" msgid "Connect to SSH host" msgstr "Připojit k hostiteli SSH" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "Hostitelé SSH jak jsou zadáni v ~/.ssh/config" msgid "No D-Bus connection to desktop session" msgstr "" "Neexistuje žádné napojení sběrnice D-Bus na sezení pracovního prostředí" msgid "GNOME Keyring" msgstr "Klíčenka GNOME" msgid "KWallet" msgstr "KWallet" msgid "Unencrypted File" msgstr "Rozšifrovat soubor" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "Příkaz v „%s“ není dostupný" msgid "Document Templates" msgstr "Šablony dokumentů" msgid "Create new documents from your templates" msgstr "Vytvořit nový dokumentu ze své šablony" #, python-format msgid "%s template" msgstr "Šablona %s" msgid "Empty File" msgstr "Prázdný soubor" msgid "New Folder" msgstr "Nová složka" msgid "Create New Document..." msgstr "Vytvořit nový dokument…" msgid "Create a new document from template" msgstr "Vytvořit nový dokument ze šablony" msgid "Create Document In..." msgstr "Vytvořit dokument v…" msgid "Textfiles" msgstr "Textové soubory" msgid "Append To..." msgstr "Připojit k…" msgid "Append..." msgstr "Připojit…" msgid "Write To..." msgstr "Zapsat do…" msgid "Get Text Contents" msgstr "Získat textový obsah" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "Akce správce souborů Thunar" msgid "Select in File Manager" msgstr "Vybrat ve správci souborů" msgid "Show Properties" msgstr "Zobrazit vlastnosti" msgid "Show information about file in file manager" msgstr "Zobrazit informace o souborech ve správci souborů" msgid "Send To..." msgstr "Odeslat do…" msgid "Symlink In..." msgstr "Symbolický odkaz v…" msgid "Create a symlink to file in a chosen location" msgstr "Vytvořit symbolický odkaz na soubor ve zvoleném umístění" msgid "Empty Trash" msgstr "Vyprázdnit koš" msgid "Thunar Send To Objects" msgstr "Objekty „Odeslat do“ aplikace Thunar" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Kontakty a akce v Thunderbird/Icedove" msgid "Compose New Email" msgstr "Napsat nový e-mail" msgid "Compose a new message in Thunderbird" msgstr "Napsat novou zprávu v aplikaci Thunderbird" #, fuzzy msgid "Attach in Email To..." msgstr "Odeslat e-mailem…" #, fuzzy msgid "Compose Email With" msgstr "Napsat e-mail" #, fuzzy msgid "Compose a new message using the text as body" msgstr "Napsat novou zprávu v aplikaci Thunderbird" msgid "Thunderbird Address Book" msgstr "Adresář aplikace Thunderbird" msgid "Contacts from Thunderbird Address Book" msgstr "Kontakty z adresáře poštovního klienta Thunderbird" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Top" msgid "Show running tasks and allow sending signals to them" msgstr "Zobrazuje běžící úlohy a umožňuje jim zaslat signál" msgid "Sort Order" msgstr "Řazení" msgid "Commandline" msgstr "Příkazový řádek" msgid "CPU usage (descending)" msgstr "Využití procesoru (sestupně)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Využití paměti (sestupně)" msgid "Send Signal..." msgstr "Zaslat signál…" msgid "Signals" msgstr "Signály" msgid "Running Tasks" msgstr "Běžící úlohy" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid: %(pid)s cpu: %(cpu)g%% paměť: %(mem)g%% čas: %(time)s" msgid "Running tasks for current user" msgstr "Úlohy běžící pro současného uživatele" msgid "Trash" msgstr "Koš" msgid "Access trash contents" msgstr "Přístup k obsahu koše" msgid "Move to Trash" msgstr "Přesunout do koše" msgid "Move this file to trash" msgstr "Přesunout tento soubor do koše" msgid "Restore" msgstr "Obnovit" msgid "Move file back to original location" msgstr "Přesunout soubor zpět na původní místo" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "Koš je prázdný" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "Koš obsahuje jeden soubor" msgstr[1] "Koš obsahuje %(num)s soubory" msgstr[2] "Koš obsahuje %(num)s souborů" msgid "Triggers" msgstr "Spouštěče" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Přiřadit globální klávesové zkratky (spouštěče) objektům vytvořeným pomocí " "„Napsat příkaz“" msgid "Add Trigger..." msgstr "Přidat spouštěč…" msgid "Remove Trigger" msgstr "Odstranit spouštěč" msgid "URL Actions" msgstr "Akce s URL" msgid "Download and Open" msgstr "Stáhnout a otevřít" msgid "Download To..." msgstr "Stáhnout do…" msgid "Download URL to a chosen location" msgstr "Stáhnout URL do vybraného místa" msgid "Wikipedia" msgstr "Wikipedie" msgid "Search in Wikipedia" msgstr "Hledat na Wikipedii" msgid "Wikipedia language" msgstr "Jazyk Wikipedie" #. TRANS: Default wikipedia language code msgid "en" msgstr "cs" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Vyhledat tento výraz na %s.wikipedia.org" msgid "Window List" msgstr "Seznam oken" msgid "All windows on all workspaces" msgstr "Všechna okna na všech pracovních plochách" msgid "Activate" msgstr "Aktivovat" msgid "Shade" msgstr "Zakrýt" msgid "Unshade" msgstr "Odkrýt" msgid "Minimize" msgstr "Minimalizovat" msgid "Unminimize" msgstr "Zrušit minimalizaci" msgid "Maximize" msgstr "Maximalizovat" msgid "Unmaximize" msgstr "Zrušit maximalizaci" msgid "Maximize Vertically" msgstr "Maximalizovat svisle" msgid "Unmaximize Vertically" msgstr "Zrušit svislou maximalizaci" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Okno na ploše %(wkspc)s" msgid "Frontmost Window" msgstr "Okno zcela nahoře" msgid "Next Window" msgstr "Následující okno" msgid "Jump to this window's workspace and focus" msgstr "Přejít na pracovní plochu s tímto oknem a zaměřit jej" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "%d okno" msgstr[1] "%d okna" msgstr[2] "%d oken" msgid "Active workspace" msgstr "Aktivní pracovní plocha" msgid "Jump to this workspace" msgstr "Přejít na tuto pracovní plochu" msgid "Workspaces" msgstr "Pracovní plochy" msgid "Volumes and Disks" msgstr "Svazky a disky" msgid "Mounted volumes and disks" msgstr "Připojené svazky a disky" #, python-format msgid "Volume mounted at %s" msgstr "Svazek připojen v %s" msgid "Unmount" msgstr "Odpojit" msgid "Unmount this volume" msgstr "Odpojit tento svazek" msgid "Eject" msgstr "Vysunout" msgid "Unmount and eject this media" msgstr "Odpojit a vysunout toto médium" msgid "Show Text" msgstr "Zobrazit text" msgid "Display text in a window" msgstr "Zobrazit text v okně" msgid "Large Type" msgstr "Rozsáhlý typ" msgid "Show Notification" msgstr "Zobrazovat oznámení" msgid "Tracker" msgstr "Tracker" msgid "Tracker desktop search integration" msgstr "Vyhledávač Tracker integrovaný v pracovním prostředí" msgid "Search in Tracker" msgstr "Vyhledat prohledávačem Tracker" msgid "Open Tracker Search Tool and search for this term" msgstr "Otevřít vyhledávací nástroj Tracker a vyhledat tento výraz" msgid "Get Tracker Results..." msgstr "Získat výsledky prohledávače Tracker…" msgid "Show Tracker results for query" msgstr "Zobrazit výsledky dotazu z prohledávače Tracker" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "Výsledky pro „%s“" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "Najít soubory" msgid "Search filesystem using locate" msgstr "Prohledat souborový systém pomocí programu „locate“" msgid "Ignore case distinctions when searching files" msgstr "Při vyhledávání souborů nebrat ohled na velikost písmen" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Záložky ve Firefoxu" msgid "Index of Firefox bookmarks" msgstr "Seznam záložek v prohlížeči Firefox" #, fuzzy msgid "Firefox Keywords" msgstr "Záložky ve Firefoxu" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "Prohledat web pomocí vyhledávacího stroje OpenSearch" msgid "Search With..." msgstr "Prohledat pomocí…" msgid "Search For..." msgstr "Vyhledat…" #, fuzzy msgid "Search Terms" msgstr "Vyhledávací stroje" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Použijte prosím „%s“" #, fuzzy msgid "Resume playback" msgstr "Pokračovat v přehrávání v přehrávači Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Následující" #, fuzzy msgid "Skip to next track" msgstr "Přeskočit na následující stopu v přehrávači Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Předchozí" #, fuzzy msgid "Skip to previous track" msgstr "Přeskočit na předchozí stopu v přehrávači Audacious" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "Přístup ke kontaktům v komunikátoru Pidgin" msgid "Show offline contacts" msgstr "Zobrazovat odpojené kontakty" msgid "Open Chat" msgstr "Otevřít diskuzi" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d znak)" msgstr[1] "%s (%d znaky)" msgstr[2] "%s (%d znaků)" msgid "Send Message..." msgstr "Odeslat zprávu…" msgid "Available" msgstr "Dostupný" msgid "Away" msgstr "Pryč" msgid "Pidgin Contacts" msgstr "Kontakty Pidgin" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Zkrácené odkazy" msgid "Create short aliases of long URLs" msgstr "Vytvořit zkrácené přezdívky pro dlouhé URL" msgid "Error" msgstr "Chyba" msgid "Shorten With..." msgstr "Zkrátit pomocí…" msgid "Services" msgstr "Služby" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "Přehrávání a přidávání skladeb do fronty a procházení hudební knihovny" msgid "Include artists in top level" msgstr "Zahrnout umělce do nejvyšší úrovně" msgid "Include albums in top level" msgstr "Zahrnout alba do nejvyšší úrovně" msgid "Play tracks in Rhythmbox" msgstr "Přehrát skladby v přehrávači Rhythmbox" msgid "Add tracks to the play queue" msgstr "Přidat skladbu do fronty přehrávaných skladeb" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "od interpreta %(artist)s z alba %(album)s" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "od interpreta %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Skladby od interpreta %s" msgid "Albums" msgstr "Alba" msgid "Music albums in Rhythmbox Library" msgstr "Hudební album v knihovně Rhythmbox" msgid "Artists" msgstr "Umělci" msgid "Music artists in Rhythmbox Library" msgstr "Hudební umělec v knihovně Rhythmbox" msgid "Songs" msgstr "Skladby" msgid "Songs in Rhythmbox library" msgstr "Skladba v knihovně Rhythmbox" msgid "Getting Things GNOME" msgstr "Getting Things GNOME" msgid "Browse and create new tasks in GTG" msgstr "Procházení a vytváření nových úkolů v GTG" #, python-format msgid "due: %s" msgstr "termín: %s" #, python-format msgid "start: %s" msgstr "začít: %s" #, python-format msgid "tags: %s" msgstr "značky: %s" msgid "Open task in Getting Things GNOME!" msgstr "Otevřít úkol v Getting Things GNOME!" msgid "Delete" msgstr "Smazat" msgid "Permanently remove this task" msgstr "Trvale odstranit tento úkol" msgid "Mark Done" msgstr "Označit „Dokončeno“" msgid "Mark this task as done" msgstr "Označit tento úkol jako dokončený" msgid "Dismiss" msgstr "Zahodit" msgid "Mark this task as not to be done anymore" msgstr "Označit úkol, že již nebude dokončen" msgid "Create Task" msgstr "Vytvořit úkol" msgid "Create new task in Getting Things GNOME" msgstr "Vytvořit nový úkol v aplikaci Getting Things GNOME" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "Hledat v nápovědě pro vývojáře DevHelp" msgid "Empathy" msgstr "Empathy" msgid "Access to Empathy Contacts" msgstr "Přístup ke kontaktům v komunikátoru Empathy" msgid "Busy" msgstr "Nerušit" msgid "Not Available" msgstr "Nedostupný" msgid "Invisible" msgstr "Neviditelný" msgid "Offline" msgstr "Odpojený" msgid "Change Global Status To..." msgstr "Změnit globální stav na…" msgid "Empathy Contacts" msgstr "Kontakty v komunikátoru Empathy" msgid "Empathy Account Status" msgstr "Stav účtu Empathy" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Alternativní aktivace" # Překlad viz dotaz v konferenci kupfer: http://mail.gnome.org/archives/kupfer-list/2010-April/msg00003.html #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Vložení do zásobníku" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Sestavit příkaz" msgid "Mark Default Action" msgstr "Označit výchozí akci" msgid "Forget Object" msgstr "Zapomenout objekt" msgid "Reset All" msgstr "U všech vrátit původní" msgid "Select Quit" msgstr "Zvolit ukončení" msgid "Select Selected File" msgstr "Zvolit vybraný soubor" msgid "Select Selected Text" msgstr "Zvolit vybraný text" msgid "Show Help" msgstr "Zobrazit nápovědu" msgid "Show Preferences" msgstr "Zobrazit předvolby" msgid "Switch to First Pane" msgstr "Přepnout na první panel" msgid "Toggle Text Mode" msgstr "Přepnout textový režim" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Ve zdroji %(src)s nebylo pro dotaz \"%(query)s\" nic nalezeno" msgid "No matches" msgstr "Nic nenalezeno" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Nic nenalezeno" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Nastavit akci „%(action)s“ jako výchozí pro objekt „%(object)s“" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "Zapomenout informace o „%s“" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Zobrazit hlavní rozhraní" msgid "Show with Selection" msgstr "Zobrazit s výběrem" #. TRANS: Plugin info fields msgid "Description" msgstr "Popis" msgid "Author" msgstr "Autor" msgid "Version" msgstr "Verze" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Je zapotřebí modul Python „%s“" msgid "Plugin could not be read due to an error:" msgstr "Zásuvný modul nemohl být načten kvůli výskytu chyby:" msgid "Content of" msgstr "Obsah" #. TRANS: Plugin contents header msgid "Sources" msgstr "Zdroje" #. TRANS: Plugin contents header msgid "Actions" msgstr "Akce" #, python-format msgid "Using encrypted password storage: %s" msgstr "Použití šifrovaného úložiště s heslem: %s" #, python-format msgid "Using password storage: %s" msgstr "Použití úložiště s heslem: %s" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Nastavení" msgid "Set username and password" msgstr "Nastavit jméno a heslo" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Výběr složky" msgid "Reset all shortcuts to default values?" msgstr "Nastavit všechny klávesové zkratky na výchozí hodnoty?" msgid "Shortcut" msgstr "Klávesová zkratka" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "Marek Černocký " msgid "A free software (GPLv3+) launcher" msgstr "Spouštěč vydaný pod svobodnou licencí (GPLv3+)" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Tento program je svobodný software: Můžete jej dále šířit a/nebo upravovat " "za podmínek licence GNU General Public License v podobě, v jaké ji vydala " "Free Software Foundation, a to buď ve verzi 3 této licence nebo (dle vaší " "volby) v libovolné novější verzi.\n" "\n" "Tento program je šířen ve víře, že bude užitečný, ale BEZ JAKÝCHKOLIV ZÁRUK, " "a to i bez předpokládané záruky na PRODEJNOST nebo VHODNOST PRO KONKRÉTNÍ " "ÚČEL. Více podrobností najdete přímo v licenci GNU General Public License.\n" "\n" "Spolu s tímto programem byste měli obdržet kopii licence GNU General Public " "License. Pokud se tak nestalo, podívejte se na .\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Nelze najít běžící aplikaci Kupfer" #~ msgid "Compose Email" #~ msgstr "Napsat e-mail" #~ msgid "Send in Email To..." #~ msgstr "Odeslat e-mailem…" #~ msgid "Type to search %s" #~ msgstr "Pište, prohledá se %s" #~ msgid "No action" #~ msgstr "Žádná akce" #~ msgid "GNOME Terminal Profiles" #~ msgstr "Profily terminálu GNOME" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Profily pro spouštění terminálu GNOME" #~ msgid "Multihead Support" #~ msgstr "Podpora více monitorů" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Vypočítat výraz začínajících „=“" #~ msgid "Epiphany Bookmarks" #~ msgstr "Záložky v Epiphany" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Seznam záložek v prohlížeči Epiphany" #~ msgid "Include visited sites" #~ msgstr "Zahrnout navštívené stránky" #~ msgid "Firefox tag" #~ msgstr "Štítky ve Firefoxu" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Pokračovat v přehrávání v přehrávači Rhythmbox" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Pozastavit přehrávání v přehrávači Rhythmbox" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Přeskočit na následující stopu v přehrávači Rhythmbox" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Přeskočit na předchozí stopu v přehrávači Rhythmbox" #~ msgid "Search the Web" #~ msgstr "Prohledat web" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Nedávno použité dokumenty v aplikaci Abiword" #~ msgid "Abiword Recent Items" #~ msgstr "Nedávné položky Abiword" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "Rozhraní ke správci balíčků APT" #~ msgid "Installation method" #~ msgstr "Instalační metoda" #~ msgid "Show Package Information" #~ msgstr "Zobrazit informace o balíčku" #~ msgid "Install" #~ msgstr "Nainstalovat" #~ msgid "Install package using the configured method" #~ msgstr "Nainstalovat balíček pomocí nastavené metody" #~ msgid "Packages matching \"%s\"" #~ msgstr "Odpovídající balíčky „%s“" #~ msgid "Search Package Name..." #~ msgstr "Vyhledat balíček podle názvu…" #~ msgid "Ascii & Unicode Icon Set" #~ msgstr "Sada ikon ASCII a Unikód" #~ msgid "" #~ "Provides the Ascii and Unicode icon sets that use letters and symbols to " #~ "produce icons for the objects found in Kupfer." #~ msgstr "" #~ "Poskytuje sadu ikon ASCII a Unikód, které používají písmena a symboly k " #~ "vytvoření ikon pro objekty nalezené v aplikaci Kupfer." #~ msgid "Ascii" #~ msgstr "ASCII" #~ msgid "Unicode" #~ msgstr "Unikód" #~ msgid "Chromium Bookmarks" #~ msgstr "Záložky v prohlížeči Chromium" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Seznam záložek v prohlížeči Chromium" #~ msgid "Claws Mail" #~ msgstr "Claws Mail" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Kontakty a akce v Claws Mail" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Napsat nový e-mail v poštovním klientovi Claws Mail" #~ msgid "Receive All Email" #~ msgstr "Přijmout všechny e-maily" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "" #~ "Přijmout pomocí poštovního klienta Claws Mail nové zprávy ze všech účtů" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "" #~ "Napsat novou zprávu v poštovním klientovi Claws Mail a přiložit soubor" #~ msgid "Claws Mail Address Book" #~ msgstr "Adresář z Claws Mail" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Kontakty z adresáře poštovního klienta Claws Mail" #~ msgid "Configure a custom terminal emulator" #~ msgstr "Nastavit vlastní emulátor terminálu" #~ msgid "Custom Theme" #~ msgstr "Vlastní motiv" #~ msgid "Use a custom color theme" #~ msgstr "Použít motiv s vlastními barvami" #~ msgid "Theme:" #~ msgstr "Motiv:" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Kontakty aplikace Evolution" #~ msgid "Compose a new message in Evolution" #~ msgstr "Napsat nový e-mail v poštovním klientovi Evolution" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "" #~ "Napsat novou zprávu v poštovním klientovi Evolution a přiložit soubor" #~ msgid "Evolution Address Book" #~ msgstr "Adresář aplikace Evolution" #~ msgid "Filezilla" #~ msgstr "Filezilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Zobrazit servery a pracovat s FTP pomocí aplikace Filezilla" #~ msgid "Open Site with Filezilla" #~ msgstr "Připojit se k serveru pomocí aplikace Filezilla" #~ msgid "Filezilla Sites" #~ msgstr "Servery Filezilla" #~ msgid "Sites from Filezilla" #~ msgstr "Servery z aplikace Filezilla" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Přístup ke kontaktům v komunikátoru Gajim" #~ msgid "Free for Chat" #~ msgstr "Ukecaný" #~ msgid "Gajim Contacts" #~ msgstr "Kontakty v komunikátoru Gajim" #~ msgid "Gajim Account Status" #~ msgstr "Stav účtu Gajim" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Načítání kontaktů a psaní nových e-mailů v Gmail" #~ msgid "Load contacts' pictures" #~ msgstr "Načítat obrázky kontaktů" #~ msgid "Load additional information" #~ msgstr "Načíst doplňující informace" #~ msgid "Work email" #~ msgstr "E-mail do práce" #~ msgid "Home email" #~ msgstr "E-mail domů" #~ msgid "Other email" #~ msgstr "Jiný e-mail" #~ msgid "Work address" #~ msgstr "Adresa do práce" #~ msgid "Home address" #~ msgstr "Adresa domů" #~ msgid "Other address" #~ msgstr "Jiná adresa" #~ msgid "Car phone" #~ msgstr "Telefon do auta" #~ msgid "Fax" #~ msgstr "Fax" #~ msgid "Home phone" #~ msgstr "Telefon domů" #~ msgid "Home fax" #~ msgstr "Fax domů" #~ msgid "Internal phone" #~ msgstr "Interní telefon" #~ msgid "Mobile" #~ msgstr "Mobilní telefon" #~ msgid "Other" #~ msgstr "Jiný" #~ msgid "VOIP" #~ msgstr "VOIP" #~ msgid "Work phone" #~ msgstr "Telefon do práce" #~ msgid "Work fax" #~ msgstr "Fax do práce" #~ msgid "Compose Email in Gmail" #~ msgstr "Napsat e-mail v pošťáku Gmail" #~ msgid "Open web browser and compose new email in Gmail" #~ msgstr "Otevřít webový prohlížeč a napsat nový e-mail v pošťáku Gmail" #~ msgid "Edit Contact in Gmail" #~ msgstr "Upravit kontakt na službě Gmail" #~ msgid "Open web browser and edit contact in Gmail" #~ msgstr "Otevřít webový prohlížeč a upravit kontakt na službě Gmail" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Kontakty ze služeb Google (Gmail)" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Zobrazit alba a odesílat soubory do služby Picasa" #~ msgid "Users to show: (,-separated)" #~ msgstr "Zobrazit uživatele: (oddělujte ,)" #~ msgid "Load user and album icons" #~ msgstr "Načítat ikony uživatelů a alb" #~ msgid "Uploading Pictures" #~ msgstr "Odesílají se obrázky" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Odeslat obrázky do webového alba Picasa" #~ msgid "Creating album:" #~ msgstr "Vytvoření alba:" #~ msgid "Album created by Kupfer" #~ msgstr "Album vytvořené aplikací Kupfer" #~ msgid "File:" #~ msgstr "Soubor:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "Jedno album" #~ msgstr[1] "%(num)d alba" #~ msgstr[2] "%(num)d alb" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "jedna fotka" #~ msgstr[1] "%(num)s fotky" #~ msgstr[2] "%(num)s fotek" #~ msgid "Upload to Picasa Album..." #~ msgstr "Odeslat do alba Picasa…" #~ msgid "Upload files to Picasa album" #~ msgstr "Odeslat soubory do alba Picasa" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Odeslat jako nové album Picasa" #~ msgid "Create album from selected local directory" #~ msgstr "Vytvořit album z vybrané místní složky" #~ msgid "Picasa Albums" #~ msgstr "Alba Picasa" #~ msgid "User albums in Picasa" #~ msgstr "Uživatelská alba ve službě Picasa" #~ msgid "Google Search" #~ msgstr "Vyhledávač Google" #~ msgid "Search Google with results shown directly" #~ msgstr "Vyhledávání pomocí Google s přímým zobrazením výsledků" #~ msgid "Show More Results For \"%s\"" #~ msgstr "Zobrazit více výsledků pro „%s“" #~ msgid "%s total found" #~ msgstr "Celkem nalezeno %s" #~ msgid "Gwibber" #~ msgstr "Gwibber" #~ msgid "" #~ "Microblogging with Gwibber. Allows sending and receiving messages from " #~ "social networks like Twitter, Identi.ca etc. Requires the package " #~ "'gwibber-service'." #~ msgstr "" #~ "Mikroblogování se službou Gwibber. Umožňuje odesílat a přijímat zprávy ze " #~ "sociálních sítí jako je Twitter, Identi.ca atd. Vyžaduje balíček „gwibber-" #~ "service“." #~ msgid "Maximum number of messages to show" #~ msgstr "Maximální počet zobrazovaných zpráv" #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s na %(service)s" #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s na %(where)s" #~ msgid "Send Message" #~ msgstr "Odeslat zprávu" #~ msgid "Send message to all Gwibber accounts" #~ msgstr "Odeslat zprávu na všechny účty Gwibber" #~ msgid "Send Message To..." #~ msgstr "Odeslat zprávu na…" #~ msgid "Send message to a Gwibber account" #~ msgstr "Odeslat zprávu na účet Gwibber" #~ msgid "Send message to selected Gwibber account" #~ msgstr "Odeslat zprávu na vybraný účet Gwibber" #~ msgid "Reply..." #~ msgstr "Odpovědět…" #~ msgid "Delete Message" #~ msgstr "Smazat zprávu" #~ msgid "Send Private Message..." #~ msgstr "Odeslat soukromou zprávu…" #~ msgid "Send direct message to user" #~ msgstr "Odeslat přímou zprávu uživateli" #~ msgid "Retweet" #~ msgstr "Znovu napsat" #~ msgid "Retweet To..." #~ msgstr "Znovu napsat na…" #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Znovu napsat zprávu na všechny účty Gwibber" #~ msgid "Retweet message to a Gwibber account" #~ msgstr "Znovu napsat zprávu na účet Gwibber" #~ msgid "Open in Browser" #~ msgstr "Otevřít v prohlížeči" #~ msgid "Open message in default web browser" #~ msgstr "Otevřít zprávu ve výchozím prohlížeči" #~ msgid "Gwibber Accounts" #~ msgstr "Účty Gwibber" #~ msgid "Accounts configured in Gwibber" #~ msgstr "Účty nastavené ve službě Gwibber" #~ msgid "Gwibber Messages" #~ msgstr "Zprávy Gwibber" #~ msgid "Recent messages received by Gwibber" #~ msgstr "Poslední zprávy přijaté na Gwibber" #~ msgid "Gwibber Messages for %s" #~ msgstr "Zprávy Gwibber pro službu %s" #~ msgid "Gwibber Streams" #~ msgstr "Proudy Gwibber" #~ msgid "Streams configured in Gwibber" #~ msgstr "Proudy nastavené ve službě Gwibber" #~ msgid "Gwibber Messages in %s" #~ msgstr "Zprávy Gwibber v proudu %s" #~ msgid "Gwibber (Simple)" #~ msgstr "Gwibber (jednoduchý)" #~ msgid "Send updates via the microblogging client Gwibber" #~ msgstr "Poslat aktualizaci přes mikroblogovacího klienta Gwibber" #~ msgid "Send Update" #~ msgstr "Poslat aktualizaci" #~ msgid "Unable to activate Gwibber service" #~ msgstr "Nelze aktivovat službu Gwibber" #~ msgid "OpenOffice / LibreOffice" #~ msgstr "OpenOffice / LibreOffice" #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Dokumenty nedávno použité v OpenOffice/LibreOffice" #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "Nedávné položky OpenOffice/LibreOffice" #~ msgid "Opera Mail" #~ msgstr "Opera Mail" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Kontakty a akce poštovního klienta Opera Mail" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Napsat nový e-mail v poštovním klientovi Opera Mail" #~ msgid "Opera Mail Contacts" #~ msgstr "Kontakty v Opera Mail" #~ msgid "Contacts from Opera Mail" #~ msgstr "Kontakty z adresáře poštovního klienta Opera Mail" #~ msgid "Opera Bookmarks" #~ msgstr "Záložky v Opeře" #~ msgid "Index of Opera bookmarks" #~ msgstr "Seznam záložek v prohlížeči Opera" #~ msgid "PuTTY Sessions" #~ msgstr "Sezení PuTTY" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Rychlý přístup k sezením PuTTY" #~ msgid "Start Session" #~ msgstr "Spustit sezení" #~ msgid "reStructuredText" #~ msgstr "reStructuredText" #~ msgid "Render reStructuredText and show the result" #~ msgstr "Vykreslit reStructuredText a zobrazit výsledek" #~ msgid "View as HTML Document" #~ msgstr "Zobrazit jako dokument HTML" #~ msgid "System Services" #~ msgstr "Systémové služby" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "" #~ "Spustit, zastavit nebo restartovat systémové služby přes inicializační " #~ "skripty" #~ msgid "Sudo-like Command" #~ msgstr "Příkaz typu sudo" #~ msgid "Start Service" #~ msgstr "Spustit službu" #~ msgid "Stop Service" #~ msgstr "Zastavit službu" #~ msgid "%s Service" #~ msgstr "Služba %s" #~ msgid "Show QRCode" #~ msgstr "Zobrazit kód QR" #~ msgid "Display text as QRCode in a window" #~ msgstr "Zobrazit text jako kód QR v okně" #~ msgid "Access to Skype contacts" #~ msgstr "Přístup ke kontaktům komunikátoru Skype" #~ msgid "Skype Me" #~ msgstr "Zavolat mi" #~ msgid "Logged Out" #~ msgstr "Odhlášeno" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Volat" #~ msgid "Place a call to contact" #~ msgstr "Umístit volání do kontaktu" #~ msgid "Skype Contacts" #~ msgstr "Kontakty v komunikátoru Skype" #~ msgid "Skype Statuses" #~ msgstr "Stav komunikátoru Skype" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Svazky z historie TrueCrypt" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "Svazek TrueCrypt: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Připojit svazek" #~ msgid "Mount in Truecrypt" #~ msgstr "Připojit v Truecrypt" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Zkusit připojit soubor jako svazek Truecrypt" #~ msgid "Dismount All Volumes" #~ msgstr "Odpojit všechny svazky" #~ msgid "TrueCrypt Volumes" #~ msgstr "Svazky TrueCrypt" #~ msgid "Terminal Server Client" #~ msgstr "Terminal Server Client" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Sezení uložené v Terminal Server Client" #~ msgid "TSClient sessions" #~ msgstr "Sezení TSClient" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Uložená sezení v Terminal Server Client" #~ msgid "Vim" #~ msgstr "Vim" #~ msgid "Recently used documents in Vim" #~ msgstr "Nedávno použité dokumenty v aplikaci Vim" #~ msgid "Vim Recent Documents" #~ msgstr "Nedávné dokumenty Vim" #~ msgid "Close (Save All)" #~ msgstr "Zavřít (Uložit vše)" #~ msgid "Send..." #~ msgstr "Odeslat…" #~ msgid "Send ex command" #~ msgstr "Odeslat příkaz ex" #~ msgid "Insert in Vim..." #~ msgstr "Vložit ve Vim…" #~ msgid "Active Vim Sessions" #~ msgstr "Aktivovat sezení Vim" #~ msgid "Vim Session %s" #~ msgstr "Sezení Vim %s" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Záložky a akce klienta Vinagre" #~ msgid "Start Vinagre Session" #~ msgstr "Spustit sezení Vinagre" #~ msgid "Vinagre Bookmarks" #~ msgstr "Záložky ve Vinagre" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "Ovládání virtuálních strojů ve VirtualBoxu. Podporuje jak Sun VirtualBox, " #~ "tak Open Source Editon." #~ msgid "Force use CLI interface" #~ msgstr "Vynutit použití řádkového rozhraní" #~ msgid "Power On" #~ msgstr "Zapnout" #~ msgid "Power On Headless" #~ msgstr "Zapnout bez grafiky" #~ msgid "Send Power Off Signal" #~ msgstr "Zaslat signál pro vypnutí" #~ msgid "Reboot" #~ msgstr "Restartovat" #~ msgid "Resume" #~ msgstr "Obnovit" #~ msgid "Save State" #~ msgstr "Uložit stav" #~ msgid "Power Off" #~ msgstr "Vypnout" #~ msgid "VirtualBox Machines" #~ msgstr "Virtuální stroje ve VirtualBoxu" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "Přístup do stránek uchovaných v Zim - Místní Wiki a zápisník" #~ msgid "Page names start with :colon" #~ msgstr "Názvy stránek začínat :dvojtečkou" #~ msgid "Default page name for quick notes" #~ msgstr "Název výchozí stránky pro rychlé poznámky" #~ msgid "Note %x %X" #~ msgstr "Poznámka %x %X" #~ msgid "" #~ "Strftime tags can be used: %H - hour, %M - minutes, etc\n" #~ "Please check python documentation for details.\n" #~ "NOTE: comma will be replaced by _" #~ msgstr "" #~ "Můžete využívat značek Strftime: %H – hodina, %M – minuty, atd.\n" #~ "Podrobnosti najdete v dokumentaci k jazyku Python.\n" #~ "POZNÁMKA: čárka bude nahrazena _" #~ msgid "Default namespace for quick notes" #~ msgstr "Výchozí jmenný prostor pro rychlé poznámky" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Stránka Zim ze zápisníku „%s“" #~ msgid "Create Zim Page" #~ msgstr "Vytvořit stránku Zim" #~ msgid "Create page in default notebook" #~ msgstr "Vytvořit stránku ve výchozím zápisníku" #~ msgid "Create Zim Page In..." #~ msgstr "Vytvořit stránku Zim v…" #~ msgid "Insert QuickNote into Zim" #~ msgstr "Vložit rychlou poznámku do Zim" #~ msgid "Quick note selected text into Zim notebook" #~ msgstr "Z vybraného textu rychlou poznámku v zápisníku Zim" #~ msgid "Create Subpage..." #~ msgstr "Vytvořit podstránku…" #~ msgid "Zim Notebooks" #~ msgstr "Zápisníky Zim" #~ msgid "Zim Pages" #~ msgstr "Stránky Zim" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Stránky uchované v zápisnících Zim" kupfer-328/po/da.po000066400000000000000000001550361500175051100142330ustar00rootroot00000000000000# Danish translation for kupfer. # Copyright (C) 2010 kupfer's COPYRIGHT HOLDER # This file is distributed under the same license as the kupfer package. # joehansen , 2010. # # compose -> skriv (opret, komponer) # email -> e-post (kunne nok også være brev, e-brev nogle af stederne) # suspend -> hvile # volume -> diskenhed (eller drev?) # msgid "" msgstr "" "Project-Id-Version: kupfer master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2010-09-28 17:30+01:00\n" "Last-Translator: Joe Hansen \n" "Language-Team: Danish \n" "Language: da\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" msgid "User credentials" msgstr "Brugerakkreditiver" msgid "_User:" msgstr "_Bruger:" msgid "_Password:" msgstr "_Adgangskode:" msgid "_Change" msgstr "_Ændr" msgid "Set Keyboard Shortcut" msgstr "Angiv tastaturgenvej" msgid "Please press desired key combination" msgstr "Tryk venligst på ønsket tastekombination" msgid "Keybinding could not be bound" msgstr "Tastaturgenvej kunne ikke sættes" msgid "Kupfer Preferences" msgstr "Kupferindstillinger" msgid "Start automatically on login" msgstr "Start automatisk ved logind" msgid "Start" msgstr "Start" msgid "Show icon in notification area" msgstr "Vis ikon i statusfelt" msgid "Icon set:" msgstr "" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" #, fuzzy msgid "Terminal emulator:" msgstr "Åbn terminal her" #, fuzzy msgid "Desktop Environment" msgstr "Programmer til skrivebordsmiljø" msgid "General" msgstr "Generelt" msgid "Global Keyboard Shortcuts" msgstr "Globale tastaturgenveje" msgid "Reset" msgstr "Nulstil" msgid "Browser Keyboard Shortcuts" msgstr "Tastaturgenveje til browser" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "Brug enkelttastkommandoer (mellemrum, /, punktum, komma etc.)" msgid "Keyboard" msgstr "Tastatur" msgid "Plugins" msgstr "Udvidelsesmodul" #, fuzzy msgid "Inclusion in Top Level Searches" msgstr "Inkluder sange i overniveau" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" #, fuzzy msgid "Indexed Folders" msgstr "Ny mappe" msgid "Folders whose files are always available in the catalog." msgstr "" msgid "Catalog" msgstr "Katalog" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Programopstarter" msgid "Convenient command and access tool for applications and documents" msgstr "Nemt kommando- og adgangsværktøj til programmer og dokumenter" msgid "Execute in Kupfer" msgstr "Kør i Kupfer" msgid "Saved Kupfer Command" msgstr "Gemt Kupferkommando" # lyder lidt sort det her (også den engelske) # tror de mener at det er en kommando, de ikke kan udføre #, python-format msgid "Could not to carry out '%s'" msgstr "Kunne ikke at udføre '%s'" #, python-format msgid "\"%s\" produced a result" msgstr "\"%s\" gav et resultat" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Ingen tilladelse til at køre \"%s\" (ikke kørbar)" #, python-format msgid "Command in \"%s\" is not available" msgstr "Kommando i \"%s\" er ikke tilgængelig" #, python-format msgid "Keyboard relay is active for display %s" msgstr "" msgid "do not present main interface on launch" msgstr "præsenter ikke hovedgrænseflade ved opstart" msgid "list available plugins" msgstr "vis tilgængelige udvidelsesmoduler" msgid "enable debug info" msgstr "aktiver fejlsøgningsinfo" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "" msgid "show usage help" msgstr "vis hjælp" msgid "show version information" msgstr "vis versionsinformation" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Brug: kupfer [ TILVALG | FIL ... ]" msgid "Available plugins:" msgstr "Tilgængelige udvidelsesmoduler:" # skal den oversættes? #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "Skriv for at søge" #, python-format msgid "%s is empty" msgstr "%s er tom" #, fuzzy msgid "Text" msgstr "Vis tekst" msgid "Run after Delay..." msgstr "Kør efter forsinkelse..." msgid "Perform command after a specified time interval" msgstr "Udfør kommando efter et specifikt tidsinterval" msgid "Multiple Objects" msgstr "Flere objekter" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s objekt" msgstr[1] "%s objekter" # oversættes? #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "" #, fuzzy msgid "Aim" msgstr "Vim" #, fuzzy msgid "Google Talk" msgstr "Google oversæt" msgid "ICQ" msgstr "" msgid "MSN" msgstr "" msgid "QQ" msgstr "" msgid "Yahoo" msgstr "" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "" msgid "Can not be used with multiple objects" msgstr "" msgid "Open" msgstr "Åbn" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Intet standardprogram til %(file)s (%(type)s)" #, fuzzy, python-format msgid "Please use \"%s\"" msgstr "Markeret fil \"%s\"" msgid "Set Default Application..." msgstr "Angiv standardprogram..." msgid "Open with default application" msgstr "Åbn med standardprogram" msgid "Reveal" msgstr "Afslør" msgid "Open parent folder" msgstr "Åbn overmappe" msgid "Open Terminal Here" msgstr "Åbn terminal her" msgid "Open this location in a terminal" msgstr "Åbn denne placering i en terminal" msgid "Run in Terminal" msgstr "Kør i terminal" msgid "Run (Execute)" msgstr "Kør (afvikl)" msgid "Run this program in a Terminal" msgstr "Kør dette program i en terminal" msgid "Run this program" msgstr "Kør dette program" msgid "Go To" msgstr "Gå til" msgid "Open URL" msgstr "Åbn adresse" msgid "Open URL with default viewer" msgstr "Åbn adresse med standardviser" msgid "Launch" msgstr "Start" msgid "Show application window" msgstr "Vis programvindue" msgid "Launch application" msgstr "Start program" msgid "Launch Again" msgstr "Start igen" msgid "Launch another instance of this application" msgstr "Start en anden instans af dette program" msgid "Close" msgstr "Luk" msgid "Attempt to close all application windows" msgstr "Forsøg at lukke alle programvinduer" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Kør" msgid "Perform command" msgstr "Udfør kommando" #, fuzzy msgid "(Empty Text)" msgstr "Tom fil" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "\"%(text)s\"" msgstr[1] "(%(num)d linjer) \"%(text)s\"" # den forstår jeg ikke? hvad betyder et. al. # forkortelse for 'et alia', som betyder 'og andre'. Det er forkert at # have punktum efter 'et'. Den rigtige måde at skrive det på er 'et # al.' Kunne evt. være m.fl. på dansk #. TRANS: Multiple artist description "Artist1 et. al. " #, fuzzy, python-format msgid "%s et. al." msgstr "%s m.fl." #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Rekursiv kilde for %(dir)s, (%(levels)d niveauer)" #, python-format msgid "Directory source %s" msgstr "Mappekilde %s" msgid "Home Folder" msgstr "Hjemmemappe" msgid "Catalog Index" msgstr "Katalogindeks" msgid "An index of all available sources" msgstr "Et indeks af alle tilgængelige kilder" msgid "Root catalog" msgstr "Rodkatalog" msgid "Please Configure Plugin" msgstr "Konfigurer venligst udvidelsesmodul" #, python-format msgid "Plugin %s is not configured" msgstr "Udvidelsesmodulet %s er ikke konfigureret" #, python-format msgid "Invalid user credentials for %s" msgstr "Ugyldige brugerakkreditiver for %s" msgid "Applications" msgstr "Programmer" msgid "All applications and preferences" msgstr "Alle programmer og indstillinger" msgid "Applications for Desktop Environment" msgstr "Programmer til skrivebordsmiljø" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "Åbn med..." msgid "Open with any application" msgstr "Åbn med vilkårligt program" msgid "Set default application to open this file type" msgstr "Angiv standardprogram til at åbne denne filtype med" #, fuzzy msgid "Reset Associations" msgstr "Adressehandlinger" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "Dybe arkiver" msgid "Allow browsing inside compressed archive files" msgstr "Tillad at der kan gennemses i komprimerede arkivfiler" #, python-format msgid "Content of %s" msgstr "Indhold af %s" #, fuzzy msgid "Archive Manager" msgstr "Arkiv" #, fuzzy msgid "Use Archive Manager actions" msgstr "Handlinger for filhåndteringen Thunar" msgid "Compressed archive type for 'Create Archive In'" msgstr "Komprimeret arkivtype for 'Opret arkiv i'" # Hvad med 'Udpak'? Da de netop taler om pakkede filer, synes jeg dette # passer bedre (udpak, udtræk) msgid "Extract Here" msgstr "Udpak her" msgid "Extract compressed archive" msgstr "Udpak komprimeret arkiv" msgid "Create Archive" msgstr "Opret arkiv" msgid "Create a compressed archive from folder" msgstr "Opret et komprimeret arkiv fra mappe" msgid "Create Archive In..." msgstr "Opret arkiv i..." #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Arkiv" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "Kontroller Audacious' afspilning og afspilningsliste" msgid "Include songs in top level" msgstr "Inkluder sange i overniveau" msgid "Enqueue" msgstr "Sæt i kø" msgid "Add track to the Audacious play queue" msgstr "Tilføj numre til Audacious' afspilningskø" msgid "Dequeue" msgstr "Fjern fra kø" msgid "Remove track from the Audacious play queue" msgstr "Fjern numre fra Audacious' afspilningskø" msgid "Play" msgstr "Afspil" msgid "Jump to track in Audacious" msgstr "Gå til nummer i Audacious" msgid "Resume playback in Audacious" msgstr "Genoptag afspilning i Audacious" msgid "Pause" msgstr "Pause" msgid "Pause playback in Audacious" msgstr "Sæt afspilning på pause i Audacious" msgid "Next" msgstr "Næste" msgid "Jump to next track in Audacious" msgstr "Gå til næste nummer i Audacious" msgid "Previous" msgstr "Forrige" msgid "Jump to previous track in Audacious" msgstr "Gå til forrige nummer i Audacious" msgid "Clear Queue" msgstr "Ryd kø" msgid "Clear the Audacious play queue" msgstr "Ryd Audacious' afspilningskø" msgid "Shuffle" msgstr "Vilkårlig rækkefølge" msgid "Toggle shuffle in Audacious" msgstr "Slå vilkårlig rækkefølge i Audacious til/fra" msgid "Repeat" msgstr "Gentag" msgid "Toggle repeat in Audacious" msgstr "Slå gentag i Audacious til/fra" msgid "Show Playing" msgstr "Vis afspilning" msgid "Tell which song is currently playing" msgstr "Vis hvilken sang der nu afspilles" msgid "Playlist" msgstr "Afspilningsliste" msgid "Calculator" msgstr "Lommeregner" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "Beregn" msgid "Clipboards" msgstr "Udklipsholdere" msgid "Recent clipboards and clipboard proxy objects" msgstr "" #, fuzzy msgid "Number of recent clipboards to remember" msgstr "Antal seneste udklipsholdere" msgid "Include selected text in clipboard history" msgstr "" #, fuzzy msgid "Copy selected text to primary clipboard" msgstr "Kopier markering til primær udklipsholder" msgid "Selected Text" msgstr "Valgt tekst" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Udklipsholder \"%(desc)s\"" msgstr[1] "Udklipsholder \"%(desc)s\" med %(num)d linjer" #, fuzzy msgid "Clipboard Text" msgstr "Udklipsholdere" #, fuzzy msgid "Clipboard File" msgstr "Udklipsholdere" #, fuzzy msgid "Clipboard Files" msgstr "Udklipsholdere" msgid "Clear" msgstr "Ryd" msgid "Remove all recent clipboards" msgstr "Fjern alle seneste udklipsholdere" msgid "Shell Commands" msgstr "Skalkommandoer" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" msgid "Run (Get Output)" msgstr "Kør (hent uddata)" msgid "Run program and return its output" msgstr "Kør program og returner dets uddata" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command #, fuzzy msgid "Pass to Command..." msgstr "Sidste kommando" msgid "Run program with object as an additional parameter" msgstr "" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin #, fuzzy msgid "Write to Command..." msgstr "Skriv til..." #, fuzzy msgid "Run program and supply text on the standard input" msgstr "Kør program og returner dets uddata" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "" #, fuzzy msgid "Run command-line programs" msgstr "Kør kommandolinjeprogrammer" msgid "GTK+" msgstr "" #, fuzzy msgid "GNOME Terminal" msgstr "GNOME-terminalprofiler" #, fuzzy msgid "XFCE Terminal" msgstr "Kør i terminal" #, fuzzy msgid "LXTerminal" msgstr "Kør i terminal" #, fuzzy msgid "X Terminal" msgstr "Kør i terminal" msgid "Urxvt" msgstr "" msgid "Konsole" msgstr "" msgid "Save As..." msgstr "Gem som..." #, fuzzy msgid "Restart Kupfer" msgstr "Genstart tjeneste" msgid "Quit" msgstr "Afslut" msgid "Quit Kupfer" msgstr "Afslut Kupfer" msgid "About Kupfer" msgstr "Om Kufper" msgid "Show information about Kupfer authors and license" msgstr "Vis information om Kupfers forfattere og licens" msgid "Kupfer Help" msgstr "Kupferhjælp" msgid "Get help with Kupfer" msgstr "Få hjælp til Kupfer" msgid "Show preferences window for Kupfer" msgstr "Vis indstillingsvindue for Kupfer" msgid "Search Contents" msgstr "Søg i indhold" msgid "Search inside this catalog" msgstr "Søg i dette katalog" msgid "Copy" msgstr "Kopier" msgid "Copy to clipboard" msgstr "Kopier til udklipsholder" msgid "Rescan" msgstr "Genskan" msgid "Force reindex of this source" msgstr "Fremtving omindeksering af denne kilde" msgid "Last Command" msgstr "Sidste kommando" msgid "Internal Kupfer Objects" msgstr "Interne Kupferobjekter" msgid "Last Result" msgstr "Sidste resultat" msgid "Command Results" msgstr "Kommandoresultater" #, fuzzy msgid "Custom Terminal" msgstr "Kør i terminal" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Kommando" msgid "Execute flag" msgstr "Kørselsflag" msgid "Default Email Client" msgstr "Standard for e-post-klient" msgid "Compose email using the system's default mailto: handler" msgstr "Opret e-post med brug af systemets standard mailto:-håndtering" #, fuzzy msgid "Compose Email To" msgstr "Opret e-post" msgid "Dictionary" msgstr "Ordbog" msgid "Look up word in dictionary" msgstr "Slå et ord op i ordbogen" msgid "Look Up" msgstr "Slå op" msgid "Documents" msgstr "Dokumenter" msgid "Recently used documents and bookmarked folders" msgstr "Seneste brugte dokumenter og bogmærkede mapper" msgid "Max recent document days" msgstr "Maks. dage for seneste dokument" msgid "Recent Items" msgstr "Seneste punkter" msgid "Recently used documents" msgstr "Seneste brugte dokumenter" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "%s dokumenter" #, python-format msgid "Recently used documents for %s" msgstr "Seneste brugte dokumenter for %s" msgid "Places" msgstr "Steder" msgid "Bookmarked folders" msgstr "Bogmærkede mapper" #, fuzzy msgid "DuckDuckGo Search" msgstr "Googlesøgning" msgid "Search the web securely with DuckDuckGo" msgstr "" msgid "Favorites" msgstr "Favoritter" msgid "Mark commonly used items and store objects for later use" msgstr "Marker ofte brugte punkter og gem objekter til senere brug" msgid "Shelf of \"Favorite\" items" msgstr "Hylde af \"Favoritpunkter\"" msgid "Add to Favorites" msgstr "Tilføj til favoritter" msgid "Add item to favorites shelf" msgstr "Tilføj punkt til favorithylde" msgid "Remove from Favorites" msgstr "Fjern fra favoritter" msgid "Remove item from favorites shelf" msgstr "Fjern punkt fra favorithylde" msgid "File Actions" msgstr "Filhandlinger" msgid "More file actions" msgstr "Flere filhandlinger" msgid "Move To..." msgstr "Flyt til..." msgid "Move file to new location" msgstr "Flyt fil til ny placering" msgid "Rename To..." msgstr "Omdøb til..." msgid "Copy To..." msgstr "Kopier til..." msgid "Copy file to a chosen location" msgstr "Kopier fil til en valgt placering" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "Handlinger med højere prioritet" msgid "Tools to work with commands as objects" msgstr "Værktøjer til arbejde med kommandoer som objekter" msgid "Select in Kupfer" msgstr "Vælg i Kupfer" #, python-format msgid "Result of %s (%s)" msgstr "Resultat af %s (%s)" msgid "Run (Take Result)" msgstr "Kør (tag resultat)" msgid "Take the command result as a proxy object" msgstr "Tag kommandoresultatet som et proxyobjekt" # ville nok skrive: # (smid resultat væk) # eller (kassér resultat) sidstnævne anbefales af ordlisten msgid "Run (Discard Result)" msgstr "Kør (kassér resultat)" msgid "Image Tools" msgstr "Billedværktøjer" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Billedtransformeringsværktøjer" msgid "Scale..." msgstr "Skaler..." msgid "Scale image to fit inside given pixel measure(s)" msgstr "Skaler billede så det passer inden for angivet størrelsesforhold" msgid "Rotate Clockwise" msgstr "Roter med uret" msgid "Rotate Counter-Clockwise" msgstr "Roter mod uret" msgid "Autorotate" msgstr "Automatisk rotering" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "Roter JPEG (internt) ifølge egne EXIF-metadata" msgid "Kupfer Plugins" msgstr "Kupferudvidelsesmoduler" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Tilgå Kupfers udvidelsesmodulliste i Kupfer" msgid "Show Information" msgstr "Vis information" msgid "Show Source Code" msgstr "Vis kildekode" msgid "enabled" msgstr "aktiveret" msgid "disabled" msgstr "deaktiveret" msgid "Notes" msgstr "Noter" msgid "Gnote or Tomboy notes" msgstr "Gnote- eller Tomboynoter" msgid "Work with application" msgstr "Arbejd med program" msgid "Open with notes application" msgstr "Åbn med noteprogram" msgid "Append to Note..." msgstr "Tilføj til note..." msgid "Add text to existing note" msgstr "Tilføj tekst til eksisterende note" msgid "Create Note" msgstr "Opret note" msgid "Create a new note from this text" msgstr "Opret en ny note fra denne tekst" msgid "Get Note Search Results..." msgstr "Hent notesøgningsresultater..." msgid "Show search results for this query" msgstr "Vis søgeresultat for denne forespørgsel" #, python-format msgid "today, %s" msgstr "i dag, %s" #, python-format msgid "yesterday, %s" msgstr "i går, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Sidst opdateret %s" msgid "Quicksilver Icons" msgstr "" msgid "Quick Image Viewer" msgstr "" msgid "View Image" msgstr "" # 'GNU Screen' er navnet på et program, en såkaldt 'terminalmultiplekser' # der tillader multitasking inden for en enkelt terminal (bl.a. brugbart # hvis man vil flytte et program der kører i en terminal til en anden) msgid "GNU Screen" msgstr "GNN Screen" msgid "Active GNU Screen sessions" msgstr "Aktive sessioner af GNU Screen" # (processen er koblet til en terminal) msgid "Attached" msgstr "Tilkoblet" # (processen er ikke tilkoblet en terminal - kører i 'baggrunden') msgid "Detached" msgstr "Afkoblet" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "%(status)s session (%(pid)s) oprettet %(time)s" msgid "Screen Sessions" msgstr "Screen-sessioner" msgid "Attach" msgstr "Tilføj" msgid "Send Keys" msgstr "" msgid "Send synthetic keyboard events using xautomation" msgstr "" msgid "Paste to Foreground Window" msgstr "" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "" msgid "Send keys to foreground window" msgstr "" msgid "Type Text" msgstr "" msgid "Type the text to foreground window" msgstr "" msgid "GNOME Session Management" msgstr "GNOME-sessionshåndtering" msgid "Special items and actions for GNOME environment" msgstr "Specielle punkter og handlinger til GNOME-miljøet" msgid "Log Out..." msgstr "Log ud..." msgid "Log out or change user" msgstr "Log ud eller ændr bruger" msgid "Shut Down..." msgstr "Luk ned..." msgid "Shut down, restart or suspend computer" msgstr "Luk ned, genstart eller sæt computer i hvile" msgid "Lock Screen" msgstr "Lås skærm" msgid "Enable screensaver and lock" msgstr "Aktiver pauseskærm og lås" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "XFCE-sessionshåndtering" msgid "Special items and actions for XFCE environment" msgstr "Specielle punkter og handlinger XFCE-miljøet" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "SSH-værter" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "Tilføjer SSH-værterne fundet i ~/.ssh/config." msgid "SSH host" msgstr "SSH-vært" msgid "Connect" msgstr "Forbind" msgid "Connect to SSH host" msgstr "Forbind til SSH-vært" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "SSH-værter som angivet i ~/.ssh/config" msgid "No D-Bus connection to desktop session" msgstr "Ingen D-Bus-forbindelse til skrivebordssession" #, fuzzy msgid "GNOME Keyring" msgstr "GNOME-terminalprofiler" msgid "KWallet" msgstr "" #, fuzzy msgid "Unencrypted File" msgstr "Markeret fil" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "Kommando i \"%s\" er ikke tilgængelig" msgid "Document Templates" msgstr "Dokumentskabeloner" msgid "Create new documents from your templates" msgstr "Opret nye dokumenter fra dine skabeloner" #, python-format msgid "%s template" msgstr "%s-skabelon" msgid "Empty File" msgstr "Tom fil" msgid "New Folder" msgstr "Ny mappe" msgid "Create New Document..." msgstr "Opret nyt dokument..." msgid "Create a new document from template" msgstr "Opret et nyt dokument fra skabelon" msgid "Create Document In..." msgstr "Opret dokument i..." msgid "Textfiles" msgstr "Tekstfiler" msgid "Append To..." msgstr "Tilføj til..." msgid "Append..." msgstr "Tilføj..." msgid "Write To..." msgstr "Skriv til..." msgid "Get Text Contents" msgstr "Hent tekstindhold" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "Handlinger for filhåndteringen Thunar" msgid "Select in File Manager" msgstr "Vælg i filhåndtering" msgid "Show Properties" msgstr "Vis egenskaber" msgid "Show information about file in file manager" msgstr "Vis information om fil i filhåndtering" msgid "Send To..." msgstr "Send til..." msgid "Symlink In..." msgstr "" #, fuzzy msgid "Create a symlink to file in a chosen location" msgstr "Kopier fil til en valgt placering" msgid "Empty Trash" msgstr "Tøm papirkurv" msgid "Thunar Send To Objects" msgstr "Send til-objekter for Thunar" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Thunderbird-/Icedovekontakter og -handlinger" msgid "Compose New Email" msgstr "Skriv ny e-post" msgid "Compose a new message in Thunderbird" msgstr "Opret en ny besked i Thunderbird" #, fuzzy msgid "Attach in Email To..." msgstr "Send i en e-post til..." #, fuzzy msgid "Compose Email With" msgstr "Opret e-post" #, fuzzy msgid "Compose a new message using the text as body" msgstr "Opret en ny besked i Thunderbird" msgid "Thunderbird Address Book" msgstr "Thunderbirds adressebog" msgid "Contacts from Thunderbird Address Book" msgstr "Kontakter fra Thunderbirds adressebog" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Øverst" msgid "Show running tasks and allow sending signals to them" msgstr "Vis kørende opgaver og tillad at der bliver sendt signaler til dem" msgid "Sort Order" msgstr "Sorteringsrækkefølge" msgid "Commandline" msgstr "Kommandolinje" msgid "CPU usage (descending)" msgstr "CPU-forbrug (faldende)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Hukommelsesforbrug (faldende)" msgid "Send Signal..." msgstr "Send signal..." msgid "Signals" msgstr "Signaler" msgid "Running Tasks" msgstr "Igangværende opgaver" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid: %(pid)s cpu: %(cpu)g%% huk: %(mem)g%% tid: %(time)s" msgid "Running tasks for current user" msgstr "Igangværende opgaver for aktuel bruger" msgid "Trash" msgstr "Papirkurv" msgid "Access trash contents" msgstr "Tilgå papirkurvsindhold" msgid "Move to Trash" msgstr "Flyt til papirkurv" msgid "Move this file to trash" msgstr "Flyt denne fil til papirkurven" msgid "Restore" msgstr "Gendan" msgid "Move file back to original location" msgstr "Flyt fil tilbage til oprindelig placering" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "Papirkurv er tom" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "Papirkurv indeholder en fil" msgstr[1] "Papirkurve indeholder %(num)s filer" msgid "Triggers" msgstr "Udløsere" #, fuzzy msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Tildel globale tastaturgenveje (udløsere) til objekter oprettet med " "'kompositionskommandoen' (Ctrl+Retur)." msgid "Add Trigger..." msgstr "Tilføj udløser..." msgid "Remove Trigger" msgstr "Fjern udløser" msgid "URL Actions" msgstr "Adressehandlinger" msgid "Download and Open" msgstr "Hent og åbn" msgid "Download To..." msgstr "Hent til..." msgid "Download URL to a chosen location" msgstr "Hent adresseindhold til en valgt placering" msgid "Wikipedia" msgstr "Wikipedia" msgid "Search in Wikipedia" msgstr "Søg i Wikipedia" msgid "Wikipedia language" msgstr "Wikipediasprog" #. TRANS: Default wikipedia language code msgid "en" msgstr "da" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Søg efter denne tekst på %s.wikipedia.org" msgid "Window List" msgstr "Vinduesliste" msgid "All windows on all workspaces" msgstr "Alle vinduer på alle arbejdsområder" msgid "Activate" msgstr "Aktiver" msgid "Shade" msgstr "Skygge" msgid "Unshade" msgstr "Fjern skygge" msgid "Minimize" msgstr "Minimer" msgid "Unminimize" msgstr "Fjern minimering" msgid "Maximize" msgstr "Maksimer" msgid "Unmaximize" msgstr "Fjern maksimering" msgid "Maximize Vertically" msgstr "Maksimer vandret" msgid "Unmaximize Vertically" msgstr "Fjern vandret maksimering" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Vindue på %(wkspc)s" msgid "Frontmost Window" msgstr "Forreste vindue" msgid "Next Window" msgstr "Næste vindue" msgid "Jump to this window's workspace and focus" msgstr "Spring til dette vindues arbejdsområde og fokuser" #, fuzzy, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "Næste vindue" msgstr[1] "Næste vindue" #, fuzzy msgid "Active workspace" msgstr "Spring til dette arbejdsområde" msgid "Jump to this workspace" msgstr "Spring til dette arbejdsområde" msgid "Workspaces" msgstr "Arbejdsområde" msgid "Volumes and Disks" msgstr "Diskenheder og diske" msgid "Mounted volumes and disks" msgstr "Monterede diskenheder og diske" #, python-format msgid "Volume mounted at %s" msgstr "Diskenhed monteret på %s" msgid "Unmount" msgstr "Afmonter" msgid "Unmount this volume" msgstr "Afmonter denne diskenhed" msgid "Eject" msgstr "Skub ud" msgid "Unmount and eject this media" msgstr "Afmonter og skub dette medie ud" msgid "Show Text" msgstr "Vis tekst" msgid "Display text in a window" msgstr "Vis tekst i et vindue" msgid "Large Type" msgstr "Stor type" msgid "Show Notification" msgstr "Vis påmindelse" #, fuzzy msgid "Tracker" msgstr "Tracker 0.6" msgid "Tracker desktop search integration" msgstr "Skrivebordsintegrering for søgning via Tracker" msgid "Search in Tracker" msgstr "Søg i Tracker" msgid "Open Tracker Search Tool and search for this term" msgstr "Åbn søgeværktøjet Trackers og søg efter denne tekst" msgid "Get Tracker Results..." msgstr "Indhent Trackerresultater..." msgid "Show Tracker results for query" msgstr "Vis Trackerresultater for søgning" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "Resultater for \"%s\"" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "Find filer" msgid "Search filesystem using locate" msgstr "Søg i filsystemet med brug af kommandoen locate" msgid "Ignore case distinctions when searching files" msgstr "Ignorer forskel på små/store bogstaver under søgning" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Firefoxbogmærker" msgid "Index of Firefox bookmarks" msgstr "Indeks af Firefoxbogmærker" #, fuzzy msgid "Firefox Keywords" msgstr "Firefoxbogmærker" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "Søg på internettet med OpenSearchs søgemotorer" msgid "Search With..." msgstr "Søg med..." msgid "Search For..." msgstr "Søg efter..." #, fuzzy msgid "Search Terms" msgstr "Søgemotorer" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Markeret fil \"%s\"" #, fuzzy msgid "Resume playback" msgstr "Genoptag afspilning i Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Næste" #, fuzzy msgid "Skip to next track" msgstr "Gå til næste nummer i Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Forrige" #, fuzzy msgid "Skip to previous track" msgstr "Gå til forrige nummer i Audacious" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "Adgang til Pidginkontakter" msgid "Show offline contacts" msgstr "Vis frakoblede kontakter" msgid "Open Chat" msgstr "Åbn snak" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d tegn)" msgstr[1] "%s (%d tegn)" msgid "Send Message..." msgstr "Send besked..." msgid "Available" msgstr "Tilgængelig" # fraværende eller ude msgid "Away" msgstr "Fraværende" msgid "Pidgin Contacts" msgstr "Pidginkontakter" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Forkort henvisninger" msgid "Create short aliases of long URLs" msgstr "Opret korte aliasser på lange internetadresser" msgid "Error" msgstr "Fejl" msgid "Shorten With..." msgstr "Forkort med..." msgid "Services" msgstr "Tjenester" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "Afspil og sæt numre i kø og gennemse musikbiblioteket" msgid "Include artists in top level" msgstr "Inkluder kunstnere i overniveau" msgid "Include albums in top level" msgstr "Inkluder album i overniveau" msgid "Play tracks in Rhythmbox" msgstr "Afspil numre i Rhythmbox" msgid "Add tracks to the play queue" msgstr "Tilføj numre til afspilningskøen" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "af %(artist)s fra %(album)s" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "af %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Numre af %s" msgid "Albums" msgstr "Album" msgid "Music albums in Rhythmbox Library" msgstr "Musikalbum i Rhythmboxbibliotek" msgid "Artists" msgstr "Kunstnere" msgid "Music artists in Rhythmbox Library" msgstr "Musikkunstnere i Rhythmboxbibliotek" msgid "Songs" msgstr "Sange" msgid "Songs in Rhythmbox library" msgstr "Sange i Rhythmboxbibliotek" msgid "Getting Things GNOME" msgstr "Getting Things GNOME" msgid "Browse and create new tasks in GTG" msgstr "Gennemse og opret nye opgaver i GTG" #, python-format msgid "due: %s" msgstr "forfalden: %s" #, python-format msgid "start: %s" msgstr "start: %s" #, python-format msgid "tags: %s" msgstr "mærker: %s" msgid "Open task in Getting Things GNOME!" msgstr "Åbn opgave i Getting Things GNOME!" msgid "Delete" msgstr "Slet" msgid "Permanently remove this task" msgstr "Fjern permanent denne opgave" msgid "Mark Done" msgstr "Markering færdig" msgid "Mark this task as done" msgstr "Marker denne opgave som færdig" msgid "Dismiss" msgstr "Afvis" msgid "Mark this task as not to be done anymore" msgstr "Marker at denne opgave ikke længere skal udføres" msgid "Create Task" msgstr "Opret opgave" msgid "Create new task in Getting Things GNOME" msgstr "Opret ny opgave i Getting Things GNOME" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "Søg i Devhelp" #, fuzzy msgid "Empathy" msgstr "Gajimkontakter" #, fuzzy msgid "Access to Empathy Contacts" msgstr "Adgang til Gajimkontakter" msgid "Busy" msgstr "Optaget" msgid "Not Available" msgstr "Ikke tilgængelig" msgid "Invisible" msgstr "Usynlig" msgid "Offline" msgstr "Afkoblet" msgid "Change Global Status To..." msgstr "Ændr global status til..." #, fuzzy msgid "Empathy Contacts" msgstr "Gajimkontakter" #, fuzzy msgid "Empathy Account Status" msgstr "Gajims kontostatus" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Alternativ aktivering" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Kommatricket" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Kompositionskommando" #, fuzzy msgid "Mark Default Action" msgstr "Angiv standardprogram..." msgid "Forget Object" msgstr "" msgid "Reset All" msgstr "Nulstil alle" msgid "Select Quit" msgstr "Vælg afslut" msgid "Select Selected File" msgstr "Vælg valgt fil" msgid "Select Selected Text" msgstr "Vælg valgt tekst" msgid "Show Help" msgstr "Vis hjælp" msgid "Show Preferences" msgstr "Vis indstillinger" msgid "Switch to First Pane" msgstr "Skift til første panel" msgid "Toggle Text Mode" msgstr "Skift teksttilstand" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Ingen resultater i %(src)s for \"%(query)s\"" msgid "No matches" msgstr "Ingen resultater" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Ingen resultater" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Vis hovedgrænseflade" msgid "Show with Selection" msgstr "Vis med markering" #. TRANS: Plugin info fields msgid "Description" msgstr "Beskrivelse" msgid "Author" msgstr "Forfatter" msgid "Version" msgstr "Version" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Pythonmodul '%s' kræves" msgid "Plugin could not be read due to an error:" msgstr "Udvidelsesmodul kunne ikke læses på grund af en fejl:" msgid "Content of" msgstr "Indhold af" #. TRANS: Plugin contents header msgid "Sources" msgstr "Kilder" #. TRANS: Plugin contents header msgid "Actions" msgstr "Handlinger" #, python-format msgid "Using encrypted password storage: %s" msgstr "" #, python-format msgid "Using password storage: %s" msgstr "" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Konfiguration" msgid "Set username and password" msgstr "Angiv brugernavn og adgangskode" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Vælg en mappe" msgid "Reset all shortcuts to default values?" msgstr "Nulstil alle genveje til standardværdier?" msgid "Shortcut" msgstr "Genvej" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "" "Joe Hansen, 2010.\n" "\n" "Dansk-gruppen \n" "Mere info: http://www.dansk-gruppen.dk" msgid "A free software (GPLv3+) launcher" msgstr "En programstarter der er fri software (GPLv3+)" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Dette program er fri software. Du kan redistribuere og/eller modificere\n" "det under de betingelser som er angivet i GNU General Public License, som\n" "udgivet af Free Software Foundation. Enten version 3 af licensen eller\n" "(efter eget valg) enhver senere version.\n" "\n" "Dette program distribueres i håb om, at det vil vise sig nyttigt, men UDEN\n" "NOGEN FORM FOR GARANTI, uden selv de underforståede garantier omkring\n" "SALGBARHED eller EGNETHED TIL ET BESTEMT FORMÅL. Yderligere detaljer kan\n" "læses i GNU General Public License.\n" "\n" "Du bør have modtaget en kopi af GNU General Public License sammen med\n" "dette program. Hvis ikke, så se .\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Kunne ikke finde kørende Kupfer" #~ msgid "Compose Email" #~ msgstr "Opret e-post" #~ msgid "Send in Email To..." #~ msgstr "Send i en e-post til..." #~ msgid "Type to search %s" #~ msgstr "Skriv for at søge %s" #~ msgid "No action" #~ msgstr "Ingen handling" #~ msgid "GNOME Terminal Profiles" #~ msgstr "GNOME-terminalprofiler" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Kør GNOME-terminalprofiler" #~ msgid "Selected Text \"%s\"" #~ msgstr "Valgt tekst \"%s\"" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Beregn udtryk der starter med '='" #~ msgid "Recent clipboards" #~ msgstr "Seneste udklipsholdere" #~ msgid "Include recent selections" #~ msgstr "Inkluder seneste markeringer" #~ msgid "Epiphany Bookmarks" #~ msgstr "Epiphanybogmærker" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Indeks af Epiphanybogmærker" #~ msgid "Include visited sites" #~ msgstr "Inkluder besøgte sider" #~ msgid "" #~ "Provides current nautilus selection, using Kupfer's Nautilus Extension" #~ msgstr "" #~ "Giver adgang til den aktuelle markering i nautilus ved brug af Kupfers " #~ "Nautilusudvidelse" #~ msgid "Selected File \"%s\"" #~ msgstr "Markeret fil \"%s\"" #~ msgid "Selected Files" #~ msgstr "Valgte filer" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Genoptag afspilning i Rhythmbox" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Sæt afspilning i Rhythmbox på pause" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Hop til næste nummer i Rhythmbox" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Hop til forrige nummer i Rhythmbox" #~ msgid "Search the Web" #~ msgstr "Søg på internettet" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Seneste dokumenter i Abiword" #~ msgid "Abiword Recent Items" #~ msgstr "Abiwords seneste punkter" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "Grænseflade til pakkehåndteringen APT" #~ msgid "Installation method" #~ msgstr "Installationsmetode" #~ msgid "Show Package Information" #~ msgstr "Vis pakkeinformation" #~ msgid "Install" #~ msgstr "Installer" #~ msgid "Install package using the configured method" #~ msgstr "Installer pakke med brug af den konfigurerede metode" #~ msgid "Packages matching \"%s\"" #~ msgstr "Pakker der matcher \"%s\"" #~ msgid "Search Package Name..." #~ msgstr "Søg efter pakkenavn..." #~ msgid "Chromium Bookmarks" #~ msgstr "Chromiumbogmærker" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Indeks af Chromiumbogmærker" #~ msgid "Claws Mail" #~ msgstr "Claws Mail" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Claws Mail-kontakter og handlinger" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Skriv en ny besked i Claws Mail" #~ msgid "Receive All Email" #~ msgstr "Modtag al e-post" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "Modtag nye beskeder fra alle kontakter i ClawsMail" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Opret ny besked i Claws Mail og vedhæft fil" #~ msgid "Claws Mail Address Book" #~ msgstr "Claws' postadressebog" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Kontakter fra Claws' postadressebog" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Evolutionkontakter" #~ msgid "Compose a new message in Evolution" #~ msgstr "Opret en ny besked i Evolution" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Opret ny besked i Evolution og tilføj fil" #~ msgid "Evolution Address Book" #~ msgstr "Evolutions adressebog" #~ msgid "Filezilla" #~ msgstr "Filezilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Vis sider og håndter ftp-adresser med Filezilla" #~ msgid "Open Site with Filezilla" #~ msgstr "Åbn side med Filezilla" #~ msgid "Filezilla Sites" #~ msgstr "Filezillasider" #~ msgid "Sites from Filezilla" #~ msgstr "Sider fra Filezilla" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Adgang til Gajimkontakter" #~ msgid "Free for Chat" #~ msgstr "Ledig til snak" #~ msgid "Gajim Contacts" #~ msgstr "Gajimkontakter" #~ msgid "Gajim Account Status" #~ msgstr "Gajims kontostatus" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Indlæs kontakter og Skriv ny e-post i Gmail" #~ msgid "Load contacts' pictures" #~ msgstr "Indlæs kontakters billeder" #~ msgid "Compose Email in GMail" #~ msgstr "Skriv e-post i GMail" #~ msgid "Open web browser and compose new email in GMail" #~ msgstr "Åbn internetbrowser og skriv ny e-post i GMail" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Kontakter fra Googletjenester (Gmail)" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Vis album og overfør filer til Picasa" #~ msgid "Users to show: (,-separated)" #~ msgstr "Brugere at vise: (kommaadskilt)" #~ msgid "Load user and album icons" #~ msgstr "Indlæs bruger- og albumikoner" #~ msgid "Uploading Pictures" #~ msgstr "Overfører billeder" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Overfører billeder til Picasa Webalbum" #~ msgid "Creating album:" #~ msgstr "Opretter album:" #~ msgid "Album created by Kupfer" #~ msgstr "Album oprettet af Kupfer" #~ msgid "File:" #~ msgstr "Fil:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "Et album" #~ msgstr[1] "%(num)d albummer" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "et billede" #~ msgstr[1] "%(num)s billeder" #~ msgid "Upload to Picasa Album..." #~ msgstr "Overfør til Picasa-album..." #~ msgid "Upload files to Picasa album" #~ msgstr "Overfør filer til Picasa-album" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Overfør til Picasa som nyt album" #~ msgid "Create album from selected local directory" #~ msgstr "Opret album fra valgt lokal mappe" #~ msgid "Picasa Albums" #~ msgstr "Picasa-album" #~ msgid "User albums in Picasa" #~ msgstr "Brugeralbum i Picasa" #~ msgid "Search Google with results shown directly" #~ msgstr "Søg med Google og få resultater vist direkte" #~ msgid "Show More Results For \"%s\"" #~ msgstr "Vis flere resultater for \"%s\"" #~ msgid "%s total found" #~ msgstr "%s fundet i alt" #~ msgid "Translate text with Google Translate" #~ msgstr "Oversæt tekst med Google oversæt" #~ msgid "Google Translate connection timed out" #~ msgstr "Forbindelse til Google oversæt fik tidsudløb" #~ msgid "Error connecting to Google Translate" #~ msgstr "Fejl ved forbindelse til Google oversæt" #~ msgid "Translate To..." #~ msgstr "Oversæt til..." #~ msgid "Translate into %s" #~ msgstr "Oversæt til %s" #~ msgid "Languages" #~ msgstr "Sprog" #~ msgid "Show translated page in browser" #~ msgstr "Vis oversat side i browser" #~ msgid "Show Translation To..." #~ msgstr "Vis oversættelse til..." #~ msgid "Show translation in browser" #~ msgstr "Vis oversættelse i browser" #, fuzzy #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s %(when)s" #, fuzzy #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s" #, fuzzy #~ msgid "Send Message" #~ msgstr "Send besked..." #, fuzzy #~ msgid "Send Message To..." #~ msgstr "Send besked..." #~ msgid "Reply..." #~ msgstr "Svar..." #, fuzzy #~ msgid "Delete Message" #~ msgstr "Send besked..." #, fuzzy #~ msgid "Send Private Message..." #~ msgstr "Send direkte besked..." #, fuzzy #~ msgid "Send direct message to user" #~ msgstr "Send direkte besked til..." #, fuzzy #~ msgid "Retweet To..." #~ msgstr "Omdøb til..." #, fuzzy #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Modtag nye beskeder fra alle kontakter i ClawsMail" #, fuzzy #~ msgid "Open in Browser" #~ msgstr "Åbn overmappe" #, fuzzy #~ msgid "Open message in default web browser" #~ msgstr "Åbn adresse med standardviser" #, fuzzy #~ msgid "Gwibber Accounts" #~ msgstr "Gajims kontostatus" #, fuzzy #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Seneste brugte dokumenter i OpenOffice" #, fuzzy #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "OpenOffices seneste punkter" #~ msgid "Opera Bookmarks" #~ msgstr "Operabogmærker" #~ msgid "Index of Opera bookmarks" #~ msgstr "Indeks af Operabogmærker" #~ msgid "Opera Mail" #~ msgstr "Opera Mail" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Opera Mail-kontakter og handlinger" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Opret en ny besked i Opera Mail" #~ msgid "Opera Mail Contacts" #~ msgstr "Opera Mail-kontakter" #~ msgid "Contacts from Opera Mail" #~ msgstr "Kontakter fra Opera Mail" #~ msgid "PuTTY Sessions" #~ msgstr "PuTTY-sessioner" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Hurtig adgang til PuTTY-sessioner" #~ msgid "Start Session" #~ msgstr "Start session" #~ msgid "reStructuredText" #~ msgstr "reStructuredText" #~ msgid "Render reStructuredText and show the result" #~ msgstr "Optegn reStructuredText og vis resultatet" #~ msgid "View as HTML Document" #~ msgstr "Vis som HTML-dokument" #~ msgid "System Services" #~ msgstr "Systemtjenester" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "Start, stop eller genstart systemtjenester via init-skript" #~ msgid "Sudo-like Command" #~ msgstr "Sudo-lignende kommando" #~ msgid "Start Service" #~ msgstr "Start tjeneste" #~ msgid "Stop Service" #~ msgstr "Stop tjeneste" #~ msgid "%s Service" #~ msgstr "%s-tjeneste" #, fuzzy #~ msgid "Show QRCode" #~ msgstr "Vis kildekode" #, fuzzy #~ msgid "Display text as QRCode in a window" #~ msgstr "Vis tekst i et vindue" #~ msgid "Access to Skype contacts" #~ msgstr "Adgang til Skypekontakter" # tror 'Skype Me' skal være uoversat (det er vist navnet på en # skype-funktion som i øvrigt ikke findes længere iflg. nogle hurtigt # skimmede googleresultater) #~ msgid "Skype Me" #~ msgstr "Skype Me" #~ msgid "Logged Out" #~ msgstr "Logget ud" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Opkald" #~ msgid "Place a call to contact" #~ msgstr "Foretag et opkald til en kontakt" #~ msgid "Skype Contacts" #~ msgstr "Skypekontakter" #~ msgid "Skype Statuses" #~ msgstr "Skypestatusser" #~ msgid "Tracker 0.6" #~ msgstr "Tracker 0.6" #~ msgid "Tracker tags" #~ msgstr "Trackermærker" #~ msgid "Tracker Tags" #~ msgstr "Trackermærker" #~ msgid "Browse Tracker's tags" #~ msgstr "Gennemse Trackers mærker" #~ msgid "Tag %s" #~ msgstr "Mærket %s" #~ msgid "Objects tagged %s with Tracker" #~ msgstr "Objekter mærket %s med Tracker" #~ msgid "Add Tag..." #~ msgstr "Tilføj mærke..." #~ msgid "Add tracker tag to file" #~ msgstr "Tilføj trackermærke til fil" #~ msgid "Remove Tag..." #~ msgstr "Fjern mærke..." #~ msgid "Remove tracker tag from file" #~ msgstr "Fjern trackermærke fra fil" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Diskenheder fra TrueCrypts historik" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "TrueCryptdiskenhed: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Monter diskenhed" #~ msgid "Mount in Truecrypt" #~ msgstr "Monter i Truecrypt" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Forsøg at montere fil som Truecryptdiskenhed" #~ msgid "Dismount All Volumes" #~ msgstr "Afmonter alle diskenheder" #~ msgid "TrueCrypt Volumes" #~ msgstr "TrueCryptdiskenheder" #~ msgid "Terminal Server Client" #~ msgstr "Terminalserverklient" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Session gemt i Terminalserverklient" #~ msgid "TSClient sessions" #~ msgstr "TSClient-sessioner" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Gemte sessioner i Terminalserverklient" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Vinagrebogmærker og -handlinger" #~ msgid "Start Vinagre Session" #~ msgstr "Start Vinagresession" #~ msgid "Vinagre Bookmarks" #~ msgstr "Vinagrebogmærker" #~ msgid "Recently used documents in Vim" #~ msgstr "Seneste dokumenter i Vim" #~ msgid "Vim Recent Documents" #~ msgstr "Vims seneste dokumenter" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "Kontroller VirtualBox Virtual Machines. Understøtter både Sun VirtualBox " #~ "og open source-udgaven." # Tændt, tænd # mon ikke det er 'Tænd'? #~ msgid "Power On" #~ msgstr "Tænd" #~ msgid "Power On Headless" #~ msgstr "Tænd headless" #~ msgid "Send Power Off Signal" #~ msgstr "Send sluksignal" #~ msgid "Reboot" #~ msgstr "Genstart" #~ msgid "Resume" #~ msgstr "Genoptag" #~ msgid "Save State" #~ msgstr "Gem tilstand" #~ msgid "Power Off" #~ msgstr "Sluk" #~ msgid "VirtualBox Machines" #~ msgstr "VirtualBox-maskiner" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "" #~ "Adgang til sider gemt i Zim - En skrivebordswiki og et disponeringsprogram" #~ msgid "Page names start with :colon" #~ msgstr "Sidenavne starter med :colon" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Zimside fra notebog \"%s\"" #~ msgid "Create Zim Page" #~ msgstr "Opret Zimside" #~ msgid "Create page in default notebook" #~ msgstr "Opret side i standardnotebog" #~ msgid "Create Zim Page In..." #~ msgstr "Opret Zimside i..." #~ msgid "Create Subpage..." #~ msgstr "Opret underside..." #~ msgid "Zim Notebooks" #~ msgstr "Zimnotebøger" #~ msgid "Zim Pages" #~ msgstr "Zimsider" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Sider gemt i Zimnotebøger" #~ msgid "Directories" #~ msgstr "Mapper" #~ msgid "Interface" #~ msgstr "Grænseflade" #~ msgid "Hide Kupfer when focus is lost" #~ msgstr "Skjul Kupfer når fokus mistes" #~ msgid "" #~ "Tick the box next to a source to make sure its objects are exported to " #~ "the top level of the catalog. An unticked source's contents are only " #~ "available by locating its subcatalog and entering it.\n" #~ "\n" #~ "Note: Kupfer is an integrator, not an indexer itself. Kupfer is not " #~ "designed to carry a catalog larger than a couple of thousand objects, and " #~ "may become slow if overly large subcatalogs are included in the top level." #~ msgstr "" #~ "Afkryds boksen ved siden af en kilde for at sikre dig at dens objekter " #~ "eksporteres til topniveauet på kataloget. En manglende afkrydsning for en " #~ "kilde vil gøre, at dens indhold kun er tilgængeligt ved at finde dens " #~ "underkatalog og tilgå dette underkatalog.\n" #~ "\n" #~ "Bemærk: Kupfer er en integrator, ikke et indekseringsprogram i sig selv. " #~ "Kupfer er ikke designet til at håndtere et katalog større end et par " #~ "tusinde objekter, og kan blive langsom hvis mange store underkataloger " #~ "indgår under topniveauet." #~ msgid "Text Matches" #~ msgstr "Tekstresultater" #~ msgid "noun" #~ msgstr "navneord" #~ msgid "verb" #~ msgstr "udsagnsord" #~ msgid "adjective" #~ msgstr "tillægsord" #~ msgid "Twitter" #~ msgstr "Twitter" #~ msgid "Microblogging with Twitter: send updates and show friends' tweets" #~ msgstr "Mikroblogning med Twitter: Send opdatering og vis venners tweet'er" #~ msgid "Load friends' pictures" #~ msgstr "Indlæs venners billeder" #~ msgid "Load friends' public tweets" #~ msgstr "Indlæs venners offentlige tweet'er" #~ msgid "Load timeline" #~ msgstr "Indlæs tidslinje" #~ msgid "Post Update to Twitter" #~ msgstr "Indsend opdatering til Twitter" #~ msgid "Twitter Timeline" #~ msgstr "Twittertidslinje" #~ msgid "Twitter Friends" #~ msgstr "Twittervenner" #~ msgid "Timeline for %s" #~ msgstr "Tidslinje for %s" #~ msgid "OpenOffice" #~ msgstr "OpenOffice" #~ msgid "Preferred terminal" #~ msgstr "Foretrukne terminal" #~ msgid "" #~ "The preferred terminal emulator. It's used to launch the SSH sessions." #~ msgstr "" #~ "Den foretrukne terminalemulator. Den bruges til at starte SSH-sessionerne " #~ "op." #~ msgid "" #~ "The flag which makes the terminal execute everything following it inside " #~ "the terminal (e.g. '-x' for gnome-terminal and terminal, '-e' for konsole " #~ "and urxvt)." #~ msgstr "" #~ "Flaget som får terminalen til at køre alt, der følger efter inden i " #~ "terminalen (f.eks. '-x' til gnome-terminal og terminal, '-e' til konsole " #~ "og urxvt)." #~ msgid "Tracker 0.8" #~ msgstr "Tracker 0.8" kupfer-328/po/de.po000066400000000000000000001757051500175051100142440ustar00rootroot00000000000000# German translations for the kupfer package. # Copyright (C) 2009 Ulrik Sverdrup # This file is distributed under the same license as the kupfer package. (GPLv3) # Ulrik Sverdrup , 2009. # Thibaud Roth , 2009. # Mario Blättermann , 2009-2011, 2013. # Christian Kirbach , 2009. # Daniel Winzen , 2012. # msgid "" msgstr "" "Project-Id-Version: kupfer master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-24 22:20+0100\n" "PO-Revision-Date: 2017-02-24 22:30+0100\n" "Last-Translator: Ulrik Sverdrup\n" "Language-Team: German \n" "Language: 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: Poedit 1.8.11\n" msgid "User credentials" msgstr "Anmeldedaten" msgid "_User:" msgstr "_Benutzer:" msgid "_Password:" msgstr "_Passwort:" msgid "_Change" msgstr "Ä_ndern" msgid "Set Keyboard Shortcut" msgstr "Tastenkombination festlegen" msgid "Please press desired key combination" msgstr "Bitte die gewünschte Tastenkombination drücken" msgid "Keybinding could not be bound" msgstr "Tastenkürzel konnte nicht gefunden werden" msgid "Kupfer Preferences" msgstr "Kupfer-Einstellungen" msgid "Start automatically on login" msgstr "Beim Anmelden automatisch starten" msgid "Show icon in notification area" msgstr "Symbol im Benachrichtigungsfeld anzeigen" msgid "Terminal emulator:" msgstr "Terminal-Emulator:" msgid "Desktop Environment" msgstr "Arbeitsumgebung" msgid "Icon set:" msgstr "Symbolsatz:" msgid "Large Icon Size:" msgstr "Symbolgröße (groß)" msgid "Small Icon Size:" msgstr "Symbolgröße (klein)" msgid "Appearance" msgstr "Erscheinungsbild" msgid "General" msgstr "Allgemein" msgid "Global Keyboard Shortcuts" msgstr "Globale Tastenkombinationen" msgid "Reset" msgstr "Zurücksetzen" msgid "Browser Keyboard Shortcuts" msgstr "Tastenkombinationen für Browser" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "" "Einzelne Tastaturbefehle verwenden (Leerzeichen, Schrägstrich, Punkt, Komma " "usw.)" msgid "Action accelerators use Alt" msgstr "Tastenkürtzel für Befehle benutzen Alt" msgid "Action accelerators use Ctrl" msgstr "Tastenkürtzel für Befehle benutzen Strg" msgid "Keyboard" msgstr "Tastatur" msgid "Plugins" msgstr "Erweiterungen" msgid "Inclusion in Top Level Searches" msgstr "Einbeziehung in Suchvorgänge der ersten Ebene" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "Aktivierte Quellen beziehen ihre Objekte in Suchvorgänge der ersten Ebene " "ein.\n" "Die Inhalte einer deaktivierten Quelle sind nur über deren Unterkatalog " "verfügbar." msgid "Indexed Folders" msgstr "Indizierte Ordner" msgid "Folders whose files are always available in the catalog." msgstr "Ordner, deren Dateien immer im Katalog verfügbar sind." msgid "Catalog" msgstr "Katalog" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Anwendungsstarter" msgid "Convenient command and access tool for applications and documents" msgstr "" "Praktisches Befehls- und Zugriffswerkzeug für Anwendungen und Dokumente" msgid "Execute in Kupfer" msgstr "In Kupfer ausführen" msgid "Saved Kupfer Command" msgstr "Gespeicherter Kupfer-Befehl" #, python-format msgid "Could not to carry out '%s'" msgstr "Aktion »%s« konnte nicht ausgeführt werden" #, python-format msgid "\"%s\" produced a result" msgstr "»%s« hatte eine Ausgabe" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Keine Zugriffsrechte zur Ausführung von »%s« (nicht ausführbar)" #, python-format msgid "Command in \"%s\" is not available" msgstr "Befehl in »%s« ist nicht verfügbar" #, python-format msgid "Keyboard relay is active for display %s" msgstr "Tastatur-Weiterleitungsdienst ist aktiv für Anzeige %s" msgid "do not present main interface on launch" msgstr "Hauptoberfläche beim Start nicht anzeigen" msgid "list available plugins" msgstr "Verfügbare Plugins auflisten" msgid "enable debug info" msgstr "Informationen zur Fehlerdiagnose aktivieren" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "Plugin-Helfer ausführen" msgid "show usage help" msgstr "Hilfe anzeigen" msgid "show version information" msgstr "Versionsinformationen anzeigen" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Aufruf: kupfer [OPTIONEN | DATEI …]" msgid "Available plugins:" msgstr "Verfügbare Erweiterungen:" #, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgid "Type to search" msgstr "Eingeben, um zu suchen" #, python-format msgid "%s is empty" msgstr "%s ist leer" msgid "Text" msgstr "Text" msgid "Run after Delay..." msgstr "Verzögert ausführen …" msgid "Perform command after a specified time interval" msgstr "Einen Befehl nach einer angegebenen Zeit ausführen" msgid "Multiple Objects" msgstr "Mehrere Objekte" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s Objekt" msgstr[1] "%s Objekte" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "unbekannt" msgid "Aim" msgstr "Aim" msgid "Google Talk" msgstr "Google Talk" msgid "ICQ" msgstr "ICQ" msgid "MSN" msgstr "MSN" msgid "QQ" msgstr "QQ" msgid "Yahoo" msgstr "Yahoo" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "%s unterstützt diesen Vorgang nicht" msgid "Can not be used with multiple objects" msgstr "Kann nicht mit mehreren Objekten verwendet werden" msgid "Open" msgstr "Öffnen" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Keine Standardanwendung für %(file)s (%(type)s)" #, python-format msgid "Please use \"%s\"" msgstr "Bitte benutzen Sie »%s«" msgid "Set Default Application..." msgstr "Standardanwendung auswählen …" msgid "Open with default application" msgstr "Mit der Standardanwendung öffnen" msgid "Get Parent Folder" msgstr "Übergeordneten Ordner" msgid "Open Terminal Here" msgstr "Hier ein Terminal öffnen" msgid "Open this location in a terminal" msgstr "Diesen Ort in einem Terminal öffnen" msgid "Run in Terminal" msgstr "Im Terminal ausführen" msgid "Run (Execute)" msgstr "Ausführen (Starten)" msgid "Run this program in a Terminal" msgstr "Dieses Programm in einem Terminal ausführen" msgid "Run this program" msgstr "Dieses Programm ausführen" msgid "Go To" msgstr "Gehe zu" msgid "Open URL" msgstr "Adresse öffnen" msgid "Open URL with default viewer" msgstr "Adresse mit dem Standardbetrachter öffnen" msgid "Launch" msgstr "Starten" msgid "Show application window" msgstr "Anwendungsfenster anzeigen" msgid "Launch application" msgstr "Anwendung starten" msgid "Launch Again" msgstr "Neu starten" msgid "Launch another instance of this application" msgstr "Eine andere Instanz dieser Anwendung starten" msgid "Close" msgstr "Schließen" msgid "Attempt to close all application windows" msgstr "Versuchen, alle Anwendungsfenster zu schließen" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Ausführen" msgid "Perform command" msgstr "Befehl ausführen" msgid "(Empty Text)" msgstr "(Leerer Text)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "»%(text)s«" msgstr[1] "(%(num)d Zeilen) »%(text)s«" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s et. al." #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Rekursive Quelle von %(dir)s, (%(levels)d Ebenen)" #, python-format msgid "Directory source %s" msgstr "Quellordner %s" msgid "Home Folder" msgstr "Persönlicher Ordner" msgid "Catalog Index" msgstr "Katalogindex" msgid "An index of all available sources" msgstr "Ein Index aller verfügbaren Quellen" msgid "Root catalog" msgstr "Standardkatalog" msgid "Please Configure Plugin" msgstr "Bitte das Plugin konfigurieren" #, python-format msgid "Plugin %s is not configured" msgstr "Plugin %s ist nicht konfiguriert" #, python-format msgid "Invalid user credentials for %s" msgstr "Ungültige Anmeldedaten für %s" msgid "Applications" msgstr "Anwendungen" msgid "All applications and preferences" msgstr "Alle Anwendungen und Einstellungen" msgid "Applications for Desktop Environment" msgstr "Anwendungen für die Arbeitsumgebung" msgid "Use Desktop Filter" msgstr "Filter der Arbeitsumgebung verwenden" msgid "Open With..." msgstr "Öffnen mit …" msgid "Open with any application" msgstr "Mit einer Anwendung öffnen" msgid "Set default application to open this file type" msgstr "Standardanwendung für diesen Dateityp auswählen" msgid "Reset Associations" msgstr "Verknüpfungen zurücksetzen" msgid "Reset program associations for files of this type." msgstr "Alle verknüpfte Anwendungen für diesen Dateityp zurücksetzen." msgid "Deep Archives" msgstr "In Archive vertiefen" msgid "Allow browsing inside compressed archive files" msgstr "Suchen innerhalb gepackter Archivdateien ermöglichen" #, python-format msgid "Content of %s" msgstr "Inhalt von %s" msgid "Archive Manager" msgstr "Archivmanager" msgid "Use Archive Manager actions" msgstr "Aktionen des Archivmanagers verwenden" msgid "Compressed archive type for 'Create Archive In'" msgstr "Archivtyp für »Archiv erstellen in«" msgid "Extract Here" msgstr "Hier entpacken" msgid "Extract compressed archive" msgstr "Komprimiertes Archiv entpacken" msgid "Create Archive" msgstr "Archiv erstellen" msgid "Create a compressed archive from folder" msgstr "Ein komprimiertes Archiv aus einem Ordner erstellen" msgid "Create Archive In..." msgstr "Archiv erstellen in …" #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Archiv" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "Wiedergabe und Wiedergabeliste von Audacious steuern" msgid "Include songs in top level" msgstr "Lieder auf der ersten Ebene anzeigen" msgid "Enqueue" msgstr "Zur Wiedergabeliste hinzufügen" msgid "Add track to the Audacious play queue" msgstr "Titel zur Wiedergabeliste von Audacious hinzufügen" msgid "Dequeue" msgstr "Titel entfernen" msgid "Remove track from the Audacious play queue" msgstr "Titel aus der Wiedergabeliste von Audacious entfernen" msgid "Play" msgstr "Abspielen" msgid "Jump to track in Audacious" msgstr "In Audacious zu einem Titel springen" msgid "Resume playback in Audacious" msgstr "Wiedergabe in Audacious fortsetzen" msgid "Pause" msgstr "Pause" msgid "Pause playback in Audacious" msgstr "Wiedergabe in Audacious pausieren" msgid "Next" msgstr "Nächstes" msgid "Jump to next track in Audacious" msgstr "In Audacious zum nächsten Titel springen" msgid "Previous" msgstr "Vorheriges" msgid "Jump to previous track in Audacious" msgstr "In Audacious zum vorherigen Titel springen" msgid "Clear Queue" msgstr "Warteschlange leeren" msgid "Clear the Audacious play queue" msgstr "Warteschlange von Audacious leeren" msgid "Shuffle" msgstr "Zufall" msgid "Toggle shuffle in Audacious" msgstr "Zufallswiedergabe in Audacious ein-/ausschalten" msgid "Repeat" msgstr "Wiederholen" msgid "Toggle repeat in Audacious" msgstr "Wiederholung in Audacious ein-/ausschalten" msgid "Show Playing" msgstr "Wiedergegebenen Titel anzeigen" msgid "Tell which song is currently playing" msgstr "Aktuell gespieltes Lied anzeigen" msgid "Playlist" msgstr "Wiedergabeliste" msgid "Calculator" msgstr "Rechner" msgid "Calculate mathematical expressions" msgstr "Mathematische Ausdrücke berechnen" msgid "Calculate" msgstr "Berechnen" msgid "Clipboards" msgstr "Zwischenablagen" msgid "Recent clipboards and clipboard proxy objects" msgstr "Letzte (Proxy-)Objekte in der Zwischenablage" msgid "Number of recent clipboards to remember" msgstr "Anzahl der vorzuhaltenden Einträge in der Zwischenablage" msgid "Include selected text in clipboard history" msgstr "Ausgewählten Text in Zwischenspeicher-Chronik einfügen" msgid "Copy selected text to primary clipboard" msgstr "Ausgewählten Text in die primäre Zwischenablage kopieren" msgid "Selected Text" msgstr "Ausgewählten Text" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Zwischenablage »%(desc)s«" msgstr[1] "Zwischenablage mit %(num)d Zeilen »%(desc)s«" msgid "Clipboard Text" msgstr "Text in Zwischenablage" msgid "Clipboard File" msgstr "Datei in Zwischenablage" msgid "Clipboard Files" msgstr "Dateien in Zwischenablage" msgid "Clear" msgstr "Leeren" msgid "Remove all recent clipboards" msgstr "Alle aktuellen Zwischenablagen entfernen" msgid "Shell Commands" msgstr "Shell-Befehle" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Befehlszeilenprogramme ausführen. Mit dem Symbol %s markierte Aktionen " "werden in einer Subshell ausgeführt." msgid "Run (Get Output)" msgstr "Ausführen (Ausgabe erhalten)" msgid "Run program and return its output" msgstr "Programm ausführen und dessen Ausgabe zurückgeben" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "An Befehl übergeben …" msgid "Run program with object as an additional parameter" msgstr "Programm mit Objekt als zusätzlichem Parameter ausführen" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "In Befehl schreiben …" msgid "Run program and supply text on the standard input" msgstr "Programm ausführen und Text über die Standardausgabe zurückgeben" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "Mittels Befehl filtern …" msgid "Run command-line programs" msgstr "Befehlszeilenprogramme ausführen" msgid "GTK+" msgstr "GTK+" msgid "GNOME Terminal" msgstr "GNOME-Terminal" msgid "XFCE Terminal" msgstr "XFCE-Terminal" msgid "LXTerminal" msgstr "LXTerminal" msgid "X Terminal" msgstr "X-Terminal" msgid "Urxvt" msgstr "Urxvt" msgid "Konsole" msgstr "Konsole" msgid "Save As..." msgstr "Speichern unter …" msgid "Restart Kupfer" msgstr "Kupfer neu starten" msgid "Quit" msgstr "Beenden" msgid "Quit Kupfer" msgstr "Kupfer beenden" msgid "About Kupfer" msgstr "Info zu Kupfer" msgid "Show information about Kupfer authors and license" msgstr "Informationen über die Kupfer-Autoren und Lizenz anzeigen" msgid "Kupfer Help" msgstr "Kupfer-Hilfe" msgid "Get help with Kupfer" msgstr "Hilfe zu Kupfer erhalten" msgid "Show preferences window for Kupfer" msgstr "Kupfers Einstellungsfenster anzeigen" msgid "Search Contents" msgstr "Inhalt durchsuchen" msgid "Search inside this catalog" msgstr "Im Katalog suchen" msgid "Copy" msgstr "Kopieren" msgid "Copy to clipboard" msgstr "In die Zwischenablage kopieren" msgid "Rescan" msgstr "Neu einlesen" msgid "Force reindex of this source" msgstr "Neuindizierung dieser Quelle erzwingen" msgid "Last Command" msgstr "Letzter Befehl" msgid "Internal Kupfer Objects" msgstr "Interne Kupfer-Objekte" msgid "Last Result" msgstr "Letzte Ausgabe" msgid "Command Results" msgstr "Befehlsausgaben" msgid "Custom Terminal" msgstr "Benutzerdefiniertes Terminal" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Befehl" msgid "Execute flag" msgstr "Ausführungsargument" msgid "Default Email Client" msgstr "Vorgegebenes E-Mail-Programm" msgid "Compose email using the system's default mailto: handler" msgstr "E-Mail mit dem »mailto:«-Handler des Systems verfassen" msgid "Compose Email To" msgstr "Neue E-Mail verfassen an" msgid "Dictionary" msgstr "Wörterbuch" msgid "Look up word in dictionary" msgstr "Ein Wort im Wörterbuch nachschlagen" msgid "Look Up" msgstr "Nachschlagen" msgid "Documents" msgstr "Dokumente" msgid "Recently used documents and bookmarked folders" msgstr "Kürzlich verwendete Dokumente und als Lesezeichen gespeicherte Ordner" msgid "Max recent document days" msgstr "Maximale Anzahl der Tage für zuletzt geöffnete Dokumente" msgid "Recent Items" msgstr "Zuletzt geöffnete Objekte" msgid "Recently used documents" msgstr "Zuletzt geöffnete Dokumente" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "%s Dokumente" #, python-format msgid "Recently used documents for %s" msgstr "Zuletzt geöffnete Dokumente für %s" msgid "Places" msgstr "Orte" msgid "Bookmarked folders" msgstr "Als Lesezeichen gespeicherte Ordner" msgid "Toggle Recent Documents" msgstr "Zuletzt geöffnete Dokumente umschalten" msgid "Enable/disable listing recent documents in content for this application" msgstr "" "Zuletzt geöffnete Dokumente zeigen als Inhalt dieser Anwendung umschalten" msgid "DuckDuckGo Search" msgstr "DuckDuckGo-Suche" msgid "Search the web securely with DuckDuckGo" msgstr "Das Web sicher mit DuckDuckGo durchsuchen" msgid "Favorites" msgstr "Favoriten" msgid "Mark commonly used items and store objects for later use" msgstr "Häufig benutzte Objekte zur späteren Benutzung markieren und speichern" msgid "Shelf of \"Favorite\" items" msgstr "»Favoriten«-Ablage" msgid "Add to Favorites" msgstr "Zu den Favoriten hinzufügen" msgid "Add item to favorites shelf" msgstr "Das Objekt zur Favoriten-Ablage hinzufügen" msgid "Remove from Favorites" msgstr "Aus den Favoriten entfernen" msgid "Remove item from favorites shelf" msgstr "Objekt aus der Favoriten-Ablage entfernen" msgid "File Actions" msgstr "Datei-Aktionen" msgid "More file actions" msgstr "Mehr Datei-Aktionen" msgid "Move To..." msgstr "Verschieben nach …" msgid "Move file to new location" msgstr "Archiv an einen neuen Ort verschieben" msgid "Rename To..." msgstr "Umbenennen in …" msgid "Copy To..." msgstr "Kopieren nach …" msgid "Copy file to a chosen location" msgstr "Datei an einen ausgesuchten Ort kopieren" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "Glob" msgid "Select objects using '*' and '?' as wildcards." msgstr "" "Objekte auswählen die mit einem Muster (‘*’ und ‘?’ sind erlaubt) " "übereinstimmen." msgid "Higher-order Actions" msgstr "Aktionen höherer Ordnung" msgid "Tools to work with commands as objects" msgstr "Werkzeuge zur Arbeit mit Befehlen als Objekte" msgid "Select in Kupfer" msgstr "In Kupfer auswählen" #, python-format msgid "Result of %s (%s)" msgstr "Ergebnisse von %s (%s)" msgid "Run (Take Result)" msgstr "Ausführen (Ergebnis annehmen)" msgid "Take the command result as a proxy object" msgstr "Ausgabe des Befehls als Proxy-Objekt verwenden" msgid "Run (Discard Result)" msgstr "Ausführen (Ergebnis verwerfen)" msgid "Image Tools" msgstr "Bildwerkzeuge" msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Werkzeuge zur Bildumwandlung (mithilfe 'convert' / ImageMagick)" msgid "Scale..." msgstr "Skalieren …" msgid "Scale image to fit inside given pixel measure(s)" msgstr "Bild zum Einpassen in die angegebenen Pixelgrößen skalieren" msgid "Rotate Clockwise" msgstr "Im Uhrzeigersinn drehen" msgid "Rotate Counter-Clockwise" msgstr "Gegen den Uhrzeigersinn drehen" msgid "Autorotate" msgstr "Automatisch drehen" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "JPEG anhand der EXIF-Metadaten drehen" msgid "Kupfer Plugins" msgstr "Kupfer-Plugins" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Zugriff auf die Kupfer-Pluginliste in Kupfer" msgid "Show Information" msgstr "Informationen anzeigen" msgid "Show Source Code" msgstr "Quellcode anzeigen" msgid "enabled" msgstr "aktiviert" msgid "disabled" msgstr "deaktiviert" msgid "Notes" msgstr "Notizen" msgid "Gnote or Tomboy notes" msgstr "Gnote- oder Tomboy-Notizen" msgid "Work with application" msgstr "Mit einer Anwendung arbeiten" msgid "Open with notes application" msgstr "Mit der Notiz-Anwendung öffnen" msgid "Append to Note..." msgstr "An eine Notiz anfügen …" msgid "Add text to existing note" msgstr "Den Text zu einer bereits vorhandenen Notiz hinzufügen" msgid "Append..." msgstr "Anhängen …" msgid "Create Note" msgstr "Notiz erstellen" msgid "Create a new note from this text" msgstr "Eine neue Notiz aus diesem Text erstellen" msgid "Get Note Search Results..." msgstr "Suchergebnisse für Notizen einholen …" msgid "Show search results for this query" msgstr "Suchergebnisse für diese Abfrage anzeigen" #, python-format msgid "today, %s" msgstr "heute, %s" #, python-format msgid "yesterday, %s" msgstr "gestern, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Zuletzt aktualisiert %s" msgid "Quicksilver Icons" msgstr "Quicksilver-Symbole" msgid "Quick Image Viewer" msgstr "Bild-Schnellanzeiger" msgid "View Image" msgstr "Bildansicht" msgid "GNU Screen" msgstr "GNU Screen" msgid "Active GNU Screen sessions" msgstr "Aktive GNU Screen-Sitzungen" msgid "Attached" msgstr "Verbunden" msgid "Detached" msgstr "Nicht verbunden" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "%(status)s Sitzung (%(pid)s) erstellt %(time)s" msgid "Screen Sessions" msgstr "Screen-Sitzungen" msgid "Attach" msgstr "Verbinden" msgid "Send Keys" msgstr "Tastatursignale senden" msgid "Send synthetic keyboard events using xautomation" msgstr "Synthetische Tastatursignale mit xautomation senden" msgid "Paste to Foreground Window" msgstr "In aktives Fenster einfügen" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "In die Zwischenablage kopieren und Strg+V an das aktive Fenster senden" msgid "Send keys to foreground window" msgstr "Tastatursignale an das aktive Fenster senden" msgid "Type Text" msgstr "Text eingeben" msgid "Type the text to foreground window" msgstr "Text in das aktive Fenster eingeben" msgid "GNOME Session Management" msgstr "GNOME-Sitzungsverwaltung" msgid "Special items and actions for GNOME environment" msgstr "Spezielle Objekte und Aktionen für die GNOME-Arbeitsumgebung" msgid "Log Out..." msgstr "Abmelden …" msgid "Log out or change user" msgstr "Abmelden und Benutzer wechseln" msgid "Shut Down..." msgstr "Herunterfahren …" msgid "Shut down, restart or suspend computer" msgstr "" "Den Rechner herunterfahren, neu starten oder in den Ruhezustand versetzen" msgid "Lock Screen" msgstr "Bildschirm sperren" msgid "Enable screensaver and lock" msgstr "Bildschirmschoner aktivieren und sperren" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "XFCE-Sitzungsverwaltung" msgid "Special items and actions for XFCE environment" msgstr "Spezielle Objekte und Aktionen für die XFCE-Arbeitsumgebung" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "SSH-Rechner" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "Fügt die in ~/.ssh/config gefundenen Rechner hinzu." msgid "SSH host" msgstr "SSH-Rechner" msgid "Connect" msgstr "Verbinden" msgid "Connect to SSH host" msgstr "Mit einem SSH-Rechner verbinden" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "SSH-Rechner wie in ~/.ssh/config angegeben" msgid "No D-Bus connection to desktop session" msgstr "Keine D-Bus-Verbindung zur Desktopsitzung" #, python-format msgid "Dependency '%s' is not available" msgstr "Abhängigkeit »%s« ist nicht verfügbar" msgid "Document Templates" msgstr "Dokumentvorlagen" msgid "Create new documents from your templates" msgstr "Neue Dokumente aus Ihren Vorlagen erstellen" #, python-format msgid "%s template" msgstr "Vorlage %s" msgid "Empty File" msgstr "Leere Datei" msgid "New Folder" msgstr "Neuer Ordner" msgid "Create New Document..." msgstr "Neues Dokument erstellen …" msgid "Create a new document from template" msgstr "Ein neues Dokument aus einer Vorlage erstellen" msgid "Create Document In..." msgstr "Dokument erstellen in …" msgid "Textfiles" msgstr "Textdateien" msgid "Append To..." msgstr "Anhängen an …" msgid "Write To..." msgstr "Schreiben an …" msgid "Write the text to a new file in specified directory" msgstr "Text in eine neu erstellten Datei in ausgewählten Ordner schreiben" msgid "Get Text Contents" msgstr "Textinhalte holen" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "Aktionen des Dateimanagers Thunar" msgid "Select in File Manager" msgstr "Im Dateimanager auswählen" msgid "Show Properties" msgstr "Eigenschaften anzeigen" msgid "Show information about file in file manager" msgstr "Informationen über die Datei im Dateimanager anzeigen" msgid "Send To..." msgstr "Senden an …" msgid "Symlink In..." msgstr "Verknüpfung zu …" msgid "Create a symlink to file in a chosen location" msgstr "Verknüpfung zur Datei am gewählten Ort erstellen" msgid "Empty Trash" msgstr "Papierkorb leeren" msgid "Thunar Send To Objects" msgstr "Objekte aus Thunar versenden" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Kontakte und Aktionen in Thunderbird/Icedove" msgid "Compose New Email" msgstr "Neue E-Mail verfassen" msgid "Compose a new message in Thunderbird" msgstr "Eine neue E-Mail mit Thunderbird erstellen" msgid "Attach in Email To..." msgstr "In E-Mail senden an …" msgid "Compose Email With" msgstr "Neue E-Mail verfassen damit" msgid "Compose a new message using the text as body" msgstr "Eine neue E-Mail mit dem Text erstellen" msgid "Thunderbird Address Book" msgstr "Thunderbird-Adressbuch" msgid "Contacts from Thunderbird Address Book" msgstr "Kontakte aus dem Adressbuch von Thunderbird" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Top" msgid "Show running tasks and allow sending signals to them" msgstr "Anzeigen aktiver Prozesse und Senden von Signalen" msgid "Sort Order" msgstr "Sortierreihenfolge" msgid "Commandline" msgstr "Befehlszeile" msgid "CPU usage (descending)" msgstr "Prozessorlast (absteigend)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Speichernutzung (absteigend)" msgid "Send Signal..." msgstr "Signal senden …" msgid "Signals" msgstr "Signale" msgid "Running Tasks" msgstr "Laufende Prozesse" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "PID: %(pid)s Proz.: %(cpu)g%% Speich.: %(mem)g%% Zeit: %(time)s" msgid "Running tasks for current user" msgstr "Laufende Prozesse des derzeitigen Benutzers" msgid "Trash" msgstr "Papierkorb" msgid "Access trash contents" msgstr "Zugriff auf den Inhalt des Papierkorbs" msgid "Move to Trash" msgstr "In den Papierkorb verschieben" msgid "Move this file to trash" msgstr "Diese Datei in den Papierkorb verschieben" msgid "Restore" msgstr "Wiederherstellen" msgid "Move file back to original location" msgstr "Datei wieder an den ursprünglichen Ort verschieben" msgid "" "Could not delete files:\n" " " msgstr "" "Dateien könnte nicht gelöscht werden:\n" " " msgid "Trash is empty" msgstr "Der Papierkorb ist leer" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "Es ist ein Objekt im Papierkorb" msgstr[1] "Es sind %(num)s Objekte im Papierkorb" msgid "Triggers" msgstr "Auslöser" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Globale Tastenkürzel (Auslöser) zu mit dem »Compose-Befehl« (Strg+Eingabe) " "erstellten Objekten hinzufügen" msgid "Add Trigger..." msgstr "Auslöser hinzufügen …" msgid "Remove Trigger" msgstr "Auslöser entfernen …" msgid "URL Actions" msgstr "URL-Aktionen" msgid "Download and Open" msgstr "Herunterladen und öffnen" msgid "Download To..." msgstr "Herunterladen nach …" msgid "Download URL to a chosen location" msgstr "URL in einen ausgewählten Ort herunterladen" msgid "Wikipedia" msgstr "Wikipedia" msgid "Search in Wikipedia" msgstr "In Wikipedia suchen" msgid "Wikipedia language" msgstr "Wikipedia-Sprache" #. TRANS: Default wikipedia language code msgid "en" msgstr "de" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Nach diesem Suchbegriff auf %s.wikipedia.org suchen" msgid "Window List" msgstr "Fensterliste" msgid "All windows on all workspaces" msgstr "Alle Fenster und Arbeitsflächen" msgid "Activate" msgstr "Aktivieren" msgid "Shade" msgstr "Verstecken" msgid "Unshade" msgstr "Zeigen" msgid "Minimize" msgstr "Minimieren" msgid "Unminimize" msgstr "Minimierung aufheben" msgid "Maximize" msgstr "Maximieren" msgid "Unmaximize" msgstr "Maximierung aufheben" msgid "Maximize Vertically" msgstr "Vertikal maximieren" msgid "Unmaximize Vertically" msgstr "Maximierung vertikal aufheben" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Fenster auf %(wkspc)s" msgid "Frontmost Window" msgstr "Vorderstes Fenster" msgid "Next Window" msgstr "Nächstes Fenster" msgid "Jump to this window's workspace and focus" msgstr "Zur Arbeitsfläche springen und Fenster fokussieren" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "%d Fenster" msgstr[1] "%d Fenster" msgid "Active workspace" msgstr "Aktive Arbeitsfläche" msgid "Jump to this workspace" msgstr "Zu dieser Arbeitsfläche springen" msgid "Workspaces" msgstr "Arbeitsflächen" msgid "Volumes and Disks" msgstr "Partitionen und Festplatten" msgid "Mounted volumes and disks" msgstr "Eingebundene Partitionen und Festplatten" #, python-format msgid "Volume mounted at %s" msgstr "Partition in %s eingebunden" msgid "Unmount" msgstr "Aushängen" msgid "Unmount finished" msgstr "Aushängen abgeschlossen" #, python-format msgid "\"%s\" was successfully unmounted" msgstr "Aushängen von »%s« ohne Fehler abgeschlossen" msgid "Unmount this volume" msgstr "Diese Partition aushängen" msgid "Eject" msgstr "Auswerfen" msgid "Unmount and eject this media" msgstr "Aushängen und das Medium auswerfen" msgid "Show Text" msgstr "Text anzeigen" msgid "Display text in a window" msgstr "Text in einem Fenster anzeigen" msgid "Large Type" msgstr "Groß" msgid "Show Notification" msgstr "Benachrichtigung anzeigen" msgid "Tracker" msgstr "Tracker" msgid "Tracker desktop search integration" msgstr "Einbindung der Tracker Desktop-Suche" msgid "Search in Tracker" msgstr "Mit Tracker suchen" msgid "Open Tracker Search Tool and search for this term" msgstr "Tracker Suchwerkzeug öffnen und nach diesem Begriff suchen" msgid "Get Tracker Results..." msgstr "Tracker-Ergebnisse einholen …" msgid "Show Tracker results for query" msgstr "Tracker Ergebnisse für den Suchbegriff anzeigen" #, python-format msgid "Tracker Search for \"%s\"" msgstr "Tracker-Suche nach »%s«" #, python-format msgid "Results for \"%s\"" msgstr "Ergebnisse für »%s«" msgid "Tracker Full Text Search" msgstr "Tracker Volltextsuche" msgid "Use '?' prefix to get full text results" msgstr "»?«-Prefix verwenden für Volltextsuche" msgid "Locate Files" msgstr "Datei finden" msgid "Search filesystem using locate" msgstr "Das Dateisystem mit locate durchsuchen" msgid "Ignore case distinctions when searching files" msgstr "Groß-/Kleinschreibung während der Suche ignorieren" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Lesezeichen in Firefox" msgid "Index of Firefox bookmarks" msgstr "Index der Lesezeichen in Firefox" msgid "Firefox Keywords" msgstr "Schlüsselwörter in Firefox" msgid "Search the web with Firefox keywords" msgstr "Das Internet mit Firefox Schlüsselwörter durchsuchen" msgid "Search With..." msgstr "Suchen mit …" msgid "Search For..." msgstr "Suchen nach …" msgid "Search Terms" msgstr "Suchbegriffe" msgid "Media Player Control" msgstr "Mediaspieler-Bedienung" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, python-format msgid "Play/Pause (%s)" msgstr "Abspielen/Pause (%s)" msgid "Resume playback" msgstr "Wiedergabe fortsetzen" #. TRANS: %s is a media player name #, python-format msgid "Next (%s)" msgstr "Nächstes (%s)" msgid "Skip to next track" msgstr "Zum nächsten Titel springen" #. TRANS: %s is a media player name #, python-format msgid "Previous (%s)" msgstr "Vorheriges (%s)" msgid "Skip to previous track" msgstr "Zum vorherigen Titel springen" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "Stopp (%s)" msgid "Stop playback" msgstr "Wiedergabe halten" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "Zugriff auf Pidgin-Kontakte" msgid "Show offline contacts" msgstr "Abgemeldete Kontakte anzeigen" msgid "Open Chat" msgstr "Unterhaltung öffnen" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d Zeichen)" msgstr[1] "%s (%d Zeichen)" msgid "Send Message..." msgstr "Nachricht senden …" msgid "Available" msgstr "Verfügbar" msgid "Away" msgstr "Abwesend" msgid "Pidgin Contacts" msgstr "Pidgin-Kontakte" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Links abkürzen" msgid "Create short aliases of long URLs" msgstr "Schnellzugriffe für lange Adressen erstellen" msgid "Error" msgstr "Fehler" msgid "Shorten With..." msgstr "Abkürzen als …" msgid "Services" msgstr "Dienste" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "" "Titel abspielen und zur Wiedergabeliste hinzufügen und die Musikbibliothek " "durchsuchen" msgid "Include artists in top level" msgstr "Künstler auf der ersten Ebene anzeigen" msgid "Include albums in top level" msgstr "Alben auf der ersten Ebene anzeigen" msgid "Play tracks in Rhythmbox" msgstr "Titel in Rhythmbox abspielen" msgid "Add tracks to the play queue" msgstr "Titel zur Wiedergabeliste hinzufügen" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "von %(artist)s aus %(album)s" msgid "Get File" msgstr "Datei holen" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "von %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Lieder von %s" msgid "Albums" msgstr "Alben" msgid "Music albums in Rhythmbox Library" msgstr "Alben in der Rhythmbox-Bibliothek" msgid "Artists" msgstr "Künstler" msgid "Music artists in Rhythmbox Library" msgstr "Künstler in der Rhythmbox-Bibliothek" msgid "Songs" msgstr "Lieder" msgid "Songs in Rhythmbox library" msgstr "Lieder in der Rhythmbox-Bibliothek" msgid "Getting Things GNOME" msgstr "Getting Things GNOME" msgid "Browse and create new tasks in GTG" msgstr "GTG durchsuchen und neue Aufgaben erstellen" #, python-format msgid "due: %s" msgstr "Fällig: %s" #, python-format msgid "start: %s" msgstr "Beginn: %s" #, python-format msgid "tags: %s" msgstr "Schlagworte: %s" msgid "Open task in Getting Things GNOME!" msgstr "Aufgabe in Getting Things GNOME! öffnen" msgid "Delete" msgstr "Löschen" msgid "Permanently remove this task" msgstr "Diese Aufgabe dauerhaft entfernen" msgid "Mark Done" msgstr "Erledigt" msgid "Mark this task as done" msgstr "Diese Aufgabe als erledigt markieren" msgid "Dismiss" msgstr "Verwerfen" msgid "Mark this task as not to be done anymore" msgstr "Diese Aufgabe als nicht mehr zu erledigen markieren" msgid "Create Task" msgstr "Aufgabe anlegen" msgid "Create new task in Getting Things GNOME" msgstr "Neue Aufgabe in Getting Things GNOME! anlegen" msgid "Devhelp" msgstr "Hilfe für Entwickler" msgid "Search in Devhelp" msgstr "In der Hilfe für Entwickler suchen" msgid "Nemo" msgstr "Nemo" msgid "File manager actions" msgstr "Aktionen des Dateimanagers" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Alternative Aktivierung" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Komma-Trick" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Compose-Befehl" msgid "Mark Default Action" msgstr "Als Standardanwendung markieren" msgid "Forget Object" msgstr "Objekt vergessen" msgid "Reset All" msgstr "Alle zurücksetzen" msgid "Select Quit" msgstr "Beenden wählen" msgid "Select Selected File" msgstr "Ausgewählte Datei wählen" msgid "Select Selected Text" msgstr "Markierten Text wählen" msgid "Select Clipboard File" msgstr "Datei in Zwischenablage wählen" msgid "Select Clipboard Text" msgstr "Text in Zwischenablage wählen" msgid "Show Help" msgstr "Hilfe anzeigen" msgid "Show Preferences" msgstr "Einstellungen anzeigen" msgid "Switch to 1st Pane" msgstr "In 1. Leiste wechseln" msgid "Switch to 2nd Pane" msgstr "In 2. Leiste wechseln" msgid "Switch to 3rd Pane" msgstr "In 3. Leiste wechseln" msgid "Toggle Text Mode" msgstr "Textmodus umschalten" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Keine Treffer in %(src)s für »%(query)s«" msgid "No matches" msgstr "Keine Treffer" #, python-format msgid "No action matches \"%s\"" msgstr "Keine Aktion für »%s«" #, python-format msgid "Assign Accelerator to \"%(action)s\"" msgstr "Tastenkürtzel für »%(action)s« bestimmen" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "»%(action)s« als Vorgabe für »%(object)s« festlegen" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "»%s« vergessen" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Haupt-Bedienoberfläche anzeigen" msgid "Show with Selection" msgstr "Mit Auswahl anzeigen" #. TRANS: Plugin info fields msgid "Description" msgstr "Beschreibung" msgid "Author" msgstr "Autor" msgid "Version" msgstr "Version" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Python-Modul »%s« wird benötigt" msgid "Plugin could not be read due to an error:" msgstr "Plugin konnte wegen eines Fehlers nicht gelesen werden:" msgid "Content of" msgstr "Inhalt von" #. TRANS: Plugin contents header msgid "Sources" msgstr "Quellen" #. TRANS: Plugin contents header msgid "Actions" msgstr "Aktionen" #, python-format msgid "Using encrypted password storage: %s" msgstr "Verschlüsselter Passwortspeicher %s wird verwendet" #, python-format msgid "Using password storage: %s" msgstr "Passwortspeicher %s wird verwendet" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Einstellungen" msgid "Set username and password" msgstr "Benutzername und Passwort festlegen" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Einen Ordner auswählen" msgid "Reset all shortcuts to default values?" msgstr "" "Sollen alle Tastenkombinationen auf Standardwerte zurückgesetzt werden?" msgid "Shortcut" msgstr "Kürzel" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "" "Thibaud Roth \n" "Mario Blättermann \n" "Christian Kirbach \n" "Daniel Winzen \n" "Ulrik Sverdrup" msgid "A free software (GPLv3+) launcher" msgstr "Ein freier Anwendungsstarter (GPLv3+)" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Dieses Programm ist freie Software, Sie können sie weitergeben und/oder\n" "verändern, solange Sie sich an die Regeln der GNU General Public License\n" "halten, so wie sie von der Free Software Foundation festgelegt wurden;\n" "entweder in Version 3 der Lizenz oder (nach Ihrem Ermessen) in jeder " "folgenden Lizenz.\n" "\n" "Dieses Programm wurde mit dem Ziel veröffentlicht, dass Sie es nützlich " "finden,\n" "jedoch OHNE JEDWEDE GARANTIE, sogar ohne eine implizite Garantie\n" "der VERKAUFBARKEIT oder der NUTZBARKEIT FÜR EINEN SPEZIELLEN ZWECK.\n" "Schauen Sie für weitere Informationen bitte in der GNU General Public " "License (GNU GPL) nach.\n" "\n" "Mit diesem Programm sollten Sie außerdem eine Kopie der GNU General Public " "License erhalten\n" "haben. Wenn dem nicht so ist, so schreiben Sie bitte an die\n" "Free Software Foundation, Inc.,\n" "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Laufender Kupfer-Prozess konnte nicht gefunden werden" #~ msgid "Start" #~ msgstr "Start" #~ msgid "Reveal" #~ msgstr "Beinhaltenden Ordner öffnen" #~ msgid "GNOME Keyring" #~ msgstr "GNOME-Schlüsselbund" #~ msgid "KWallet" #~ msgstr "KWallet" #~ msgid "Unencrypted File" #~ msgstr "Unverschlüsselte Datei" #~ msgid "Empathy" #~ msgstr "Empathy" #~ msgid "Access to Empathy Contacts" #~ msgstr "Zugriff auf Empathy-Kontakte" #~ msgid "Busy" #~ msgstr "Beschäftigt" #~ msgid "Not Available" #~ msgstr "Nicht verfügbar" #~ msgid "Invisible" #~ msgstr "Verborgen" #~ msgid "Offline" #~ msgstr "Abgemeldet" #~ msgid "Change Global Status To..." #~ msgstr "Globalen Status ändern in …" #~ msgid "Empathy Contacts" #~ msgstr "Empathy-Kontakte" #~ msgid "Empathy Account Status" #~ msgstr "Kontenstatus von Empathy" #~ msgid "Type to search %s" #~ msgstr "Eingeben, um »%s« zu durchsuchen" #~ msgid "No action" #~ msgstr "Keine Aktion" #~ msgid "Compose Email" #~ msgstr "Neue E-Mail verfassen" #~ msgid "Send in Email To..." #~ msgstr "In E-Mail senden an …" #~ msgid "GNOME Terminal Profiles" #~ msgstr "GNOME-Terminal-Profile" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "GNOME-Terminal-Profile starten" #~ msgid "Multihead Support" #~ msgstr "Multihead-Unterstützung" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Ausdrücke beginnend mit »=« berechnen" #~ msgid "Epiphany Bookmarks" #~ msgstr "Lesezeichen in Epiphany" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Index der Lesezeichen in Epiphany" #~ msgid "Include visited sites" #~ msgstr "Besuchte Seiten einbeziehen" #~ msgid "Firefox tag" #~ msgstr "Firefox-Tag" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Wiedergabe in Rhythmbox fortsetzen" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Wiedergabe in Rhythmbox pausieren" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "In Rhythmbox zum nächsten Titel springen" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "In Rhythmbox zum vorherigen Titel springen" #~ msgid "Search the Web" #~ msgstr "Das Internet durchsuchen" #~ msgid "Search the web with OpenSearch search engines" #~ msgstr "Das Internet mit den OpenSearch-Suchmaschinen durchsuchen" #~ msgid "Search Engines" #~ msgstr "Suchmaschinen" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Kürzlich in Abiword verwendete Dokumente" #~ msgid "Abiword Recent Items" #~ msgstr "Letzte Abiword-Dokumente" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "Schnittstelle für die APT-Paketverwaltung" #~ msgid "Installation method" #~ msgstr "Installationsmethode" #~ msgid "Show Package Information" #~ msgstr "Paketinformationen anzeigen" #~ msgid "Install" #~ msgstr "Installieren" #~ msgid "Install package using the configured method" #~ msgstr "Das Paket mit Hilfe der konfigurierten Methode installieren" #~ msgid "Packages matching \"%s\"" #~ msgstr "Pakete, auf die »%s« zutrifft" #~ msgid "Search Package Name..." #~ msgstr "Nach Paketnamen suchen …" #~ msgid "Ascii & Unicode Icon Set" #~ msgstr "ASCII- und Unicode-Symbolsatz" #~ msgid "" #~ "Provides the Ascii and Unicode icon sets that use letters and symbols to " #~ "produce icons for the objects found in Kupfer." #~ msgstr "" #~ "Stellt ASCII- und Unicode-Symbolsätze bereit, aus denen Buchstaben und " #~ "Symbole für die in Kupfer gefundenen Objekte erstellt werden." #~ msgid "Ascii" #~ msgstr "ASCII" #~ msgid "Unicode" #~ msgstr "Unicode" #~ msgid "Chromium Bookmarks" #~ msgstr "Lesezeichen in Chromium" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Index der Chromium-Lesezeichen" #~ msgid "Claws Mail" #~ msgstr "Claws Mail" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Kontakte und Aktionen in Claws Mail" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Eine neue E-Mail mit Claws Mail erstellen" #~ msgid "Receive All Email" #~ msgstr "Alle E-Mails empfangen" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "Neue E-Mails für alle Konten in Claws Mail empfangen" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Eine neue Nachricht in Claws Mail erstellen und Datei anhängen" #~ msgid "Claws Mail Address Book" #~ msgstr "Adressbuch von Claws Mail" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Kontakte aus dem Adressbuch von Claws Mail" #~ msgid "Configure a custom terminal emulator" #~ msgstr "Einen Terminalemulator benutzerdefiniert einstellen" #~ msgid "Custom Theme" #~ msgstr "Benutzerdefiniertes Thema" #~ msgid "Use a custom color theme" #~ msgstr "Ein benutzerdefiniertes Farbthema verwenden" #~ msgid "Theme:" #~ msgstr "Thema:" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Evolution-Kontakte" #~ msgid "Compose a new message in Evolution" #~ msgstr "Eine neue E-Mail mit Evolution erstellen" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Eine neue Nachricht in Evolution erstellen und Datei anhängen" #~ msgid "Evolution Address Book" #~ msgstr "Adressbuch von Evolution" #~ msgid "Filezilla" #~ msgstr "Filezilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Seiten anzeigen und FTP-Adressen von Filezilla verarbeiten lassen" #~ msgid "Open Site with Filezilla" #~ msgstr "Seite mit Filezilla öffnen" #~ msgid "Filezilla Sites" #~ msgstr "Filezilla-Seiten" #~ msgid "Sites from Filezilla" #~ msgstr "Seiten von Filezilla" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Zugriff auf Gajim-Kontakte" #~ msgid "Free for Chat" #~ msgstr "Verfügbar für Unterhaltungen" #~ msgid "Gajim Contacts" #~ msgstr "Gajim-Kontakte" #~ msgid "Gajim Account Status" #~ msgstr "Kontenstatus von Gajim" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Kontakte laden und eine neue Nachricht in Google Mail erstellen" #~ msgid "Load contacts' pictures" #~ msgstr "Bilder für Kontakte laden" #~ msgid "Load additional information" #~ msgstr "Weitere Informationen laden" #~ msgid "Work email" #~ msgstr "E-Mail, geschäftlich" #~ msgid "Home email" #~ msgstr "E-Mail, privat" #~ msgid "Other email" #~ msgstr "Andere E-Mail" #~ msgid "Work address" #~ msgstr "Adresse, Arbeitsplatz" #~ msgid "Home address" #~ msgstr "Privatadresse" #~ msgid "Other address" #~ msgstr "Andere Adresse" #~ msgid "Car phone" #~ msgstr "Autotelefon" #~ msgid "Fax" #~ msgstr "Fax" #~ msgid "Home phone" #~ msgstr "Telefon, privat" #~ msgid "Home fax" #~ msgstr "Fax, privat" #~ msgid "Internal phone" #~ msgstr "Internes Telefon" #~ msgid "Mobile" #~ msgstr "Mobiltelefon" #~ msgid "Other" #~ msgstr "Andere" #~ msgid "VOIP" #~ msgstr "VOIP" #~ msgid "Work phone" #~ msgstr "Telefon, dienstlich" #~ msgid "Work fax" #~ msgstr "Fax, dienstlich" #~ msgid "Compose Email in Gmail" #~ msgstr "Neue E-Mail in GMail verfassen" #~ msgid "Open web browser and compose new email in Gmail" #~ msgstr "Webbrowser öffnen und eine neue Nachricht in GMail erstellen" #~ msgid "Edit Contact in Gmail" #~ msgstr "Kontakt in Gmail bearbeiten" #~ msgid "Open web browser and edit contact in Gmail" #~ msgstr "Webbrowser öffnen und den Kontakt in GMail bearbeiten" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Kontakte aus Google-Diensten (Google Mail)" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Alben anzeigen und Dateien zu Picasa hochladen" #~ msgid "Users to show: (,-separated)" #~ msgstr "Anzuzeigende Benutzer (durch Kommata getrennt):" #~ msgid "Load user and album icons" #~ msgstr "Symbole für Benutzer und Alben laden" #~ msgid "Uploading Pictures" #~ msgstr "Bilder werden übertragen" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Bilder werden zum Picasa-Webalbum übertragen" #~ msgid "Creating album:" #~ msgstr "Album wird erstellt:" #~ msgid "Album created by Kupfer" #~ msgstr "Album erstellt von Kupfer" #~ msgid "File:" #~ msgstr "Datei:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "One album" #~ msgstr[1] "%(num)d Alben" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "Ein Foto" #~ msgstr[1] "%(num)s Fotos" #~ msgid "Upload to Picasa Album..." #~ msgstr "Bilder zum Picasa-Album hochladen …" #~ msgid "Upload files to Picasa album" #~ msgstr "Dateien zum Picasa-Album hochladen" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Dateien zu Picasa als neues Album hochladen" #~ msgid "Create album from selected local directory" #~ msgstr "Album aus dem gewählten lokalen Ordner erstellen" #~ msgid "Picasa Albums" #~ msgstr "Picasa-Alben" #~ msgid "User albums in Picasa" #~ msgstr "Benutzeralben in Picasa" #~ msgid "Google Search" #~ msgstr "Google-Suche" #~ msgid "Search Google with results shown directly" #~ msgstr "Mit Google suchen und Ergebnisse direkt anzeigen" #~ msgid "Show More Results For \"%s\"" #~ msgstr "Weitere Ergebnisse für »%s« anzeigen" #~ msgid "%s total found" #~ msgstr "%s insgesamt gefunden" #~ msgid "Gwibber" #~ msgstr "Gwibber" #~ msgid "" #~ "Microblogging with Gwibber. Allows sending and receiving messages from " #~ "social networks like Twitter, Identi.ca etc. Requires the package " #~ "'gwibber-service'." #~ msgstr "" #~ "Microblogging mit Gwibber. Erlaubt das Senden und Empfangen von " #~ "Nachrichten in sozialen Netzwerken wie Twitter, Identi.ca usw. Dafür wird " #~ "das Paket »gwibber-service« benötigt." #~ msgid "Maximum number of messages to show" #~ msgstr "Maximale Anzahl anzuzeigender Nachrichten" #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s auf %(service)s" #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s am %(when)s auf %(where)s" #~ msgid "Send Message" #~ msgstr "Nachricht senden" #~ msgid "Send message to all Gwibber accounts" #~ msgstr "Nachricht an alle Gwibber-Konten senden" #~ msgid "Send Message To..." #~ msgstr "Nachricht senden an …" #~ msgid "Send message to a Gwibber account" #~ msgstr "Nachricht an ein Gwibber-Konto senden" #~ msgid "Send message to selected Gwibber account" #~ msgstr "Nachricht an das ausgewählte Gwibber-Konto senden" #~ msgid "Reply..." #~ msgstr "Antworten …" #~ msgid "Delete Message" #~ msgstr "Nachricht löschen" #~ msgid "Send Private Message..." #~ msgstr "Private Nachricht senden …" #~ msgid "Send direct message to user" #~ msgstr "Direkte Nachricht an Benutzer senden" #~ msgid "Retweet" #~ msgstr "Antworten" #~ msgid "Retweet To..." #~ msgstr "Antworten an …" #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Auf die Nachricht an alle Gwibber-Konten antworten" #~ msgid "Retweet message to a Gwibber account" #~ msgstr "Auf eine Nachricht über ein Gwibber-Konto antworten" #~ msgid "Open in Browser" #~ msgstr "Im Browser öffnen" #~ msgid "Open message in default web browser" #~ msgstr "Nachricht im vorgegebenen Webbrowser öffnen" #~ msgid "Gwibber Accounts" #~ msgstr "Gwibber-Konten" #~ msgid "Accounts configured in Gwibber" #~ msgstr "In Gwibber eingerichtete Konten" #~ msgid "Gwibber Messages" #~ msgstr "Gwibber-Nachrichten" #~ msgid "Recent messages received by Gwibber" #~ msgstr "Von Gwibber kürzlich empfangene Nachrichten" #~ msgid "Gwibber Messages for %s" #~ msgstr "Gwibber-Nachrichten für %s" #~ msgid "Gwibber Streams" #~ msgstr "Gwibber-Streams" #~ msgid "Streams configured in Gwibber" #~ msgstr "In Gwibber eingerichtete Streams" #~ msgid "Gwibber Messages in %s" #~ msgstr "Gwibber-Nachrichten in %s" #~ msgid "Gwibber (Simple)" #~ msgstr "Gwibber (einfach)" #~ msgid "Send updates via the microblogging client Gwibber" #~ msgstr "Aktualisierungen über den Microblogging-Client Gwibber senden" #~ msgid "Send Update" #~ msgstr "Aktualisierung senden" #~ msgid "Unable to activate Gwibber service" #~ msgstr "Gwibber-Dienst konnte nicht aktiviert werden" #~ msgid "OpenOffice / LibreOffice" #~ msgstr "OpenOffice / LibreOffice" #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Kürzlich in OpenOffice/LibreOffice verwendete Dokumente" #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "In OpenOffice/LibreOffice zuletzt geöffnete Objekte" #~ msgid "Opera Mail" #~ msgstr "Opera Mail" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Kontakte und Aktionen in Opera Mail" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Eine neue E-Mail mit Opera Mail erstellen" #~ msgid "Opera Mail Contacts" #~ msgstr "Opera-Mail-Kontakte" #~ msgid "Contacts from Opera Mail" #~ msgstr "Kontakte aus Opera Mail" #~ msgid "Opera Bookmarks" #~ msgstr "Lesezeichen in Opera" #~ msgid "Index of Opera bookmarks" #~ msgstr "Index der Lesezeichen in Opera" #~ msgid "PuTTY Sessions" #~ msgstr "PuTTY-Sitzungen" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Schneller Zugriff auf PuTTY-Sitzungen" #~ msgid "Start Session" #~ msgstr "Sitzung starten" #~ msgid "reStructuredText" #~ msgstr "reStructuredText" #~ msgid "Render reStructuredText and show the result" #~ msgstr "reStructuredText darstellen" #~ msgid "View as HTML Document" #~ msgstr "Als HTML-Dokument betrachten" #~ msgid "System Services" #~ msgstr "Systemdienste" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "Systemdienste über Init-Skripte starten, stoppen oder neu starten" #~ msgid "Sudo-like Command" #~ msgstr "Sudo-ähnlicher Befehl" #~ msgid "Start Service" #~ msgstr "Dienst starten" #~ msgid "Stop Service" #~ msgstr "Dienst stoppen" #~ msgid "%s Service" #~ msgstr "%s-Dienst" #~ msgid "Show QRCode" #~ msgstr "QRCode anzeigen" #~ msgid "Display text as QRCode in a window" #~ msgstr "Text als QRCode in einem Fenster anzeigen" #~ msgid "Access to Skype contacts" #~ msgstr "Zugriff auf Skype-Kontakte" #~ msgid "Skype Me" #~ msgstr "Skype Me" #~ msgid "Logged Out" #~ msgstr "Abgemeldet" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Anrufen" #~ msgid "Place a call to contact" #~ msgstr "Einen Kontakt anrufen" #~ msgid "Skype Contacts" #~ msgstr "Skype-Kontakte" #~ msgid "Skype Statuses" #~ msgstr "Skype-Status" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Datenträger der TrueCrypt-Chronik" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "TrueCrypt-Datenträger: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Datenträger einhängen" #~ msgid "Mount in Truecrypt" #~ msgstr "In TrueCrypt einhängen" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Versuchen, eine Datei in TrueCrypt einzuhängen" #~ msgid "Dismount All Volumes" #~ msgstr "Alle Datenträger aushängen" #~ msgid "TrueCrypt Volumes" #~ msgstr "TrueCrypt-Datenträger" #~ msgid "Terminal Server Client" #~ msgstr "Terminal Server Client" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Sitzung gespeichert im Terminal-Server-Client" #~ msgid "TSClient sessions" #~ msgstr "TSClient-Sitzungen" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Gespeicherte Sitzungen im Terminal-Server-Client" #~ msgid "Vim" #~ msgstr "Vim" #~ msgid "Recently used documents in Vim" #~ msgstr "Kürzlich in Vim verwendete Dokumente" #~ msgid "Close (Save All)" #~ msgstr "Schließen (alle speichern)" #~ msgid "Send..." #~ msgstr "Senden …" #~ msgid "Send ex command" #~ msgstr "Abbrechen-Befehl senden" #~ msgid "Insert in Vim..." #~ msgstr "In Vim einfügen …" #~ msgid "Active Vim Sessions" #~ msgstr "Aktive Vim-Sitzungen" #~ msgid "Vim Session %s" #~ msgstr "Vim-Sitzung %s" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Vinagre-Lesezeichen und -Aktionen" #~ msgid "Start Vinagre Session" #~ msgstr "Vinagre-Sitzung starten" #~ msgid "Vinagre Bookmarks" #~ msgstr "Lesezeichen in Vinagre" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "Steuerung von VirtualBox-Maschinen. Unterstützt sowohl VirtualBox von Sun " #~ "als auch die Open Source Edition." #~ msgid "Force use CLI interface" #~ msgstr "Befehlszeilenschnittstelle erzwingen" #~ msgid "Power On" #~ msgstr "Einschalten" # Der Headless mode von VirtualBox kann verwendet werden, um eine virtuelle Maschine auf einem Host ohne grafisches Frontend zu betreiben. #~ msgid "Power On Headless" #~ msgstr "Ohne Grafikausgabe (headless) einschalten" #~ msgid "Send Power Off Signal" #~ msgstr "Signal zum Ausschalten senden" #~ msgid "Reboot" #~ msgstr "Neu starten" #~ msgid "Resume" #~ msgstr "Fortsetzen" #~ msgid "Save State" #~ msgstr "Status speichern" #~ msgid "Power Off" #~ msgstr "Ausschalten" #~ msgid "VirtualBox Machines" #~ msgstr "VirtualBox-Maschinen" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "Zugriff auf in Zim gespeicherte Seiten - ein Desktop-Wiki" #~ msgid "Page names start with :colon" #~ msgstr "Seitennamen beginnen mit :colon" #~ msgid "Default page name for quick notes" #~ msgstr "Vorgegebener Seitenname für Quicknotes" #~ msgid "Note %x %X" #~ msgstr "Notiz %x %X" #~ msgid "" #~ "Strftime tags can be used: %H - hour, %M - minutes, etc\n" #~ "Please check python documentation for details.\n" #~ "NOTE: comma will be replaced by _" #~ msgstr "" #~ "Strftime-Tags sind verwendbar: %H - Stunde, %M - Minuten usw.\n" #~ "Details hierzu finden Sie in der Python-Dokumentation.\n" #~ "Achtung: Das Komma wird durch einen Unterstrich ersetzt." #~ msgid "Default namespace for quick notes" #~ msgstr "Vorgegebener Namensraum für Quicknotes" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Zim-Seite aus Notizbuch »%s«" #~ msgid "Create Zim Page" #~ msgstr "Zim-Seite erstellen" #~ msgid "Create page in default notebook" #~ msgstr "Zim-Seite im vorgegebenen Notizbuch erstellen" #~ msgid "Create Zim Page In..." #~ msgstr "Zim-Seite erstellen in …" #~ msgid "Insert QuickNote into Zim" #~ msgstr "Quicknote in Zim einfügen" #~ msgid "Quick note selected text into Zim notebook" #~ msgstr "Ausgewählten Text der Quicknote in das Zim-Notizbuch einfügen" #~ msgid "Create Subpage..." #~ msgstr "Unterseite erstellen …" #~ msgid "Zim Notebooks" #~ msgstr "Zim-Notizbücher" #~ msgid "Zim Pages" #~ msgstr "Zim-Seiten" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "In Zim-Notizbüchern gespeicherte Seiten" #~ msgid "Selected File" #~ msgstr "Ausgewählte Datei" #~ msgid "" #~ "Provides current nautilus selection, using Kupfer's Nautilus Extension" #~ msgstr "" #~ "Gibt aktuelle Nautilus-Auswahl aus, indem es Kupfers Nautilus-Erweiterung " #~ "verwendet" #~ msgid "Selected File \"%s\"" #~ msgstr "Ausgewählte Datei »%s«" #~ msgid "Selected Files" #~ msgstr "Ausgewählte Dateien" #~ msgid "Tracker 0.6" #~ msgstr "Tracker 0.6" #~ msgid "Tracker tags" #~ msgstr "Tracker-Schlagworte" #~ msgid "Tracker Tags" #~ msgstr "Tracker-Schlagworte" #~ msgid "Browse Tracker's tags" #~ msgstr "Tracker-Schlagworte anzeigen" #~ msgid "Tag %s" #~ msgstr "Schlagwort %s" #~ msgid "Objects tagged %s with Tracker" #~ msgstr "Objekte mit dem Schlagwort %s in Tracker" #~ msgid "Add Tag..." #~ msgstr "Schlagwort hinzufügen …" #~ msgid "Add tracker tag to file" #~ msgstr "Tracker-Schlagwort zur Datei hinzufügen" #~ msgid "Remove Tag..." #~ msgstr "Schlagwort entfernen …" #~ msgid "Remove tracker tag from file" #~ msgstr "Tracker-Schlagwort von der Datei entfernen" #~ msgid "Translate text with Google Translate" #~ msgstr "Text mit Google Translate übersetzen" #~ msgid "Google Translate connection timed out" #~ msgstr "Zeitüberschreitung bei Google Translate" #~ msgid "Error connecting to Google Translate" #~ msgstr "Fehler bei der Verbindung mit Google Translate" #~ msgid "Translate To..." #~ msgstr "Übersetzen nach …" #~ msgid "Translate into %s" #~ msgstr "Übersetzen nach %s" #~ msgid "Languages" #~ msgstr "Sprachen" #~ msgid "Show translated page in browser" #~ msgstr "Übersetzte Seite im Browser anzeigen" #~ msgid "Show Translation To..." #~ msgstr "Anzeigen der Übersetzung nach …" #~ msgid "Show translation in browser" #~ msgstr "Übersetzung im Browser anzeigen" #~ msgid "run keyboard shortcut relay service on this display" #~ msgstr "" #~ "Weiterleitungsdienst für Tastenkombinationen in dieser Anzeige starten" #~ msgid "Selected Text \"%s\"" #~ msgstr "Markierter Text »%s«" #~ msgid "Recent clipboards" #~ msgstr "Aktuelle Zwischenablagen" #~ msgid "Include recent selections" #~ msgstr "Kürzlich getroffene Auswahlen einschließen" #~ msgid "Text Matches" #~ msgstr "Übereinstimmungen im Text" #~ msgid "noun" #~ msgstr "Substantiv" #~ msgid "verb" #~ msgstr "Verb" #~ msgid "adjective" #~ msgstr "Adjektiv" #~ msgid "Directories" #~ msgstr "Ordner" #~ msgid "Exported Objects from Plugins" #~ msgstr "Von Plugins exportierte Objekte" #~ msgid "Interface" #~ msgstr "Schnittstelle" #~ msgid "Hide Kupfer when focus is lost" #~ msgstr "Kupfer verbergen, wenn Fenster nicht fokussiert ist" #~ msgid "Preferred terminal" #~ msgstr "Bevorzugtes Terminal" #~ msgid "" #~ "The preferred terminal emulator. It's used to launch the SSH sessions." #~ msgstr "" #~ "Die bevorzugte Terminalemulation. Sie wird zum Start von SSH-Sitzungen " #~ "verwendet." #~ msgid "" #~ "The flag which makes the terminal execute everything following it inside " #~ "the terminal (e.g. '-x' for gnome-terminal and terminal, '-e' for konsole " #~ "and urxvt)." #~ msgstr "" #~ "Das Argument, welches das Terminal anweist, alles Nachfolgende im " #~ "Terminal auszuführen (z.B. »-x« für gnome-terminal und terminal, »-e« für " #~ "konsole und urxvt)." #~ msgid "Tracker 0.8" #~ msgstr "Tracker 0.8" kupfer-328/po/el.po000066400000000000000000002251411500175051100142420ustar00rootroot00000000000000# Greek translation for kupfer. # Copyright (C) 2013 kupfer's COPYRIGHT HOLDER # This file is distributed under the same license as the kupfer package. # Dimitris Spingos , 2013. # keratea , 2013. # Dimitris Spingos (Δημήτρης Σπίγγος) , 2013. msgid "" msgstr "" "Project-Id-Version: kupfer master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2013-07-05 09:52+0300\n" "Last-Translator: Dimitris Spingos (Δημήτρης Σπίγγος) \n" "Language-Team: team@gnome.gr\n" "Language: el\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: Virtaal 0.7.1\n" msgid "User credentials" msgstr "Διαπιστευτήρια χρήστη" msgid "_User:" msgstr "_Χρήστης:" msgid "_Password:" msgstr "_Κωδικός πρόσβασης:" msgid "_Change" msgstr "Α_λλαγή" msgid "Set Keyboard Shortcut" msgstr "Ορισμός συντόμευσης πληκτρολογίου" msgid "Please press desired key combination" msgstr "Παρακαλούμε, πατήστε τον επιθυμητό συνδυασμό πλήκτρων" msgid "Keybinding could not be bound" msgstr "Ο συνδυασμός πλήκτρων δεν μπόρεσε να προσαρτηθεί" msgid "Kupfer Preferences" msgstr "Προτιμήσεις Kupfer" msgid "Start automatically on login" msgstr "Αυτόματη έναρξη στη σύνδεση" msgid "Start" msgstr "Έναρξη" msgid "Show icon in notification area" msgstr "Εμφάνιση εικονιδίου στην περιοχή ειδοποίησης" msgid "Icon set:" msgstr "Ομάδα εικονιδίων:" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" msgid "Terminal emulator:" msgstr "Προσομοιωτής τερματικού:" msgid "Desktop Environment" msgstr "Περιβάλλον επιφάνειας εργασίας" msgid "General" msgstr "Γενικά" msgid "Global Keyboard Shortcuts" msgstr "Γενικές συντομεύσεις πληκτρολογίου" msgid "Reset" msgstr "Επαναφορά" msgid "Browser Keyboard Shortcuts" msgstr "Συντομεύσεις πληκτρολογίου περιηγητή" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "Χρήση μονών εντολών πληκτρολόγησης (διάστημα, /, περίοδος, κόμμα κλπ.)" msgid "Keyboard" msgstr "Πληκτρολόγιο" msgid "Plugins" msgstr "Πρόσθετα" msgid "Inclusion in Top Level Searches" msgstr "Συμπερίληψη στις αναζητήσεις κορυφαίου επιπέδου" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "Οι σημειωμένες πηγές έχουν τα αντικείμενά τους να συμπεριλαμβάνονται στις " "αναζητήσεις κορυφαίου επιπέδου.\n" "Τα περιεχόμενα μιας ασημείωτης πηγής είναι διαθέσιμα μόνο με εντοπισμό του " "υποκαταλόγου της." msgid "Indexed Folders" msgstr "Φάκελοι από ευρετήριο" msgid "Folders whose files are always available in the catalog." msgstr "Φάκελοι των οποίων τα αρχεία είναι πάντα διαθέσιμα στον κατάλογο." msgid "Catalog" msgstr "Κατάλογος" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Εκκινητής εφαρμογής" msgid "Convenient command and access tool for applications and documents" msgstr "Βολικό εργαλείο εντολών και πρόσβασης για εφαρμογές και έγγραφα" msgid "Execute in Kupfer" msgstr "Εκτέλεση στο Kupfer" msgid "Saved Kupfer Command" msgstr "Αποθηκευμένη εντολή Kupfer" #, python-format msgid "Could not to carry out '%s'" msgstr "Αδύνατη η εκτέλεση του '%s'" #, python-format msgid "\"%s\" produced a result" msgstr "το \"%s\" παρήγαγε ένα αποτέλεσμα" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Χωρίς δικαίωμα εκτέλεσης του \"%s\" (μη εκτελέσιμο)" #, python-format msgid "Command in \"%s\" is not available" msgstr "Η εντολή στο \"%s\" δεν είναι διαθέσιμη" #, python-format msgid "Keyboard relay is active for display %s" msgstr "Η μεταγωγή πληκτρολογίου είναι ενεργή για εμφάνιση του %s" msgid "do not present main interface on launch" msgstr "να μην εμφανίζεται η κύρια διεπαφή στην έναρξη" msgid "list available plugins" msgstr "λίστα διαθέσιμων προσθέτων" msgid "enable debug info" msgstr "ενεργοποίηση πληροφοριών αποσφαλμάτωσης" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "εκτέλεση βοηθού προσθέτου" msgid "show usage help" msgstr "εμφάνιση βοήθειας χρήσης" msgid "show version information" msgstr "εμφάνιση πληροφοριών έκδοσης" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Χρήση: kupfer [ ΕΠΙΛΟΓΕΣ | ΑΡΧΕΙΟ ... ]" msgid "Available plugins:" msgstr "Διαθέσιμα πρόσθετα:" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "Πληκτρολογήστε για αναζήτηση" #, python-format msgid "%s is empty" msgstr "το %s είναι κενό" msgid "Text" msgstr "Κείμενο" msgid "Run after Delay..." msgstr "Εκτέλεση μετά από καθυστέρηση..." msgid "Perform command after a specified time interval" msgstr "Εκτέλεση της εντολής μετά από έναν καθορισμένο χρονικό διάστημα" msgid "Multiple Objects" msgstr "Πολλαπλά αντικείμενα" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s αντικείμενο" msgstr[1] "%s αντικείμενα" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "άγνωστο" msgid "Aim" msgstr "Aim" msgid "Google Talk" msgstr "Google Talk" msgid "ICQ" msgstr "ICQ" msgid "MSN" msgstr "MSN" msgid "QQ" msgstr "QQ" msgid "Yahoo" msgstr "Yahoo" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "το %s δεν υποστηρίζει αυτή τη λειτουργία" msgid "Can not be used with multiple objects" msgstr "Αδύνατη η χρήση του με πολλαπλά αντικείμενα" msgid "Open" msgstr "Άνοιγμα" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Χωρίς προεπιλεγμένη εφαρμογή για %(file)s (%(type)s)" #, python-format msgid "Please use \"%s\"" msgstr "Παρακαλούμε χρησιμοποιήστε το \"%s\"" msgid "Set Default Application..." msgstr "Ορισμός προεπιλεγμένης εφαρμογής..." msgid "Open with default application" msgstr "Άνοιγμα με την προεπιλεγμένη εφαρμογή" msgid "Reveal" msgstr "Αποκάλυψη" msgid "Open parent folder" msgstr "Άνοιγμα γονικού φακέλου" msgid "Open Terminal Here" msgstr "Άνοιγμα τερματικού εδώ" msgid "Open this location in a terminal" msgstr "Άνοιγμα αυτής της τοποθεσίας σε τερματικό" msgid "Run in Terminal" msgstr "Εκτέλεση σε τερματικό" msgid "Run (Execute)" msgstr "Τρέξιμο (εκτέλεση)" msgid "Run this program in a Terminal" msgstr "Εκτέλεση αυτού του προγράμματος σε τερματικό" msgid "Run this program" msgstr "Εκτέλεση αυτού του προγράμματος" msgid "Go To" msgstr "Μετάβαση σε" msgid "Open URL" msgstr "Άνοιγμα URL" msgid "Open URL with default viewer" msgstr "Άνοιγμα URL με προεπιλεγμένη προβολή" msgid "Launch" msgstr "Έναρξη" msgid "Show application window" msgstr "Εμφάνιση παραθύρου εφαρμογής" msgid "Launch application" msgstr "Έναρξη εφαρμογής" msgid "Launch Again" msgstr "Έναρξη πάλι" msgid "Launch another instance of this application" msgstr "Έναρξη ενός άλλου στιγμιότυπου αυτής της εφαρμογής" msgid "Close" msgstr "Κλείσιμο" msgid "Attempt to close all application windows" msgstr "Προσπάθεια για κλείσιμο όλων των παραθύρων εφαρμογής" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Εκτέλεση" msgid "Perform command" msgstr "Εντολή εκτέλεσης" msgid "(Empty Text)" msgstr "(κενό κείμενο)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "\"%(text)s\"" msgstr[1] "(%(num)d γραμμές) \"%(text)s\"" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s κ.α." #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Αναδρομική πηγή των %(dir)s, (%(levels)d επιπέδων)" #, python-format msgid "Directory source %s" msgstr "Προέλευση καταλόγου %s" msgid "Home Folder" msgstr "Προσωπικός φάκελος" msgid "Catalog Index" msgstr "Ευρετήριο καταλόγου" msgid "An index of all available sources" msgstr "Ένα ευρετήριο όλων των διαθέσιμων πηγών" msgid "Root catalog" msgstr "Πηγαίος κατάλογος" msgid "Please Configure Plugin" msgstr "Παρακαλούμε, ρυθμίστε το πρόσθετο" #, python-format msgid "Plugin %s is not configured" msgstr "Το πρόσθετο %s δεν ρυθμίστηκε" #, python-format msgid "Invalid user credentials for %s" msgstr "Άκυρα διαπιστευτήρια χρήστη για το %s" msgid "Applications" msgstr "Εφαρμογές" msgid "All applications and preferences" msgstr "Όλες οι εφαρμογές και προτιμήσεις" msgid "Applications for Desktop Environment" msgstr "Εφαρμογές για το περιβάλλον επιφάνειας εργασίας" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "Άνοιγμα με..." msgid "Open with any application" msgstr "Άνοιγμα με οποιαδήποτε εφαρμογή" msgid "Set default application to open this file type" msgstr "Ορισμός προεπιλεγμένης εφαρμογής για άνοιγμα με αυτόν τον τύπο αρχείου" #, fuzzy msgid "Reset Associations" msgstr "Ενέργειες URL" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "Βαθιές αρχειοθήκες" msgid "Allow browsing inside compressed archive files" msgstr "Να επιτρέπεται η περιήγηση μέσα σε συμπιεσμένα αρχεία αρχειοθήκης" #, python-format msgid "Content of %s" msgstr "Περιεχόμενα του %s" msgid "Archive Manager" msgstr "Διαχειριστής αρχειοθήκης" msgid "Use Archive Manager actions" msgstr "Χρήση ενεργειών διαχειριστή αρχειοθήκης" msgid "Compressed archive type for 'Create Archive In'" msgstr "Τύπος συμπιεσμένης αρχειοθήκης για 'Δημιουργία αρχειοθήκης σε'" msgid "Extract Here" msgstr "Αποσυμπίεση εδώ" msgid "Extract compressed archive" msgstr "Εξαγωγή συμπιεσμένης αρχειοθήκης" msgid "Create Archive" msgstr "Δημιουργία αρχειοθήκης" msgid "Create a compressed archive from folder" msgstr "Δημιουργία συμπιεσμένης αρχειοθήκης από φάκελο" msgid "Create Archive In..." msgstr "Δημιουργία αρχειοθήκης σε..." #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Αρχειοθήκη" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "Έλεγχος αναπαραγωγής Audacious και λίστας αναπαραγωγής" msgid "Include songs in top level" msgstr "Να συμπεριλαμβάνονται τα τραγούδια στο κορυφαίο επίπεδο" msgid "Enqueue" msgstr "Σε αναμονή" msgid "Add track to the Audacious play queue" msgstr "Προσθήκη κομματιού στην σειρά αναπαραγωγής του Audacious" msgid "Dequeue" msgstr "Αφαίρεση από την αναμονή" msgid "Remove track from the Audacious play queue" msgstr "Αφαίρεση κομματιού από τη σειρά αναπαραγωγής του Audacious" msgid "Play" msgstr "Αναπαραγωγή" msgid "Jump to track in Audacious" msgstr "Μετάβαση σε κομμάτι στο Audacious" msgid "Resume playback in Audacious" msgstr "Συνέχιση αναπαραγωγής στο Audacious" msgid "Pause" msgstr "Παύση" msgid "Pause playback in Audacious" msgstr "Παύση αναπαραγωγής στο Audacious" msgid "Next" msgstr "Επόμενο" msgid "Jump to next track in Audacious" msgstr "Μετάβαση στο επόμενο κομμάτι στο Audacious" msgid "Previous" msgstr "Προηγούμενο" msgid "Jump to previous track in Audacious" msgstr "Μετάβαση στο προηγούμενο κομμάτι στο Audacious" msgid "Clear Queue" msgstr "Καθαρισμός αναμονής" msgid "Clear the Audacious play queue" msgstr "Καθαρισμός της σειρά αναπαραγωγής του Audacious" msgid "Shuffle" msgstr "Ανακάτεμα" msgid "Toggle shuffle in Audacious" msgstr "Εναλλαγή ανακατέματος στο Audacious" msgid "Repeat" msgstr "Επανάληψη" msgid "Toggle repeat in Audacious" msgstr "Εναλλαγή επανάληψης στο Audacious" msgid "Show Playing" msgstr "Εμφάνιση αναπαραγωγής" msgid "Tell which song is currently playing" msgstr "Να λέει ποιο τραγούδι αναπαράγεται τώρα" msgid "Playlist" msgstr "Λίστα αναπαραγωγής" msgid "Calculator" msgstr "Αριθμομηχανή" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "Υπολογισμός" msgid "Clipboards" msgstr "Πρόχειρα" msgid "Recent clipboards and clipboard proxy objects" msgstr "Πρόσφατα πρόχειρα και αντικείμενα μεσολαβητή προχείρων" msgid "Number of recent clipboards to remember" msgstr "Αριθμός πρόσφατων προχείρων για απομνημόνευση" msgid "Include selected text in clipboard history" msgstr "Να συμπεριλαμβάνεται το επιλεγμένο κείμενο στο ιστορικό προχείρου" msgid "Copy selected text to primary clipboard" msgstr "Αντιγραφή επιλεγμένου κειμένου στο κύριο πρόχειρο" msgid "Selected Text" msgstr "Επιλεγμένο κείμενο" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Πρόχειρο \"%(desc)s\"" msgstr[1] "Πρόχειρο με %(num)d γραμμές \"%(desc)s\"" msgid "Clipboard Text" msgstr "Κείμενο προχείρου" msgid "Clipboard File" msgstr "Αρχείο προχείρου" msgid "Clipboard Files" msgstr "Αρχεία προχείρου" msgid "Clear" msgstr "Καθαρισμός" msgid "Remove all recent clipboards" msgstr "Αφαίρεση όλων των πρόσφατων προχείρων" msgid "Shell Commands" msgstr "Εντολές φλοιού" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Εκτέλεση προγραμμάτων γραμμής εντολών. Οι ενέργειες που σημειώθηκαν με το " "σύμβολο %s εκτελούνται σε έναν υποφλοιό." msgid "Run (Get Output)" msgstr "Εκτέλεση (λήψη εξόδου)" msgid "Run program and return its output" msgstr "Εκτέλεση προγράμματος και επιστροφή της εξόδου του" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "Πέρασμα στην εντολή..." msgid "Run program with object as an additional parameter" msgstr "Εκτέλεση προγράμματος με αντικείμενο ως μία πρόσθετη παράμετρος" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "Εγγραφή στην εντολή..." msgid "Run program and supply text on the standard input" msgstr "Εκτέλεση προγράμματος και τροφοδοσία κειμένου στην τυπική είσοδο" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "Φιλτράρισμα μέσα από την εντολή..." msgid "Run command-line programs" msgstr "Εκτέλεση προγραμμάτων γραμμής εντολών" msgid "GTK+" msgstr "GTK+" msgid "GNOME Terminal" msgstr "Τερματικό GNOME" msgid "XFCE Terminal" msgstr "Τερματικό XFCE" msgid "LXTerminal" msgstr "Τερματικό LX" msgid "X Terminal" msgstr "Τερματικό Χ" msgid "Urxvt" msgstr "Urxvt" msgid "Konsole" msgstr "Κονσόλα" msgid "Save As..." msgstr "Αποθήκευση ως..." #, fuzzy msgid "Restart Kupfer" msgstr "Επανεκκίνηση υπηρεσίας" msgid "Quit" msgstr "Έξοδος" msgid "Quit Kupfer" msgstr "Έξοδος από το Kupfer" msgid "About Kupfer" msgstr "Σχετικά με το Kupfer" msgid "Show information about Kupfer authors and license" msgstr "Εμφάνιση πληροφοριών για τους συγγραφείς του Kupfer και την άδεια" msgid "Kupfer Help" msgstr "Βοήθεια Kupfer" msgid "Get help with Kupfer" msgstr "Λήψη βοήθειας με το Kupfer" msgid "Show preferences window for Kupfer" msgstr "Εμφάνιση παραθύρου προτιμήσεων για το Kupfer" msgid "Search Contents" msgstr "Αναζήτηση περιεχομένων" msgid "Search inside this catalog" msgstr "Αναζήτηση μέσα σε αυτόν τον κατάλογο" msgid "Copy" msgstr "Αντιγραφή" msgid "Copy to clipboard" msgstr "Αντιγραφή στο πρόχειρο" msgid "Rescan" msgstr "Επανασάρωση" msgid "Force reindex of this source" msgstr "Αναγκαστική επαναευρετηριοποίηση αυτής της πηγής" msgid "Last Command" msgstr "Τελευταία εντολή" msgid "Internal Kupfer Objects" msgstr "Εσωτερικά αντικείμενα Kupfer" msgid "Last Result" msgstr "Τελευταίο αποτέλεσμα" msgid "Command Results" msgstr "Αποτελέσματα εντολής" msgid "Custom Terminal" msgstr "Προσαρμοσμένο τερματικό" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Εντολή" msgid "Execute flag" msgstr "Εκτέλεση σημαίας" msgid "Default Email Client" msgstr "Προεπιλεγμένος πελάτης αλληλογραφίας" msgid "Compose email using the system's default mailto: handler" msgstr "" "Σύνταξη αλληλογραφίας χρησιμοποιώντας τον προεπιλεγμένο χειριστή mailto: του " "συστήματος" #, fuzzy msgid "Compose Email To" msgstr "Σύνταξη αλληλογραφίας" msgid "Dictionary" msgstr "Λεξικό" msgid "Look up word in dictionary" msgstr "Αναζήτηση λέξης σε λεξικό" msgid "Look Up" msgstr "Αναζήτηση" msgid "Documents" msgstr "Έγγραφα" msgid "Recently used documents and bookmarked folders" msgstr "Πρόσφατα χρησιμοποιημένα έγγραφα και φάκελοι με σελιδοδείκτες" msgid "Max recent document days" msgstr "Μέγιστος αριθμός ημερών για πρόσφατα έγγραφα" msgid "Recent Items" msgstr "Πρόσφατα στοιχεία" msgid "Recently used documents" msgstr "Πρόσφατα χρησιμοποιημένα αρχεία" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "%s Έγγραφα" #, python-format msgid "Recently used documents for %s" msgstr "Πρόσφατα χρησιμοποιημένα έγγραφα για %s" msgid "Places" msgstr "Τοποθεσίες" msgid "Bookmarked folders" msgstr "Φάκελοι με σελιδοδείκτες" msgid "DuckDuckGo Search" msgstr "Αναζήτηση DuckDuckGo" msgid "Search the web securely with DuckDuckGo" msgstr "Αναζήτηση του ιστού με ασφάλεια με το DuckDuckGo" msgid "Favorites" msgstr "Αγαπημένα" msgid "Mark commonly used items and store objects for later use" msgstr "" "Σημείωση κοινών χρησιμοποιούμενων στοιχείων και αποθήκευση αντικειμένων για " "μεταγενέστερη χρήση" msgid "Shelf of \"Favorite\" items" msgstr "Ράφι των στοιχείων \"Αγαπημένα\"" msgid "Add to Favorites" msgstr "Προσθήκη στα αγαπημένα" msgid "Add item to favorites shelf" msgstr "Προσθήκη στοιχείου στο ράφι αγαπημένων" msgid "Remove from Favorites" msgstr "Απομάκρυνση από τα αγαπημένα" msgid "Remove item from favorites shelf" msgstr "Αφαίρεση στοιχείου από το ράφι αγαπημένων" msgid "File Actions" msgstr "Ενέργειες αρχείου" msgid "More file actions" msgstr "Περισσότερες ενέργειες αρχείου" msgid "Move To..." msgstr "Μετακίνηση σε..." msgid "Move file to new location" msgstr "Μετακίνηση αρχείου σε νέα τοποθεσία" msgid "Rename To..." msgstr "Μετονομασία σε..." msgid "Copy To..." msgstr "Αντιγραφή σε..." msgid "Copy file to a chosen location" msgstr "Αντιγραφή αρχείου σε επιλεγμένη θέση" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "Glob" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "Ενέργειες μεγαλύτερης τάξης" msgid "Tools to work with commands as objects" msgstr "Εργαλεία για εργασία με εντολές όπως αντικείμενα" msgid "Select in Kupfer" msgstr "Επιλογή στο Kupfer" #, python-format msgid "Result of %s (%s)" msgstr "Αποτέλεσμα του %s (%s)" msgid "Run (Take Result)" msgstr "Εκτέλεση (λήψη αποτελέσματος)" msgid "Take the command result as a proxy object" msgstr "Λήψη του αποτελέσματος εντολής ως αντικειμένου μεσολαβητή" msgid "Run (Discard Result)" msgstr "Εκτέλεση (απόρριψη αποτελέσματος)" msgid "Image Tools" msgstr "Εργαλεία εικόνας" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Εργαλεία μετασχηματισμού εικόνας" msgid "Scale..." msgstr "Κλιμάκωση..." msgid "Scale image to fit inside given pixel measure(s)" msgstr "" "Κλιμάκωση εικόνας για προσαρμογή μέσα στις δοσμένες μετρήσεις εικονοστοιχείου" msgid "Rotate Clockwise" msgstr "Δεξιόστροφη περιστροφή" msgid "Rotate Counter-Clockwise" msgstr "Αριστερόστροφη περιστροφή" msgid "Autorotate" msgstr "Αυτόματη περιστροφή" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "Περιστροφή JPEG (επί τόπου) σύμφωνα με τα μεταδεδομένα του EXIF" msgid "Kupfer Plugins" msgstr "Πρόσθετα Kupfer" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Πρόσβαση λίστας προσθέτων του Kupfer στο Kupfer" msgid "Show Information" msgstr "Εμφάνιση πληροφοριών" msgid "Show Source Code" msgstr "Εμφάνιση πηγαίου κώδικα" msgid "enabled" msgstr "ενεργό" msgid "disabled" msgstr "ανενεργό" msgid "Notes" msgstr "Σημειώσεις" msgid "Gnote or Tomboy notes" msgstr "Σημειώσεις Gnote ή Tomboy" msgid "Work with application" msgstr "Εργασία με την εφαρμογή" msgid "Open with notes application" msgstr "Άνοιγμα με εφαρμογή σημειώσεων" msgid "Append to Note..." msgstr "Προσάρτηση στη σημείωση..." msgid "Add text to existing note" msgstr "Προσθήκη κειμένου στην υπάρχουσα σημείωση" msgid "Create Note" msgstr "Δημιουργία σημείωσης" msgid "Create a new note from this text" msgstr "Δημιουργία νέας σημείωσης από αυτό το κείμενο" msgid "Get Note Search Results..." msgstr "Λήψη αποτελεσμάτων αναζήτησης σημείωσης..." msgid "Show search results for this query" msgstr "Εμφάνιση αποτελεσμάτων αναζήτησης για αυτό το ερώτημα" #, python-format msgid "today, %s" msgstr "σήμερα, %s" #, python-format msgid "yesterday, %s" msgstr "χτες, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Τελευταία ενημέρωση του %s" msgid "Quicksilver Icons" msgstr "Εικονίδια Quicksilver" msgid "Quick Image Viewer" msgstr "Γρήγορη προβολή εικόνων" msgid "View Image" msgstr "Προβολή εικόνας" msgid "GNU Screen" msgstr "Οθόνη GNU" msgid "Active GNU Screen sessions" msgstr "Ενεργές συνεδρίες οθόνης GNU" msgid "Attached" msgstr "Επισύναψη" msgid "Detached" msgstr "Απόσπαση" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "συνεδρία %(status)s (%(pid)s) δημιουργήθηκε στις %(time)s" msgid "Screen Sessions" msgstr "Συνεδρίες οθόνης" msgid "Attach" msgstr "Επισύναψη" msgid "Send Keys" msgstr "Αποστολή πλήκτρων" msgid "Send synthetic keyboard events using xautomation" msgstr "Αποστολή τεχνητών συμβάντων πληκτρολογίου χρησιμοποιώντας xautomation" msgid "Paste to Foreground Window" msgstr "Επικόλληση στο παράθυρο προσκηνίου" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "Αντιγραφή στο πρόχειρο και αποστολή Ctrl+V στο παράθυρο προσκηνίου" msgid "Send keys to foreground window" msgstr "Αποστολή πλήκτρων στο παράθυρο προσκηνίου" msgid "Type Text" msgstr "Πληκτρολόγηση κειμένου" msgid "Type the text to foreground window" msgstr "Πληκτρολογήστε το κείμενο στο παράθυρο προσκηνίου" msgid "GNOME Session Management" msgstr "Διαχείριση συνεδρίας GNOME" msgid "Special items and actions for GNOME environment" msgstr "Ειδικά στοιχεία και ενέργειες για περιβάλλον GNOME" msgid "Log Out..." msgstr "Αποσύνδεση..." msgid "Log out or change user" msgstr "Αποσύνδεση ή αλλαγή χρήστη" msgid "Shut Down..." msgstr "Τερματισμός..." msgid "Shut down, restart or suspend computer" msgstr "Τερματισμός, επανεκκίνηση ή αναστολή υπολογιστή" msgid "Lock Screen" msgstr "Κλείδωμα οθόνης" msgid "Enable screensaver and lock" msgstr "Ενεργοποίηση προφύλαξης οθόνης και κλείδωμα" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "Διαχείριση συνεδρίας XFCE" msgid "Special items and actions for XFCE environment" msgstr "Ειδικά στοιχεία και ενέργειες για περιβάλλον XFCE" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "Οικοδεσπότες SSH" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "Προσθέτει τους οικοδεσπότες SSH που βρέθηκαν στο ~/.ssh/config." msgid "SSH host" msgstr "Οικοδεσπότης SSH" msgid "Connect" msgstr "Σύνδεση" msgid "Connect to SSH host" msgstr "Σύνδεση με οικοδεσπότη SSH" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "Οικοδεσπότες SSH όπως ορίστηκαν στο ~/.ssh/config" msgid "No D-Bus connection to desktop session" msgstr "Χωρίς σύνδεση διαύλου δεδομένων στη συνεδρία επιφάνειας εργασίας" msgid "GNOME Keyring" msgstr "Κλειδοθήκη GNOME" msgid "KWallet" msgstr "KWallet" msgid "Unencrypted File" msgstr "Ακρυπτογράφητο αρχείο" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "Η εντολή στο \"%s\" δεν είναι διαθέσιμη" msgid "Document Templates" msgstr "Πρότυπα εγγράφων" msgid "Create new documents from your templates" msgstr "Δημιουργία νέων εγγράφων από τα πρότυπά σας" #, python-format msgid "%s template" msgstr "πρότυπο %s" msgid "Empty File" msgstr "Κενό αρχείο" msgid "New Folder" msgstr "Νέος φάκελος" msgid "Create New Document..." msgstr "Δημιουργία νέου εγγράφου..." msgid "Create a new document from template" msgstr "Δημιουργία νέου εγγράφου από πρότυπο" msgid "Create Document In..." msgstr "Δημιουργία εγγράφου σε..." msgid "Textfiles" msgstr "Αρχεία κειμένου" msgid "Append To..." msgstr "Προσάρτηση σε..." msgid "Append..." msgstr "Προσάρτηση..." msgid "Write To..." msgstr "Εγγραφή σε..." msgid "Get Text Contents" msgstr "Λήψη περιεχομένων κειμένου" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "Ενέργειες του διαχειριστή αρχείων Thunar" msgid "Select in File Manager" msgstr "Επιλογή στον διαχειριστή αρχείων" msgid "Show Properties" msgstr "Εμφάνιση ιδιοτήτων" msgid "Show information about file in file manager" msgstr "Εμφάνιση πληροφοριών για το αρχείο στον διαχειριστή αρχείων" msgid "Send To..." msgstr "Αποστολή σε..." msgid "Symlink In..." msgstr "Συμβολικός δεσμός σε..." msgid "Create a symlink to file in a chosen location" msgstr "Δημιουργία συμβολικού δεσμού σε αρχείο σε επιλεγμένη θέση" msgid "Empty Trash" msgstr "Άδειασμα απορριμμάτων" msgid "Thunar Send To Objects" msgstr "Αποστολή αντικειμένων από το Thunar" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Επαφές και ενέργειες Thunderbird/Icedove" msgid "Compose New Email" msgstr "Σύνταξη νέας αλληλογραφίας" msgid "Compose a new message in Thunderbird" msgstr "Σύνταξη νέου μηνύματος στο Thunderbird" #, fuzzy msgid "Attach in Email To..." msgstr "Αποστολή με αλληλογραφία σε..." #, fuzzy msgid "Compose Email With" msgstr "Σύνταξη αλληλογραφίας" #, fuzzy msgid "Compose a new message using the text as body" msgstr "Σύνταξη νέου μηνύματος στο Thunderbird" msgid "Thunderbird Address Book" msgstr "Βιβλίο διευθύνσεων Thunderbird" msgid "Contacts from Thunderbird Address Book" msgstr "Επαφές από το βιβλίο διευθύνσεων από το Thunderbird" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Κορυφή" msgid "Show running tasks and allow sending signals to them" msgstr "" "Εμφάνιση εκτελούμενων εργασιών και δυνατότητα αποστολής σημάτων σε αυτές" msgid "Sort Order" msgstr "Σειρά ταξινόμησης" msgid "Commandline" msgstr "Γραμμή εντολών" msgid "CPU usage (descending)" msgstr "Xρήση CPU (φθίνουσα)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Χρήση μνήμης (φθίνουσα)" msgid "Send Signal..." msgstr "Αποστολή σήματος..." msgid "Signals" msgstr "Σήματα" msgid "Running Tasks" msgstr "Εκτέλεση εργασιών" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid: %(pid)s ΚΜΕ: %(cpu)g%% μνήμη: %(mem)g%% διάρκεια: %(time)s" msgid "Running tasks for current user" msgstr "Εκτελούμενες εργασίες για τον τρέχοντα χρήστη" msgid "Trash" msgstr "Απορρίμματα" msgid "Access trash contents" msgstr "Πρόσβαση στα περιεχόμενα απορριμμάτων" msgid "Move to Trash" msgstr "Μετακίνηση στα απορρίμματα" msgid "Move this file to trash" msgstr "Μεταφορά αυτού του αρχείου στα απορρίμματα" msgid "Restore" msgstr "Επαναφορά" msgid "Move file back to original location" msgstr "Μετακίνηση αρχείου πίσω στην αρχική θέση" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "Τα απορρίμματα είναι άδεια" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "Τα απορρίμματα περιέχουν ένα αρχείο" msgstr[1] "Τα απορρίμματα περιέχουν %(num)s αρχεία" msgid "Triggers" msgstr "Εναύσματα" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Απόδοση γενικών συνδυασμών πλήκτρων (εναύσματα) σε αντικείμενα που " "δημιουργήθηκαν με την 'εντολή σύνθεση'." msgid "Add Trigger..." msgstr "Προσθήκη εναύσματος..." msgid "Remove Trigger" msgstr "Αφαίρεση εναύσματος" msgid "URL Actions" msgstr "Ενέργειες URL" msgid "Download and Open" msgstr "Μεταφόρτωση και άνοιγμα" msgid "Download To..." msgstr "Μεταφόρτωση σε..." msgid "Download URL to a chosen location" msgstr "Μεταφόρτωση URL σε μια επιλεγμένη θέση" msgid "Wikipedia" msgstr "Βικιπαίδεια" msgid "Search in Wikipedia" msgstr "Αναζήτηση στη βικιπαίδεια" msgid "Wikipedia language" msgstr "Γλώσσα βικιπαίδειας" #. TRANS: Default wikipedia language code msgid "en" msgstr "el" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Αναζήτηση για αυτόν τον όρο στο %s.wikipedia.org" msgid "Window List" msgstr "Λίστα παραθύρων" msgid "All windows on all workspaces" msgstr "Όλα τα παράθυρα σε όλους τους χώρους εργασίας" msgid "Activate" msgstr "Ενεργοποίηση" msgid "Shade" msgstr "Σκίαση" msgid "Unshade" msgstr "Αποσκίαση" msgid "Minimize" msgstr "Ελαχιστοποίηση" msgid "Unminimize" msgstr "Απελαχιστοποίηση" msgid "Maximize" msgstr "Μεγιστοποίηση" msgid "Unmaximize" msgstr "Aπομεγιστοποίηση" msgid "Maximize Vertically" msgstr "Κάθετη μεγιστοποίηση" msgid "Unmaximize Vertically" msgstr "Κάθετη απομεγιστοποίηση" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Παράθυρο στο %(wkspc)s" msgid "Frontmost Window" msgstr "Το πιο μπροστινό παράθυρο" msgid "Next Window" msgstr "Επόμενο παράθυρο" msgid "Jump to this window's workspace and focus" msgstr "Μετάβαση σε αυτό τον χώρο εργασίας του παραθύρου και εστίαση" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "%d παράθυρο" msgstr[1] "%d παράθυρα" msgid "Active workspace" msgstr "Ενεργός χώρος εργασίας" msgid "Jump to this workspace" msgstr "Μετάβαση σε αυτόν τον χώρο εργασίας" msgid "Workspaces" msgstr "Χώροι εργασίας" msgid "Volumes and Disks" msgstr "Τόμοι και δίσκοι" msgid "Mounted volumes and disks" msgstr "Προσαρτημένοι τόμοι και δίσκοι" #, python-format msgid "Volume mounted at %s" msgstr "Τόμος προσαρτημένος στο %s" msgid "Unmount" msgstr "Αποπροσάρτηση" msgid "Unmount this volume" msgstr "Προσάρτηση αυτού του τόμου" msgid "Eject" msgstr "Εξαγωγή" msgid "Unmount and eject this media" msgstr "Αποπροσάρτηση και εξαγωγή αυτού του μέσου" msgid "Show Text" msgstr "Εμφάνιση κειμένου" msgid "Display text in a window" msgstr "Εμφάνιση κειμένου σε παράθυρο" msgid "Large Type" msgstr "Μεγάλος τύπος" msgid "Show Notification" msgstr "Εμφάνιση ειδοποίησης" msgid "Tracker" msgstr "Tracker" msgid "Tracker desktop search integration" msgstr "Ολοκλήρωση αναζήτησης επιφάνειας εργασίας Tracker" msgid "Search in Tracker" msgstr "Αναζήτηση στο Tracker" msgid "Open Tracker Search Tool and search for this term" msgstr "Άνοιγμα του εργαλείου αναζήτησης Tracker και αναζήτηση αυτού του όρου" msgid "Get Tracker Results..." msgstr "Λήψη αποτελεσμάτων του Tracker..." msgid "Show Tracker results for query" msgstr "Εμφάνιση αποτελεσμάτων του Tracker για ερώτημα" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "Αποτελέσματα για \"%s\"" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "Εντοπισμός αρχείων" msgid "Search filesystem using locate" msgstr "Αναζήτηση συστήματος αρχείων χρησιμοποιώντας εντοπισμό" msgid "Ignore case distinctions when searching files" msgstr "Παράβλεψη διακρίσεων πεζών-κεφαλαίων κατά την αναζήτηση αρχείων" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Σελιδοδείκτες Firefox" msgid "Index of Firefox bookmarks" msgstr "Ευρετήριο σελιδοδεικτών του Firefox" #, fuzzy msgid "Firefox Keywords" msgstr "Σελιδοδείκτες Firefox" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "Αναζήτηση στον ιστό με μηχανές αναζήτησης OpenSearch" msgid "Search With..." msgstr "Αναζήτηση με..." msgid "Search For..." msgstr "Αναζήτηση για..." #, fuzzy msgid "Search Terms" msgstr "Μηχανές αναζήτησης" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Παρακαλούμε χρησιμοποιήστε το \"%s\"" #, fuzzy msgid "Resume playback" msgstr "Συνέχιση αναπαραγωγής στο Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Επόμενο" #, fuzzy msgid "Skip to next track" msgstr "Μετάβαση στο επόμενο κομμάτι στο Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Προηγούμενο" #, fuzzy msgid "Skip to previous track" msgstr "Μετάβαση στο προηγούμενο κομμάτι στο Audacious" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "Πρόσβαση στις επαφές του Pidgin" msgid "Show offline contacts" msgstr "Εμφάνιση επαφών εκτός σύνδεσης" msgid "Open Chat" msgstr "Ανοικτή συνομιλία" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d χαρακτήρας)" msgstr[1] "%s (%d χαρακτήρες)" msgid "Send Message..." msgstr "Αποστολή μηνύματος..." msgid "Available" msgstr "Διαθέσιμες" msgid "Away" msgstr "Απουσιάζει" msgid "Pidgin Contacts" msgstr "Επαφές Pidgin" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Συντόμευση συνδέσμων" msgid "Create short aliases of long URLs" msgstr "Δημιουργία σύντομων ψευδωνύμων μεγάλων URLs" msgid "Error" msgstr "Σφάλμα" msgid "Shorten With..." msgstr "Συντόμευση με..." msgid "Services" msgstr "Υπηρεσίες" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "" "Αναπαραγωγή, τοποθέτηση κομματιών σε αναμονή και περιήγηση της μουσικής " "βιβλιοθήκης" msgid "Include artists in top level" msgstr "Να συμπεριλαμβάνονται οι καλλιτέχνες στο κορυφαίο επίπεδο" msgid "Include albums in top level" msgstr "Να συμπεριλαμβάνονται οι δίσκοι στο κορυφαίο επίπεδο" msgid "Play tracks in Rhythmbox" msgstr "Αναπαραγωγή κομματιών στο Rhythmbox" msgid "Add tracks to the play queue" msgstr "Προσθήκη κομματιών στη σειρά αναπαραγωγής" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "κατά %(artist)s από %(album)s" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "κατά %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Κομμάτια κατά %s" msgid "Albums" msgstr "Δίσκοι" msgid "Music albums in Rhythmbox Library" msgstr "Μουσικοί δίσκοι στη βιβλιοθήκη Rhythmbox" msgid "Artists" msgstr "Καλλιτέχνες" msgid "Music artists in Rhythmbox Library" msgstr "Μουσικοί καλλιτέχνες στη βιβλιοθήκη Rhythmbox" msgid "Songs" msgstr "Τραγούδια" msgid "Songs in Rhythmbox library" msgstr "Τραγούδια στη βιβλιοθήκη Rhythmbox" msgid "Getting Things GNOME" msgstr "Getting Things GNOME" msgid "Browse and create new tasks in GTG" msgstr "Περιήγηση και δημιουργία νέων εργασιών στο GTG" #, python-format msgid "due: %s" msgstr "λήξη: %s" #, python-format msgid "start: %s" msgstr "έναρξη: %s" #, python-format msgid "tags: %s" msgstr "ετικέτες: %s" msgid "Open task in Getting Things GNOME!" msgstr "Άνοιγμα εργασίας στο Getting Things GNOME!" msgid "Delete" msgstr "Διαγραφή" msgid "Permanently remove this task" msgstr "Μόνιμη απομάκρυνση αυτής της εργασίας" msgid "Mark Done" msgstr "Έτοιμο" msgid "Mark this task as done" msgstr "Σημείωση αυτής της εργασίας ως έτοιμης" msgid "Dismiss" msgstr "Αποδέσμευση" msgid "Mark this task as not to be done anymore" msgstr "Σημείωση αυτής της εργασίας να μην γίνει πια" msgid "Create Task" msgstr "Δημιουργία εργασίας" msgid "Create new task in Getting Things GNOME" msgstr "Δημιουργία νέας εργασίας στο Getting Things GNOME" msgid "Devhelp" msgstr "Βοήθεια ανάπτυξης" msgid "Search in Devhelp" msgstr "Αναζήτηση στη βοήθεια ανάπτυξης" msgid "Empathy" msgstr "Empathy" msgid "Access to Empathy Contacts" msgstr "Πρόσβαση στις επαφές του Empathy" msgid "Busy" msgstr "Απασχολημένος" msgid "Not Available" msgstr "Μη διαθέσιμος" msgid "Invisible" msgstr "Αόρατος" msgid "Offline" msgstr "Αποσυνδεδεμένος" msgid "Change Global Status To..." msgstr "Αλλαγή της γενικής κατάστασης σε..." msgid "Empathy Contacts" msgstr "Επαφές του Empathy" msgid "Empathy Account Status" msgstr "Κατάσταση λογαριασμού του Empathy" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Εναλλακτική ενεργοποίηση" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Τέχνασμα κόμμα (πολλά αντικείμενα)" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Εντολή σύνθεσης" msgid "Mark Default Action" msgstr "Σημείωση προεπιλεγμένης ενέργειας" msgid "Forget Object" msgstr "Παράλειψη αντικειμένου" msgid "Reset All" msgstr "Επαναφορά όλων" msgid "Select Quit" msgstr "Επιλογή εξόδου" msgid "Select Selected File" msgstr "Επιλογή του επιλεγμένου αρχείου" msgid "Select Selected Text" msgstr "Επιλογή του επιλεγμένου κειμένου" msgid "Show Help" msgstr "Εμφάνιση βοήθειας" msgid "Show Preferences" msgstr "Εμφάνιση προτιμήσεων" msgid "Switch to First Pane" msgstr "Εναλλαγή σε πρώτο παράθυρο" msgid "Toggle Text Mode" msgstr "Εναλλαγή σε κατάσταση κειμένου" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Δεν υπάρχει συμφωνία στο %(src)s για το \"%(query)s\"" msgid "No matches" msgstr "Καμία συμφωνία" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Καμία συμφωνία" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Κάντε το \"%(action)s\" προεπιλογή για \"%(object)s\"" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "Παράλειψη σχετικά με το \"%s\"" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Εμφάνιση κύριας διεπαφής" msgid "Show with Selection" msgstr "Εμφάνιση με επιλογή" #. TRANS: Plugin info fields msgid "Description" msgstr "Περιγραφή" msgid "Author" msgstr "Δημιουργός" msgid "Version" msgstr "Έκδοση" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Χρειάζεται η ενότητα Python '%s'" msgid "Plugin could not be read due to an error:" msgstr "Το πρόσθετο δεν μπόρεσε να διαβαστεί λόγω ενός σφάλματος:" msgid "Content of" msgstr "Περιεχόμενο του" #. TRANS: Plugin contents header msgid "Sources" msgstr "Πηγές" #. TRANS: Plugin contents header msgid "Actions" msgstr "Ενέργειες" #, python-format msgid "Using encrypted password storage: %s" msgstr "Χρήση κρυπτογραφημένης αποθήκευσης κωδικού πρόσβασης: %s" #, python-format msgid "Using password storage: %s" msgstr "Χρήση αποθήκευσης κωδικού πρόσβασης: %s" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Διαμόρφωση" msgid "Set username and password" msgstr "Εισάγετε το όνομα χρήστη και κωδικό πρόσβασης." #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Επιλέξτε έναν κατάλογο" msgid "Reset all shortcuts to default values?" msgstr "Επαναφορά όλων των συντομεύσεων στις προεπιλεγμένες τιμές;" msgid "Shortcut" msgstr "Συντόμευση" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "" "Ελληνική μεταφραστική ομάδα του GNOME\n" " Δημήτρης Σπίγγος \n" "Για περισσότερα δείτε: http://gnome.gr" msgid "A free software (GPLv3+) launcher" msgstr "Ένας εκκινητής ελεύθερου λογισμικού (GPLv3+)" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Αυτό το πρόγραμμα είναι ελεύθερο λογισμικό: Επιτρέπεται η αναδιανομή ή/και " "τροποποίησή του υπό τους όρους της Γενικής Άδειας Δημόσιας Χρήσης\n" "GNU, όπως αυτή έχει δημοσιευτεί από το Ίδρυμα Ελεύθερου Λογισμικού,\n" "είτε της έκδοσης 3 της Άδειας, είτε (κατ' επιλογήν) οποιασδήποτε\n" "μεταγενέστερης έκδοσης.\n" "\n" "Το πρόγραμμα αυτό διανέμεται με την ελπίδα ότι θα αποδειχθεί χρήσιμο,\n" "παρόλα αυτά ΧΩΡΙΣ ΚΑΜΙΑ ΕΓΓΥΗΣΗ – χωρίς ούτε και την σιωπηρή εγγύηση\n" "ΕΜΠΟΡΕΥΣΙΜΟΤΗΤΑΣ ή ΚΑΤΑΛΛΗΛΟΤΗΤΑΣ ΓΙΑ ΣΥΓΚΕΚΡΙΜΕΝΗ ΧΡΗΣΗ. Για\n" "περισσότερες λεπτομέρειες ανατρέξτε στη Γενική Άδεια Δημόσιας Χρήσης\n" "GNU.\n" "\n" "Θα πρέπει να έχετε λάβει ένα αντίγραφο της Γενικής Άδειας Δημόσιας\n" "Χρήσης GNU μαζί με αυτό το πρόγραμμα. Εάν όχι, δείτε εδώ: .\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Αδύνατη η εύρεση εκτελούμενου Kupfer" #~ msgid "Compose Email" #~ msgstr "Σύνταξη αλληλογραφίας" #~ msgid "Send in Email To..." #~ msgstr "Αποστολή με αλληλογραφία σε..." #~ msgid "Type to search %s" #~ msgstr "Πληκτρολογήστε για αναζήτηση του %s" #~ msgid "No action" #~ msgstr "Καμία ενέργεια" #~ msgid "GNOME Terminal Profiles" #~ msgstr "Κατατομές τερματικού GNOME" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Έναρξη κατατομών τερματικού GNOME" #~ msgid "Multihead Support" #~ msgstr "Υποστήριξη πολλαπλής κεφαλής" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Υπολογισμός εκφράσεων που ξεκινούν με '='" #~ msgid "Epiphany Bookmarks" #~ msgstr "Σελιδοδείκτες Epiphany" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Ευρετήριο σελιδοδεικτών του Epiphany" #~ msgid "Include visited sites" #~ msgstr "Να συμπεριλαμβάνονται οι τόποι που επισκέφτηκαν" #~ msgid "Firefox tag" #~ msgstr "Ετικέτα Firefox" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Συνέχιση αναπαραγωγής στο Rhythmbox" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Παύση αναπαραγωγής στο Rhythmbox" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Μετάβαση στο επόμενο κομμάτι στο Rhythmbox" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Μετάβαση στο προηγούμενο κομμάτι στο Rhythmbox" #~ msgid "Search the Web" #~ msgstr "Αναζήτηση στον ιστό" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Πρόσφατα χρησιμοποιημένα έγγραφα στο Abiword" #~ msgid "Abiword Recent Items" #~ msgstr "Πρόσφατα στοιχεία Abiword" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "Διεπαφή με τον διαχειριστή πακέτου APT" #~ msgid "Installation method" #~ msgstr "Μέθοδος εγκατάστασης" #~ msgid "Show Package Information" #~ msgstr "Εμφάνιση πληροφοριών πακέτου" #~ msgid "Install" #~ msgstr "Εγκατάσταση" #~ msgid "Install package using the configured method" #~ msgstr "Εγκατάσταση πακέτου χρησιμοποιώντας τη ρυθμισμένη μέθοδο" #~ msgid "Packages matching \"%s\"" #~ msgstr "Πακέτα που ταιριάζουν στο \"%s\"" #~ msgid "Search Package Name..." #~ msgstr "Όνομα πακέτου αναζήτησης..." #~ msgid "Ascii & Unicode Icon Set" #~ msgstr "Ομάδα εικονιδίων Ascii & Unicode" #~ msgid "" #~ "Provides the Ascii and Unicode icon sets that use letters and symbols to " #~ "produce icons for the objects found in Kupfer." #~ msgstr "" #~ "Παρέχει τις ομάδες εικονιδίων Ascii και Unicode που χρησιμοποιούν " #~ "γράμματα και σύμβολα για να παράξουν εικονίδια για αντικείμενα που " #~ "βρέθηκαν στο Kupfer." #~ msgid "Ascii" #~ msgstr "Ascii" #~ msgid "Unicode" #~ msgstr "Unicode" #~ msgid "Chromium Bookmarks" #~ msgstr "Σελιδοδείκτες Chromium" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Ευρετήριο σελιδοδεικτών του Chromium" #~ msgid "Claws Mail" #~ msgstr "Claws Mail" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Επαφές και ενέργειες Claws Mail" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Σύνταξη νέου μηνύματος στο Claws Mail" #~ msgid "Receive All Email" #~ msgstr "Λήψη όλων των μηνυμάτων" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "Λήψη νέων μηνυμάτων από όλους τους λογαριασμούς στο ClawsMail" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Σύνταξη νέου μηνύματος στο Claws Mail και επισύναψη αρχείου" #~ msgid "Claws Mail Address Book" #~ msgstr "Το βιβλίο διευθύνσεων του Claws Mail" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Επαφές από το βιβλίο διευθύνσεων του Claws Mail" #~ msgid "Configure a custom terminal emulator" #~ msgstr "Ρύθμιση προσαρμοσμένου εξομοιωτή τερματικού" #~ msgid "Custom Theme" #~ msgstr "Προσαρμοσμένο θέμα" #~ msgid "Use a custom color theme" #~ msgstr "Χρήση προσαρμοσμένου χρωματικού θέματος" #~ msgid "Theme:" #~ msgstr "Θέμα:" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Επαφές Evolution" #~ msgid "Compose a new message in Evolution" #~ msgstr "Σύνταξη νέου μηνύματος στο Evolution" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Σύνταξη νέου μηνύματος στο Evolution και επισύναψη αρχείου" #~ msgid "Evolution Address Book" #~ msgstr "Βιβλίο διευθύνσεων Evolution" #~ msgid "Filezilla" #~ msgstr "FileZilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Εμφάνιση τόπων και χειρισμός διευθύνσεων ftp από το Filezilla" #~ msgid "Open Site with Filezilla" #~ msgstr "Άνοιγμα τόπου με Filezilla" #~ msgid "Filezilla Sites" #~ msgstr "Τόποι Filezilla" #~ msgid "Sites from Filezilla" #~ msgstr "Τόποι από Filezilla" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Πρόσβαση στις επαφές του Gajim" #~ msgid "Free for Chat" #~ msgstr "Ελεύθερος για συνομιλία" #~ msgid "Gajim Contacts" #~ msgstr "Επαφές του Gajim" #~ msgid "Gajim Account Status" #~ msgstr "Κατάσταση λογαριασμού Gajim" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Φόρτωση επαφών και σύνταξη νέου μηνύματος σε Gmail" #~ msgid "Load contacts' pictures" #~ msgstr "Φόρτωση εικόνων επαφών" #~ msgid "Load additional information" #~ msgstr "Φόρτωση πρόσθετων πληροφοριών" #~ msgid "Work email" #~ msgstr "Ηλεκτρονικό ταχυδρομείο εργασίας" #~ msgid "Home email" #~ msgstr "Ηλεκτρονικό ταχυδρομείο οικίας" #~ msgid "Other email" #~ msgstr "Άλλα ηλεκτρονικά ταχυδρομεία" #~ msgid "Work address" #~ msgstr "Διεύθυνση εργασίας" #~ msgid "Home address" #~ msgstr "Διεύθυνση οικίας" #~ msgid "Other address" #~ msgstr "Άλλες διευθύνσεις" #~ msgid "Car phone" #~ msgstr "Τηλέφωνο αυτοκινήτου" #~ msgid "Fax" #~ msgstr "Φαξ" #~ msgid "Home phone" #~ msgstr "Τηλέφωνο οικίας" #~ msgid "Home fax" #~ msgstr "Φαξ οικίας" #~ msgid "Internal phone" #~ msgstr "Εσωτερικό τηλέφωνο" #~ msgid "Mobile" #~ msgstr "Κινητό τηλέφωνο" #~ msgid "Other" #~ msgstr "Άλλο" #~ msgid "VOIP" #~ msgstr "VOIP" #~ msgid "Work phone" #~ msgstr "Τηλέφωνο εργασίας" #~ msgid "Work fax" #~ msgstr "Φαξ εργασίας" #~ msgid "Compose Email in Gmail" #~ msgstr "Σύνταξη μηνύματος σε Gmail" #~ msgid "Open web browser and compose new email in Gmail" #~ msgstr "Άνοιγμα περιηγητή ιστού και σύνταξη νέου μηνύματος σε Gmail" #~ msgid "Edit Contact in Gmail" #~ msgstr "Επεξεργασία επαφής σε Gmail" #~ msgid "Open web browser and edit contact in Gmail" #~ msgstr "Άνοιγμα περιηγητή ιστού και επεξεργασία επαφής σε Gmail" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Επαφές από υπηρεσίες Google (Gmail)" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Εμφάνιση συλλογών και ανέβασμα αρχείων στο Picasa" #~ msgid "Users to show: (,-separated)" #~ msgstr "Εμφανιζόμενοι χρήστες: (διαχωρισμός με ,)" #~ msgid "Load user and album icons" #~ msgstr "Φόρτωση εικονιδίων χρήστη και δίσκου" #~ msgid "Uploading Pictures" #~ msgstr "Ανέβασμα εικόνων" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Ανέβασμα εικόνων στη συλλογή ιστού Picasa" #~ msgid "Creating album:" #~ msgstr "Δημιουργία συλλογής:" #~ msgid "Album created by Kupfer" #~ msgstr "Η συλλογή δημιουργήθηκε από το Kupfer" #~ msgid "File:" #~ msgstr "Αρχείο:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "Μία συλλογή" #~ msgstr[1] "%(num)d συλλογές" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "μία φωτογραφία" #~ msgstr[1] "%(num)s φωτογραφίες" #~ msgid "Upload to Picasa Album..." #~ msgstr "Ανέβασμα στη συλλογή του Picasa..." #~ msgid "Upload files to Picasa album" #~ msgstr "Ανέβασμα αρχείων στη συλλογή του Picasa" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Ανέβασμα στο Picasa ως νέα συλλογή" #~ msgid "Create album from selected local directory" #~ msgstr "Δημιουργία συλλογής από επιλεγμένο τοπικό κατάλογο" #~ msgid "Picasa Albums" #~ msgstr "Συλλογές Picasa" #~ msgid "User albums in Picasa" #~ msgstr "Συλλογές χρήστη στο Picasa" #~ msgid "Google Search" #~ msgstr "Αναζήτηση Google" #~ msgid "Search Google with results shown directly" #~ msgstr "Αναζήτηση Google με άμεσα εμφανιζόμενα αποτελέσματα" #~ msgid "Show More Results For \"%s\"" #~ msgstr "Εμφάνιση περισσότερων αποτελεσμάτων για \"%s\"" #~ msgid "%s total found" #~ msgstr "βρέθηκαν συνολικά %s" #~ msgid "Gwibber" #~ msgstr "Gwibber" #~ msgid "" #~ "Microblogging with Gwibber. Allows sending and receiving messages from " #~ "social networks like Twitter, Identi.ca etc. Requires the package " #~ "'gwibber-service'." #~ msgstr "" #~ "Μικροϊστολόγιο με το Gwibber. Επιτρέπει την αποστολή και λήψη μηνυμάτων " #~ "από τα κοινωνικά δίκτυα όπως Twitter, Identi.ca κλπ. Απαιτεί το πακέτο " #~ "'gwibber-service'." #~ msgid "Maximum number of messages to show" #~ msgstr "Μέγιστος αριθμός εμφανιζόμενων μηνυμάτων" #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s στο %(service)s" #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s στο %(where)s" #~ msgid "Send Message" #~ msgstr "Αποστολή μηνύματος" #~ msgid "Send message to all Gwibber accounts" #~ msgstr "Αποστολή μηνύματος σε όλους τους λογαριασμούς Gwibber" #~ msgid "Send Message To..." #~ msgstr "Αποστολή μηνύματος προς..." #~ msgid "Send message to a Gwibber account" #~ msgstr "Αποστολή μηνύματος σε έναν λογαριασμό Gwibber" #~ msgid "Send message to selected Gwibber account" #~ msgstr "Αποστολή μηνύματος σε επιλεγμένο λογαριασμό Gwibber" #~ msgid "Reply..." #~ msgstr "Απάντηση..." #~ msgid "Delete Message" #~ msgstr "Διαγραφή μηνύματος" #~ msgid "Send Private Message..." #~ msgstr "Αποστολή ιδιωτικού μηνύματος..." #~ msgid "Send direct message to user" #~ msgstr "Αποστολή άμεσου μηνύματος στον χρήστη" #~ msgid "Retweet" #~ msgstr "Απάντηση" #~ msgid "Retweet To..." #~ msgstr "Απάντηση προς..." #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Απάντηση μηνύματος σε όλους τους λογαριασμούς Gwibber" #~ msgid "Retweet message to a Gwibber account" #~ msgstr "Απάντηση μηνύματος σε λογαριασμό Gwibber" #~ msgid "Open in Browser" #~ msgstr "Άνοιγμα στον περιηγητή" #~ msgid "Open message in default web browser" #~ msgstr "Άνοιγμα μηνύματος σε προεπιλεγμένο περιηγητή ιστού" #~ msgid "Gwibber Accounts" #~ msgstr "Λογαριασμοί Gwibber" #~ msgid "Accounts configured in Gwibber" #~ msgstr "Ρυθμισμένοι λογαριασμοί στο Gwibber" #~ msgid "Gwibber Messages" #~ msgstr "Μηνύματα Gwibber" #~ msgid "Recent messages received by Gwibber" #~ msgstr "Τα πρόσφατα μηνύματα ελήφθησαν από το Gwibber" #~ msgid "Gwibber Messages for %s" #~ msgstr "Μηνύματα Gwibber για %s" #~ msgid "Gwibber Streams" #~ msgstr "Ροές Gwibber" #~ msgid "Streams configured in Gwibber" #~ msgstr "Ρυθμισμένες ροές στο Gwibber" #~ msgid "Gwibber Messages in %s" #~ msgstr "Μηνύματα Gwibber στο %s" #~ msgid "Gwibber (Simple)" #~ msgstr "Gwibber (Απλό)" #~ msgid "Send updates via the microblogging client Gwibber" #~ msgstr "Αποστολή ενημερώσεων μέσα από πελάτη μικροϊστολογίου Gwibber" #~ msgid "Send Update" #~ msgstr "Αποστολή ενημέρωσης" #~ msgid "Unable to activate Gwibber service" #~ msgstr "Αδύνατη η ενεργοποίηση υπηρεσίας Gwibber" #~ msgid "OpenOffice / LibreOffice" #~ msgstr "OpenOffice / LibreOffice" #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Πρόσφατα χρησιμοποιημένα έγγραφα στο OpenOffice/LibreOffice" #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "Πρόσφατα στοιχεία OpenOffice/LibreOffice" #~ msgid "Opera Mail" #~ msgstr "Opera Mail" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Επαφές και ενέργειες Opera Mail" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Σύνταξη νέου μηνύματος στο Opera Mail" #~ msgid "Opera Mail Contacts" #~ msgstr "Επαφές Opera Mail" #~ msgid "Contacts from Opera Mail" #~ msgstr "Επαφές από Opera Mail" #~ msgid "Opera Bookmarks" #~ msgstr "Σελιδοδείκτες Opera" #~ msgid "Index of Opera bookmarks" #~ msgstr "Ευρετήριο σελιδοδεικτών του Opera" #~ msgid "PuTTY Sessions" #~ msgstr "Συνεδρίες PuTTY" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Γρήγορη πρόσβαση σε συνεδρίες PuTTY" #~ msgid "Start Session" #~ msgstr "Έναρξη συνεδρίας" #~ msgid "reStructuredText" #~ msgstr "reStructuredText" #~ msgid "Render reStructuredText and show the result" #~ msgstr "Απόδοση reStructuredText και εμφάνιση του αποτελέσματος" #~ msgid "View as HTML Document" #~ msgstr "Προβολή ως εγγράφου HTML" #~ msgid "System Services" #~ msgstr "Υπηρεσίες συστήματος" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "" #~ "Έναρξη, διακοπή ή επανεκκίνηση υπηρεσιών συστήματος μέσα από σενάρια init" #~ msgid "Sudo-like Command" #~ msgstr "Εντολή μορφής Sudo" #~ msgid "Start Service" #~ msgstr "Έναρξη υπηρεσίας" #~ msgid "Stop Service" #~ msgstr "Διακοπή υπηρεσίας" #~ msgid "%s Service" #~ msgstr "%s υπηρεσία" #~ msgid "Show QRCode" #~ msgstr "Εμφάνιση QRCode" #~ msgid "Display text as QRCode in a window" #~ msgstr "Εμφάνιση κειμένου σε παράθυρο ως QRCode" #~ msgid "Access to Skype contacts" #~ msgstr "Πρόσβαση σε επαφές του Skype" #~ msgid "Skype Me" #~ msgstr "Καλέστε με" #~ msgid "Logged Out" #~ msgstr "Αποσύνδεση" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Κλήση" #~ msgid "Place a call to contact" #~ msgstr "Κλήση στην επαφή" #~ msgid "Skype Contacts" #~ msgstr "Επαφές Skype" #~ msgid "Skype Statuses" #~ msgstr "Καταστάσεις Skype" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Τόμοι από το ιστορικό TrueCrypt" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "Τόμος TrueCrypt: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Προσάρτηση τόμου" #~ msgid "Mount in Truecrypt" #~ msgstr "Προσάρτηση στο Truecrypt" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Προσπάθεια προσάρτησης αρχείου ως τόμο Truecrypt" #~ msgid "Dismount All Volumes" #~ msgstr "Αποπροσάρτηση όλων των τόμων" #~ msgid "TrueCrypt Volumes" #~ msgstr "Τόμοι TrueCrypt" #~ msgid "Terminal Server Client" #~ msgstr "Πελάτης διακομιστή τερματικού" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Αποθηκευμένη συνεδρία στον πελάτη διακομιστή τερματικού" #~ msgid "TSClient sessions" #~ msgstr "Συνεδρίες TSClient" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Αποθηκευμένες συνεδρίες στον πελάτη διακομιστή τερματικού" #~ msgid "Vim" #~ msgstr "Vim" #~ msgid "Recently used documents in Vim" #~ msgstr "Πρόσφατα χρησιμοποιημένα έγγραφα στο Vim" #~ msgid "Vim Recent Documents" #~ msgstr "Πρόσφατα έγγραφα Vim" #~ msgid "Close (Save All)" #~ msgstr "Κλείσιμο (Αποθήκευση όλων)" #~ msgid "Send..." #~ msgstr "Αποστολή..." #~ msgid "Send ex command" #~ msgstr "Αποστολή εντολής ex" #~ msgid "Insert in Vim..." #~ msgstr "Εισαγωγή στο Vim..." #~ msgid "Active Vim Sessions" #~ msgstr "Ενεργές συνεδρίες Vim" #~ msgid "Vim Session %s" #~ msgstr "Συνεδρία %s του Vim" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Σελιδοδείκτες και ενέργειες Vinagre" #~ msgid "Start Vinagre Session" #~ msgstr "Έναρξη συνεδρίας Vinagre" #~ msgid "Vinagre Bookmarks" #~ msgstr "Σελιδοδείκτες Vinagre" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "Έλεγχος εικονικών μηχανημάτων VirtualBox. Υποστηρίζει και το Sun " #~ "VirtualBox και την έκδοση ανοικτού λογισμικού." #~ msgid "Force use CLI interface" #~ msgstr "Αναγκαστική χρήση διεπαφής CLI" #~ msgid "Power On" #~ msgstr "Ενεργοποίηση" #~ msgid "Power On Headless" #~ msgstr "Ακέφαλη ενεργοποίηση" #~ msgid "Send Power Off Signal" #~ msgstr "Αποστολή σήματος τερματισμού" #~ msgid "Reboot" #~ msgstr "Επανεκκίνηση" #~ msgid "Resume" #~ msgstr "Συνέχεια" #~ msgid "Save State" #~ msgstr "Αποθήκευση κατάστασης" #~ msgid "Power Off" #~ msgstr "Απενεργοποίηση" #~ msgid "VirtualBox Machines" #~ msgstr "Μηανήματα VirtualBox" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "" #~ "Πρόσβαση σε σελίδες αποθηκευμένες στο Zim - Μια επιφάνεια εργασίας βίκι " #~ "και περίγραμμα" #~ msgid "Page names start with :colon" #~ msgstr "Τα ονόματα σελίδων ξεκινούν με: διπλή τελεία" #~ msgid "Default page name for quick notes" #~ msgstr "Προεπιλεγμένο όνομα σελίδας για γρήγορες σημειώσεις" #~ msgid "Note %x %X" #~ msgstr "Σημείωση %x %X" #~ msgid "" #~ "Strftime tags can be used: %H - hour, %M - minutes, etc\n" #~ "Please check python documentation for details.\n" #~ "NOTE: comma will be replaced by _" #~ msgstr "" #~ "Ετικέτες Strftime μπορούν να χρησιμοποιηθούν: %H - ώρες, %M - λεπτά, κλπ\n" #~ "Παρακαλούμε, δείτε την τεκμηρίωση python για λεπτομέρειες.\n" #~ "ΣΗΜΕΙΩΣΗ: το κόμμα θα αντικατασταθεί από _" #~ msgid "Default namespace for quick notes" #~ msgstr "Προεπιλεγμένος χώρος ονόματος για γρήγορες σημειώσεις" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Σελίδα Zim από σημειωματάριο \"%s\"" #~ msgid "Create Zim Page" #~ msgstr "Δημιουργία σελίδας Zim" #~ msgid "Create page in default notebook" #~ msgstr "Δημιουργία σελίδας σε προεπιλεγμένο σημειωματάριο" #~ msgid "Create Zim Page In..." #~ msgstr "Δημιουργία σελίδας Zim σε..." #~ msgid "Insert QuickNote into Zim" #~ msgstr "Εισαγωγή γρήγορης σημείωσης στο Zim" #~ msgid "Quick note selected text into Zim notebook" #~ msgstr "Γρήγορη σημείωση επιλεγμένου κειμένου στο σημειωματάριο Zim" #~ msgid "Create Subpage..." #~ msgstr "Δημιουργία υποσελίδας..." #~ msgid "Zim Notebooks" #~ msgstr "Σημειωματάρια Zim" #~ msgid "Zim Pages" #~ msgstr "Σελίδες Zim" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Αποθηκευμένες σελίδες σε σημειωματάρια Zim" kupfer-328/po/en.po000066400000000000000000000664651500175051100142600ustar00rootroot00000000000000# English translations for the kupfer package -- just for curly quotes # Copyright (C) 2012 Ulrik Sverdrup # This file is distributed under the same license as the kupfer package. (GPLv3) # msgid "" msgstr "" "Project-Id-Version: kupfer \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2009-06-23 20:19+0200\n" "Last-Translator: Ulrik Sverdrup \n" "Language-Team: (US) English\n" "Language: \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" msgid "User credentials" msgstr "" msgid "_User:" msgstr "" msgid "_Password:" msgstr "" msgid "_Change" msgstr "" msgid "Set Keyboard Shortcut" msgstr "" msgid "Please press desired key combination" msgstr "" msgid "Keybinding could not be bound" msgstr "" msgid "Kupfer Preferences" msgstr "" msgid "Start automatically on login" msgstr "" msgid "Start" msgstr "" msgid "Show icon in notification area" msgstr "" msgid "Icon set:" msgstr "" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" msgid "Terminal emulator:" msgstr "" msgid "Desktop Environment" msgstr "" msgid "General" msgstr "" msgid "Global Keyboard Shortcuts" msgstr "" msgid "Reset" msgstr "" msgid "Browser Keyboard Shortcuts" msgstr "" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "" msgid "Keyboard" msgstr "" msgid "Plugins" msgstr "" msgid "Inclusion in Top Level Searches" msgstr "" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" msgid "Indexed Folders" msgstr "" msgid "Folders whose files are always available in the catalog." msgstr "" msgid "Catalog" msgstr "" msgid "Kupfer" msgstr "" msgid "Application Launcher" msgstr "" msgid "Convenient command and access tool for applications and documents" msgstr "" msgid "Execute in Kupfer" msgstr "" msgid "Saved Kupfer Command" msgstr "" #, python-format msgid "Could not to carry out '%s'" msgstr "Could not carry out ‘%s’" #, python-format msgid "\"%s\" produced a result" msgstr "“%s” produced a result" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "No permission to run “%s” (not executable)" #, python-format msgid "Command in \"%s\" is not available" msgstr "Command in “%s” is not available" #, python-format msgid "Keyboard relay is active for display %s" msgstr "" msgid "do not present main interface on launch" msgstr "" msgid "list available plugins" msgstr "" msgid "enable debug info" msgstr "" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "" msgid "show usage help" msgstr "" msgid "show version information" msgstr "" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "" msgid "Available plugins:" msgstr "" #, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" msgid "Type to search" msgstr "" #, python-format msgid "%s is empty" msgstr "" msgid "Text" msgstr "" msgid "Run after Delay..." msgstr "" msgid "Perform command after a specified time interval" msgstr "" msgid "Multiple Objects" msgstr "" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "" msgstr[1] "" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "" msgid "unknown" msgstr "" msgid "Aim" msgstr "" msgid "Google Talk" msgstr "" msgid "ICQ" msgstr "" msgid "MSN" msgstr "" msgid "QQ" msgstr "" msgid "Yahoo" msgstr "" msgid "Skype" msgstr "" #, python-format msgid "%s does not support this operation" msgstr "" msgid "Can not be used with multiple objects" msgstr "" msgid "Open" msgstr "" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "" #, python-format msgid "Please use \"%s\"" msgstr "Please use “%s”" msgid "Set Default Application..." msgstr "" msgid "Open with default application" msgstr "" msgid "Reveal" msgstr "" msgid "Open parent folder" msgstr "" msgid "Open Terminal Here" msgstr "" msgid "Open this location in a terminal" msgstr "" msgid "Run in Terminal" msgstr "" msgid "Run (Execute)" msgstr "" msgid "Run this program in a Terminal" msgstr "" msgid "Run this program" msgstr "" msgid "Go To" msgstr "" msgid "Open URL" msgstr "" msgid "Open URL with default viewer" msgstr "" msgid "Launch" msgstr "" msgid "Show application window" msgstr "" msgid "Launch application" msgstr "" msgid "Launch Again" msgstr "" msgid "Launch another instance of this application" msgstr "" msgid "Close" msgstr "" msgid "Attempt to close all application windows" msgstr "" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "" msgid "Perform command" msgstr "" msgid "(Empty Text)" msgstr "" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "“%(text)s”" msgstr[1] "(%(num)d lines) “%(text)s”" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "" #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "" #, python-format msgid "Directory source %s" msgstr "" msgid "Home Folder" msgstr "" msgid "Catalog Index" msgstr "" msgid "An index of all available sources" msgstr "" msgid "Root catalog" msgstr "" msgid "Please Configure Plugin" msgstr "" #, python-format msgid "Plugin %s is not configured" msgstr "" #, python-format msgid "Invalid user credentials for %s" msgstr "" msgid "Applications" msgstr "" msgid "All applications and preferences" msgstr "" msgid "Applications for Desktop Environment" msgstr "" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "" msgid "Open with any application" msgstr "" msgid "Set default application to open this file type" msgstr "" msgid "Reset Associations" msgstr "" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "" msgid "Allow browsing inside compressed archive files" msgstr "" #, python-format msgid "Content of %s" msgstr "" msgid "Archive Manager" msgstr "" msgid "Use Archive Manager actions" msgstr "" msgid "Compressed archive type for 'Create Archive In'" msgstr "Compressed archive type for ‘Create Archive In’" msgid "Extract Here" msgstr "" msgid "Extract compressed archive" msgstr "" msgid "Create Archive" msgstr "" msgid "Create a compressed archive from folder" msgstr "" msgid "Create Archive In..." msgstr "" #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "" msgid "Audacious" msgstr "" msgid "Control Audacious playback and playlist" msgstr "" msgid "Include songs in top level" msgstr "" msgid "Enqueue" msgstr "" msgid "Add track to the Audacious play queue" msgstr "" msgid "Dequeue" msgstr "" msgid "Remove track from the Audacious play queue" msgstr "" msgid "Play" msgstr "" msgid "Jump to track in Audacious" msgstr "" msgid "Resume playback in Audacious" msgstr "" msgid "Pause" msgstr "" msgid "Pause playback in Audacious" msgstr "" msgid "Next" msgstr "" msgid "Jump to next track in Audacious" msgstr "" msgid "Previous" msgstr "" msgid "Jump to previous track in Audacious" msgstr "" msgid "Clear Queue" msgstr "" msgid "Clear the Audacious play queue" msgstr "" msgid "Shuffle" msgstr "" msgid "Toggle shuffle in Audacious" msgstr "" msgid "Repeat" msgstr "" msgid "Toggle repeat in Audacious" msgstr "" msgid "Show Playing" msgstr "" msgid "Tell which song is currently playing" msgstr "" msgid "Playlist" msgstr "" msgid "Calculator" msgstr "" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "" #, fuzzy msgid "Clipboards" msgstr "Clipboard “%(desc)s”" msgid "Recent clipboards and clipboard proxy objects" msgstr "" msgid "Number of recent clipboards to remember" msgstr "" msgid "Include selected text in clipboard history" msgstr "" msgid "Copy selected text to primary clipboard" msgstr "" #, fuzzy msgid "Selected Text" msgstr "Selected File “%s”" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Clipboard “%(desc)s”" msgstr[1] "Clipboard with %(num)d lines “%(desc)s”" #, fuzzy msgid "Clipboard Text" msgstr "Clipboard “%(desc)s”" #, fuzzy msgid "Clipboard File" msgstr "Clipboard “%(desc)s”" #, fuzzy msgid "Clipboard Files" msgstr "Clipboard “%(desc)s”" msgid "Clear" msgstr "" msgid "Remove all recent clipboards" msgstr "" msgid "Shell Commands" msgstr "" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" msgid "Run (Get Output)" msgstr "" msgid "Run program and return its output" msgstr "" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "" msgid "Run program with object as an additional parameter" msgstr "" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "" msgid "Run program and supply text on the standard input" msgstr "" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "" msgid "Run command-line programs" msgstr "" msgid "GTK+" msgstr "" msgid "GNOME Terminal" msgstr "" msgid "XFCE Terminal" msgstr "" msgid "LXTerminal" msgstr "" msgid "X Terminal" msgstr "" msgid "Urxvt" msgstr "" msgid "Konsole" msgstr "" msgid "Save As..." msgstr "" msgid "Restart Kupfer" msgstr "" msgid "Quit" msgstr "" msgid "Quit Kupfer" msgstr "" msgid "About Kupfer" msgstr "" msgid "Show information about Kupfer authors and license" msgstr "" msgid "Kupfer Help" msgstr "" msgid "Get help with Kupfer" msgstr "" msgid "Show preferences window for Kupfer" msgstr "" msgid "Search Contents" msgstr "" msgid "Search inside this catalog" msgstr "" msgid "Copy" msgstr "" msgid "Copy to clipboard" msgstr "" msgid "Rescan" msgstr "" msgid "Force reindex of this source" msgstr "" msgid "Last Command" msgstr "" msgid "Internal Kupfer Objects" msgstr "" msgid "Last Result" msgstr "" msgid "Command Results" msgstr "" msgid "Custom Terminal" msgstr "" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "" msgid "Execute flag" msgstr "" msgid "Default Email Client" msgstr "" msgid "Compose email using the system's default mailto: handler" msgstr "" msgid "Compose Email To" msgstr "" msgid "Dictionary" msgstr "" msgid "Look up word in dictionary" msgstr "" msgid "Look Up" msgstr "" msgid "Documents" msgstr "" msgid "Recently used documents and bookmarked folders" msgstr "" msgid "Max recent document days" msgstr "" msgid "Recent Items" msgstr "" msgid "Recently used documents" msgstr "" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "" #, python-format msgid "Recently used documents for %s" msgstr "" msgid "Places" msgstr "" msgid "Bookmarked folders" msgstr "" msgid "DuckDuckGo Search" msgstr "" msgid "Search the web securely with DuckDuckGo" msgstr "" msgid "Favorites" msgstr "" msgid "Mark commonly used items and store objects for later use" msgstr "" msgid "Shelf of \"Favorite\" items" msgstr "Shelf of “Favorite” items" msgid "Add to Favorites" msgstr "" msgid "Add item to favorites shelf" msgstr "" msgid "Remove from Favorites" msgstr "" msgid "Remove item from favorites shelf" msgstr "" msgid "File Actions" msgstr "" msgid "More file actions" msgstr "" msgid "Move To..." msgstr "" msgid "Move file to new location" msgstr "" msgid "Rename To..." msgstr "" msgid "Copy To..." msgstr "" msgid "Copy file to a chosen location" msgstr "" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "" msgid "Tools to work with commands as objects" msgstr "" msgid "Select in Kupfer" msgstr "" #, fuzzy, python-format msgid "Result of %s (%s)" msgstr "Results for “%s”" msgid "Run (Take Result)" msgstr "" msgid "Take the command result as a proxy object" msgstr "" msgid "Run (Discard Result)" msgstr "" msgid "Image Tools" msgstr "" msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "" msgid "Scale..." msgstr "" msgid "Scale image to fit inside given pixel measure(s)" msgstr "" msgid "Rotate Clockwise" msgstr "" msgid "Rotate Counter-Clockwise" msgstr "" msgid "Autorotate" msgstr "" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "" msgid "Kupfer Plugins" msgstr "" msgid "Access Kupfer's plugin list in Kupfer" msgstr "" msgid "Show Information" msgstr "" msgid "Show Source Code" msgstr "" msgid "enabled" msgstr "" msgid "disabled" msgstr "" msgid "Notes" msgstr "" msgid "Gnote or Tomboy notes" msgstr "" msgid "Work with application" msgstr "" msgid "Open with notes application" msgstr "" msgid "Append to Note..." msgstr "" msgid "Add text to existing note" msgstr "" msgid "Create Note" msgstr "" msgid "Create a new note from this text" msgstr "" msgid "Get Note Search Results..." msgstr "" #, fuzzy msgid "Show search results for this query" msgstr "Show More Results For “%s”" #, python-format msgid "today, %s" msgstr "" #, python-format msgid "yesterday, %s" msgstr "" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "" msgid "Quicksilver Icons" msgstr "" msgid "Quick Image Viewer" msgstr "" msgid "View Image" msgstr "" msgid "GNU Screen" msgstr "" msgid "Active GNU Screen sessions" msgstr "" msgid "Attached" msgstr "" msgid "Detached" msgstr "" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "" msgid "Screen Sessions" msgstr "" msgid "Attach" msgstr "" msgid "Send Keys" msgstr "" msgid "Send synthetic keyboard events using xautomation" msgstr "" msgid "Paste to Foreground Window" msgstr "" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "" msgid "Send keys to foreground window" msgstr "" msgid "Type Text" msgstr "" msgid "Type the text to foreground window" msgstr "" msgid "GNOME Session Management" msgstr "" msgid "Special items and actions for GNOME environment" msgstr "" msgid "Log Out..." msgstr "" msgid "Log out or change user" msgstr "" msgid "Shut Down..." msgstr "" msgid "Shut down, restart or suspend computer" msgstr "" msgid "Lock Screen" msgstr "" msgid "Enable screensaver and lock" msgstr "" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "" msgid "Special items and actions for XFCE environment" msgstr "" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "" msgid "SSH host" msgstr "" msgid "Connect" msgstr "" msgid "Connect to SSH host" msgstr "" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "" msgid "No D-Bus connection to desktop session" msgstr "" msgid "GNOME Keyring" msgstr "" msgid "KWallet" msgstr "" msgid "Unencrypted File" msgstr "" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "Command in “%s” is not available" msgid "Document Templates" msgstr "" msgid "Create new documents from your templates" msgstr "" #, python-format msgid "%s template" msgstr "" msgid "Empty File" msgstr "" msgid "New Folder" msgstr "" msgid "Create New Document..." msgstr "" msgid "Create a new document from template" msgstr "" msgid "Create Document In..." msgstr "" msgid "Textfiles" msgstr "" msgid "Append To..." msgstr "" msgid "Append..." msgstr "" msgid "Write To..." msgstr "" msgid "Get Text Contents" msgstr "" msgid "Thunar" msgstr "" msgid "File manager Thunar actions" msgstr "" #, fuzzy msgid "Select in File Manager" msgstr "Selected File “%s”" msgid "Show Properties" msgstr "" msgid "Show information about file in file manager" msgstr "" msgid "Send To..." msgstr "" msgid "Symlink In..." msgstr "" msgid "Create a symlink to file in a chosen location" msgstr "" msgid "Empty Trash" msgstr "" msgid "Thunar Send To Objects" msgstr "" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "" msgid "Compose New Email" msgstr "" msgid "Compose a new message in Thunderbird" msgstr "" msgid "Attach in Email To..." msgstr "" msgid "Compose Email With" msgstr "" msgid "Compose a new message using the text as body" msgstr "" msgid "Thunderbird Address Book" msgstr "" msgid "Contacts from Thunderbird Address Book" msgstr "" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "" msgid "Show running tasks and allow sending signals to them" msgstr "" msgid "Sort Order" msgstr "" msgid "Commandline" msgstr "" msgid "CPU usage (descending)" msgstr "" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "" msgid "Send Signal..." msgstr "" msgid "Signals" msgstr "" msgid "Running Tasks" msgstr "" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "" msgid "Running tasks for current user" msgstr "" msgid "Trash" msgstr "" msgid "Access trash contents" msgstr "" msgid "Move to Trash" msgstr "" msgid "Move this file to trash" msgstr "" msgid "Restore" msgstr "" msgid "Move file back to original location" msgstr "" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "" msgstr[1] "" msgid "Triggers" msgstr "" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Assign global keybindings (triggers) to objects created with ‘Compose " "Command’." msgid "Add Trigger..." msgstr "" msgid "Remove Trigger" msgstr "" msgid "URL Actions" msgstr "" msgid "Download and Open" msgstr "" msgid "Download To..." msgstr "" msgid "Download URL to a chosen location" msgstr "" msgid "Wikipedia" msgstr "" msgid "Search in Wikipedia" msgstr "" msgid "Wikipedia language" msgstr "" #. TRANS: Default wikipedia language code msgid "en" msgstr "" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "" msgid "Window List" msgstr "" msgid "All windows on all workspaces" msgstr "" msgid "Activate" msgstr "" msgid "Shade" msgstr "" msgid "Unshade" msgstr "" msgid "Minimize" msgstr "" msgid "Unminimize" msgstr "" msgid "Maximize" msgstr "" msgid "Unmaximize" msgstr "" msgid "Maximize Vertically" msgstr "" msgid "Unmaximize Vertically" msgstr "" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "" msgid "Frontmost Window" msgstr "" msgid "Next Window" msgstr "" msgid "Jump to this window's workspace and focus" msgstr "" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "" msgstr[1] "" msgid "Active workspace" msgstr "" msgid "Jump to this workspace" msgstr "" msgid "Workspaces" msgstr "" msgid "Volumes and Disks" msgstr "" msgid "Mounted volumes and disks" msgstr "" #, python-format msgid "Volume mounted at %s" msgstr "" msgid "Unmount" msgstr "" msgid "Unmount finished" msgstr "" #, python-format msgid "\"%s\" was successfully unmounted" msgstr "“%s” was successfully unmounted" msgid "Unmount this volume" msgstr "" msgid "Eject" msgstr "" msgid "Unmount and eject this media" msgstr "" msgid "Show Text" msgstr "" msgid "Display text in a window" msgstr "" msgid "Large Type" msgstr "" msgid "Show Notification" msgstr "" msgid "Tracker" msgstr "" msgid "Tracker desktop search integration" msgstr "" msgid "Search in Tracker" msgstr "" msgid "Open Tracker Search Tool and search for this term" msgstr "" msgid "Get Tracker Results..." msgstr "" #, fuzzy msgid "Show Tracker results for query" msgstr "Show More Results For “%s”" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "Results for “%s”" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "" msgid "Search filesystem using locate" msgstr "" msgid "Ignore case distinctions when searching files" msgstr "" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "" msgid "Index of Firefox bookmarks" msgstr "" msgid "Firefox Keywords" msgstr "" msgid "Search the web with Firefox keywords" msgstr "" msgid "Search With..." msgstr "" msgid "Search For..." msgstr "" msgid "Search Terms" msgstr "" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Please use “%s”" msgid "Resume playback" msgstr "" #. TRANS: %s is a media player name #, python-format msgid "Next (%s)" msgstr "" msgid "Skip to next track" msgstr "" #. TRANS: %s is a media player name #, python-format msgid "Previous (%s)" msgstr "" msgid "Skip to previous track" msgstr "" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "" msgid "Access to Pidgin Contacts" msgstr "" msgid "Show offline contacts" msgstr "" msgid "Open Chat" msgstr "" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "" msgstr[1] "" msgid "Send Message..." msgstr "" msgid "Available" msgstr "" msgid "Away" msgstr "" msgid "Pidgin Contacts" msgstr "" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "" msgid "Create short aliases of long URLs" msgstr "" msgid "Error" msgstr "" msgid "Shorten With..." msgstr "" msgid "Services" msgstr "" msgid "Rhythmbox" msgstr "" msgid "Play and enqueue tracks and browse the music library" msgstr "" msgid "Include artists in top level" msgstr "" msgid "Include albums in top level" msgstr "" msgid "Play tracks in Rhythmbox" msgstr "" msgid "Add tracks to the play queue" msgstr "" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "" msgid "Albums" msgstr "" msgid "Music albums in Rhythmbox Library" msgstr "" msgid "Artists" msgstr "" msgid "Music artists in Rhythmbox Library" msgstr "" msgid "Songs" msgstr "" msgid "Songs in Rhythmbox library" msgstr "" msgid "Getting Things GNOME" msgstr "" msgid "Browse and create new tasks in GTG" msgstr "" #, python-format msgid "due: %s" msgstr "" #, python-format msgid "start: %s" msgstr "" #, python-format msgid "tags: %s" msgstr "" msgid "Open task in Getting Things GNOME!" msgstr "" msgid "Delete" msgstr "" msgid "Permanently remove this task" msgstr "" msgid "Mark Done" msgstr "" msgid "Mark this task as done" msgstr "" msgid "Dismiss" msgstr "" msgid "Mark this task as not to be done anymore" msgstr "" msgid "Create Task" msgstr "" msgid "Create new task in Getting Things GNOME" msgstr "" msgid "Devhelp" msgstr "" msgid "Search in Devhelp" msgstr "" msgid "Empathy" msgstr "" msgid "Access to Empathy Contacts" msgstr "" msgid "Busy" msgstr "" msgid "Not Available" msgstr "" msgid "Invisible" msgstr "" msgid "Offline" msgstr "" msgid "Change Global Status To..." msgstr "" msgid "Empathy Contacts" msgstr "" msgid "Empathy Account Status" msgstr "" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "" msgid "Mark Default Action" msgstr "" #, fuzzy msgid "Forget Object" msgstr "Forget About “%s”" msgid "Reset All" msgstr "" msgid "Select Quit" msgstr "" #, fuzzy msgid "Select Selected File" msgstr "Selected File “%s”" msgid "Select Selected Text" msgstr "" msgid "Show Help" msgstr "" msgid "Show Preferences" msgstr "" msgid "Switch to First Pane" msgstr "" msgid "Toggle Text Mode" msgstr "" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "No matches in %(src)s for “%(query)s”" msgid "No matches" msgstr "" #, python-format msgid "No action matches \"%s\"" msgstr "" #, python-format msgid "Assign Accelerator to \"%(action)s\"" msgstr "Assign Accelerator to “%(action)s”" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Make “%(action)s” Default for “%(object)s”" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "Forget About “%s”" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "" msgid "Show with Selection" msgstr "" #. TRANS: Plugin info fields msgid "Description" msgstr "" msgid "Author" msgstr "" msgid "Version" msgstr "" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Python module ‘%s’ is needed" msgid "Plugin could not be read due to an error:" msgstr "" msgid "Content of" msgstr "" #. TRANS: Plugin contents header msgid "Sources" msgstr "" #. TRANS: Plugin contents header msgid "Actions" msgstr "" #, python-format msgid "Using encrypted password storage: %s" msgstr "" #, python-format msgid "Using password storage: %s" msgstr "" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "" msgid "Set username and password" msgstr "" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "" msgid "Reset all shortcuts to default values?" msgstr "" msgid "Shortcut" msgstr "" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "Ulrik Sverdrup " msgid "A free software (GPLv3+) launcher" msgstr "" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Calculate expressions starting with ‘=’" #~ msgid "Packages matching \"%s\"" #~ msgstr "Packages matching “%s”" kupfer-328/po/en_GB.po000066400000000000000000000673431500175051100146240ustar00rootroot00000000000000# British English translations for the kupfer package # Copyright (C) 2009--2010 Ulrik Sverdrup # This file is distributed under the same license as the kupfer package. (GPLv3) # msgid "" msgstr "" "Project-Id-Version: kupfer \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2009-06-23 20:19+0200\n" "Last-Translator: Ulrik Sverdrup \n" "Language-Team: British English\n" "Language: \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" msgid "User credentials" msgstr "" msgid "_User:" msgstr "" msgid "_Password:" msgstr "" msgid "_Change" msgstr "" msgid "Set Keyboard Shortcut" msgstr "" msgid "Please press desired key combination" msgstr "" msgid "Keybinding could not be bound" msgstr "" msgid "Kupfer Preferences" msgstr "" msgid "Start automatically on login" msgstr "" msgid "Start" msgstr "" msgid "Show icon in notification area" msgstr "" msgid "Icon set:" msgstr "" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" msgid "Terminal emulator:" msgstr "" msgid "Desktop Environment" msgstr "" msgid "General" msgstr "" msgid "Global Keyboard Shortcuts" msgstr "" msgid "Reset" msgstr "" msgid "Browser Keyboard Shortcuts" msgstr "" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "" msgid "Keyboard" msgstr "" msgid "Plugins" msgstr "" msgid "Inclusion in Top Level Searches" msgstr "" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" msgid "Indexed Folders" msgstr "" msgid "Folders whose files are always available in the catalog." msgstr "" msgid "Catalog" msgstr "" msgid "Kupfer" msgstr "" msgid "Application Launcher" msgstr "" msgid "Convenient command and access tool for applications and documents" msgstr "" msgid "Execute in Kupfer" msgstr "" msgid "Saved Kupfer Command" msgstr "" #, python-format msgid "Could not to carry out '%s'" msgstr "Could not carry out ‘%s’" #, python-format msgid "\"%s\" produced a result" msgstr "“%s” produced a result" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "No permission to run “%s” (not executable)" #, python-format msgid "Command in \"%s\" is not available" msgstr "Command in “%s” is not available" #, python-format msgid "Keyboard relay is active for display %s" msgstr "" msgid "do not present main interface on launch" msgstr "" msgid "list available plugins" msgstr "" msgid "enable debug info" msgstr "" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "" msgid "show usage help" msgstr "" msgid "show version information" msgstr "" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "" msgid "Available plugins:" msgstr "" #, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" msgid "Type to search" msgstr "" #, fuzzy, python-format msgid "%s is empty" msgstr "The wastebasket is empty" msgid "Text" msgstr "" msgid "Run after Delay..." msgstr "" msgid "Perform command after a specified time interval" msgstr "" msgid "Multiple Objects" msgstr "" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "" msgstr[1] "" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "" msgid "unknown" msgstr "" msgid "Aim" msgstr "" msgid "Google Talk" msgstr "" msgid "ICQ" msgstr "" msgid "MSN" msgstr "" msgid "QQ" msgstr "" msgid "Yahoo" msgstr "" msgid "Skype" msgstr "" #, python-format msgid "%s does not support this operation" msgstr "" msgid "Can not be used with multiple objects" msgstr "" msgid "Open" msgstr "" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "" #, python-format msgid "Please use \"%s\"" msgstr "Please use “%s”" msgid "Set Default Application..." msgstr "" msgid "Open with default application" msgstr "" msgid "Reveal" msgstr "" msgid "Open parent folder" msgstr "" msgid "Open Terminal Here" msgstr "" msgid "Open this location in a terminal" msgstr "" msgid "Run in Terminal" msgstr "" msgid "Run (Execute)" msgstr "" msgid "Run this program in a Terminal" msgstr "" msgid "Run this program" msgstr "" msgid "Go To" msgstr "" msgid "Open URL" msgstr "" msgid "Open URL with default viewer" msgstr "" msgid "Launch" msgstr "" msgid "Show application window" msgstr "" msgid "Launch application" msgstr "" msgid "Launch Again" msgstr "" msgid "Launch another instance of this application" msgstr "" msgid "Close" msgstr "" msgid "Attempt to close all application windows" msgstr "" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "" msgid "Perform command" msgstr "" #, fuzzy msgid "(Empty Text)" msgstr "Empty the Wastebasket" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "“%(text)s”" msgstr[1] "(%(num)d lines) “%(text)s”" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "" #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "" #, python-format msgid "Directory source %s" msgstr "" msgid "Home Folder" msgstr "" msgid "Catalog Index" msgstr "" msgid "An index of all available sources" msgstr "" msgid "Root catalog" msgstr "" msgid "Please Configure Plugin" msgstr "" #, python-format msgid "Plugin %s is not configured" msgstr "" #, python-format msgid "Invalid user credentials for %s" msgstr "" msgid "Applications" msgstr "" msgid "All applications and preferences" msgstr "" msgid "Applications for Desktop Environment" msgstr "" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "" msgid "Open with any application" msgstr "" msgid "Set default application to open this file type" msgstr "" msgid "Reset Associations" msgstr "" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "" msgid "Allow browsing inside compressed archive files" msgstr "" #, python-format msgid "Content of %s" msgstr "" msgid "Archive Manager" msgstr "" msgid "Use Archive Manager actions" msgstr "" msgid "Compressed archive type for 'Create Archive In'" msgstr "Compressed archive type for ‘Create Archive In’" msgid "Extract Here" msgstr "" msgid "Extract compressed archive" msgstr "" msgid "Create Archive" msgstr "" msgid "Create a compressed archive from folder" msgstr "" msgid "Create Archive In..." msgstr "" #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "" msgid "Audacious" msgstr "" msgid "Control Audacious playback and playlist" msgstr "" msgid "Include songs in top level" msgstr "" msgid "Enqueue" msgstr "" msgid "Add track to the Audacious play queue" msgstr "" msgid "Dequeue" msgstr "" msgid "Remove track from the Audacious play queue" msgstr "" msgid "Play" msgstr "" msgid "Jump to track in Audacious" msgstr "" msgid "Resume playback in Audacious" msgstr "" msgid "Pause" msgstr "" msgid "Pause playback in Audacious" msgstr "" msgid "Next" msgstr "" msgid "Jump to next track in Audacious" msgstr "" msgid "Previous" msgstr "" msgid "Jump to previous track in Audacious" msgstr "" msgid "Clear Queue" msgstr "" msgid "Clear the Audacious play queue" msgstr "" msgid "Shuffle" msgstr "" msgid "Toggle shuffle in Audacious" msgstr "" msgid "Repeat" msgstr "" msgid "Toggle repeat in Audacious" msgstr "" msgid "Show Playing" msgstr "" msgid "Tell which song is currently playing" msgstr "" msgid "Playlist" msgstr "" msgid "Calculator" msgstr "" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "" #, fuzzy msgid "Clipboards" msgstr "Clipboard “%(desc)s”" msgid "Recent clipboards and clipboard proxy objects" msgstr "" msgid "Number of recent clipboards to remember" msgstr "" msgid "Include selected text in clipboard history" msgstr "" msgid "Copy selected text to primary clipboard" msgstr "" #, fuzzy msgid "Selected Text" msgstr "Selected File “%s”" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Clipboard “%(desc)s”" msgstr[1] "Clipboard with %(num)d lines “%(desc)s”" #, fuzzy msgid "Clipboard Text" msgstr "Clipboard “%(desc)s”" #, fuzzy msgid "Clipboard File" msgstr "Clipboard “%(desc)s”" #, fuzzy msgid "Clipboard Files" msgstr "Clipboard “%(desc)s”" msgid "Clear" msgstr "" msgid "Remove all recent clipboards" msgstr "" msgid "Shell Commands" msgstr "" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" msgid "Run (Get Output)" msgstr "" msgid "Run program and return its output" msgstr "" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "" msgid "Run program with object as an additional parameter" msgstr "" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "" msgid "Run program and supply text on the standard input" msgstr "" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "" msgid "Run command-line programs" msgstr "" msgid "GTK+" msgstr "" msgid "GNOME Terminal" msgstr "" msgid "XFCE Terminal" msgstr "" msgid "LXTerminal" msgstr "" msgid "X Terminal" msgstr "" msgid "Urxvt" msgstr "" msgid "Konsole" msgstr "" msgid "Save As..." msgstr "" msgid "Restart Kupfer" msgstr "" msgid "Quit" msgstr "" msgid "Quit Kupfer" msgstr "" msgid "About Kupfer" msgstr "" msgid "Show information about Kupfer authors and license" msgstr "" msgid "Kupfer Help" msgstr "" msgid "Get help with Kupfer" msgstr "" msgid "Show preferences window for Kupfer" msgstr "" #, fuzzy msgid "Search Contents" msgstr "Access the content of the wastebasket" msgid "Search inside this catalog" msgstr "" msgid "Copy" msgstr "" msgid "Copy to clipboard" msgstr "" msgid "Rescan" msgstr "" msgid "Force reindex of this source" msgstr "" msgid "Last Command" msgstr "" msgid "Internal Kupfer Objects" msgstr "" msgid "Last Result" msgstr "" msgid "Command Results" msgstr "" msgid "Custom Terminal" msgstr "" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "" msgid "Execute flag" msgstr "" msgid "Default Email Client" msgstr "" msgid "Compose email using the system's default mailto: handler" msgstr "" msgid "Compose Email To" msgstr "" msgid "Dictionary" msgstr "" msgid "Look up word in dictionary" msgstr "" msgid "Look Up" msgstr "" msgid "Documents" msgstr "" msgid "Recently used documents and bookmarked folders" msgstr "" msgid "Max recent document days" msgstr "" msgid "Recent Items" msgstr "" msgid "Recently used documents" msgstr "" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "" #, python-format msgid "Recently used documents for %s" msgstr "" msgid "Places" msgstr "" msgid "Bookmarked folders" msgstr "" msgid "DuckDuckGo Search" msgstr "" msgid "Search the web securely with DuckDuckGo" msgstr "" msgid "Favorites" msgstr "Favourites" msgid "Mark commonly used items and store objects for later use" msgstr "" msgid "Shelf of \"Favorite\" items" msgstr "Shelf of “Favourite” items" msgid "Add to Favorites" msgstr "Add to Favourites" msgid "Add item to favorites shelf" msgstr "Add item to favourites shelf" msgid "Remove from Favorites" msgstr "Remove from Favourites" msgid "Remove item from favorites shelf" msgstr "Remove item from favourites shelf" msgid "File Actions" msgstr "" #, fuzzy msgid "More file actions" msgstr "Move this file to the wastebasket" msgid "Move To..." msgstr "" msgid "Move file to new location" msgstr "" msgid "Rename To..." msgstr "" msgid "Copy To..." msgstr "" msgid "Copy file to a chosen location" msgstr "" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "" msgid "Tools to work with commands as objects" msgstr "" msgid "Select in Kupfer" msgstr "" #, fuzzy, python-format msgid "Result of %s (%s)" msgstr "Results for “%s”" msgid "Run (Take Result)" msgstr "" msgid "Take the command result as a proxy object" msgstr "" msgid "Run (Discard Result)" msgstr "" msgid "Image Tools" msgstr "" msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "" msgid "Scale..." msgstr "" msgid "Scale image to fit inside given pixel measure(s)" msgstr "" msgid "Rotate Clockwise" msgstr "" msgid "Rotate Counter-Clockwise" msgstr "" msgid "Autorotate" msgstr "" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "" msgid "Kupfer Plugins" msgstr "" msgid "Access Kupfer's plugin list in Kupfer" msgstr "" msgid "Show Information" msgstr "" msgid "Show Source Code" msgstr "" msgid "enabled" msgstr "" msgid "disabled" msgstr "" msgid "Notes" msgstr "" msgid "Gnote or Tomboy notes" msgstr "" msgid "Work with application" msgstr "" msgid "Open with notes application" msgstr "" msgid "Append to Note..." msgstr "" msgid "Add text to existing note" msgstr "" msgid "Create Note" msgstr "" msgid "Create a new note from this text" msgstr "" msgid "Get Note Search Results..." msgstr "" #, fuzzy msgid "Show search results for this query" msgstr "Show More Results For “%s”" #, python-format msgid "today, %s" msgstr "" #, python-format msgid "yesterday, %s" msgstr "" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "" msgid "Quicksilver Icons" msgstr "" msgid "Quick Image Viewer" msgstr "" msgid "View Image" msgstr "" msgid "GNU Screen" msgstr "" msgid "Active GNU Screen sessions" msgstr "" msgid "Attached" msgstr "" msgid "Detached" msgstr "" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "" msgid "Screen Sessions" msgstr "" msgid "Attach" msgstr "" msgid "Send Keys" msgstr "" msgid "Send synthetic keyboard events using xautomation" msgstr "" msgid "Paste to Foreground Window" msgstr "" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "" msgid "Send keys to foreground window" msgstr "" msgid "Type Text" msgstr "" msgid "Type the text to foreground window" msgstr "" msgid "GNOME Session Management" msgstr "" msgid "Special items and actions for GNOME environment" msgstr "" msgid "Log Out..." msgstr "" msgid "Log out or change user" msgstr "" msgid "Shut Down..." msgstr "" msgid "Shut down, restart or suspend computer" msgstr "" msgid "Lock Screen" msgstr "" msgid "Enable screensaver and lock" msgstr "" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "" msgid "Special items and actions for XFCE environment" msgstr "" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "" msgid "SSH host" msgstr "" msgid "Connect" msgstr "" msgid "Connect to SSH host" msgstr "" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "" msgid "No D-Bus connection to desktop session" msgstr "" msgid "GNOME Keyring" msgstr "" msgid "KWallet" msgstr "" msgid "Unencrypted File" msgstr "" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "Command in “%s” is not available" msgid "Document Templates" msgstr "" msgid "Create new documents from your templates" msgstr "" #, python-format msgid "%s template" msgstr "" msgid "Empty File" msgstr "" msgid "New Folder" msgstr "" msgid "Create New Document..." msgstr "" msgid "Create a new document from template" msgstr "" msgid "Create Document In..." msgstr "" msgid "Textfiles" msgstr "" msgid "Append To..." msgstr "" msgid "Append..." msgstr "" msgid "Write To..." msgstr "" msgid "Get Text Contents" msgstr "" msgid "Thunar" msgstr "" msgid "File manager Thunar actions" msgstr "" #, fuzzy msgid "Select in File Manager" msgstr "Selected File “%s”" msgid "Show Properties" msgstr "" msgid "Show information about file in file manager" msgstr "" msgid "Send To..." msgstr "" msgid "Symlink In..." msgstr "" msgid "Create a symlink to file in a chosen location" msgstr "" msgid "Empty Trash" msgstr "Empty the Wastebasket" msgid "Thunar Send To Objects" msgstr "" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "" msgid "Compose New Email" msgstr "" msgid "Compose a new message in Thunderbird" msgstr "" msgid "Attach in Email To..." msgstr "" msgid "Compose Email With" msgstr "" msgid "Compose a new message using the text as body" msgstr "" msgid "Thunderbird Address Book" msgstr "" msgid "Contacts from Thunderbird Address Book" msgstr "" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "" msgid "Show running tasks and allow sending signals to them" msgstr "" msgid "Sort Order" msgstr "" msgid "Commandline" msgstr "" msgid "CPU usage (descending)" msgstr "" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "" msgid "Send Signal..." msgstr "" msgid "Signals" msgstr "" msgid "Running Tasks" msgstr "" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "" msgid "Running tasks for current user" msgstr "" msgid "Trash" msgstr "Wastebasket" msgid "Access trash contents" msgstr "Access the content of the wastebasket" msgid "Move to Trash" msgstr "Move to Wastebasket" msgid "Move this file to trash" msgstr "Move this file to the wastebasket" msgid "Restore" msgstr "" msgid "Move file back to original location" msgstr "" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "The wastebasket is empty" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "The wastebasket contains one file" msgstr[1] "The wastebasket contains %(num)s files" msgid "Triggers" msgstr "" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Assign global keybindings (triggers) to objects created with ‘Compose " "Command’." msgid "Add Trigger..." msgstr "" msgid "Remove Trigger" msgstr "" msgid "URL Actions" msgstr "" msgid "Download and Open" msgstr "" msgid "Download To..." msgstr "" msgid "Download URL to a chosen location" msgstr "" msgid "Wikipedia" msgstr "" msgid "Search in Wikipedia" msgstr "" msgid "Wikipedia language" msgstr "" #. TRANS: Default wikipedia language code msgid "en" msgstr "" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "" msgid "Window List" msgstr "" msgid "All windows on all workspaces" msgstr "" msgid "Activate" msgstr "" msgid "Shade" msgstr "" msgid "Unshade" msgstr "" msgid "Minimize" msgstr "Minimise" msgid "Unminimize" msgstr "Unminimise" msgid "Maximize" msgstr "Maximise" msgid "Unmaximize" msgstr "Unmaximise" msgid "Maximize Vertically" msgstr "Maximise Vertically" msgid "Unmaximize Vertically" msgstr "Unmaximise Vertically" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "" msgid "Frontmost Window" msgstr "" msgid "Next Window" msgstr "" msgid "Jump to this window's workspace and focus" msgstr "" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "" msgstr[1] "" msgid "Active workspace" msgstr "" msgid "Jump to this workspace" msgstr "" msgid "Workspaces" msgstr "" msgid "Volumes and Disks" msgstr "" msgid "Mounted volumes and disks" msgstr "" #, python-format msgid "Volume mounted at %s" msgstr "" msgid "Unmount" msgstr "" msgid "Unmount this volume" msgstr "" msgid "Eject" msgstr "" msgid "Unmount and eject this media" msgstr "" msgid "Show Text" msgstr "" msgid "Display text in a window" msgstr "" msgid "Large Type" msgstr "" msgid "Show Notification" msgstr "" msgid "Tracker" msgstr "" msgid "Tracker desktop search integration" msgstr "" msgid "Search in Tracker" msgstr "" msgid "Open Tracker Search Tool and search for this term" msgstr "" msgid "Get Tracker Results..." msgstr "" #, fuzzy msgid "Show Tracker results for query" msgstr "Show More Results For “%s”" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "Results for “%s”" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "" msgid "Search filesystem using locate" msgstr "" msgid "Ignore case distinctions when searching files" msgstr "" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "" msgid "Index of Firefox bookmarks" msgstr "" msgid "Firefox Keywords" msgstr "" msgid "Search the web with Firefox keywords" msgstr "" msgid "Search With..." msgstr "" msgid "Search For..." msgstr "" #, fuzzy msgid "Search Terms" msgstr "Access the content of the wastebasket" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Please use “%s”" msgid "Resume playback" msgstr "" #. TRANS: %s is a media player name #, python-format msgid "Next (%s)" msgstr "" msgid "Skip to next track" msgstr "" #. TRANS: %s is a media player name #, python-format msgid "Previous (%s)" msgstr "" msgid "Skip to previous track" msgstr "" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "" #, fuzzy msgid "Access to Pidgin Contacts" msgstr "Access the content of the wastebasket" msgid "Show offline contacts" msgstr "" msgid "Open Chat" msgstr "" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "" msgstr[1] "" msgid "Send Message..." msgstr "" msgid "Available" msgstr "" msgid "Away" msgstr "" msgid "Pidgin Contacts" msgstr "" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "" msgid "Create short aliases of long URLs" msgstr "" msgid "Error" msgstr "" msgid "Shorten With..." msgstr "" msgid "Services" msgstr "" msgid "Rhythmbox" msgstr "" msgid "Play and enqueue tracks and browse the music library" msgstr "" msgid "Include artists in top level" msgstr "" msgid "Include albums in top level" msgstr "" msgid "Play tracks in Rhythmbox" msgstr "" msgid "Add tracks to the play queue" msgstr "" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "" msgid "Albums" msgstr "" msgid "Music albums in Rhythmbox Library" msgstr "" msgid "Artists" msgstr "" msgid "Music artists in Rhythmbox Library" msgstr "" msgid "Songs" msgstr "" msgid "Songs in Rhythmbox library" msgstr "" msgid "Getting Things GNOME" msgstr "" msgid "Browse and create new tasks in GTG" msgstr "" #, python-format msgid "due: %s" msgstr "" #, python-format msgid "start: %s" msgstr "" #, python-format msgid "tags: %s" msgstr "" msgid "Open task in Getting Things GNOME!" msgstr "" msgid "Delete" msgstr "" msgid "Permanently remove this task" msgstr "" msgid "Mark Done" msgstr "" msgid "Mark this task as done" msgstr "" msgid "Dismiss" msgstr "" msgid "Mark this task as not to be done anymore" msgstr "" msgid "Create Task" msgstr "" msgid "Create new task in Getting Things GNOME" msgstr "" msgid "Devhelp" msgstr "" msgid "Search in Devhelp" msgstr "" msgid "Empathy" msgstr "" #, fuzzy msgid "Access to Empathy Contacts" msgstr "Access the content of the wastebasket" msgid "Busy" msgstr "" msgid "Not Available" msgstr "" msgid "Invisible" msgstr "" msgid "Offline" msgstr "" msgid "Change Global Status To..." msgstr "" msgid "Empathy Contacts" msgstr "" msgid "Empathy Account Status" msgstr "" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "" msgid "Mark Default Action" msgstr "" #, fuzzy msgid "Forget Object" msgstr "Forget About “%s”" msgid "Reset All" msgstr "" msgid "Select Quit" msgstr "" #, fuzzy msgid "Select Selected File" msgstr "Selected File “%s”" msgid "Select Selected Text" msgstr "" msgid "Show Help" msgstr "" msgid "Show Preferences" msgstr "" msgid "Switch to First Pane" msgstr "" msgid "Toggle Text Mode" msgstr "" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "No matches in %(src)s for “%(query)s”" msgid "No matches" msgstr "" #, python-format msgid "No action matches \"%s\"" msgstr "" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Make “%(action)s” Default for “%(object)s”" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "Forget About “%s”" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "" msgid "Show with Selection" msgstr "" #. TRANS: Plugin info fields msgid "Description" msgstr "" msgid "Author" msgstr "" msgid "Version" msgstr "" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Python module ‘%s’ is needed" msgid "Plugin could not be read due to an error:" msgstr "" msgid "Content of" msgstr "" #. TRANS: Plugin contents header msgid "Sources" msgstr "" #. TRANS: Plugin contents header msgid "Actions" msgstr "" #, python-format msgid "Using encrypted password storage: %s" msgstr "" #, python-format msgid "Using password storage: %s" msgstr "" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "" msgid "Set username and password" msgstr "" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "" msgid "Reset all shortcuts to default values?" msgstr "" msgid "Shortcut" msgstr "" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "Ulrik Sverdrup " msgid "A free software (GPLv3+) launcher" msgstr "" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Calculate expressions starting with ‘=’" #~ msgid "Packages matching \"%s\"" #~ msgstr "Packages matching “%s”" kupfer-328/po/es.po000066400000000000000000002067341500175051100142600ustar00rootroot00000000000000# Spanish translations for the kupfer package # Traduccion al Espanol para el paquete kupfer # Copyright (C) 2009 Ulrik Sverdrup # This file is distributed under the same license as the kupfer package. (GPLv3) # Ulrik Sverdrup , 2009. # Jorge González , 2009, 2010. # Daniel Mustieles , 2011, 2012. # Leonardo Masuero , 2020. # msgid "" msgstr "" "Project-Id-Version: kupfer.master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2012-12-31 11:35+0100\n" "Last-Translator: Daniel Mustieles \n" "Language-Team: Español; Castellano \n" "Language: \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: Gtranslator 2.91.5\n" msgid "User credentials" msgstr "Credenciales del usuario" msgid "_User:" msgstr "_Usuario:" msgid "_Password:" msgstr "Contrase_ña:" msgid "_Change" msgstr "_Cambiar" msgid "Set Keyboard Shortcut" msgstr "Establecer atajo de teclado" msgid "Please press desired key combination" msgstr "Pulse la combinación de teclas deseada" msgid "Keybinding could not be bound" msgstr "No se puede vincular la combinación de teclas" msgid "Kupfer Preferences" msgstr "Preferencias de Kupfer" msgid "Start automatically on login" msgstr "Iniciar automáticamente al iniciar sesión" msgid "Start" msgstr "Inicio" msgid "Show icon in notification area" msgstr "Mostrar icono en el área de notificación" msgid "Icon set:" msgstr "Conjunto de iconos:" msgid "Large Icon Size:" msgstr "Tamaño de los iconos grandes:" msgid "Small Icon Size:" msgstr "Tamaño de los iconos pequeños" msgid "Terminal emulator:" msgstr "Emulador de la terminal:" msgid "Desktop Environment" msgstr "Entorno de Escritorio" msgid "General" msgstr "General" msgid "Global Keyboard Shortcuts" msgstr "Atajos de teclado globales" msgid "Reset" msgstr "Restablecer" msgid "Browser Keyboard Shortcuts" msgstr "Atajos de teclado del examinador" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "Usar comandos de una sola tecla (espacio, /, punto, coma, etc.)" msgid "Action accelerators use Alt" msgstr "Los aceleradores de acción usan Alt" msgid "Action accelerators use Ctrl" msgstr "Los aceleradores de acción usan Ctrl" msgid "Keyboard" msgstr "Teclado" msgid "Plugins" msgstr "Complementos" msgid "Inclusion in Top Level Searches" msgstr "Incluir en búsquedas de nivel superior" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "Las fuentes marcadas tienen sus objetos incluidos en los niveles superiores " "de búsqueda.\n" "Los contenidos de una fuente desmarcada sólo están disponibles encontrando " "su subcatálogo." msgid "Indexed Folders" msgstr "Carpetas indexadas" msgid "Folders whose files are always available in the catalog." msgstr "Carpetas cuyos archivos están siempre disponibles en el catálogo." msgid "Catalog" msgstr "Catálogo" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Lanzador de aplicaciones" msgid "Convenient command and access tool for applications and documents" msgstr "Herramienta para acceso y manejo de aplicaciones y documentos" msgid "Execute in Kupfer" msgstr "Ejecutar en Kupfer" msgid "Saved Kupfer Command" msgstr "Comando de Kupfer guardado" #, python-format msgid "Could not to carry out '%s'" msgstr "No se pudo ejecutar «%s»" #, python-format msgid "\"%s\" produced a result" msgstr "«%s» genera un resultado" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "No se tienen permisos para ejecutar «%s» (no es ejecutable)" #, python-format msgid "Command in \"%s\" is not available" msgstr "El comando «%s» no está disponible" #, python-format msgid "Keyboard relay is active for display %s" msgstr "La transmisión de teclado está activa para la pantalla %s" msgid "do not present main interface on launch" msgstr "no mostrar interfaz principal al iniciar" msgid "list available plugins" msgstr "lista de complementos disponibles" msgid "enable debug info" msgstr "activar mensajes de depuración" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "ejecutar plugin-helper" msgid "show usage help" msgstr "mostrar ayuda de uso" msgid "show version information" msgstr "mostrar información de la versión" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Uso: kupfer [OPCIONES | ARCHIVO ...]" msgid "Available plugins:" msgstr "Complementos disponibles:" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "Teclear para buscar" #, python-format msgid "%s is empty" msgstr "%s está vacío" msgid "Text" msgstr "Texto" msgid "Run after Delay..." msgstr "Ejecutar después de un retraso…" msgid "Perform command after a specified time interval" msgstr "Ejecutar un comando después de un intervalo de tiempo especificado" msgid "Multiple Objects" msgstr "Objetos múltiples" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s objeto" msgstr[1] "%s objetos" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "desconocido" msgid "Aim" msgstr "Aim" msgid "Google Talk" msgstr "Google Talk" msgid "ICQ" msgstr "ICQ" msgid "MSN" msgstr "MSN" msgid "QQ" msgstr "QQ" msgid "Yahoo" msgstr "Yahoo" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "%s no soporta esta operación" msgid "Can not be used with multiple objects" msgstr "No se puede usar con varios objetos" msgid "Open" msgstr "Abrir" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "No existe una aplicación predeterminada para %(file)s (%(type)s)" #, python-format msgid "Please use \"%s\"" msgstr "Por favor, use «%s»" msgid "Set Default Application..." msgstr "Establecer aplicación predeterminada…" msgid "Open with default application" msgstr "Abrir con la aplicación predeterminada" msgid "Reveal" msgstr "Mostrar" msgid "Open parent folder" msgstr "Abrir carpeta padre" msgid "Open Terminal Here" msgstr "Abrir terminal aquí" msgid "Open this location in a terminal" msgstr "Abrir esta ubicación en una terminal" msgid "Run in Terminal" msgstr "Ejecutar en un terminal" msgid "Run (Execute)" msgstr "Ejecutar" msgid "Run this program in a Terminal" msgstr "Ejecutar este programa en una terminal" msgid "Run this program" msgstr "Ejecutar este programa" msgid "Go To" msgstr "Ir a" msgid "Open URL" msgstr "Abrir URL" msgid "Open URL with default viewer" msgstr "Abrir URL con el visor predeterminado" msgid "Launch" msgstr "Lanzar" msgid "Show application window" msgstr "Mostrar la ventana de la aplicación" msgid "Launch application" msgstr "Iniciar aplicación" msgid "Launch Again" msgstr "Iniciar de nuevo" msgid "Launch another instance of this application" msgstr "Iniciar otra instancia de esta aplicación" msgid "Close" msgstr "Cerrar" msgid "Attempt to close all application windows" msgstr "Intentar cerrar todas las ventanas de la aplicación" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Ejecutar" msgid "Perform command" msgstr "Ejecutar comando" msgid "(Empty Text)" msgstr "(Texto vacío)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "\"%(text)s\"" msgstr[1] "(%(num)d líneas) \"%(text)s\"" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s et. al." #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Fuente recursiva de %(dir)s, (%(levels)d niveles)" #, python-format msgid "Directory source %s" msgstr "Carpeta inicial %s" msgid "Home Folder" msgstr "Carpeta personal" msgid "Catalog Index" msgstr "Índice del Catálogo" msgid "An index of all available sources" msgstr "Un índice de todas las fuentes disponibles" msgid "Root catalog" msgstr "Catálogo Raíz" msgid "Please Configure Plugin" msgstr "Configurar el complemento" #, python-format msgid "Plugin %s is not configured" msgstr "El complemento %s no está configurado" #, python-format msgid "Invalid user credentials for %s" msgstr "Las credenciales de usuario no son válidas para %s" msgid "Applications" msgstr "Aplicaciones" msgid "All applications and preferences" msgstr "Todas las aplicaciones y preferencias" msgid "Applications for Desktop Environment" msgstr "Aplicaciones para el entorno de escritorio" msgid "Use Desktop Filter" msgstr "Usar filtro de escritorio" msgid "Open With..." msgstr "Abrir con…" msgid "Open with any application" msgstr "Abrir con una aplicación" msgid "Set default application to open this file type" msgstr "" "Establecer la aplicación predeterminada para abrir este tipo de archivo" #, fuzzy msgid "Reset Associations" msgstr "Acciones de URL" msgid "Reset program associations for files of this type." msgstr "Restablecer las asociaciones de programas para este tipo de archivos." msgid "Deep Archives" msgstr "Archivadores profundos" msgid "Allow browsing inside compressed archive files" msgstr "Permitir examinar dentro de archivadores comprimidos" #, python-format msgid "Content of %s" msgstr "Contenido de %s" msgid "Archive Manager" msgstr "Gestor de archivadores" msgid "Use Archive Manager actions" msgstr "Usar acciones del Gestor de archivadores" msgid "Compressed archive type for 'Create Archive In'" msgstr "Tipo de archivo comprimido para «Crear archivador en»" msgid "Extract Here" msgstr "Extraer aquí" msgid "Extract compressed archive" msgstr "Extraer archivador comprimido" msgid "Create Archive" msgstr "Crear archivador" msgid "Create a compressed archive from folder" msgstr "Crear un archivador comprimido desde carpeta" msgid "Create Archive In..." msgstr "Crear archivador en…" #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Archivador" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "Controlar la reproducción y listas de reproducción de Audacious" msgid "Include songs in top level" msgstr "Incluir canciones en nivel superior" msgid "Enqueue" msgstr "Encolar" msgid "Add track to the Audacious play queue" msgstr "Añadir pistas a la cola de reproducción de Audacious" msgid "Dequeue" msgstr "Dequeue" msgid "Remove track from the Audacious play queue" msgstr "Quitar pistas de la cola de reproducción de Audacious" msgid "Play" msgstr "Reproducir" msgid "Jump to track in Audacious" msgstr "Saltar a la pista siguiente en Audacious" msgid "Resume playback in Audacious" msgstr "Continuar reproducción en Audacious" msgid "Pause" msgstr "Pausar" msgid "Pause playback in Audacious" msgstr "Pausar reproducción en Audacious" msgid "Next" msgstr "Siguiente" msgid "Jump to next track in Audacious" msgstr "Saltar a la pista siguiente en Audacious" msgid "Previous" msgstr "Anterior" msgid "Jump to previous track in Audacious" msgstr "Saltar a la pista anterior en Audacious" msgid "Clear Queue" msgstr "Limpiar la cola" msgid "Clear the Audacious play queue" msgstr "Limpiar la cola de reproducción de Audacious" msgid "Shuffle" msgstr "Aleatorio" msgid "Toggle shuffle in Audacious" msgstr "Conmutar la reproducción aleatoria en Audacious" msgid "Repeat" msgstr "Repetir" msgid "Toggle repeat in Audacious" msgstr "Conmutar la repetición en Audacious" msgid "Show Playing" msgstr "Mostrar en reproducción" msgid "Tell which song is currently playing" msgstr "Mostrar qué canción se esta reproduciendo" msgid "Playlist" msgstr "Lista de reproducción" msgid "Calculator" msgstr "Calculadora" msgid "Calculate mathematical expressions" msgstr "Calcular expresiones matematicas" msgid "Calculate" msgstr "Calcular" msgid "Clipboards" msgstr "Portapapeles" msgid "Recent clipboards and clipboard proxy objects" msgstr "Portapapeles recientes y objetos proxy del portapapeles" msgid "Number of recent clipboards to remember" msgstr "Numero de portapapeles recientes que recordar" msgid "Include selected text in clipboard history" msgstr "Incluir el texto seleccionado en el histórico del portapapeles" msgid "Copy selected text to primary clipboard" msgstr "Copiar el texto seleccionado al portapapeles primario" msgid "Selected Text" msgstr "Texto seleccionado" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Portapapeles \"%(desc)s\"" msgstr[1] "Portapapeles con %(num)d líneas «%(desc)s»" msgid "Clipboard Text" msgstr "Texto del portapapeles" msgid "Clipboard File" msgstr "Archivo del portapapeles" msgid "Clipboard Files" msgstr "Archivos del portapapeles" msgid "Clear" msgstr "Limpiar" msgid "Remove all recent clipboards" msgstr "Limpiar todos los elementos recientes en el portapapeles" msgid "Shell Commands" msgstr "Comandos de consola" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Ejecutar programas de línea de comandos. Las acciones marcadas con el " "símbolo «%s» se ejecutan en una subterminal." msgid "Run (Get Output)" msgstr "Ejecutar (obtener salida)" msgid "Run program and return its output" msgstr "Ejecutar un programa y obtener su salida" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "Enviar a un comando…" msgid "Run program with object as an additional parameter" msgstr "Ejecutar programa con un objeto como un parámetro adicional" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "Redirigir a un comando…" msgid "Run program and supply text on the standard input" msgstr "Ejecutar programa y proporcionar texto en la salida extándar" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "Filtrar a través de un comando…" msgid "Run command-line programs" msgstr "Ejecutar programas de línea de comandos" msgid "GTK+" msgstr "GTK+" msgid "GNOME Terminal" msgstr "Terminal de GNOME" msgid "XFCE Terminal" msgstr "Terminal de XFCE" msgid "LXTerminal" msgstr "LXTerminal" msgid "X Terminal" msgstr "Terminal X" msgid "Urxvt" msgstr "Urxvt" msgid "Konsole" msgstr "Konsole" msgid "Save As..." msgstr "Guardar como…" #, fuzzy msgid "Restart Kupfer" msgstr "Reiniciar servicio" msgid "Quit" msgstr "Salir" msgid "Quit Kupfer" msgstr "Salir de Kupfer" msgid "About Kupfer" msgstr "Acerca de Kupfer" msgid "Show information about Kupfer authors and license" msgstr "Mostrar información de los autores y licencia de Kupfer" msgid "Kupfer Help" msgstr "Ayuda de Kupfer" msgid "Get help with Kupfer" msgstr "Obtener ayuda sobre Kupfer" msgid "Show preferences window for Kupfer" msgstr "Mostrar la ventana de preferencias de Kupfer" msgid "Search Contents" msgstr "Buscar contenido" msgid "Search inside this catalog" msgstr "Buscar dentro del catálogo" msgid "Copy" msgstr "Copiar" msgid "Copy to clipboard" msgstr "Copiar al portapapeles" msgid "Rescan" msgstr "Rescanear" msgid "Force reindex of this source" msgstr "Forzar reindexación de esta fuente" msgid "Last Command" msgstr "Último comando" msgid "Internal Kupfer Objects" msgstr "Objetos internos de Kupfer" msgid "Last Result" msgstr "Último resultado" msgid "Command Results" msgstr "Resultados del comando" msgid "Custom Terminal" msgstr "Terminal personalizada" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" "Configurar un emulador de terminal personalizado.\n" "\n" "El complemento agrega otra alternativa de terminal (selecciónela en la página principal)." msgid "Command" msgstr "Comando" msgid "Execute flag" msgstr "Ejecutar opción" msgid "Default Email Client" msgstr "Cliente de correo-e predeterminado" msgid "Compose email using the system's default mailto: handler" msgstr "" "Redactar un correo-e usando el manejador predeterminado del sistema para " "«mailto:»" #, fuzzy msgid "Compose Email To" msgstr "Redactar un correo nuevo" msgid "Dictionary" msgstr "Diccionario" msgid "Look up word in dictionary" msgstr "Buscar palabra en el diccionario" msgid "Look Up" msgstr "Buscar" msgid "Documents" msgstr "Documentos" msgid "Recently used documents and bookmarked folders" msgstr "Documentos recientemente usados y carpetas en marcadores" msgid "Max recent document days" msgstr "Días máximos de documentos recientes" msgid "Recent Items" msgstr "Elementos recientes" msgid "Recently used documents" msgstr "Documentos usados recientemente" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "Documentos %s" #, python-format msgid "Recently used documents for %s" msgstr "Documentos recientes para %s" msgid "Places" msgstr "Lugares" msgid "Bookmarked folders" msgstr "Carpetas marcadas" msgid "DuckDuckGo Search" msgstr "Busqueda DuckDuckGo" msgid "Search the web securely with DuckDuckGo" msgstr "Buscar en la web con seguridad usando DuckDuckGo" msgid "Favorites" msgstr "Favoritos" msgid "Mark commonly used items and store objects for later use" msgstr "" "Marcar elementos usados comúnmente y almacenar objetos para un uso posterior" msgid "Shelf of \"Favorite\" items" msgstr "Cajón de elementos favoritos" msgid "Add to Favorites" msgstr "Agregar a favoritos" msgid "Add item to favorites shelf" msgstr "Añadir elementos al cajón de favoritos" msgid "Remove from Favorites" msgstr "Quitar de favoritos" msgid "Remove item from favorites shelf" msgstr "Quitar elemento del cajón de favoritos" msgid "File Actions" msgstr "Acciones sobre archivos" msgid "More file actions" msgstr "Más acciones sobre archivos" msgid "Move To..." msgstr "Mover a…" msgid "Move file to new location" msgstr "Mover archivo a ubicación nueva" msgid "Rename To..." msgstr "Renombrar a…" msgid "Copy To..." msgstr "Copiar a…" msgid "Copy file to a chosen location" msgstr "Copiar archivo a una ubicación elegida" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "Glob" msgid "Select objects using '*' and '?' as wildcards." msgstr "Seleccionar objetos usando '*' y '?' como comodines." msgid "Higher-order Actions" msgstr "Acciones de nivel más alto" msgid "Tools to work with commands as objects" msgstr "Herramientas para trabajar como comandos como objetos" msgid "Select in Kupfer" msgstr "Seleccionar en Kupfer" #, python-format msgid "Result of %s (%s)" msgstr "Resultado de %s (%s)" msgid "Run (Take Result)" msgstr "Ejecutar (obtener el resultado)" msgid "Take the command result as a proxy object" msgstr "Tomar el resultado del comando como un objeto del proxy" msgid "Run (Discard Result)" msgstr "Ejecutar (descartar resultado)" msgid "Image Tools" msgstr "Herramientas de imagen" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Herramientas de transformación de imagen" msgid "Scale..." msgstr "Escalar…" msgid "Scale image to fit inside given pixel measure(s)" msgstr "Escalar imagen para ajustar dentro de las medidas dadas" msgid "Rotate Clockwise" msgstr "Rotar en el sentido de las agujas del reloj" msgid "Rotate Counter-Clockwise" msgstr "Rotar en sentido contrario a las agujas de reloj" msgid "Autorotate" msgstr "Rotar automáticamente" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "Rotar JPEG (en el sitio) respecto a su metadatos EXIF" msgid "Kupfer Plugins" msgstr "Complementos de Kupfer" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Acceder a la lista de complementos de Kupfer" msgid "Show Information" msgstr "Mostrar información" msgid "Show Source Code" msgstr "Mostrar el código fuente" msgid "enabled" msgstr "activado" msgid "disabled" msgstr "desactivado" msgid "Notes" msgstr "Notas" msgid "Gnote or Tomboy notes" msgstr "Notas de GNote o Tomboy" msgid "Work with application" msgstr "Trabajar con aplicación" msgid "Open with notes application" msgstr "Abrir con la aplicación de notas" msgid "Append to Note..." msgstr "Añadir a nota…" msgid "Add text to existing note" msgstr "Añadir texto a una nota existente" msgid "Create Note" msgstr "Crear nota" msgid "Create a new note from this text" msgstr "Crear una nota nueva desde este texto" msgid "Get Note Search Results..." msgstr "Obtener los resultados de búsqueda de notas…" msgid "Show search results for this query" msgstr "Mostrar los resultados de búsqueda para esta consulta" #, python-format msgid "today, %s" msgstr "hoy, %s" #, python-format msgid "yesterday, %s" msgstr "ayer, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Última actualización %s" msgid "Quicksilver Icons" msgstr "Iconos Quicksilver" msgid "Quick Image Viewer" msgstr "Visor rápido de imágenes" msgid "View Image" msgstr "Ver imagen" msgid "GNU Screen" msgstr "GNU Screen" msgid "Active GNU Screen sessions" msgstr "Sesiones activas de GNU Screen" msgid "Attached" msgstr "Adjunto" msgid "Detached" msgstr "No adjunto" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "sesión %(status)s %(pid)s) creada %(time)s" msgid "Screen Sessions" msgstr "Sesiones de Screen" msgid "Attach" msgstr "Adjuntar" msgid "Send Keys" msgstr "Enviar teclas" msgid "Send synthetic keyboard events using xautomation" msgstr "Enviar eventos sintéticos de teclado usando xautomation" msgid "Paste to Foreground Window" msgstr "Pegar en la ventana de primer plano" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "Copiar al portapapeles y enviar Ctrl+V a la ventana en primer plano" msgid "Send keys to foreground window" msgstr "Enviar teclas a la ventana en primer plano" msgid "Type Text" msgstr "Escribir texto" msgid "Type the text to foreground window" msgstr "Escribir el texto en la ventana en primer plano" msgid "GNOME Session Management" msgstr "Gestión de la sesión de GNOME" msgid "Special items and actions for GNOME environment" msgstr "Elementos y acciones especiales para el entorno GNOME" msgid "Log Out..." msgstr "Cerrar sesión…" msgid "Log out or change user" msgstr "Cerrar sesión o cambiar de usuario" msgid "Shut Down..." msgstr "Apagar…" msgid "Shut down, restart or suspend computer" msgstr "Apagar, reiniciar o suspender el equipo" msgid "Lock Screen" msgstr "Bloquear pantalla" msgid "Enable screensaver and lock" msgstr "Iniciar salvapantallas y bloquear" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "Gestión de la sesión de XFCE" msgid "Special items and actions for XFCE environment" msgstr "Elementos y acciones especiales para el entorno XFCE" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "Servidores SSH" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "Añadir los servidores SSH encontrados en ~/.ssh/config." msgid "SSH host" msgstr "Servidor SSH" msgid "Connect" msgstr "Conectar" msgid "Connect to SSH host" msgstr "Conectar al servidor SSH" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "Servidores SSH especificados en ~/.ssh/config" msgid "No D-Bus connection to desktop session" msgstr "Sin conexión de D-Bus con la sesión del escritorio" msgid "GNOME Keyring" msgstr "Depósito de claves de GNOME" msgid "KWallet" msgstr "KWallet" msgid "Unencrypted File" msgstr "Archivo no cifrado" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "El comando «%s» no está disponible" msgid "Document Templates" msgstr "Plantillas de documentos" msgid "Create new documents from your templates" msgstr "Crear documentos nuevos desde sus plantillas" #, python-format msgid "%s template" msgstr "Plantilla de %s" msgid "Empty File" msgstr "Archivo vacío" msgid "New Folder" msgstr "Carpeta nueva" msgid "Create New Document..." msgstr "Crear un documento nuevo…" msgid "Create a new document from template" msgstr "Crear un documento nuevo desde una plantilla" msgid "Create Document In..." msgstr "Crear documento en…" msgid "Textfiles" msgstr "Archivos de texto" msgid "Append To..." msgstr "Añadir a…" msgid "Append..." msgstr "Añadir…" msgid "Write To..." msgstr "Escribir a…" msgid "Get Text Contents" msgstr "Obtener el contenido del texto" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "Acciones Thunar del gestor de archivos" msgid "Select in File Manager" msgstr "Seleccionar en el gestor de archivos" msgid "Show Properties" msgstr "Mostrar las propiedades" msgid "Show information about file in file manager" msgstr "Mostrar información acerca del archivo en el gestor de archivos" msgid "Send To..." msgstr "Enviar a…" msgid "Symlink In..." msgstr "Crear enlace simbólico en…" msgid "Create a symlink to file in a chosen location" msgstr "Crear un enlace simbólico a un archivo en la ubicación elegida" msgid "Empty Trash" msgstr "Vacía la papelera" msgid "Thunar Send To Objects" msgstr "Objetos enviar a de Thunar" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Contactos y acciones de Thunderbird/Icedove" msgid "Compose New Email" msgstr "Redactar un correo electrónico nuevo" msgid "Compose a new message in Thunderbird" msgstr "Escribir un mensaje nuevo en Thunderbird" #, fuzzy msgid "Attach in Email To..." msgstr "Enviar un correo-e a…" #, fuzzy msgid "Compose Email With" msgstr "Redactar un correo nuevo" #, fuzzy msgid "Compose a new message using the text as body" msgstr "Escribir un mensaje nuevo en Thunderbird" msgid "Thunderbird Address Book" msgstr "Libreta de direcciones de Thunderbird" msgid "Contacts from Thunderbird Address Book" msgstr "Contactos de la libreta de direcciones de Thunderbird" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Top" msgid "Show running tasks and allow sending signals to them" msgstr "Mostrar las tareas en ejecución y permitir mandarlas señales" msgid "Sort Order" msgstr "Ordenación" msgid "Commandline" msgstr "Línea de comandos" msgid "CPU usage (descending)" msgstr "Uso de CPU (descendiente)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Uso de memoria (descendiente)" msgid "Send Signal..." msgstr "Enviar señal…" msgid "Signals" msgstr "Señales" msgid "Running Tasks" msgstr "Tareas en ejecución" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% tiempo: %(time)s" msgid "Running tasks for current user" msgstr "Tareas en ejecución para el usuario actual" msgid "Trash" msgstr "Papelera" msgid "Access trash contents" msgstr "Acceder al contenido de la papelera" msgid "Move to Trash" msgstr "Mover a la papelera" msgid "Move this file to trash" msgstr "Mover este archivo a la papelera" msgid "Restore" msgstr "Restaurar" msgid "Move file back to original location" msgstr "Mover archivo a ubicación original" msgid "" "Could not delete files:\n" " " msgstr "" "No se pudieron eliminar los archivos:\n" " " msgid "Trash is empty" msgstr "La papelera está vacía" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "La papelera contiene un archivo" msgstr[1] "La papelera contiene %(num)s archivos" msgid "Triggers" msgstr "Disparadores" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Asignar combinaciones de teclas globales (disparadores) a objetos creados " "con «Editar comando»." msgid "Add Trigger..." msgstr "Añadir disparados…" msgid "Remove Trigger" msgstr "Quitar disparador" msgid "URL Actions" msgstr "Acciones de URL" msgid "Download and Open" msgstr "Descargar y abrir" msgid "Download To..." msgstr "Descargar en…" msgid "Download URL to a chosen location" msgstr "Descargar URL en una ubicación determinada" msgid "Wikipedia" msgstr "Wikipedia" msgid "Search in Wikipedia" msgstr "Buscar en Wikipedia" msgid "Wikipedia language" msgstr "Idioma de Wikipedia" #. TRANS: Default wikipedia language code msgid "en" msgstr "es" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Buscar este término en %s.wikipedia.org" msgid "Window List" msgstr "Lista de ventanas" msgid "All windows on all workspaces" msgstr "Todas las ventanas en todas las áreas de trabajo" msgid "Activate" msgstr "Activar" msgid "Shade" msgstr "Enrollar" msgid "Unshade" msgstr "Desenrollar" msgid "Minimize" msgstr "Minimizar" msgid "Unminimize" msgstr "Desminimizar" msgid "Maximize" msgstr "Maximizar" msgid "Unmaximize" msgstr "Desmaximizar" msgid "Maximize Vertically" msgstr "Maximizar verticamente" msgid "Unmaximize Vertically" msgstr "Desmaximizar verticalmente" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Ventana en %(wkspc)s" msgid "Frontmost Window" msgstr "Ventana de primer plano" msgid "Next Window" msgstr "Siguiente ventana" msgid "Jump to this window's workspace and focus" msgstr "Saltar al área de trabajo de esta ventana y dar foco" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "%d ventana" msgstr[1] "%d ventanas" msgid "Active workspace" msgstr "Área de trabajo activa" msgid "Jump to this workspace" msgstr "Saltar a este área de trabajo" msgid "Workspaces" msgstr "Áreas de trabajo" msgid "Volumes and Disks" msgstr "Volúmenes y discos" msgid "Mounted volumes and disks" msgstr "Volúmenes montados y discos" #, python-format msgid "Volume mounted at %s" msgstr "Volumen montado en %s" msgid "Unmount" msgstr "Desmontar" msgid "Unmount this volume" msgstr "Desmontar este volumen" msgid "Eject" msgstr "Expulsar" msgid "Unmount and eject this media" msgstr "Desmontar y expulsar el medio" msgid "Show Text" msgstr "Mostrar texto" msgid "Display text in a window" msgstr "Mostrar el texto en una ventana" msgid "Large Type" msgstr "Tipo grande" msgid "Show Notification" msgstr "Mostrar notificación" msgid "Tracker" msgstr "Tracker" msgid "Tracker desktop search integration" msgstr "Integración con la búsqueda de escritorio Tracker" msgid "Search in Tracker" msgstr "Buscar en Tracker" msgid "Open Tracker Search Tool and search for this term" msgstr "Abrir herramienta de búsqueda de Tracker" msgid "Get Tracker Results..." msgstr "Obtener resultados de Tracker…" msgid "Show Tracker results for query" msgstr "Mostrar resultados de Tracker para la consulta" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "Resultados para «%s»" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "Localizar archivos" msgid "Search filesystem using locate" msgstr "Buscar en el sistema de archivos usando locate" msgid "Ignore case distinctions when searching files" msgstr "Ignorar capitalización al buscar archivos" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Marcadores de Firefox" msgid "Index of Firefox bookmarks" msgstr "Índice de marcadores de Firefox" #, fuzzy msgid "Firefox Keywords" msgstr "Marcadores de Firefox" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "Buscar en la web con motores de búsqueda OpenSearch" msgid "Search With..." msgstr "Buscar con…" msgid "Search For..." msgstr "Buscar…" #, fuzzy msgid "Search Terms" msgstr "Motores de búsqueda" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Use «%s»" #, fuzzy msgid "Resume playback" msgstr "Continuar reproducción en Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Siguiente" #, fuzzy msgid "Skip to next track" msgstr "Saltar a la pista siguiente en Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Anterior" #, fuzzy msgid "Skip to previous track" msgstr "Saltar a la pista anterior en Audacious" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "Detener (%s)" msgid "Stop playback" msgstr "Detener la reproducción" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "Acceder a los contactos de Pidgin" msgid "Show offline contacts" msgstr "Mostrar contactos desconectados" msgid "Open Chat" msgstr "Abrir chat" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d carácter)" msgstr[1] "%s (%d carácteres)" msgid "Send Message..." msgstr "Enviar mensaje…" msgid "Available" msgstr "Disponible" msgid "Away" msgstr "Ausente" msgid "Pidgin Contacts" msgstr "Contactos de Pidgin" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Acortar enlaces" msgid "Create short aliases of long URLs" msgstr "Crear alias cortos para URL largas" msgid "Error" msgstr "Error" msgid "Shorten With..." msgstr "Acortar con…" msgid "Services" msgstr "Servicios" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "Reproducir, encolar pistas y navegar la biblioteca de música" msgid "Include artists in top level" msgstr "Incluir artistas en nivel superior" msgid "Include albums in top level" msgstr "Incluir álbum en nivel superior" msgid "Play tracks in Rhythmbox" msgstr "Reproducir pistas en Rhythmbox" msgid "Add tracks to the play queue" msgstr "Añade pistas a la cola de reproducción" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "por %(artist)s de %(album)s" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "por %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Pistas por %s" msgid "Albums" msgstr "Álbumes" msgid "Music albums in Rhythmbox Library" msgstr "Álbumes en la biblioteca de Rhythmbox" msgid "Artists" msgstr "Artistas" msgid "Music artists in Rhythmbox Library" msgstr "Artistas en la biblioteca de Rhythmbox" msgid "Songs" msgstr "Canciones" msgid "Songs in Rhythmbox library" msgstr "Canciones en la biblioteca de Rhythmbox" msgid "Getting Things GNOME" msgstr "Getting Things GNOME" msgid "Browse and create new tasks in GTG" msgstr "Examinar y crear tareas nuevas en GTG" #, python-format msgid "due: %s" msgstr "vence: %s" #, python-format msgid "start: %s" msgstr "inicio: %s" #, python-format msgid "tags: %s" msgstr "etiquetas: %s" msgid "Open task in Getting Things GNOME!" msgstr "Abrir tarea en Getting Things GNOME" msgid "Delete" msgstr "Eliminar" msgid "Permanently remove this task" msgstr "Quitar permanentemente esta tarea" msgid "Mark Done" msgstr "Marcar como realizada" msgid "Mark this task as done" msgstr "Marcar esta tarea como realizada" msgid "Dismiss" msgstr "Descartar" msgid "Mark this task as not to be done anymore" msgstr "Marcar esta tarea como para no realizar" msgid "Create Task" msgstr "Crear tarea" msgid "Create new task in Getting Things GNOME" msgstr "Crear una tarea nueva en Getting Things GNOME" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "Buscar en Devhelp" msgid "Empathy" msgstr "Empathy" msgid "Access to Empathy Contacts" msgstr "Acceder a los contactos de Empathy" msgid "Busy" msgstr "Ocupado" msgid "Not Available" msgstr "No disponible" msgid "Invisible" msgstr "Invisible" msgid "Offline" msgstr "Desconectado" msgid "Change Global Status To..." msgstr "Cambiar estado general a…" msgid "Empathy Contacts" msgstr "Contactos de Empathy" msgid "Empathy Account Status" msgstr "Estado de las cuentas de Empathy" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Activación alternativa" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Truco de la coma" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Componer comando" msgid "Mark Default Action" msgstr "Marcar la acción predeterminada" msgid "Forget Object" msgstr "Olvidar objeto" msgid "Reset All" msgstr "Restablecer todo" msgid "Select Quit" msgstr "Seleccionar Salir" msgid "Select Selected File" msgstr "Seleccionar Archivo seleccionado" msgid "Select Selected Text" msgstr "Seleccionar Texto seleccionado" msgid "Show Help" msgstr "Mostrar ayuda" msgid "Show Preferences" msgstr "Mostrar las preferencias" msgid "Switch to First Pane" msgstr "Cambiar al primer panel" msgid "Toggle Text Mode" msgstr "Cambiar a Modo Texto" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "No hay coincidencias en %(src)s para «%(query)s»" msgid "No matches" msgstr "No hay coincidencias" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "No hay coincidencias" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Hacer «%(action)s» predeterminada para «%(object)s»" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "Olvidarse de «%s»" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Mostrar la interfaz principal" msgid "Show with Selection" msgstr "Mostrar con selección" #. TRANS: Plugin info fields msgid "Description" msgstr "Descripción" msgid "Author" msgstr "Autor" msgid "Version" msgstr "Versión" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Se necesita el módulo de Python «%s»" msgid "Plugin could not be read due to an error:" msgstr "No se puede leer el complemento debido al error:" msgid "Content of" msgstr "Contenido de" #. TRANS: Plugin contents header msgid "Sources" msgstr "Fuentes" #. TRANS: Plugin contents header msgid "Actions" msgstr "Acciones" #, python-format msgid "Using encrypted password storage: %s" msgstr "Usando contraseña de almacenamiento cifrada: %s" #, python-format msgid "Using password storage: %s" msgstr "Usando contraseña de almacenamiento: %s" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Configuración" msgid "Set username and password" msgstr "Establecer el nombre de usuario y la contraseña" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Elegir una carpeta" msgid "Reset all shortcuts to default values?" msgstr "" "¿Quiere restablecer todos los atajos de teclado a los valores " "predeterminados?" msgid "Shortcut" msgstr "Atajo" msgid "Open a new number in WhatsApp Web\n" "\n" "The number format must respect:\n" "Country Code + Area Code + Number\n" "\n" "Example for a New York number: 12129999999\n" "Country Code: 1\n" "Area Code: 212\n" "Number: 9999999\n" "\n" "WhatsApp Web will open in the browser.\n" "\n" "For help visit https://faq.whatsapp.com/general/chats/how-to-use-click-to-chat/\n" "\n" msgstr "El formato del número debe respetar:\n" "Codigo País + Codigo de Area + Número\n" "\n" "Ejemplo para un número de New York: 12129382661\n" "Codigo País: 1\n" "Codigo de Area: 212\n" "Número: 9382661\n" "\n" "Se abrirá WhatsApp Web en el navegador.\n" "\n" "Si necesita ayuda visite: https://faq.whatsapp.com/general/chats/how-to-use-click-to-chat/\n" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "" "Leonardo Masuero , 2019\n" "Daniel Mustieles , 2011\n" "Jorge González , 2009-2011\n" "Leandro Leites \n" "Jesús Barbero Rodríguez " msgid "A free software (GPLv3+) launcher" msgstr "Un lanzador de aplicaciones libre (GPLv3+)" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Este programa es software libre: usted puede redistribuirlo y/o " "modificarlo \n" "bajo los términos de la Licencia Pública General GNU publicada \n" "por la Fundación para el Software Libre, ya sea la versión 3 \n" "de la Licencia, o (a su elección) cualquier versión posterior.\n" "\n" "Este programa se distribuye con la esperanza de que sea útil, pero \n" "SIN GARANTÍA ALGUNA; ni siquiera la garantía implícita \n" "MERCANTIL o de APTITUD PARA UN PROPÓSITO DETERMINADO. \n" "Consulte los detalles de la Licencia Pública General GNU para obtener \n" "una información más detallada. \n" "\n" "Debería haber recibido una copia de la Licencia Pública General GNU \n" "junto a este programa. \n" "En caso contrario, consulte .\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "No se pudo encontrar un Kupfer en ejecución" #~ msgid "Compose Email" #~ msgstr "Redactar un correo nuevo" #~ msgid "Send in Email To..." #~ msgstr "Enviar un correo-e a…" #~ msgid "Type to search %s" #~ msgstr "Teclear para buscar %s" #~ msgid "No action" #~ msgstr "Sin acción" #~ msgid "GNOME Terminal Profiles" #~ msgstr "Perfiles de la terminal de GNOME" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Lanzar los perfiles de la terminal de GNOME" #~ msgid "Multihead Support" #~ msgstr "Soporte multipantalla" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Calcular expresión empezando por «=»" #~ msgid "Epiphany Bookmarks" #~ msgstr "Marcadores de Epiphany" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Índice de marcadores de Epiphany" #~ msgid "Include visited sites" #~ msgstr "Incluir sitios visitados" #~ msgid "Firefox tag" #~ msgstr "Etiqueta de Firefox" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Continuar reproducción en Rhythmbox" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Pausar reproducción en Rhythmbox" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Saltar a la pista siguiente en Rhythmbox" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Saltar a la pista anterior en Rhythmbox" #~ msgid "Search the Web" #~ msgstr "Buscar en la web" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Documentos recientemente utilizados en Abiword" #~ msgid "Abiword Recent Items" #~ msgstr "Documentos recientes de Abiword" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "Interfaz con el gestor de paquetes APT" #~ msgid "Installation method" #~ msgstr "Método de instalación" #~ msgid "Show Package Information" #~ msgstr "Mostrar información del paquete" #~ msgid "Install" #~ msgstr "Instalar" #~ msgid "Install package using the configured method" #~ msgstr "Instalar el paquete usando el método configurado" #~ msgid "Packages matching \"%s\"" #~ msgstr "Paquetes que coinciden con «%s»" #~ msgid "Search Package Name..." #~ msgstr "Buscar paquete por nombre…" #~ msgid "Ascii & Unicode Icon Set" #~ msgstr "Conjunto de iconos ASCII y Unicode" #~ msgid "" #~ "Provides the Ascii and Unicode icon sets that use letters and symbols to " #~ "produce icons for the objects found in Kupfer." #~ msgstr "" #~ "Proporcionar el conjunto de iconos ASCII y Unicode que usan letras y " #~ "símbolos para producir iconos para los objetos encontrados en Kupfer." #~ msgid "Ascii" #~ msgstr "ASCII" #~ msgid "Unicode" #~ msgstr "Unicode" #~ msgid "Chromium Bookmarks" #~ msgstr "Marcadores de Chromium" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Índice de marcadores de Chromium" #~ msgid "Claws Mail" #~ msgstr "Claws Mail" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Contactos y acciones de Claws Mail" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Redactar un correo electrónico nuevo con Claws Mail" #~ msgid "Receive All Email" #~ msgstr "Recibir todos los correos" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "Recibir correo nuevo para todas las cuentas de Claws Mail" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Redactar mensaje nuevo con Claws Mail y adjuntar el archivo" #~ msgid "Claws Mail Address Book" #~ msgstr "Libreta de direcciones de Claws Mail" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Contactos desde la libreta de direcciones de Claws Mail" #~ msgid "Configure a custom terminal emulator" #~ msgstr "Configurar un emulador de terminal personalizada" #~ msgid "Custom Theme" #~ msgstr "Tema personalizado" #~ msgid "Use a custom color theme" #~ msgstr "Usar un tema de color personalizado" #~ msgid "Theme:" #~ msgstr "Tema:" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Contactos de Evolution" #~ msgid "Compose a new message in Evolution" #~ msgstr "Escribir un mensaje nuevo en Evolution" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Redactar mensaje nuevo con Evolution y adjuntar el archivo" #~ msgid "Evolution Address Book" #~ msgstr "Libreta de direcciones de Evolution" #~ msgid "Filezilla" #~ msgstr "Filezilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Mostrar sitios y gestionar direcciones FTP con Filezilla" #~ msgid "Open Site with Filezilla" #~ msgstr "Abrir un sitio con Filezilla" #~ msgid "Filezilla Sites" #~ msgstr "Sitios Filezilla" #~ msgid "Sites from Filezilla" #~ msgstr "Sitios de Filezilla" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Acceder a los contactos de Gajim" #~ msgid "Free for Chat" #~ msgstr "Disponible para conversar" #~ msgid "Gajim Contacts" #~ msgstr "Contactos de Gajim" #~ msgid "Gajim Account Status" #~ msgstr "Estado de las cuentas de Gajim" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Cargar contactos y redactar un correo-e nuevo en GMail" #~ msgid "Load contacts' pictures" #~ msgstr "Cargar las imágenes de los contactos" #~ msgid "Load additional information" #~ msgstr "Cargar información adicional" #~ msgid "Work email" #~ msgstr "Correo-e del trabajo" #~ msgid "Home email" #~ msgstr "Correo-e personal" #~ msgid "Other email" #~ msgstr "Otro correo-e" #~ msgid "Work address" #~ msgstr "Dirección del trabajo" #~ msgid "Home address" #~ msgstr "Dirección personal" #~ msgid "Other address" #~ msgstr "Otra dirección" #~ msgid "Car phone" #~ msgstr "Teléfono del coche" #~ msgid "Fax" #~ msgstr "Fax" #~ msgid "Home phone" #~ msgstr "Teléfono personal" #~ msgid "Home fax" #~ msgstr "Fax personal" #~ msgid "Internal phone" #~ msgstr "Teléfono interno" #~ msgid "Mobile" #~ msgstr "Móvil" #~ msgid "Other" #~ msgstr "Otro" #~ msgid "VOIP" #~ msgstr "VOIP" #~ msgid "Work phone" #~ msgstr "Teléfono del trabajo" #~ msgid "Work fax" #~ msgstr "Fax del trabajo" #~ msgid "Compose Email in Gmail" #~ msgstr "Redactar un correo-e en GMail" #~ msgid "Open web browser and compose new email in Gmail" #~ msgstr "Abrir el navegador web y redactar un correo-e nuevo en GMail" #~ msgid "Edit Contact in Gmail" #~ msgstr "Editar contacto en Gmail" #~ msgid "Open web browser and edit contact in Gmail" #~ msgstr "Abrir el navegador web y editar contacto en GMail" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Contactos de los servicios de Google (GMail)" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Mostrar álbumes y subir archivos a Picasa" #~ msgid "Users to show: (,-separated)" #~ msgstr "Usuarios para mostrar: (, -separados)" #~ msgid "Load user and album icons" #~ msgstr "Cargar los iconos de usuario y de álbumes" #~ msgid "Uploading Pictures" #~ msgstr "Subiendo imágenes" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Subiendo imágenes al álbum en Picasa Web" #~ msgid "Creating album:" #~ msgstr "Creando álbum:" #~ msgid "Album created by Kupfer" #~ msgstr "Álbum creado por Kupfer" #~ msgid "File:" #~ msgstr "Archivo:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "Un álbum" #~ msgstr[1] "%(num)d álbumes" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "una foto" #~ msgstr[1] "%(num)s fotos" #~ msgid "Upload to Picasa Album..." #~ msgstr "Subir a un álbum en Picasa…" #~ msgid "Upload files to Picasa album" #~ msgstr "Subir archivos al álbum de Picasa" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Subir a Picasa como un álbum nuevo" #~ msgid "Create album from selected local directory" #~ msgstr "Crear un álbum desde la carpeta local seleccionada" #~ msgid "Picasa Albums" #~ msgstr "Álbumes de Picasa" #~ msgid "User albums in Picasa" #~ msgstr "Álbumes de usuario en Picasa" #~ msgid "Google Search" #~ msgstr "Google Search" #~ msgid "Search Google with results shown directly" #~ msgstr "Buscar en Google mostrando directamente los resultados" #~ msgid "Show More Results For \"%s\"" #~ msgstr "Mostrar más resultados para «%s»" #~ msgid "%s total found" #~ msgstr "%s encontradas en total" #~ msgid "Gwibber" #~ msgstr "Gwibber" #~ msgid "" #~ "Microblogging with Gwibber. Allows sending and receiving messages from " #~ "social networks like Twitter, Identi.ca etc. Requires the package " #~ "'gwibber-service'." #~ msgstr "" #~ "Microblogging con Gwibber. Permite enviar y recibir mensajes de redes " #~ "sociales como Twitter, Identi.ca etc. Requiere el paquete «gwibber-" #~ "service»." #~ msgid "Maximum number of messages to show" #~ msgstr "Número máximo de mensajes que mostrar" #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s en %(service)s" #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s en %(where)s" #~ msgid "Send Message" #~ msgstr "Enviar mensaje" #~ msgid "Send message to all Gwibber accounts" #~ msgstr "Enviar mensaje a todas las cuentas de Gwibber" #~ msgid "Send Message To..." #~ msgstr "Enviar mensaje a…" #~ msgid "Send message to a Gwibber account" #~ msgstr "Enviar mensaje a una cuenta de Gwibber" #~ msgid "Send message to selected Gwibber account" #~ msgstr "Enviar mensaje a la cuenta de Gwibber seleccionada" #~ msgid "Reply..." #~ msgstr "Responder…" #~ msgid "Delete Message" #~ msgstr "Eliminar mensaje" #~ msgid "Send Private Message..." #~ msgstr "Enviar mensaje privado…" #~ msgid "Send direct message to user" #~ msgstr "Enviar mensaje directo al usuario" #~ msgid "Retweet" #~ msgstr "Replicar" #~ msgid "Retweet To..." #~ msgstr "Replicar a…" #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Replicar mensaje a todas las cuentas de Gwibber" #~ msgid "Retweet message to a Gwibber account" #~ msgstr "Replicar mensaje a una cuenta de Gwibber" #~ msgid "Open in Browser" #~ msgstr "Abrir en el navegador" #~ msgid "Open message in default web browser" #~ msgstr "Abrir mensaje en el navegador web predeterminado" #~ msgid "Gwibber Accounts" #~ msgstr "Cuentas de Gwibber" #~ msgid "Accounts configured in Gwibber" #~ msgstr "Cuentas configuradas en Gwibber" #~ msgid "Gwibber Messages" #~ msgstr "Mensajes de Gwibber" #~ msgid "Recent messages received by Gwibber" #~ msgstr "Mensajes recientes recibidos por Gwibber" #~ msgid "Gwibber Messages for %s" #~ msgstr "Mensajes de Gwibber para %s" #~ msgid "Gwibber Streams" #~ msgstr "Flujos de Gwibber" #~ msgid "Streams configured in Gwibber" #~ msgstr "Flujos configurados en Gwibber" #~ msgid "Gwibber Messages in %s" #~ msgstr "Mensajes de Gwibber en %s" #~ msgid "Gwibber (Simple)" #~ msgstr "Gwibber (simple)" #~ msgid "Send updates via the microblogging client Gwibber" #~ msgstr "" #~ "Enviar actualizaciones a través del cliente de microblogging Gwibber" #~ msgid "Send Update" #~ msgstr "Enviar actualización" #~ msgid "Unable to activate Gwibber service" #~ msgstr "No se pudo activar el servicio Gwibber" #~ msgid "OpenOffice / LibreOffice" #~ msgstr "OpenOffice / LibreOffice" #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Documentos usados recientemente en OpenOffice/LibreOffice" #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "Elementos recientes de OpenOffice/LibreOffice" #~ msgid "Opera Mail" #~ msgstr "Opera Mail" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Contactos y acciones de Opera Mail" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Redactar un correo electrónico nuevo con Opera Mail" #~ msgid "Opera Mail Contacts" #~ msgstr "Contactos de Opera Mail" #~ msgid "Contacts from Opera Mail" #~ msgstr "Contactos de Opera Mail" #~ msgid "Opera Bookmarks" #~ msgstr "Marcadores de Opera" #~ msgid "Index of Opera bookmarks" #~ msgstr "Índice de marcadores de Opera" #~ msgid "PuTTY Sessions" #~ msgstr "Sesiones PuTTY" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Acceso rápido a sesiones de PuTTY" #~ msgid "Start Session" #~ msgstr "Iniciar sesión" #~ msgid "reStructuredText" #~ msgstr "TextoRestructurado" #~ msgid "Render reStructuredText and show the result" #~ msgstr "Renderizar TextoRestructurado y mostrar el resultado" #~ msgid "View as HTML Document" #~ msgstr "Ver como documento HTML" #~ msgid "System Services" #~ msgstr "Servicios del sistema" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "" #~ "Iniciar, parar o reiniciar servicios del sistema a través de init scripts" #~ msgid "Sudo-like Command" #~ msgstr "Comandos del tipo sudo" #~ msgid "Start Service" #~ msgstr "Iniciar servicio" #~ msgid "Stop Service" #~ msgstr "Parar servicio" #~ msgid "%s Service" #~ msgstr "Servicio %s" #~ msgid "Show QRCode" #~ msgstr "Mostrar el código QR" #~ msgid "Display text as QRCode in a window" #~ msgstr "Mostrar texto como código QR en una ventana" #~ msgid "Access to Skype contacts" #~ msgstr "Acceder a los contactos de Skype" #~ msgid "Skype Me" #~ msgstr "Eskypéame" #~ msgid "Logged Out" #~ msgstr "Cerró la sesión" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Llamar" #~ msgid "Place a call to contact" #~ msgstr "Llamar al contacto" #~ msgid "Skype Contacts" #~ msgstr "Contactos de Skype" #~ msgid "Skype Statuses" #~ msgstr "Estados de Skype" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Volúmenes en el histórico de TrueCrypt" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "Volumen TrueCrypt: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Montar volumen" #~ msgid "Mount in Truecrypt" #~ msgstr "Montar en TrueCrypt" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Intentar montar el archivo como un volumen TrueCrypt" #~ msgid "Dismount All Volumes" #~ msgstr "Desmontar todos los volúmenes" #~ msgid "TrueCrypt Volumes" #~ msgstr "Volúmenes TrueCrypt" #~ msgid "Terminal Server Client" #~ msgstr "Cliente de Terminal Server" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Sesión guardada en el cliente de Terminal Server" #~ msgid "TSClient sessions" #~ msgstr "Sesiones de TSClient" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Sesiones guardadas en el cliente de Terminal Server" #~ msgid "Vim" #~ msgstr "Vim" #~ msgid "Recently used documents in Vim" #~ msgstr "Documentos recientemente utilizados en Vim" #~ msgid "Vim Recent Documents" #~ msgstr "Documentos usados recientemente en VIM" #~ msgid "Close (Save All)" #~ msgstr "Cerrar (guardar todo)" #~ msgid "Send..." #~ msgstr "Enviar…" #~ msgid "Send ex command" #~ msgstr "Enviar comando «ex»" #~ msgid "Insert in Vim..." #~ msgstr "Insertar en Vim…" #~ msgid "Active Vim Sessions" #~ msgstr "Sesiones activas de Vim" #~ msgid "Vim Session %s" #~ msgstr "Sesión %s de Vim" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Acciones y marcadores de Vinagre" #~ msgid "Start Vinagre Session" #~ msgstr "Iniciar sesión de Vinagre" #~ msgid "Vinagre Bookmarks" #~ msgstr "Marcadores de Vinagre" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "Controla máquinas virtuales de VirtualBox. Soporta Sun VirtualBox y la " #~ "versión Open Source." #~ msgid "Force use CLI interface" #~ msgstr "Forzar el uso de la interfaz CLI" #~ msgid "Power On" #~ msgstr "Encender" #~ msgid "Power On Headless" #~ msgstr "Encender «Headless»" #~ msgid "Send Power Off Signal" #~ msgstr "Enviar señal de apagado" #~ msgid "Reboot" #~ msgstr "Reiniciar" #~ msgid "Resume" #~ msgstr "Restaurar" #~ msgid "Save State" #~ msgstr "Guardar estado" #~ msgid "Power Off" #~ msgstr "Apagar" #~ msgid "VirtualBox Machines" #~ msgstr "Máquinas de VirtualBox" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "Acceder a páginas guardadas en Zim - Una wiki de escritorio" #~ msgid "Page names start with :colon" #~ msgstr "Nombre de páginas empezando por dos puntos" #~ msgid "Default page name for quick notes" #~ msgstr "Nombre de página predeterminado para notas rápidas" #~ msgid "Note %x %X" #~ msgstr "Nota %x %X" #~ msgid "" #~ "Strftime tags can be used: %H - hour, %M - minutes, etc\n" #~ "Please check python documentation for details.\n" #~ "NOTE: comma will be replaced by _" #~ msgstr "" #~ "Se puede usar etiquetas de «strftime»: %H: hora, %M: minutos, etc\n" #~ "Consulte la documentación de Python para obtener más detalles.\n" #~ "Nota: las comas se reemplazarán por «_»" #~ msgid "Default namespace for quick notes" #~ msgstr "Espacio de nombres predeterminado para notas rápidas" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Página de Zim desde el libro de notas «%s»" #~ msgid "Create Zim Page" #~ msgstr "Crear página de Zim" #~ msgid "Create page in default notebook" #~ msgstr "Crear página en el libro de notas predeterminado" #~ msgid "Create Zim Page In..." #~ msgstr "Crear página de Zim en…" #~ msgid "Insert QuickNote into Zim" #~ msgstr "Insertar nota rápida en Zim" #~ msgid "Quick note selected text into Zim notebook" #~ msgstr "Nota rápida seleccionada en el cuaderno de notas Zim" #~ msgid "Create Subpage..." #~ msgstr "Crear subpágina…" #~ msgid "Zim Notebooks" #~ msgstr "Libro de notas Zim" #~ msgid "Zim Pages" #~ msgstr "Páginas de Zim" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Páginas almacenadas en el libro de notas Zim" #~ msgid "Selected File" #~ msgstr "Archivo seleccionado" #~ msgid "" #~ "Provides current nautilus selection, using Kupfer's Nautilus Extension" #~ msgstr "" #~ "Proporciona la selección actual de Nautilus usando la extensión Kupfer " #~ "Nautilus" #~ msgid "Selected File \"%s\"" #~ msgstr "Archivo seleccionado «%s»" #~ msgid "Selected Files" #~ msgstr "Archivos seleccionados" #~ msgid "Tracker 0.6" #~ msgstr "Tracker 0.6" #~ msgid "Tracker tags" #~ msgstr "Etiquetas de Tracker" #~ msgid "Tracker Tags" #~ msgstr "Etiquetas de Tracker" #~ msgid "Browse Tracker's tags" #~ msgstr "Examinar las etiquetas de Tracker" #~ msgid "Tag %s" #~ msgstr "Etiqueta %s" #~ msgid "Objects tagged %s with Tracker" #~ msgstr "Objetos con etiqueta %s en Tracker" #~ msgid "Add Tag..." #~ msgstr "Añadir etiqueta…" #~ msgid "Add tracker tag to file" #~ msgstr "Añadir etiqueta Tracker al archivo" #~ msgid "Remove Tag..." #~ msgstr "Quitar etiqueta…" #~ msgid "Remove tracker tag from file" #~ msgstr "Quitar etiqueta Tracker del archivo" #~ msgid "Translate text with Google Translate" #~ msgstr "Traducir texto con Google" #~ msgid "Google Translate connection timed out" #~ msgstr "Expiró el tiempo de conexión con Google Translate" #~ msgid "Error connecting to Google Translate" #~ msgstr "Error al contactar con Google" #~ msgid "Translate To..." #~ msgstr "Traducir a…" #~ msgid "Translate into %s" #~ msgstr "Traducir a %s" #~ msgid "Languages" #~ msgstr "Idiomas" #~ msgid "Show translated page in browser" #~ msgstr "Mostrar la página traducida en un navegador" #~ msgid "Show Translation To..." #~ msgstr "Mostrar la traducción a…" #~ msgid "Show translation in browser" #~ msgstr "Mostrar la traducción en un navegador" #~ msgid "run keyboard shortcut relay service on this display" #~ msgstr "" #~ "ejecutar el servicio de transmisión de atajos de teclado en esta pantalla" #~ msgid "Selected Text \"%s\"" #~ msgstr "Texto seleccionado «%s»" #~ msgid "Recent clipboards" #~ msgstr "Portapapeles recientes" #~ msgid "Include recent selections" #~ msgstr "Incluir selecciones recientes" #~ msgid "Text Matches" #~ msgstr "Coincidencias del texto" #~ msgid "noun" #~ msgstr "sustantivo" #~ msgid "verb" #~ msgstr "verbo" #~ msgid "adjective" #~ msgstr "adjetivo" #~ msgid "Directories" #~ msgstr "Directorios" #~ msgid "Icon Set" #~ msgstr "Conjunto de iconos" #~ msgid "Interface" #~ msgstr "Interfaz" #~ msgid "" #~ "Objects Exported\n" #~ "from Plugins" #~ msgstr "" #~ "Objetos exportados\n" #~ "desde complementos" #~ msgid "Terminal" #~ msgstr "Terminal" #~ msgid "Command '%s' not found" #~ msgstr "No se encontró el comando «%s»" #~ msgid "Keys not yet implemented: %s" #~ msgstr "Teclas aún no implementadas: %s" #~ msgid "Tracker 0.8" #~ msgstr "Tracker 0.8" #~ msgid "Hide Kupfer when focus is lost" #~ msgstr "Ocultar Kupfer cuando pierda el foco" #~ msgid "Preferred terminal" #~ msgstr "Terminal preferida" #~ msgid "" #~ "The preferred terminal emulator. It's used to launch the SSH sessions." #~ msgstr "" #~ "El emulador de terminal preferido. Se usa para lanzar las sesiones SSH." #~ msgid "" #~ "The flag which makes the terminal execute everything following it inside " #~ "the terminal (e.g. '-x' for gnome-terminal and terminal, '-e' for konsole " #~ "and urxvt)." #~ msgstr "" #~ "La opción que hace que el terminal ejecute todo siguiéndolo dentro de la " #~ "terminal (ej. «-x» para gnome-terminal y terminal, «-e» para konsole y " #~ "urxvt)." #~ msgid "Twitter" #~ msgstr "Twitter" #~ msgid "Microblogging with Twitter: send updates and show friends' tweets" #~ msgstr "" #~ "Microblogging con Twitter: enviar actualizaciones y mostrar los «tweets» " #~ "de mis amigos" #~ msgid "Load friends' pictures" #~ msgstr "Cargar las imágenes de mis amigos" #~ msgid "Load friends' public tweets" #~ msgstr "Cargar los «tweets» públicos de mis amigos" #~ msgid "Load timeline" #~ msgstr "Cargar cronología" #~ msgid "Post Update to Twitter" #~ msgstr "Publicar actualización en Twitter" #~ msgid "Send Direct Message..." #~ msgstr "Enviar mensaje directo…" #~ msgid "Send Direct Message To..." #~ msgstr "Enviar mensaje directo a…" #~ msgid "%(user)s %(when)s" #~ msgstr "%(when)s %(user)s" #~ msgid "Twitter Timeline" #~ msgstr "Cronología en Twitter" #~ msgid "Twitter Friends" #~ msgstr "Amigos de Twitter" #~ msgid "Timeline for %s" #~ msgstr "Cronología de %s" #~ msgid "" #~ "Tick the box next to a source to make sure its objects are exported to " #~ "the top level of the catalog. An unticked source's contents are only " #~ "available by locating its subcatalog and entering it.\n" #~ "\n" #~ "Note: Kupfer is an integrator, not an indexer itself. Kupfer is not " #~ "designed to carry a catalog larger than a couple of thousand objects, and " #~ "may become slow if overly large subcatalogs are included in the top level." #~ msgstr "" #~ "Seleccionar la casilla junto a una fuente para asegurarse de que sus " #~ "objetos se exportan al nivel superior del catálogo. El contenido de una " #~ "casilla no seleccionada sólo está disponible ubicando su subcatálogo e " #~ "introduciéndolo.\n" #~ "\n" #~ "Nota: Kupfer es un integrador, no un indexador en si mismo. Kupfer no " #~ "está diseñado para catalogar más de un par de miles de objetos y puede " #~ "acabar siendo lento si se incluyen grandes subcatálogos en el nivel " #~ "superior." #~ msgid "Send message to one Gwibber account" #~ msgstr "Enviar mensaje a una cuenta de Gwibber" #~| msgid "Reply..." #~ msgid "Reply" #~ msgstr "Responder" #~ msgid "OpenOffice" #~ msgstr "OpenOffice" #~ msgid "Plugins may not be unloaded at runtime" #~ msgstr "Los complementos no se pueden descargar durante la ejecución" #~ msgid "Include in top level" #~ msgstr "Incluir en nivel superior" #~ msgid "" #~ "If enabled, objects from the plugin's source(s) will be available in the " #~ "top level.\n" #~ "Sources are always available as subcatalogs in the top level." #~ msgstr "" #~ "Si está activado, los objetos de la(s) fuente(s) del complemento estarán " #~ "disponibles en el nivel superior.\n" #~ "Las fuentes siempre están disponibles como subcatálogos en el nivel " #~ "superior." #~ msgid "Keybinding" #~ msgstr "Atajos de teclado" #~ msgid "Applied" #~ msgstr "Aplicado" #~ msgid "Gnome Session Management" #~ msgstr "Gestión de la sesión de GNOME" #~ msgid "Special items and actions for Gnome environment" #~ msgstr "Elementos y acciones especiales para el entorno GNOME" #~ msgid "To configure kupfer, edit:" #~ msgstr "Para configurar kupfer, editar:" #~ msgid "The default config for reference is at:" #~ msgstr "La configuración predeterminada está en:" #~ msgid "Open with %s" #~ msgstr "Abrir con %s" #~ msgid "Do" #~ msgstr "Hacer" #~ msgid "Compose New Mail To" #~ msgstr "Redactar un correo nuevo para" #~ msgid "Common" #~ msgstr "Comunes" #~ msgid "Special Items" #~ msgstr "Elementos epeciales" #~ msgid "Items and special actions" #~ msgstr "Elementos y acciones especiales" #~ msgid "Kupfer items and actions" #~ msgstr "Elementos y acciones de Kupfer" #~ msgid "Recently used documents and nautilus places" #~ msgstr "Documentos recientes y lugares de Nautilus" #~ msgid "Bookmarked locations in Nautilus" #~ msgstr "Marcadores de lugares en Nautilus" #~ msgid "(Simple) favorites plugin" #~ msgstr "Complemento simple de favoritos" #~ msgid "(no description)" #~ msgstr "(sin descripción)" #~ msgid " %(name)-20s %(version)-4s %(description)s" #~ msgstr " %(name)-20s %(version)-4s %(description)s" #~ msgid "Free-text Queries" #~ msgstr "Consultas de Free-text" #~ msgid "Basic support for free-text queries" #~ msgstr "Soporte básico para consultas de free-text" #~ msgid "Filesystem Text Matches" #~ msgstr "Coincidencias de texto en el sistema de archivos" #~ msgid "URL Text Matches" #~ msgstr "Coincidencias de texto en URL" #~ msgid "Searching..." #~ msgstr "Buscando..." #~ msgid "Searching %(source)s..." #~ msgstr "Buscando %(source)s..." #~ msgid "" #~ "%(program)s: %(desc)s\n" #~ "\t%(copyright)s\n" #~ "\t%(website)s\n" #~ msgstr "" #~ "%(program)s: %(desc)s\n" #~ "\t%(copyright)s\n" #~ "\t%(website)s\n" #~ msgid "Core" #~ msgstr "Nucleo" #~ msgid "%d lines" #~ msgstr "%d lineas" kupfer-328/po/eu.po000066400000000000000000001562741500175051100142650ustar00rootroot00000000000000# translation of eu.po to Basque # Iñaki Larrañaga Murgoitio , 2010. msgid "" msgstr "" "Project-Id-Version: eu\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2010-08-27 17:12+0200\n" "Last-Translator: Iñaki Larrañaga Murgoitio \n" "Language-Team: Basque \n" "Language: eu\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-Poedit-Language: Basque\n" "X-Poedit-SourceCharset: utf-8\n" "X-Generator: KBabel 1.11.4\n" msgid "User credentials" msgstr "Erabiltzailearen kredentzialak" msgid "_User:" msgstr "_Erabiltzailea:" msgid "_Password:" msgstr "_Pasahitza:" msgid "_Change" msgstr "_Aldatu" msgid "Set Keyboard Shortcut" msgstr "Ezarri laster-tekla" msgid "Please press desired key combination" msgstr "Sakatu nahi den tekla konbinazioa" msgid "Keybinding could not be bound" msgstr "Ezin izan da laster-tekla esleitu" msgid "Kupfer Preferences" msgstr "Kupfer-en hobespenak" msgid "Start automatically on login" msgstr "Abiarazi automatikoki saioa hastean" msgid "Start" msgstr "Hasiera" msgid "Show icon in notification area" msgstr "Erakutsi ikonoa jakinarazpen-arean" msgid "Icon set:" msgstr "" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" #, fuzzy msgid "Terminal emulator:" msgstr "Ireki terminala hemen" #, fuzzy msgid "Desktop Environment" msgstr "Mahaigainaren ingurunearentzako aplikazioak" msgid "General" msgstr "Orokorra" msgid "Global Keyboard Shortcuts" msgstr "Laster-tekla orokorrak" msgid "Reset" msgstr "Berrezarri" msgid "Browser Keyboard Shortcuts" msgstr "Arakatzailearen laster-teklak" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "Erabili tekla bakarreko komandoak (zuriunea, /, puntua, koma etab.)" msgid "Keyboard" msgstr "Teklatua" msgid "Plugins" msgstr "Pluginak" #, fuzzy msgid "Inclusion in Top Level Searches" msgstr "Sartu abestiak maila gorenean" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" #, fuzzy msgid "Indexed Folders" msgstr "Sortu karpeta" msgid "Folders whose files are always available in the catalog." msgstr "" msgid "Catalog" msgstr "Katalogoa" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Aplikazioen abiarazlea" msgid "Convenient command and access tool for applications and documents" msgstr "Komando eta atzipen tresna egokia aplikazio eta dokumentuentzat" msgid "Execute in Kupfer" msgstr "Kupfer-en exekutatu" msgid "Saved Kupfer Command" msgstr "Gordetako Kupfer komandoa" #, python-format msgid "Could not to carry out '%s'" msgstr "Ezin izan da '%s' exekutatu" #, python-format msgid "\"%s\" produced a result" msgstr "\"%s\"(e)k emaitza bat sortu du" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Baimenik ez \"%s\" exekutatzeko (ez da exekutagarria)" #, python-format msgid "Command in \"%s\" is not available" msgstr "\"%s\" komandoa ez dago eskuragarri" #, python-format msgid "Keyboard relay is active for display %s" msgstr "" msgid "do not present main interface on launch" msgstr "ez aurkeztu interfaze nagusia abioan" msgid "list available plugins" msgstr "zerrendatu plugin erabilgarriak" msgid "enable debug info" msgstr "gaitu arazte informazioa" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "" msgid "show usage help" msgstr "erakutsi erabilerari buruzko laguntza" msgid "show version information" msgstr "erakutsi bertsioaren informazioa" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Erabilera: kupfer [ AUKERAK | FITXATEGIA ... ]" msgid "Available plugins:" msgstr "Plugin erabilgarriak:" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "Idatzi bilatzeko" #, python-format msgid "%s is empty" msgstr "%s hutsa dago" #, fuzzy msgid "Text" msgstr "Erakutsi testua" msgid "Run after Delay..." msgstr "Exekutatu atzerapenaren ondoren..." msgid "Perform command after a specified time interval" msgstr "Exekutatu komandoa zehaztutako denbora tartearen ondoren" msgid "Multiple Objects" msgstr "Objektu anitzak" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "objektu %s" msgstr[1] "%s objektu" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "" #, fuzzy msgid "Aim" msgstr "Vim" #, fuzzy msgid "Google Talk" msgstr "Google Translate" msgid "ICQ" msgstr "" msgid "MSN" msgstr "" msgid "QQ" msgstr "" msgid "Yahoo" msgstr "" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "" msgid "Can not be used with multiple objects" msgstr "" msgid "Open" msgstr "Ireki" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Ez dago %(file)s (%(type)s)(r)en lehenetsitako aplikaziorik" #, fuzzy, python-format msgid "Please use \"%s\"" msgstr "\"%s\" fitxategi hautatuta" msgid "Set Default Application..." msgstr "Ezarri lehenetsitako aplikazioa..." msgid "Open with default application" msgstr "Ireki lehenetsitako aplikazioarekin" msgid "Reveal" msgstr "Erakutsi" msgid "Open parent folder" msgstr "Ireki karpeta gurasoa" msgid "Open Terminal Here" msgstr "Ireki terminala hemen" msgid "Open this location in a terminal" msgstr "Ireki kokalekua terminalean" msgid "Run in Terminal" msgstr "Exekutatu terminalean" msgid "Run (Execute)" msgstr "Exekutatu" msgid "Run this program in a Terminal" msgstr "Exekutatu programa terminalean" msgid "Run this program" msgstr "Exekutatu programa hau" msgid "Go To" msgstr "Joan" msgid "Open URL" msgstr "Ireki URLa" msgid "Open URL with default viewer" msgstr "Ireki URLa lehenetsitako ikustailearekin" msgid "Launch" msgstr "Abiarazi" msgid "Show application window" msgstr "Erakutsi aplikazioaren leihoa" msgid "Launch application" msgstr "Abiarazi aplikazioa" msgid "Launch Again" msgstr "Abiarazi berriro" msgid "Launch another instance of this application" msgstr "Abiarazi aplikazio honen beste instantzia bat" msgid "Close" msgstr "Itxi" msgid "Attempt to close all application windows" msgstr "Aplikazio guztien leihoak ixteko saiakera" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Exekutatu" msgid "Perform command" msgstr "Egikaritu komandoa" #, fuzzy msgid "(Empty Text)" msgstr "Hustu fitxategia" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "\"%(text)s\"" msgstr[1] "(%(num)d lerro) \"%(text)s\"" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s et. al." #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "%(dir)s(r)en iturburu errekurtsiboa, (%(levels)d maila)" #, python-format msgid "Directory source %s" msgstr "Direktorioaren iturburua: %s" msgid "Home Folder" msgstr "Karpeta nagusia" msgid "Catalog Index" msgstr "Katalogoaren aurkibidea" msgid "An index of all available sources" msgstr "Baliabide erabilgarri guztien aurkibidea" msgid "Root catalog" msgstr "Erroko katalogoa" msgid "Please Configure Plugin" msgstr "Konfiguratu plugina" #, python-format msgid "Plugin %s is not configured" msgstr "%s plugina ez dago konfiguratuta" #, python-format msgid "Invalid user credentials for %s" msgstr "%s(r)en baliogabeko erabiltzaile-kredentzialak" msgid "Applications" msgstr "Aplikazioak" msgid "All applications and preferences" msgstr "Aplikazio eta hobespen guztiak" msgid "Applications for Desktop Environment" msgstr "Mahaigainaren ingurunearentzako aplikazioak" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "Ireki honekin..." msgid "Open with any application" msgstr "Ireki edozein aplikaziorekin" msgid "Set default application to open this file type" msgstr "Ezarri aplikazio lehenetsia fitxategi mota hau irekitzeko" #, fuzzy msgid "Reset Associations" msgstr "URL ekintzak" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "Artxibo sakonak" msgid "Allow browsing inside compressed archive files" msgstr "Baimendu konprimitutako artxiboen barruan arakatzea" #, python-format msgid "Content of %s" msgstr "%s(r)en edukia" #, fuzzy msgid "Archive Manager" msgstr "Artxiboa" #, fuzzy msgid "Use Archive Manager actions" msgstr "Thunar fitxategi-kudeatzailearen ekintzak" msgid "Compressed archive type for 'Create Archive In'" msgstr "Konprimitutako artxibo mota 'Sortu artxiboa hemen'-entzat" msgid "Extract Here" msgstr "Erauzi hemen" msgid "Extract compressed archive" msgstr "Erauzi konprimitutako artxiboa" msgid "Create Archive" msgstr "Sortu artxiboa" msgid "Create a compressed archive from folder" msgstr "Sortu konprimitutako artxiboa karpetatik" msgid "Create Archive In..." msgstr "Sortu artxiboa hemen..." #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Artxiboa" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "Kontrolatu Audacious-en erreprodukzioak eta zerrendak" msgid "Include songs in top level" msgstr "Sartu abestiak maila gorenean" msgid "Enqueue" msgstr "Gehitu ilarari" msgid "Add track to the Audacious play queue" msgstr "Gehitu abestia Audacious-en erreprodukzio-zerrendari" msgid "Dequeue" msgstr "Kendu ilaratik" msgid "Remove track from the Audacious play queue" msgstr "Kendu abestia Audacious-en erreprodukzio-zerrendatik" msgid "Play" msgstr "Erreproduzitu" msgid "Jump to track in Audacious" msgstr "Joan abestira Audacious-en" msgid "Resume playback in Audacious" msgstr "Jarraitu erreprodukzioa Audacious-en" msgid "Pause" msgstr "Pausatu" msgid "Pause playback in Audacious" msgstr "Pausatu erreprodukzioa Audacious-en" msgid "Next" msgstr "Hurrengoa" msgid "Jump to next track in Audacious" msgstr "Joan hurrengo abestira Audacious-en" msgid "Previous" msgstr "Aurrekoa" msgid "Jump to previous track in Audacious" msgstr "Joan aurreko abestira Audacious-en" msgid "Clear Queue" msgstr "Garbitu erreprodukzio-zerrenda" msgid "Clear the Audacious play queue" msgstr "Garbitu Audacious-en erreprodukzio-zerrenda" msgid "Shuffle" msgstr "Ausaz" msgid "Toggle shuffle in Audacious" msgstr "Txandakatu ausaz erreproduzitzea Audacious-en" msgid "Repeat" msgstr "Errepikatu" msgid "Toggle repeat in Audacious" msgstr "Txandakatu erreprodukzioa errepikatzea Audacious-en" msgid "Show Playing" msgstr "Erakutsi erreproduzitzen ari den abestia" msgid "Tell which song is currently playing" msgstr "Esan unean erreproduzitzen ari den abestia" msgid "Playlist" msgstr "Erreprodukzio-zerrenda" msgid "Calculator" msgstr "Kalkulagailua" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "Kalkulatu" msgid "Clipboards" msgstr "Arbelak" msgid "Recent clipboards and clipboard proxy objects" msgstr "" #, fuzzy msgid "Number of recent clipboards to remember" msgstr "Azken aldiz erabilitako arbelen kopurua" msgid "Include selected text in clipboard history" msgstr "" #, fuzzy msgid "Copy selected text to primary clipboard" msgstr "Kopiatu hautapena arbel nagusian" msgid "Selected Text" msgstr "Hautatutako testua" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "\"%(desc)s\" arbela" msgstr[1] "Arbela \"%(desc)s\" %(num)d lerrorekin" #, fuzzy msgid "Clipboard Text" msgstr "Arbelak" #, fuzzy msgid "Clipboard File" msgstr "Arbelak" #, fuzzy msgid "Clipboard Files" msgstr "Arbelak" msgid "Clear" msgstr "Garbitu" msgid "Remove all recent clipboards" msgstr "Ezabatu azken arbel guztiak" msgid "Shell Commands" msgstr "Shell-eko komandoak" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" msgid "Run (Get Output)" msgstr "Exekutatu (eskuratu irteera)" msgid "Run program and return its output" msgstr "Exekutatu programa eta itzuli honen emaitza" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command #, fuzzy msgid "Pass to Command..." msgstr "Azken komandoa" msgid "Run program with object as an additional parameter" msgstr "" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin #, fuzzy msgid "Write to Command..." msgstr "Idatzi hemen..." #, fuzzy msgid "Run program and supply text on the standard input" msgstr "Exekutatu programa eta itzuli honen emaitza" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "" #, fuzzy msgid "Run command-line programs" msgstr "Exekutatu komando-lerroko programak" msgid "GTK+" msgstr "" #, fuzzy msgid "GNOME Terminal" msgstr "GNOMEren terminaleko profilak" #, fuzzy msgid "XFCE Terminal" msgstr "Exekutatu terminalean" #, fuzzy msgid "LXTerminal" msgstr "Exekutatu terminalean" #, fuzzy msgid "X Terminal" msgstr "Exekutatu terminalean" msgid "Urxvt" msgstr "" msgid "Konsole" msgstr "" msgid "Save As..." msgstr "Gorde honela..." #, fuzzy msgid "Restart Kupfer" msgstr "Berrabiarazi zerbitzua" msgid "Quit" msgstr "Irten" msgid "Quit Kupfer" msgstr "Irten Kupfer-etik" msgid "About Kupfer" msgstr "Kupfer-i buruz" msgid "Show information about Kupfer authors and license" msgstr "Erakutsi Kupfer-en egile eta lizentziari buruzko informazioa" msgid "Kupfer Help" msgstr "Kupfer-en laguntza" msgid "Get help with Kupfer" msgstr "Eskuratu Kupfer-en laguntza" msgid "Show preferences window for Kupfer" msgstr "Erakutsi Kupfer-en hobespenen leihoa" msgid "Search Contents" msgstr "Bilatu edukiak" msgid "Search inside this catalog" msgstr "Bilatu katalogoaren barruan" msgid "Copy" msgstr "Kopiatu" msgid "Copy to clipboard" msgstr "Kopiatu arbelean" msgid "Rescan" msgstr "Berreskaneatu" msgid "Force reindex of this source" msgstr "Behartu iturburu hau berriro indexatzea" msgid "Last Command" msgstr "Azken komandoa" msgid "Internal Kupfer Objects" msgstr "Kupfer-en barneko objektuak" msgid "Last Result" msgstr "Azken emaitza" msgid "Command Results" msgstr "Komandoaren emaitzak" #, fuzzy msgid "Custom Terminal" msgstr "Exekutatu terminalean" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Komandoa" msgid "Execute flag" msgstr "Exekutatu bandera" msgid "Default Email Client" msgstr "Posta-bezero lehenetsia" msgid "Compose email using the system's default mailto: handler" msgstr "Prestatu mezua sistemako posta-bezero lehenetsia erabiliz" #, fuzzy msgid "Compose Email To" msgstr "Prestatu mezua" msgid "Dictionary" msgstr "Hiztegia" msgid "Look up word in dictionary" msgstr "Bilatu hitza hiztegian" msgid "Look Up" msgstr "Bilatu" msgid "Documents" msgstr "Dokumentuak" msgid "Recently used documents and bookmarked folders" msgstr "Azken aldian erabilitako dokumentu eta laster-markatutako karpetak" msgid "Max recent document days" msgstr "Gehienezko azken dokumentuen egunak" msgid "Recent Items" msgstr "Azken elementuak" msgid "Recently used documents" msgstr "Azken aldian erabilitako dokumentuak" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "%s dokumentu" #, python-format msgid "Recently used documents for %s" msgstr "%s(r)en erabilitako azken dokumentuak" msgid "Places" msgstr "Lekuak" msgid "Bookmarked folders" msgstr "Laster-markatutako karpetak" #, fuzzy msgid "DuckDuckGo Search" msgstr "Google Search" msgid "Search the web securely with DuckDuckGo" msgstr "" msgid "Favorites" msgstr "Gogokoenak" msgid "Mark commonly used items and store objects for later use" msgstr "" "Markatu maiz erabilitako elementuak, eta gorde objektuak beranduago " "erabiltzeko" msgid "Shelf of \"Favorite\" items" msgstr "Gogoko elementuen apala" msgid "Add to Favorites" msgstr "Gehitu gogokoei" msgid "Add item to favorites shelf" msgstr "Gehitu elementua gogokoen apalari" msgid "Remove from Favorites" msgstr "Kendu gogokoetatik" msgid "Remove item from favorites shelf" msgstr "Kendu elementua gogokoen apaletik" msgid "File Actions" msgstr "Fitxategien ekintzak" msgid "More file actions" msgstr "Fitxategien ekintza gehiago" msgid "Move To..." msgstr "Eraman hona..." msgid "Move file to new location" msgstr "Eraman fitxategi hau kokapen berrira" msgid "Rename To..." msgstr "Aldatu izena..." msgid "Copy To..." msgstr "Kopiatu hona..." msgid "Copy file to a chosen location" msgstr "Kopiatu fitxategia aukeratutako kokapenera" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "Goi-mailako ekintzak" msgid "Tools to work with commands as objects" msgstr "Komandoekin objektu gisa lan egiteko tresnak" msgid "Select in Kupfer" msgstr "Hautatu Kupfer-en" #, python-format msgid "Result of %s (%s)" msgstr "%s (%s)(r)en emaitza" msgid "Run (Take Result)" msgstr "Exekutatu (hartu emaitza)" msgid "Take the command result as a proxy object" msgstr "Hartu komandoaren emaitza proxy-ko objektu gisa" msgid "Run (Discard Result)" msgstr "Exekutatu (baztertu emaitzak)" msgid "Image Tools" msgstr "Irudien tresnak" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Irudiak eraldatzeko tresnak" msgid "Scale..." msgstr "Eskalatu..." msgid "Scale image to fit inside given pixel measure(s)" msgstr "Eskalatu irudia emandako pixel neurrietan doitzeko" msgid "Rotate Clockwise" msgstr "Biratu erlojuaren norantzan" msgid "Rotate Counter-Clockwise" msgstr "Biratu erlojuaren aurkako norantzan" msgid "Autorotate" msgstr "Biratu automatikoki" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "Biratu JPEG bere EXIF metadatuen arabera" msgid "Kupfer Plugins" msgstr "Kupfer-en pluginak" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Atzitu Kupfer-eko pluginen zerrenda Kupfer-en" msgid "Show Information" msgstr "Erakutsi informazioa" msgid "Show Source Code" msgstr "Erakutsi iturburuaren kodea" msgid "enabled" msgstr "gaituta" msgid "disabled" msgstr "desgaituta" msgid "Notes" msgstr "Oharrak" msgid "Gnote or Tomboy notes" msgstr "Gnote edo Tomboy oharrak" msgid "Work with application" msgstr "Lan egin aplikazioarekin" msgid "Open with notes application" msgstr "Ireki oharrentzako aplikazioarekin" msgid "Append to Note..." msgstr "Erantsi oharrari..." msgid "Add text to existing note" msgstr "Gehitu testua oharrari" msgid "Create Note" msgstr "Sortu oharra" msgid "Create a new note from this text" msgstr "Sortu ohar berria testu honetatik" msgid "Get Note Search Results..." msgstr "Lortu oharreko bilaketaren emaitzak..." msgid "Show search results for this query" msgstr "Erakutsi kontsulta honen bilaketaren emaitzak" #, python-format msgid "today, %s" msgstr "gaur, %s" #, python-format msgid "yesterday, %s" msgstr "atzo, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Azken eguneraketa: %s" msgid "Quicksilver Icons" msgstr "" msgid "Quick Image Viewer" msgstr "" msgid "View Image" msgstr "" msgid "GNU Screen" msgstr "GNU Screen" msgid "Active GNU Screen sessions" msgstr "GNU Screen saio aktiboak" msgid "Attached" msgstr "Erantsita" msgid "Detached" msgstr "Askatuta" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "saioa %(status)s (%(pid)s), sorrera: %(time)s" msgid "Screen Sessions" msgstr "Screen saioak" msgid "Attach" msgstr "Erantsi" msgid "Send Keys" msgstr "" msgid "Send synthetic keyboard events using xautomation" msgstr "" msgid "Paste to Foreground Window" msgstr "" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "" msgid "Send keys to foreground window" msgstr "" msgid "Type Text" msgstr "" msgid "Type the text to foreground window" msgstr "" msgid "GNOME Session Management" msgstr "GNOME saio-kudeatzailea" msgid "Special items and actions for GNOME environment" msgstr "Elementu eta ekintza bereziak GNOME ingurunearentzat" msgid "Log Out..." msgstr "Amaitu saioa..." msgid "Log out or change user" msgstr "Amaitu saioa edo aldatu erabiltzailez" msgid "Shut Down..." msgstr "Itzali..." msgid "Shut down, restart or suspend computer" msgstr "Itzali, berrabiarazi edo eseki ordenagailua" msgid "Lock Screen" msgstr "Blokeatu pantaila" msgid "Enable screensaver and lock" msgstr "Gaitu pantaila-babeslea eta pantaila-blokeoa" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "XFCE saio-kudeatzailea" msgid "Special items and actions for XFCE environment" msgstr "Elementu eta ekintza bereziak XFCE ingurunearentzat" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "SSH ostalariak" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "~/.ssh/config fitxategian aurkitutako SSH ostalariak gehitzen ditu." msgid "SSH host" msgstr "SSH ostalaria" msgid "Connect" msgstr "Konektatu" msgid "Connect to SSH host" msgstr "Konektatu SSH ostalarira" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "~/.ssh/config-en zehaztutako SSH ostalariak" msgid "No D-Bus connection to desktop session" msgstr "Ez dago D-Bus konexiorik mahaigaineko saiora" #, fuzzy msgid "GNOME Keyring" msgstr "GNOMEren terminaleko profilak" msgid "KWallet" msgstr "" #, fuzzy msgid "Unencrypted File" msgstr "Hautatutako fitxategia" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "\"%s\" komandoa ez dago eskuragarri" msgid "Document Templates" msgstr "Dokumentuen txantiloiak" msgid "Create new documents from your templates" msgstr "Sortu dokumentu berriak zure txantiloietatik" #, python-format msgid "%s template" msgstr "%s txantiloi" msgid "Empty File" msgstr "Hustu fitxategia" msgid "New Folder" msgstr "Sortu karpeta" msgid "Create New Document..." msgstr "Sortu dokumentu berria..." msgid "Create a new document from template" msgstr "Sortu dokumentu berri bat txantiloitik" msgid "Create Document In..." msgstr "Sortu dokumentu hemen..." msgid "Textfiles" msgstr "Testu-fitxategiak" msgid "Append To..." msgstr "Erantsi honi..." msgid "Append..." msgstr "Erantsi..." msgid "Write To..." msgstr "Idatzi hemen..." msgid "Get Text Contents" msgstr "Lortu testuaren edukiak" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "Thunar fitxategi-kudeatzailearen ekintzak" msgid "Select in File Manager" msgstr "Hautatu fitxategi-kudeatzailean" msgid "Show Properties" msgstr "Erakutsi propietateak" msgid "Show information about file in file manager" msgstr "Erakutsi fitxategiari buruzko informazioa fitxategi-kudeatzailean" msgid "Send To..." msgstr "Bidali honi..." msgid "Symlink In..." msgstr "" #, fuzzy msgid "Create a symlink to file in a chosen location" msgstr "Kopiatu fitxategia aukeratutako kokapenera" msgid "Empty Trash" msgstr "Hustu zakarrontzia" msgid "Thunar Send To Objects" msgstr "Thunar-etik objektuei bidaltzea" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Thunderbird/Icedove-ko kontaktu eta ekintzak" msgid "Compose New Email" msgstr "Prestatu mezu berria" msgid "Compose a new message in Thunderbird" msgstr "Prestatu mezu berria Thunderbird-en" #, fuzzy msgid "Attach in Email To..." msgstr "Bidali mezua honi..." #, fuzzy msgid "Compose Email With" msgstr "Prestatu mezua" #, fuzzy msgid "Compose a new message using the text as body" msgstr "Prestatu mezu berria Thunderbird-en" msgid "Thunderbird Address Book" msgstr "Thunderbird-eko helbide-liburua" msgid "Contacts from Thunderbird Address Book" msgstr "Thunderbird-eko helbide-liburuko kontaktuak" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Top" msgid "Show running tasks and allow sending signals to them" msgstr "" "Erakutsi martxan dauden atazak eta ahalbidetu hauei seinaleak bidaltzea" msgid "Sort Order" msgstr "Ordenatu" msgid "Commandline" msgstr "Komando-lerroa" msgid "CPU usage (descending)" msgstr "PUZaren erabilpena (beherantz)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Memoriaren erabilpena (beherantz)" msgid "Send Signal..." msgstr "Bidali seinalea..." msgid "Signals" msgstr "Seinaleak" msgid "Running Tasks" msgstr "Exekutatzen ari diren dauden atazak" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid: %(pid)s puz: %(cpu)g%% memoria: %(mem)g%% denbora: %(time)s" msgid "Running tasks for current user" msgstr "Exekutatzen ari diren uneko erabiltzailearen atazak" msgid "Trash" msgstr "Zakarrontzia" msgid "Access trash contents" msgstr "Atzitu zakarrontziko edukia" msgid "Move to Trash" msgstr "Bota zakarrontzira" msgid "Move this file to trash" msgstr "Bota fitxategi hau zakarrontzira" msgid "Restore" msgstr "Leheneratu" msgid "Move file back to original location" msgstr "Eraman fitxategia hasierako kokalekura" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "Zakarrontzia hutsa dago" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "Zakarrontzian fitxategi bakarra dago" msgstr[1] "Zakarrontzian %(num)s fitxategi daude" msgid "Triggers" msgstr "Abiarazleak" #, fuzzy msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Esleitu laster-tekla orokorrak (abiarazleak) 'Prestatu komandoa'-rekin (Ktrl" "+Sartu) sortutako objektuei" msgid "Add Trigger..." msgstr "Gehitu abiarazlea..." msgid "Remove Trigger" msgstr "Ezabatu abiarazlea" msgid "URL Actions" msgstr "URL ekintzak" msgid "Download and Open" msgstr "Deskargatu eta ireki" msgid "Download To..." msgstr "Deskargatu hemen..." msgid "Download URL to a chosen location" msgstr "Deskargatu URLa aukeratutako kokalekura" msgid "Wikipedia" msgstr "Wikipedia" msgid "Search in Wikipedia" msgstr "Bilatu Wikipedian" msgid "Wikipedia language" msgstr "Wikipediako hizkuntza" #. TRANS: Default wikipedia language code msgid "en" msgstr "en" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Bilatu termino hau %s.wikipedia.org-en" msgid "Window List" msgstr "Leihoen zerrenda" msgid "All windows on all workspaces" msgstr "Leiho guztiak laneko area guztietan" msgid "Activate" msgstr "Aktibatu" msgid "Shade" msgstr "Bildu" msgid "Unshade" msgstr "Zabaldu" msgid "Minimize" msgstr "Minimizatu" msgid "Unminimize" msgstr "Leheneratu leihoa" msgid "Maximize" msgstr "Maximizatu" msgid "Unmaximize" msgstr "Desmaximizatu leihoa" msgid "Maximize Vertically" msgstr "Maximizatu bertikalki" msgid "Unmaximize Vertically" msgstr "Desmaximizatu bertikalki" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Leihoa %(wkspc)s laneko arean" msgid "Frontmost Window" msgstr "Aurrean dagoen leihoa" msgid "Next Window" msgstr "Hurrengo leihoa" msgid "Jump to this window's workspace and focus" msgstr "Joan leiho honen laneko areara eta jarri fokua" #, fuzzy, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "Hurrengo leihoa" msgstr[1] "Hurrengo leihoa" #, fuzzy msgid "Active workspace" msgstr "Joan laneko area honetara" msgid "Jump to this workspace" msgstr "Joan laneko area honetara" msgid "Workspaces" msgstr "Laneko areak" msgid "Volumes and Disks" msgstr "Bolumenak eta diskoak" msgid "Mounted volumes and disks" msgstr "Muntatutako bolumen eta diskoak" #, python-format msgid "Volume mounted at %s" msgstr "Bolumena %s-en muntatuta" msgid "Unmount" msgstr "Desmuntatu" msgid "Unmount this volume" msgstr "Desmuntatu bolumena" msgid "Eject" msgstr "Egotzi" msgid "Unmount and eject this media" msgstr "Desmuntatu eta egotzi euskarria" msgid "Show Text" msgstr "Erakutsi testua" msgid "Display text in a window" msgstr "Erakutsi testua leihoan" msgid "Large Type" msgstr "Mota handia" msgid "Show Notification" msgstr "Erakutsi jakinarazpena" #, fuzzy msgid "Tracker" msgstr "Tracker 0.6" msgid "Tracker desktop search integration" msgstr "Tracker mahaigaineko bilaketaren bateragarritasuna" msgid "Search in Tracker" msgstr "Bilatu Tracker-en" msgid "Open Tracker Search Tool and search for this term" msgstr "Ireki Tracker bilaketa tresna eta termino hau bilatu" msgid "Get Tracker Results..." msgstr "Lortu Tracker emaitzak..." msgid "Show Tracker results for query" msgstr "Erakutsi Tracker-eko kontsultaren emaitzak" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "\"%s\"(r)en emaitzak" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "Bilatu fitxategiak" msgid "Search filesystem using locate" msgstr "Bilatu fitxategi-sisteman 'locate' erabiliz" msgid "Ignore case distinctions when searching files" msgstr "Ezikusi egin maiuskulei/minuskulei fitxategiak bilatzean" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Firefox-en laster-markak" msgid "Index of Firefox bookmarks" msgstr "Firefox-en laster-marken indizea" #, fuzzy msgid "Firefox Keywords" msgstr "Firefox-en laster-markak" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "Bilatu webean Open Search bilaketako motorrekin" msgid "Search With..." msgstr "Bilatu honekin..." msgid "Search For..." msgstr "Hau bilatu..." #, fuzzy msgid "Search Terms" msgstr "Bilaketako motorrak" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "\"%s\" fitxategi hautatuta" #, fuzzy msgid "Resume playback" msgstr "Jarraitu erreprodukzioa Audacious-en" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Hurrengoa" #, fuzzy msgid "Skip to next track" msgstr "Joan hurrengo abestira Audacious-en" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Aurrekoa" #, fuzzy msgid "Skip to previous track" msgstr "Joan aurreko abestira Audacious-en" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "Atzitu Pidgin-eko kontaktuak" msgid "Show offline contacts" msgstr "Erakutsi deskonektatutako kontaktuak" msgid "Open Chat" msgstr "Ireki berriketa" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (karaktere %d)" msgstr[1] "%s (%d karaktere)" msgid "Send Message..." msgstr "Bidali mezua..." msgid "Available" msgstr "Erabilgarri" msgid "Away" msgstr "Kanpoan" msgid "Pidgin Contacts" msgstr "Pidgin-eko kontaktuak" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Laburtu estekak" msgid "Create short aliases of long URLs" msgstr "Sortu URL luzeen alias laburrak" msgid "Error" msgstr "Errorea" msgid "Shorten With..." msgstr "Laburtu honekin..." msgid "Services" msgstr "Zerbitzuak" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "Entzun eta jarri abestiak ilaran, eta arakatu musikaren liburutegia" msgid "Include artists in top level" msgstr "Sartu artistak maila gorenean" msgid "Include albums in top level" msgstr "Sartu albumak maila gorenean" msgid "Play tracks in Rhythmbox" msgstr "Erreproduzitu abestiak Rhythmbox-en" msgid "Add tracks to the play queue" msgstr "Gehitu abestiak erreprodukzio-zerrendari" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "%(album)s-eko %(artist)s-en arabera" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "%s(r)en arabera" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Abestiak %s-ren arabera" msgid "Albums" msgstr "Albumak" msgid "Music albums in Rhythmbox Library" msgstr "Rhythmbox liburutegiko musikaren albumak" msgid "Artists" msgstr "Artistak" msgid "Music artists in Rhythmbox Library" msgstr "Rhythmbox liburutegiko musikaren artistak" msgid "Songs" msgstr "Abestiak" msgid "Songs in Rhythmbox library" msgstr "Rhythmbox liburutegiko abestiak" msgid "Getting Things GNOME" msgstr "Getting Things GNOME" msgid "Browse and create new tasks in GTG" msgstr "Arakatu eta sortu ataza berriak GTGen" #, python-format msgid "due: %s" msgstr "iraungitzea: %s" #, python-format msgid "start: %s" msgstr "hasiera: %s" #, python-format msgid "tags: %s" msgstr "etiketak: %s" msgid "Open task in Getting Things GNOME!" msgstr "Ireki ataza 'Getting Things GNOME'n" msgid "Delete" msgstr "Ezabatu" msgid "Permanently remove this task" msgstr "Kendu betirako ataza hau" msgid "Mark Done" msgstr "Markatu eginda gisa" msgid "Mark this task as done" msgstr "Markatu ataza hau eginda balego bezala" msgid "Dismiss" msgstr "Baztertu" msgid "Mark this task as not to be done anymore" msgstr "Markatu ataza hau gehiago ez egiteko gisa" msgid "Create Task" msgstr "Sortu ataza" msgid "Create new task in Getting Things GNOME" msgstr "Sortu ataza berria 'Getting Things GNOME'n" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "Bilatu Devhelp-en" #, fuzzy msgid "Empathy" msgstr "Gajim-eko kontaktuak" #, fuzzy msgid "Access to Empathy Contacts" msgstr "Atzitu Gajim-eko kontaktuak" msgid "Busy" msgstr "Lanpetuta" msgid "Not Available" msgstr "Ez erabilgarri" msgid "Invisible" msgstr "Ikustezin" msgid "Offline" msgstr "Deskonektatuta" msgid "Change Global Status To..." msgstr "Aldatu egoera orokorra hona..." #, fuzzy msgid "Empathy Contacts" msgstr "Gajim-eko kontaktuak" #, fuzzy msgid "Empathy Account Status" msgstr "Gajim-eko kontuaren egoera" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Ordezko aktibazioa" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Koma trikimailua" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Prestatu komandoa" #, fuzzy msgid "Mark Default Action" msgstr "Ezarri lehenetsitako aplikazioa..." msgid "Forget Object" msgstr "" msgid "Reset All" msgstr "Berrezarri denak" msgid "Select Quit" msgstr "Hautatu irtetzeko" msgid "Select Selected File" msgstr "Aukeratu hautatutako fitxategia" msgid "Select Selected Text" msgstr "Aukeratu hautatutako testua" msgid "Show Help" msgstr "Erakutsi laguntza" msgid "Show Preferences" msgstr "Erakutsi hobespenak" msgid "Switch to First Pane" msgstr "Aldatu lehen panelera" msgid "Toggle Text Mode" msgstr "Aldatu testu modura" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Ez dago \"%(query)s\"(r)ekin bat datorrenik %(src)s-en" msgid "No matches" msgstr "Ez dago bat datorrenik" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Ez dago bat datorrenik" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Erakutsi interfaze nagusia" msgid "Show with Selection" msgstr "Erakutsi hautapenarekin" #. TRANS: Plugin info fields msgid "Description" msgstr "Deskribapena" msgid "Author" msgstr "Egilea" msgid "Version" msgstr "Bertsioa" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Beharrezkoa da Python-eko '%s' modulua" msgid "Plugin could not be read due to an error:" msgstr "Ezin izan da plugina irakurri errore bat dela eta:" msgid "Content of" msgstr "Edukia" #. TRANS: Plugin contents header msgid "Sources" msgstr "Iturburuak" #. TRANS: Plugin contents header msgid "Actions" msgstr "Ekintzak" #, python-format msgid "Using encrypted password storage: %s" msgstr "" #, python-format msgid "Using password storage: %s" msgstr "" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Konfigurazioa" msgid "Set username and password" msgstr "Ezarri erabiltzaile-izena eta pasahitza" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Aukeratu direktorioa" msgid "Reset all shortcuts to default values?" msgstr "Berrezarri laster-tekla guztiak lehenetsitako balioetara?" msgid "Shortcut" msgstr "Laster-tekla" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "" "Oier Mees \n" "Iñaki Larrañaga Murgoitio " msgid "A free software (GPLv3+) launcher" msgstr "Software librea (GPLv3+) den abiarazle bat" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Programa hau software librea da; birbana eta/edo alda dezakezu Software \n" "Foundation-ek argitaratutako GNU Lizentzia Publiko Orokorraren 3. " "bertsioan, \n" "edo (nahiago baduzu) beste berriago batean, jasotako baldintzak betez gero.\n" "\n" "Programa hau erabilgarria izango delakoan banatzen da, baina, INOLAKO\n" "BERMERIK GABE; era berean, ez da bermatzen beraren EGOKITASUNA \n" "MERKATURATZEKO edo HELBURU PARTIKULARRETARAKO ERABILTZEKO. \n" "Argibide gehiago nahi izanez gero, ikus GNU Lizentzia Publiko Orokorra.\n" "\n" "Programa honekin batera GNU Lizentzia Publiko Orokorraren kopia bat \n" "jasoko zenuen; hala ez bada, ikusi .\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Ezin izan da exekutatzen ari den Kupfer instantziarik aurkitu" #~ msgid "Compose Email" #~ msgstr "Prestatu mezua" #~ msgid "Send in Email To..." #~ msgstr "Bidali mezua honi..." #~ msgid "Type to search %s" #~ msgstr "Idatzi %s bilatzeko" #~ msgid "No action" #~ msgstr "Ekintzarik ez" #~ msgid "GNOME Terminal Profiles" #~ msgstr "GNOMEren terminaleko profilak" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Abiatu GNOMEren terminaleko profilak" #~ msgid "Selected Text \"%s\"" #~ msgstr "Hautatutako \"%s\" testua" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Kalkulatu '='-rekin hasten diren adierazpenak" #~ msgid "Recent clipboards" #~ msgstr "Azken arbelak" #~ msgid "Include recent selections" #~ msgstr "Sartu azken hautapenak" #~ msgid "Epiphany Bookmarks" #~ msgstr "Epiphany-ren laster-markak" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Epiphany-ren laster-marken indizea" #~ msgid "Include visited sites" #~ msgstr "Sartu bisitatutako guneak" #~ msgid "" #~ "Provides current nautilus selection, using Kupfer's Nautilus Extension" #~ msgstr "" #~ "Nautilus-en uneko hautapena eskaintzen du, Kupfer-eko Nautilus hedapenaz " #~ "baliatuz" #~ msgid "Selected File \"%s\"" #~ msgstr "\"%s\" fitxategi hautatuta" #~ msgid "Selected Files" #~ msgstr "Hautatutako fitxategiak" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Jarraitu erreprodukzioa Rhythmbox-en" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Pausatu erreprodukzioa Rhythmbox-en" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Joan hurrengo abestira Rhythmbox-en" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Joan aurreko abestira Rhythmbox-en" #~ msgid "Search the Web" #~ msgstr "Bilatu webean" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Abiword-en erabilitako azken dokumentuak" #~ msgid "Abiword Recent Items" #~ msgstr "Abiword-eko azken dokumentuak" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "APT pakete-kudeatzailearen interfazea" #~ msgid "Installation method" #~ msgstr "Instalazioaren metodoa" #~ msgid "Show Package Information" #~ msgstr "Erakutsi paketearen informazioa" #~ msgid "Install" #~ msgstr "Instalatu" #~ msgid "Install package using the configured method" #~ msgstr "Instalatu paketeak konfiguratutako metodoa erabiliz" #~ msgid "Packages matching \"%s\"" #~ msgstr "\"%s\" paketearekin bat datozenak" #~ msgid "Search Package Name..." #~ msgstr "Bilatu paketearen izena..." #~ msgid "Chromium Bookmarks" #~ msgstr "Chromium-en laster-markak" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Chromium-en laster-marken indizea" #~ msgid "Claws Mail" #~ msgstr "Claws posta-bezeroa" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Claws posta-bezeroaren kontaktuak eta ekintzak" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Prestatu mezu berria Claws posta-bezeroan" #~ msgid "Receive All Email" #~ msgstr "Jaso mezu guztiak" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "Jaso mezu berriak kontu guztietatik Claws posta-bezeroan" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Prestatu mezu berria eta erantxi fitxategia Claws-en" #~ msgid "Claws Mail Address Book" #~ msgstr "Claws-eko helbide-liburua" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Claws-eko helbide-liburuko kontaktuak" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Evolution-eko kontaktuak" #~ msgid "Compose a new message in Evolution" #~ msgstr "Prestatu mezu berria Evolution-en" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Prestatu mezu berria eta erantsi fitxategia Evolution-en" #~ msgid "Evolution Address Book" #~ msgstr "Evolution-eko helbide-liburua" #~ msgid "Filezilla" #~ msgstr "Filezilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Erakutsi guneak eta kudeatu ftp helbideak Filezilla-rekin" #~ msgid "Open Site with Filezilla" #~ msgstr "Ireki guneak Filezilla-rekin" #~ msgid "Filezilla Sites" #~ msgstr "Filezilla guneak" #~ msgid "Sites from Filezilla" #~ msgstr "Filezilla-ko guneak" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Atzitu Gajim-eko kontaktuak" #~ msgid "Free for Chat" #~ msgstr "Berriketarako libre" #~ msgid "Gajim Contacts" #~ msgstr "Gajim-eko kontaktuak" #~ msgid "Gajim Account Status" #~ msgstr "Gajim-eko kontuaren egoera" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Kargatu kontaktuak eta prestatu mezu berria Gmail-en" #~ msgid "Load contacts' pictures" #~ msgstr "Kargatu kontaktuaren argazkiak" #~ msgid "Compose Email in GMail" #~ msgstr "Prestatu mezua Gmail-en" #~ msgid "Open web browser and compose new email in GMail" #~ msgstr "Ireki web arakatzailea eta prestatu mezu berria Gmail-en" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Google zerbitzuetako (Gmail) kontaktuak" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Erakutsi albumak eta igo argazkiak Picasa-ra" #~ msgid "Users to show: (,-separated)" #~ msgstr "Erabiltzaileak erakusteko: (komaz bereiztuta)" #~ msgid "Load user and album icons" #~ msgstr "Kargatu erabiltzaile eta albumen ikonoak" #~ msgid "Uploading Pictures" #~ msgstr "Argazkiak igotzen" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Argazkiak igotzen 'Picasa Web Album'-era" #~ msgid "Creating album:" #~ msgstr "Albuma sortzen:" #~ msgid "Album created by Kupfer" #~ msgstr "Kupfer-ek sortutako albuma" #~ msgid "File:" #~ msgstr "Fitxategia:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "album bat" #~ msgstr[1] "%(num)d album" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "argazki bat" #~ msgstr[1] "%(num)s argazki" #~ msgid "Upload to Picasa Album..." #~ msgstr "Igo 'Picasa Album'-era..." #~ msgid "Upload files to Picasa album" #~ msgstr "Igo fitxategiak Picasa-ko albumera" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Igo Picasa-ra album berri gisa" #~ msgid "Create album from selected local directory" #~ msgstr "Sortu albuma hautatutako direktorio lokaletik" #~ msgid "Picasa Albums" #~ msgstr "Picasa-ko albumak" #~ msgid "User albums in Picasa" #~ msgstr "Erabiltzailearen albumak Picasa-n" #~ msgid "Search Google with results shown directly" #~ msgstr "Bilatu Google-n eta erakutsi emaitzak zuzenean" #~ msgid "Show More Results For \"%s\"" #~ msgstr "Erakutsi \"%s\"(r)en emaitza gehiago" #~ msgid "%s total found" #~ msgstr "Guztira %s aurkituta" #~ msgid "Translate text with Google Translate" #~ msgstr "Itzuli testua Google Translate-rekin" #~ msgid "Google Translate connection timed out" #~ msgstr "Google Translate-ren konexioa denboraz kanpo" #~ msgid "Error connecting to Google Translate" #~ msgstr "Errorea Google Translate-rekin konexioa ezartzean" #~ msgid "Translate To..." #~ msgstr "Itzuli hona..." #~ msgid "Translate into %s" #~ msgstr "Itzuli %s(e)ra" #~ msgid "Languages" #~ msgstr "Hizkuntzak" #~ msgid "Show translated page in browser" #~ msgstr "Erakutsi itzulitako orria arakatzailean" #~ msgid "Show Translation To..." #~ msgstr "Erakutsi itzulpena honi..." #~ msgid "Show translation in browser" #~ msgstr "Erakutsi itzulpena arakatzailean" #, fuzzy #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s %(when)s" #, fuzzy #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s" #, fuzzy #~ msgid "Send Message" #~ msgstr "Bidali mezua..." #, fuzzy #~ msgid "Send Message To..." #~ msgstr "Bidali mezua..." #~ msgid "Reply..." #~ msgstr "Erantzun..." #, fuzzy #~ msgid "Delete Message" #~ msgstr "Bidali mezua..." #, fuzzy #~ msgid "Send Private Message..." #~ msgstr "Bidali mezu zuzena..." #, fuzzy #~ msgid "Send direct message to user" #~ msgstr "Bidali mezu zuzena honi..." #, fuzzy #~ msgid "Retweet To..." #~ msgstr "Aldatu izena..." #, fuzzy #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Jaso mezu berriak kontu guztietatik Claws posta-bezeroan" #, fuzzy #~ msgid "Open in Browser" #~ msgstr "Ireki karpeta gurasoa" #, fuzzy #~ msgid "Open message in default web browser" #~ msgstr "Ireki URLa lehenetsitako ikustailearekin" #, fuzzy #~ msgid "Gwibber Accounts" #~ msgstr "Gajim-eko kontuaren egoera" #, fuzzy #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "OpenOffice.org-en erabilitako azken dokumentuak" #, fuzzy #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "OpenOffice.org-eko azken elementuak" #~ msgid "Opera Bookmarks" #~ msgstr "Opera-ko laster-markak" #~ msgid "Index of Opera bookmarks" #~ msgstr "Opera-ko laster-marken indizea" #~ msgid "Opera Mail" #~ msgstr "Opera-ren posta-bezeroa" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Opera posta-bezeroaren kontaktuak eta ekintzak" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Prestatu mezu berria Opera posta-bezeroan" #~ msgid "Opera Mail Contacts" #~ msgstr "Opera posta-bezeroko kontaktuak" #~ msgid "Contacts from Opera Mail" #~ msgstr "Opera posta-bezeroko kontaktuak" #~ msgid "PuTTY Sessions" #~ msgstr "PuTTY saioak" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Atzipen azkarra PuTTY saioentzako" #~ msgid "Start Session" #~ msgstr "Hasi saioa" #~ msgid "reStructuredText" #~ msgstr "reStructuredText" #~ msgid "Render reStructuredText and show the result" #~ msgstr "Errendatu reStructuredText eta erakutsi emaitza" #~ msgid "View as HTML Document" #~ msgstr "Ikusi HTML dokumentu gisa" #~ msgid "System Services" #~ msgstr "Sistemako zerbitzuak" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "" #~ "Hasi, gelditu edo berrabiarazi sistemako zerbitzuak 'init' script-en " #~ "bitartez" #~ msgid "Sudo-like Command" #~ msgstr "Sudo-ren antzeko komandoa" #~ msgid "Start Service" #~ msgstr "Hasi zerbitzua" #~ msgid "Stop Service" #~ msgstr "Gelditu zerbitzua" #~ msgid "%s Service" #~ msgstr "%s zerbitzua" #, fuzzy #~ msgid "Show QRCode" #~ msgstr "Erakutsi iturburuaren kodea" #, fuzzy #~ msgid "Display text as QRCode in a window" #~ msgstr "Erakutsi testua leihoan" #~ msgid "Access to Skype contacts" #~ msgstr "Atzitu Skype-ko kontaktuak" #~ msgid "Skype Me" #~ msgstr "Skype ni" #~ msgid "Logged Out" #~ msgstr "Saioa amaituta" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Deitu" #~ msgid "Place a call to contact" #~ msgstr "Deitu kontaktuari" #~ msgid "Skype Contacts" #~ msgstr "Skype-ko kontaktuak" #~ msgid "Skype Statuses" #~ msgstr "Skype-ren egoerak" #~ msgid "Tracker 0.6" #~ msgstr "Tracker 0.6" #~ msgid "Tracker tags" #~ msgstr "Tracker-eko etiketak" #~ msgid "Tracker Tags" #~ msgstr "Tracker-eko etiketak" #~ msgid "Browse Tracker's tags" #~ msgstr "Arakatu Tracker-eko etiketak" #~ msgid "Tag %s" #~ msgstr "%s etiketa" #~ msgid "Objects tagged %s with Tracker" #~ msgstr "Tracker-ekin etiketatutako %s objektu" #~ msgid "Add Tag..." #~ msgstr "Gehitu etiketa..." #~ msgid "Add tracker tag to file" #~ msgstr "Gehitu tracker-eko etiketa fitxategiari" #~ msgid "Remove Tag..." #~ msgstr "Kendu etiketa..." #~ msgid "Remove tracker tag from file" #~ msgstr "Kendu tracker-eko etiketa fitxategitik" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "TrueCrypt historiako bolumenak" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "TrueCrypt bolumena: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Muntatu bolumena" #~ msgid "Mount in Truecrypt" #~ msgstr "Muntatu Truecrypt-en" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Saiatu fitxategia muntatzen TrueCrypt bolumen gisa" #~ msgid "Dismount All Volumes" #~ msgstr "Desmuntatu bolumen guztiak" #~ msgid "TrueCrypt Volumes" #~ msgstr "TrueCrypt bolumenak" #~ msgid "Terminal Server Client" #~ msgstr "Urruneko mahaigainen bezeroa" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Saioa gorde da urruneko mahaigainen bezeroan" #~ msgid "TSClient sessions" #~ msgstr "Bezeroaren saioak" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Gordetako saioak urruneko mahaigainen bezeroan" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Vinagre-ko laster-markak eta ekintzak" #~ msgid "Start Vinagre Session" #~ msgstr "Hasi Vinagre-ren saioa" #~ msgid "Vinagre Bookmarks" #~ msgstr "Vinagre-ko laster-markak" #~ msgid "Recently used documents in Vim" #~ msgstr "Erabilitako azken dokumentuak Vim-en" #~ msgid "Vim Recent Documents" #~ msgstr "Vim-eko azken dokumentuak" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "Kontrolatu VirtualBox makina birtualak. Sun VirtualBox eta Open Source " #~ "Edizioak onartzen ditu." #~ msgid "Power On" #~ msgstr "Piztu" #~ msgid "Power On Headless" #~ msgstr "Piztu burugabea" #~ msgid "Send Power Off Signal" #~ msgstr "Bidali itzaltzeko seinalea" #~ msgid "Reboot" #~ msgstr "Berrabiarazi" #~ msgid "Resume" #~ msgstr "Jarraitu" #~ msgid "Save State" #~ msgstr "Gorde egoera" #~ msgid "Power Off" #~ msgstr "Itzali" #~ msgid "VirtualBox Machines" #~ msgstr "VirtualBox makinak" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "" #~ "Atzitu Zim-en gordetako orriak - Mahaigaineko wiki eta eskema sortzailea" #~ msgid "Page names start with :colon" #~ msgstr "Orriaren izena bi puntuekin (:) hasten da" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Zim orria \"%s\" koadernotik" #~ msgid "Create Zim Page" #~ msgstr "Sortu Zim orria" #~ msgid "Create page in default notebook" #~ msgstr "Sortu orria lehenetsitako koadernoan" #~ msgid "Create Zim Page In..." #~ msgstr "Sortu Zim orria hemen..." #~ msgid "Create Subpage..." #~ msgstr "Sortu azpi-orria..." #~ msgid "Zim Notebooks" #~ msgstr "Zim koadernoak" #~ msgid "Zim Pages" #~ msgstr "Zim orriak" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Zim koadernoetan gordetako orriak" #~ msgid "Directories" #~ msgstr "Direktorioak" #~ msgid "Interface" #~ msgstr "Interfazea" #~ msgid "Hide Kupfer when focus is lost" #~ msgstr "Ezkutatu Kupfer fokua galtzean" #~ msgid "" #~ "Tick the box next to a source to make sure its objects are exported to " #~ "the top level of the catalog. An unticked source's contents are only " #~ "available by locating its subcatalog and entering it.\n" #~ "\n" #~ "Note: Kupfer is an integrator, not an indexer itself. Kupfer is not " #~ "designed to carry a catalog larger than a couple of thousand objects, and " #~ "may become slow if overly large subcatalogs are included in the top level." #~ msgstr "" #~ "Iturburuaren ondoko koadroa markatu objektuak katalogoaren maila gorenera " #~ "esportatzen direla ziurtatzeko. Markatu gabeko iturburuen edukiak " #~ "eskuragarri daude bakarrik honen azpikatalogoa kokatuz eta honetan " #~ "sartuz.\n" #~ "\n" #~ "Oharra: Kupfer ez da indexatzaile bat, baizik eta integratzailea bat. " #~ "Kupfer ez dago diseinatuta pare bat milaka objektuko katalogoak baina " #~ "handiagokoekin lan egiteko. Horregatik, azpikatalogo handiegiak gehitzen " #~ "badira maila gorenean Kupfer mantso ibili daiteke." #~ msgid "Text Matches" #~ msgstr "Testua bat dator" #~ msgid "noun" #~ msgstr "izena" #~ msgid "verb" #~ msgstr "aditza" #~ msgid "adjective" #~ msgstr "adjetiboa" #~ msgid "Twitter" #~ msgstr "Twitter" #~ msgid "Microblogging with Twitter: send updates and show friends' tweets" #~ msgstr "" #~ "Mikrobloggintza Twitter-ekin: bidali eguneraketak eta erakutsi lagunen " #~ "tweet-ak" #~ msgid "Load friends' pictures" #~ msgstr "Kargatu lagunen argazkiak" #~ msgid "Load friends' public tweets" #~ msgstr "Kargatu lagunen tweet publikoak" #~ msgid "Load timeline" #~ msgstr "Kargatu kronologia" #~ msgid "Post Update to Twitter" #~ msgstr "Bidali eguneraketa Twitter-era" #~ msgid "Twitter Timeline" #~ msgstr "Twitter kronologia" #~ msgid "Twitter Friends" #~ msgstr "Twitter lagunak" #~ msgid "Timeline for %s" #~ msgstr "%s(r)en kronologia" #~ msgid "OpenOffice" #~ msgstr "OpenOffice.org" #~ msgid "Preferred terminal" #~ msgstr "Terminal hobetsia" #~ msgid "" #~ "The preferred terminal emulator. It's used to launch the SSH sessions." #~ msgstr "" #~ "Terminal hobetsiaren emuladorea. SSH saioak abiatzeko erabiltzen da." #~ msgid "" #~ "The flag which makes the terminal execute everything following it inside " #~ "the terminal (e.g. '-x' for gnome-terminal and terminal, '-e' for konsole " #~ "and urxvt)." #~ msgstr "" #~ "Terminalean banderaren ondoren dagoena exekutarazten du (adib. '-x' gnome-" #~ "terminal eta terminalean, '-e' konsole eta urxvt-en)." #~ msgid "Tracker 0.8" #~ msgstr "Tracker 0.8" kupfer-328/po/fr.po000066400000000000000000001700311500175051100142460ustar00rootroot00000000000000# French translation for kupfer. # Copyright (C) 2010 kupfer's COPYRIGHT HOLDER # This file is distributed under the same license as the kupfer package. # cbenz , 2010. # YannUbuntu , 2010 # Bruno Brouard , 2012. # msgid "" msgstr "" "Project-Id-Version: kupfer master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2012-02-19 12:50+0100\n" "Last-Translator: Bruno Brouard \n" "Language-Team: GNOME French Team \n" "Language: \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" msgid "User credentials" msgstr "Authentification de l'utilisateur" msgid "_User:" msgstr "_Utilisateur :" msgid "_Password:" msgstr "_Mot de passe :" msgid "_Change" msgstr "_Changer" msgid "Set Keyboard Shortcut" msgstr "Définition du raccourci clavier" msgid "Please press desired key combination" msgstr "Veuillez appuyer sur la combinaison de touches désirée" msgid "Keybinding could not be bound" msgstr "Le raccourci clavier n'a pas pu être configuré" msgid "Kupfer Preferences" msgstr "Préférences de Kupfer" msgid "Start automatically on login" msgstr "Démarrer automatiquement à l'ouverture de session" msgid "Start" msgstr "Démarrage" msgid "Show icon in notification area" msgstr "Afficher l'icône dans la zone de notification" msgid "Icon set:" msgstr "Ensemble d'icônes :" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" msgid "Terminal emulator:" msgstr "Émulateur de terminal :" msgid "Desktop Environment" msgstr "Environnement de bureau" msgid "General" msgstr "Général" msgid "Global Keyboard Shortcuts" msgstr "Raccourcis clavier généraux" msgid "Reset" msgstr "Réinitialiser" msgid "Browser Keyboard Shortcuts" msgstr "Raccourcis clavier du navigateur" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "" "Utiliser les commandes à l'aide d'une seule touche (espace, /, point, " "virgule, etc.)" msgid "Keyboard" msgstr "Clavier" msgid "Plugins" msgstr "Greffons" msgid "Inclusion in Top Level Searches" msgstr "Inclusion dans les recherches les plus courantes" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "Les éléments des sources cochées sont inclus dans les recherches les plus " "courantes.\n" "Le contenu d'une source non cochée n'est disponible qu'en localisant son " "sous-catalogue." msgid "Indexed Folders" msgstr "Dossiers indexés" msgid "Folders whose files are always available in the catalog." msgstr "" "Dossiers dont les fichiers sont toujours disponibles dans le catalogue." msgid "Catalog" msgstr "Catalogue" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Lanceur d'applications" msgid "Convenient command and access tool for applications and documents" msgstr "Outil pratique pour accéder à des documents et lancer des applications" msgid "Execute in Kupfer" msgstr "Exécuter dans Kupfer" msgid "Saved Kupfer Command" msgstr "Commande Kupfer enregistrée" # bruno ; typo ? "Could not carry out '%s'" #, python-format msgid "Could not to carry out '%s'" msgstr "Impossible d'exécuter « %s »" #, python-format msgid "\"%s\" produced a result" msgstr "« %s » a produit un résultat" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Lancement de « %s » non autorisé (non exécutable)" #, python-format msgid "Command in \"%s\" is not available" msgstr "La commande n'est pas disponible dans « %s »" #, python-format msgid "Keyboard relay is active for display %s" msgstr "Le relais du clavier est actif pour l'écran %s" msgid "do not present main interface on launch" msgstr "ne pas afficher l'interface principale au lancement" msgid "list available plugins" msgstr "afficher les greffons disponibles" msgid "enable debug info" msgstr "activer les informations de débogage" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "lancer l'assistant greffon" msgid "show usage help" msgstr "afficher l'aide" msgid "show version information" msgstr "afficher les informations de version" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Utilisation : kupfer [ OPTIONS | FICHIER ... ]" msgid "Available plugins:" msgstr "Greffons disponibles :" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s : %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "Saisir pour rechercher" #, python-format msgid "%s is empty" msgstr "%s est vide" msgid "Text" msgstr "Texte" msgid "Run after Delay..." msgstr "Exécuter après un délai..." msgid "Perform command after a specified time interval" msgstr "Exécuter la commande après le délai indiqué" msgid "Multiple Objects" msgstr "Éléments multiples" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s élément" msgstr[1] "%s éléments" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "inconnu" msgid "Aim" msgstr "Aim" msgid "Google Talk" msgstr "Google Talk" msgid "ICQ" msgstr "ICQ" msgid "MSN" msgstr "MSN" msgid "QQ" msgstr "QQ" msgid "Yahoo" msgstr "Yahoo" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "%s ne prend pas en charge cette opération" msgid "Can not be used with multiple objects" msgstr "Utilisation impossible avec plusieurs éléments" msgid "Open" msgstr "Ouvrir" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Aucune application par défaut pour %(file)s (%(type)s)" #, python-format msgid "Please use \"%s\"" msgstr "Veuillez utiliser « %s »" msgid "Set Default Application..." msgstr "Définir l'application par défaut..." msgid "Open with default application" msgstr "Ouvrir avec l'application par défaut" msgid "Reveal" msgstr "Afficher" msgid "Open parent folder" msgstr "Ouvrir le dossier parent" msgid "Open Terminal Here" msgstr "Ouvrir un terminal ici" msgid "Open this location in a terminal" msgstr "Ouvrir cet emplacement dans un terminal" msgid "Run in Terminal" msgstr "Exécuter dans un terminal" msgid "Run (Execute)" msgstr "Exécuter" msgid "Run this program in a Terminal" msgstr "Exécuter ce programme dans un terminal" msgid "Run this program" msgstr "Exécuter ce programme" msgid "Go To" msgstr "Aller à" msgid "Open URL" msgstr "Ouvrir l'URL" msgid "Open URL with default viewer" msgstr "Ouvrir l'URL avec le visionneur par défaut" msgid "Launch" msgstr "Lancer" msgid "Show application window" msgstr "Afficher la fenêtre de l'application" msgid "Launch application" msgstr "Lancer l'application" msgid "Launch Again" msgstr "Lancer à nouveau" msgid "Launch another instance of this application" msgstr "Lancer une autre instance de cette application" msgid "Close" msgstr "Fermer" msgid "Attempt to close all application windows" msgstr "Essayer de fermer toutes les fenêtres de l'application" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Exécuter" msgid "Perform command" msgstr "Exécuter la commande" msgid "(Empty Text)" msgstr "(texte vide)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "« %(text)s »" msgstr[1] "(%(num)d lignes) « %(text)s »" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s et al." #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Source récursive de %(dir)s, (%(levels)d niveaux)" #, python-format msgid "Directory source %s" msgstr "Dossier source %s" msgid "Home Folder" msgstr "Dossier personnel" msgid "Catalog Index" msgstr "Index du catalogue" msgid "An index of all available sources" msgstr "Index de toutes les sources disponibles" msgid "Root catalog" msgstr "Catalogue racine" msgid "Please Configure Plugin" msgstr "Veuillez configurer le greffon" #, python-format msgid "Plugin %s is not configured" msgstr "Le greffon %s n'est pas configuré" #, python-format msgid "Invalid user credentials for %s" msgstr "Erreur d'authentification pour %s" msgid "Applications" msgstr "Applications" msgid "All applications and preferences" msgstr "Toutes les applications et préférences" msgid "Applications for Desktop Environment" msgstr "Applications pour le bureau" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "Ouvrir avec..." msgid "Open with any application" msgstr "Ouvrir avec n'importe quelle application" msgid "Set default application to open this file type" msgstr "Sauvegarder l'application par défaut pour ouvrir ce type de fichier" #, fuzzy msgid "Reset Associations" msgstr "Actions sur les URL" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "Parcourir les archives" msgid "Allow browsing inside compressed archive files" msgstr "Parcourir l'intérieur des fichiers d'archives compressées" #, python-format msgid "Content of %s" msgstr "Contenu de %s" msgid "Archive Manager" msgstr "Gestionnaire d'archive" msgid "Use Archive Manager actions" msgstr "Utiliser les actions du gestionnaire d'archive" msgid "Compressed archive type for 'Create Archive In'" msgstr "Type d'archive pour « Créer une archive dans »" msgid "Extract Here" msgstr "Extraire ici" msgid "Extract compressed archive" msgstr "Extraire l'archive compressée" msgid "Create Archive" msgstr "Créer une archive" msgid "Create a compressed archive from folder" msgstr "Créer une archive compressée du dossier" msgid "Create Archive In..." msgstr "Créer une archive dans..." #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Archive" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "Contrôle la lecture d'Audacious et sa liste de lecture" msgid "Include songs in top level" msgstr "Inclure les pistes au premier niveau" msgid "Enqueue" msgstr "Ajouter à la file d'attente" msgid "Add track to the Audacious play queue" msgstr "Ajouter la piste à la file d'attente d'Audacious" msgid "Dequeue" msgstr "Retirer de la file d'attente" msgid "Remove track from the Audacious play queue" msgstr "Retirer la piste de la file d'attente d'Audacious" msgid "Play" msgstr "Lecture" msgid "Jump to track in Audacious" msgstr "Aller à la piste dans Audacious" msgid "Resume playback in Audacious" msgstr "Reprendre la lecture dans Audacious" msgid "Pause" msgstr "Pause" msgid "Pause playback in Audacious" msgstr "Mettre en pause Audacious" msgid "Next" msgstr "Suivant" msgid "Jump to next track in Audacious" msgstr "Aller à la piste suivante dans Audacious" msgid "Previous" msgstr "Précédent" msgid "Jump to previous track in Audacious" msgstr "Aller à la piste précédente dans Audacious" msgid "Clear Queue" msgstr "Effacer la file d'attente" msgid "Clear the Audacious play queue" msgstr "Vider la file d'attente d'Audacious" msgid "Shuffle" msgstr "Lecture aléatoire" msgid "Toggle shuffle in Audacious" msgstr "Basculer la lecture aléatoire dans Audacious" msgid "Repeat" msgstr "Répéter" msgid "Toggle repeat in Audacious" msgstr "Basculer la répétition dans Audacious" msgid "Show Playing" msgstr "Afficher la lecture en cours" msgid "Tell which song is currently playing" msgstr "Afficher le morceau en cours de lecture" msgid "Playlist" msgstr "Liste de lecture" msgid "Calculator" msgstr "Calculatrice" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "Calculer" msgid "Clipboards" msgstr "Presse-papiers" msgid "Recent clipboards and clipboard proxy objects" msgstr "" "Éléments du presse-papiers et objets de procuration de presse-papiers récents" msgid "Number of recent clipboards to remember" msgstr "Nombre d'éléments récents de presse-papiers à se rappeler" msgid "Include selected text in clipboard history" msgstr "Inclure le texte sélectionné dans l'historique du presse-papiers" msgid "Copy selected text to primary clipboard" msgstr "Copier le texte sélectionné dans le presse-papiers primaire" msgid "Selected Text" msgstr "Texte sélectionné" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Presse-papiers « %(desc)s »" msgstr[1] "Presse-papiers de %(num)d lignes « %(desc)s »" msgid "Clipboard Text" msgstr "Texte du presse-papiers" msgid "Clipboard File" msgstr "Fichier du presse-papiers" msgid "Clipboard Files" msgstr "Fichiers du presse-papiers" msgid "Clear" msgstr "Effacer" msgid "Remove all recent clipboards" msgstr "Supprimer tous les éléments récents du presse-papiers" msgid "Shell Commands" msgstr "Commandes du shell" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Exécuter des programmes en ligne de commande. Les actions marquées du " "symbole %s sont exécutées dans un sous-shell." msgid "Run (Get Output)" msgstr "Exécuter (en récupérant la sortie)" msgid "Run program and return its output" msgstr "Exécuter le programme et récupérer les sorties" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "Transmettre à la commande..." msgid "Run program with object as an additional parameter" msgstr "" "Exécuter le programme en utilisant l'élément comme argument supplémentaire" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "Écrire vers la commande..." msgid "Run program and supply text on the standard input" msgstr "Exécuter le programme et envoyer le texte sur l'entrée standard" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "Filtrer à travers la commande..." msgid "Run command-line programs" msgstr "Exécute des programmes en ligne de commande" msgid "GTK+" msgstr "GTK+" msgid "GNOME Terminal" msgstr "Terminal GNOME" msgid "XFCE Terminal" msgstr "Terminal XFCE" msgid "LXTerminal" msgstr "LXTerminal" msgid "X Terminal" msgstr "Terminal X" msgid "Urxvt" msgstr "Urxvt" msgid "Konsole" msgstr "" msgid "Save As..." msgstr "Enregistrer sous..." #, fuzzy msgid "Restart Kupfer" msgstr "Redémarrer le service" msgid "Quit" msgstr "Quitter" msgid "Quit Kupfer" msgstr "Quitte Kupfer" msgid "About Kupfer" msgstr "À propos de Kupfer" msgid "Show information about Kupfer authors and license" msgstr "Affiche des informations sur les auteurs de Kupfer et la licence" msgid "Kupfer Help" msgstr "Manuel de Kupfer" msgid "Get help with Kupfer" msgstr "Obtenir de l'aide sur Kupfer" msgid "Show preferences window for Kupfer" msgstr "Affiche la fenêtre des préférences de Kupfer" msgid "Search Contents" msgstr "Recherche de contenu" msgid "Search inside this catalog" msgstr "Rechercher à l'intérieur de ce catalogue" msgid "Copy" msgstr "Copier" msgid "Copy to clipboard" msgstr "Copier dans le presse-papiers" msgid "Rescan" msgstr "Parcourir à nouveau" msgid "Force reindex of this source" msgstr "Forcer la ré-indexation de cette source" msgid "Last Command" msgstr "Dernière commande" msgid "Internal Kupfer Objects" msgstr "Éléments internes de Kupfer" msgid "Last Result" msgstr "Dernier résultat" msgid "Command Results" msgstr "Résultats de la commande" msgid "Custom Terminal" msgstr "Terminal personnalisé" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Commande" msgid "Execute flag" msgstr "Utiliser l'option" msgid "Default Email Client" msgstr "Client de messagerie par défaut" msgid "Compose email using the system's default mailto: handler" msgstr "" "Composer un courriel en utilisant le gestionnaire par défaut mailto: du " "système" #, fuzzy msgid "Compose Email To" msgstr "Composer un courriel" msgid "Dictionary" msgstr "Dictionnaire" msgid "Look up word in dictionary" msgstr "Rechercher un mot dans un dictionnaire" msgid "Look Up" msgstr "Rechercher" msgid "Documents" msgstr "Documents" msgid "Recently used documents and bookmarked folders" msgstr "Documents récemment utilisés et dossiers en marque-page" msgid "Max recent document days" msgstr "Nombre maximal de jours pour les documents récents" msgid "Recent Items" msgstr "Éléments récents" msgid "Recently used documents" msgstr "Documents utilisés récemment" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "Documents de %s" #, python-format msgid "Recently used documents for %s" msgstr "Documents récemment utilisés pour %s" msgid "Places" msgstr "Raccourcis" msgid "Bookmarked folders" msgstr "Dossiers en marque-page" msgid "DuckDuckGo Search" msgstr "Rechercher avec DuckDuckGo" msgid "Search the web securely with DuckDuckGo" msgstr "Rechercher sur le Web en toute sécurité avec DuckDuckGo" msgid "Favorites" msgstr "Favoris" msgid "Mark commonly used items and store objects for later use" msgstr "" "Marquer les éléments fréquemment utilisés et les enregistrer pour leur " "utilisation future" msgid "Shelf of \"Favorite\" items" msgstr "Bibliothèque d'éléments « favoris »" msgid "Add to Favorites" msgstr "Ajouter aux favoris" msgid "Add item to favorites shelf" msgstr "Ajouter l'élément aux favoris" msgid "Remove from Favorites" msgstr "Supprimer des favoris" msgid "Remove item from favorites shelf" msgstr "Supprime l'élément des favoris" msgid "File Actions" msgstr "Actions sur les fichiers" msgid "More file actions" msgstr "Actions supplémentaires sur les fichiers" msgid "Move To..." msgstr "Déplacer vers..." msgid "Move file to new location" msgstr "Déplacer le fichier vers un nouvel emplacement" msgid "Rename To..." msgstr "Renommer..." msgid "Copy To..." msgstr "Copier vers..." msgid "Copy file to a chosen location" msgstr "Copier le fichier vers un emplacement choisi" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "Glob" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "Actions de haut-niveau" msgid "Tools to work with commands as objects" msgstr "Outils pour manipuler les commandes comme des objets" msgid "Select in Kupfer" msgstr "Sélectionner dans Kupfer" #, python-format msgid "Result of %s (%s)" msgstr "Résultat de %s (%s)" msgid "Run (Take Result)" msgstr "Exécuter (récupérer le résultat)" msgid "Take the command result as a proxy object" msgstr "Réutiliser le résultat de la commande en tant qu'objet de procuration" msgid "Run (Discard Result)" msgstr "Exécuter (ignorer le résultat)" msgid "Image Tools" msgstr "Outils d'image" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Outils de transformation d'images" msgid "Scale..." msgstr "Mise à l'échelle..." msgid "Scale image to fit inside given pixel measure(s)" msgstr "Redimensionne l'image pour correspondre aux nombres donnés en pixel" msgid "Rotate Clockwise" msgstr "Rotation dans le sens des aiguilles d'une montre" msgid "Rotate Counter-Clockwise" msgstr "Rotation dans le sens inverse des aiguilles d'une montre" msgid "Autorotate" msgstr "Rotation automatique" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "Rotation JPEG (en dur) selon les informations EXIF (métadata)" msgid "Kupfer Plugins" msgstr "Greffons Kupfer" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Accéder à la liste des greffons de Kupfer depuis Kupfer" msgid "Show Information" msgstr "Afficher les informations" msgid "Show Source Code" msgstr "Afficher le code source" msgid "enabled" msgstr "activé" msgid "disabled" msgstr "désactivé" msgid "Notes" msgstr "Notes" msgid "Gnote or Tomboy notes" msgstr "Notes Gnote ou Tomboy" msgid "Work with application" msgstr "Travailler avec l'application" msgid "Open with notes application" msgstr "Ouvrir avec l'application de notes" msgid "Append to Note..." msgstr "Ajouter à la note..." msgid "Add text to existing note" msgstr "Ajouter le texte à une note existante" msgid "Create Note" msgstr "Créer une note" msgid "Create a new note from this text" msgstr "Créer une nouvelle note à partir de ce texte" msgid "Get Note Search Results..." msgstr "Obtenir le résultat de la recherche dans les notes..." msgid "Show search results for this query" msgstr "Afficher les résultats de cette requête" #, python-format msgid "today, %s" msgstr "aujourd'hui, %s" #, python-format msgid "yesterday, %s" msgstr "hier, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Dernière mise à jour %s" msgid "Quicksilver Icons" msgstr "Icônes Quicksilver" msgid "Quick Image Viewer" msgstr "Quick Image Viewer" msgid "View Image" msgstr "Afficher l'image" msgid "GNU Screen" msgstr "GNU Screen" msgid "Active GNU Screen sessions" msgstr "Activer les sessions GNU Screen" msgid "Attached" msgstr "Attachée" msgid "Detached" msgstr "Détachée" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "Session %(status)s (%(pid)s) créée le %(time)s" msgid "Screen Sessions" msgstr "Sessions Screen" msgid "Attach" msgstr "Attacher" msgid "Send Keys" msgstr "Send Keys" msgid "Send synthetic keyboard events using xautomation" msgstr "Envoyer des évènements clavier synthétique en utilisant xautomation" msgid "Paste to Foreground Window" msgstr "Coller vers la fenêtre au premier plan" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "" "Copie dans le presse-papier et envoie Ctrl+V à la fenêtre au premier plan" msgid "Send keys to foreground window" msgstr "Envoyer des touches à la fenêtre au premier plan" msgid "Type Text" msgstr "Saisir du texte" msgid "Type the text to foreground window" msgstr "Saisir du texte dans la fenêtre au premier plan" msgid "GNOME Session Management" msgstr "Gestion de la session GNOME" msgid "Special items and actions for GNOME environment" msgstr "Éléments et actions spécifiques à l'environnement GNOME" msgid "Log Out..." msgstr "Fermer la session..." msgid "Log out or change user" msgstr "Fermer la session ou changer d'utilisateur" msgid "Shut Down..." msgstr "Éteindre..." msgid "Shut down, restart or suspend computer" msgstr "Éteindre, redémarrer ou mettre en veille l'ordinateur" msgid "Lock Screen" msgstr "Verrouiller l'écran" msgid "Enable screensaver and lock" msgstr "Activer l'économiseur d'écran et verrouiller" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "Gestion de la session XFCE" msgid "Special items and actions for XFCE environment" msgstr "Éléments et actions spécifiques à l'environnement XFCE" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "Hôtes SSH" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "Ajouter les hôtes SSH trouvés dans ~/.ssh/config." msgid "SSH host" msgstr "Hôte SSH" msgid "Connect" msgstr "Se connecter" msgid "Connect to SSH host" msgstr "Se connecter à un hôte SSH" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "Hôtes SSH tels qu'indiqués dans ~/.ssh/config" msgid "No D-Bus connection to desktop session" msgstr "Aucune connexion D-Bus vers la session de bureau" msgid "GNOME Keyring" msgstr "Trousseau GNOME" msgid "KWallet" msgstr "KWallet" msgid "Unencrypted File" msgstr "Fichier non chiffré" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "La commande n'est pas disponible dans « %s »" msgid "Document Templates" msgstr "Modèles de documents" msgid "Create new documents from your templates" msgstr "Créer de nouveaux documents depuis vos modèles" #, python-format msgid "%s template" msgstr "Modèle %s" msgid "Empty File" msgstr "Fichier vide" msgid "New Folder" msgstr "Nouveau dossier" msgid "Create New Document..." msgstr "Créer un nouveau document..." msgid "Create a new document from template" msgstr "Créer un nouveau document depuis un modèle" msgid "Create Document In..." msgstr "Créer un nouveau document dans..." msgid "Textfiles" msgstr "Fichiers texte" msgid "Append To..." msgstr "Ajouter à..." msgid "Append..." msgstr "Ajouter..." msgid "Write To..." msgstr "Écrire dans..." msgid "Get Text Contents" msgstr "Obtenir le contenu texte" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "Actions du gestionnaire de fichiers Thunar" msgid "Select in File Manager" msgstr "Sélectionner dans le gestionnaire de fichiers" msgid "Show Properties" msgstr "Afficher les propriétés" msgid "Show information about file in file manager" msgstr "" "Affiche les informations sur le fichier dans le gestionnaire de fichiers" msgid "Send To..." msgstr "Envoyer à..." msgid "Symlink In..." msgstr "Lien symbolique dans..." msgid "Create a symlink to file in a chosen location" msgstr "Créer un lien symbolique vers le fichier vers l'emplacement choisi" msgid "Empty Trash" msgstr "Vider la corbeille" msgid "Thunar Send To Objects" msgstr "Objets envoyés par Thunar" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Contacts et actions de Thunderbird/Icedove" msgid "Compose New Email" msgstr "Composer un nouveau courriel" msgid "Compose a new message in Thunderbird" msgstr "Composer un nouveau message dans Thunderbird" #, fuzzy msgid "Attach in Email To..." msgstr "Envoyer par courriel à..." #, fuzzy msgid "Compose Email With" msgstr "Composer un courriel" #, fuzzy msgid "Compose a new message using the text as body" msgstr "Composer un nouveau message dans Thunderbird" msgid "Thunderbird Address Book" msgstr "Carnet d'adresses de Thunderbird" msgid "Contacts from Thunderbird Address Book" msgstr "Contacts du carnet d'adresses de Thunderbird" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Top" msgid "Show running tasks and allow sending signals to them" msgstr "" "Affiche les tâches en cours d'exécution et permet de leur envoyer un signal" msgid "Sort Order" msgstr "Ordre de tri" msgid "Commandline" msgstr "Ligne de commande" msgid "CPU usage (descending)" msgstr "Utilisation du processeur (ordre descendant)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Utilisation de la mémoire (ordre descendant)" msgid "Send Signal..." msgstr "Envoyer un signal..." msgid "Signals" msgstr "Signaux" msgid "Running Tasks" msgstr "Tâches en cours d'exécution" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid : %(pid)s cpu : %(cpu)g%% mem : %(mem)g%% durée : %(time)s" msgid "Running tasks for current user" msgstr "Tâches en cours d'exécution pour l'utilisateur courant" msgid "Trash" msgstr "Corbeille" msgid "Access trash contents" msgstr "Accéder au contenu de la corbeille" msgid "Move to Trash" msgstr "Déplacer vers la corbeille" msgid "Move this file to trash" msgstr "Déplacer le fichier vers la corbeille" msgid "Restore" msgstr "Restaurer" msgid "Move file back to original location" msgstr "Déplacer le fichier vers son emplacement original" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "La corbeille est vide" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "La corbeille contient un fichier" msgstr[1] "La corbeille contient %(num)s fichiers" msgid "Triggers" msgstr "Raccourcis déclencheurs" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Attribuer des raccourcis clavier globaux (déclencheurs) aux éléments créés " "avec les commandes composées." msgid "Add Trigger..." msgstr "Ajouter un raccourci déclencheur..." msgid "Remove Trigger" msgstr "Supprimer le raccourci déclencheur" msgid "URL Actions" msgstr "Actions sur les URL" msgid "Download and Open" msgstr "Télécharger et ouvrir" msgid "Download To..." msgstr "Télécharger vers..." msgid "Download URL to a chosen location" msgstr "Télécharger l'URL vers un emplacement choisi" msgid "Wikipedia" msgstr "Wikipedia" msgid "Search in Wikipedia" msgstr "Rechercher sur Wikipedia" msgid "Wikipedia language" msgstr "Langue de Wikipedia" #. TRANS: Default wikipedia language code msgid "en" msgstr "fr" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Rechercher ce terme sur %s.wikipedia.org" msgid "Window List" msgstr "Liste des fenêtres" msgid "All windows on all workspaces" msgstr "Toutes les fenêtres de tous les espaces de travail" msgid "Activate" msgstr "Activer" msgid "Shade" msgstr "Plier" msgid "Unshade" msgstr "Déplier" msgid "Minimize" msgstr "Minimiser" msgid "Unminimize" msgstr "Restaurer" msgid "Maximize" msgstr "Maximiser" msgid "Unmaximize" msgstr "Restaurer" msgid "Maximize Vertically" msgstr "Maximiser verticalement" msgid "Unmaximize Vertically" msgstr "Restaurer verticalement" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Fenêtre sur %(wkspc)s" msgid "Frontmost Window" msgstr "Fenêtre au premier plan" msgid "Next Window" msgstr "Fenêtre suivante" msgid "Jump to this window's workspace and focus" msgstr "Afficher la fenêtre et aller sur son espace de travail" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "%d fenêtre" msgstr[1] "%d fenêtres" msgid "Active workspace" msgstr "Activer l'espace de travail" msgid "Jump to this workspace" msgstr "Aller à cet espace de travail" msgid "Workspaces" msgstr "Espaces de travail" msgid "Volumes and Disks" msgstr "Volumes et disques" msgid "Mounted volumes and disks" msgstr "Volumes et disques montés" #, python-format msgid "Volume mounted at %s" msgstr "Volume monté sur %s" msgid "Unmount" msgstr "Démonter" msgid "Unmount this volume" msgstr "Démonter ce volume" msgid "Eject" msgstr "Éjecter" msgid "Unmount and eject this media" msgstr "Démonter et éjecter ce média" msgid "Show Text" msgstr "Afficher le texte" msgid "Display text in a window" msgstr "Afficher le texte dans une fenêtre" msgid "Large Type" msgstr "Afficher en gros" msgid "Show Notification" msgstr "Afficher la notification" msgid "Tracker" msgstr "Tracker" msgid "Tracker desktop search integration" msgstr "Intégration avec le moteur de recherche Tracker pour le bureau" msgid "Search in Tracker" msgstr "Rechercher dans Tracker" msgid "Open Tracker Search Tool and search for this term" msgstr "Ouvrir le moteur de recherche Tracker et rechercher ce terme" msgid "Get Tracker Results..." msgstr "Obtenir les résultats de Tracker..." msgid "Show Tracker results for query" msgstr "Affiche les résultats de la requête de Tracker" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "Résultats pour « %s »" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "Localiser des fichiers" msgid "Search filesystem using locate" msgstr "Rechercher dans le système de fichiers en utilisant locate" msgid "Ignore case distinctions when searching files" msgstr "Ignorer la casse lors des recherches de fichiers" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Marque-pages de Firefox" msgid "Index of Firefox bookmarks" msgstr "Index des marque-pages de Firefox" #, fuzzy msgid "Firefox Keywords" msgstr "Marque-pages de Firefox" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "Rechercher sur le Web en utilisant les moteurs de recherche OpenSearch" msgid "Search With..." msgstr "Rechercher avec..." msgid "Search For..." msgstr "Rechercher..." #, fuzzy msgid "Search Terms" msgstr "Moteurs de recherche" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Veuillez utiliser « %s »" #, fuzzy msgid "Resume playback" msgstr "Reprendre la lecture dans Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Suivant" #, fuzzy msgid "Skip to next track" msgstr "Aller à la piste suivante dans Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Précédent" #, fuzzy msgid "Skip to previous track" msgstr "Aller à la piste précédente dans Audacious" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "Accéder aux contacts de Pidgin" msgid "Show offline contacts" msgstr "Afficher les contacts déconnectés" msgid "Open Chat" msgstr "Ouvrir la fenêtre de discussion" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d caractère)" msgstr[1] "%s (%d caractères)" msgid "Send Message..." msgstr "Envoyer un message..." msgid "Available" msgstr "Disponible" msgid "Away" msgstr "Absent" msgid "Pidgin Contacts" msgstr "Contacts Pidgin" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Raccourcir les liens" msgid "Create short aliases of long URLs" msgstr "Créer des raccourcis pour les URLs longues" msgid "Error" msgstr "Erreur" msgid "Shorten With..." msgstr "Raccourcir avec..." msgid "Services" msgstr "Services" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "" "Jouer, mettre en attente les pistes et parcourir la bibliothèque musicale" msgid "Include artists in top level" msgstr "Inclure les artistes au premier niveau" msgid "Include albums in top level" msgstr "Inclure les albums au premier niveau" msgid "Play tracks in Rhythmbox" msgstr "Lire les pistes dans Rhythmbox" msgid "Add tracks to the play queue" msgstr "Ajouter les pistes à la file d'attente de lecture" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "par %(artist)s sur %(album)s" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "par %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Pistes de %s" msgid "Albums" msgstr "Albums" msgid "Music albums in Rhythmbox Library" msgstr "Albums de la bibliothèque Rhythmbox" msgid "Artists" msgstr "Artistes" msgid "Music artists in Rhythmbox Library" msgstr "Artistes de la bibliothèque Rhythmbox" msgid "Songs" msgstr "Chansons" msgid "Songs in Rhythmbox library" msgstr "Chansons de la bibliothèque Rhythmbox" msgid "Getting Things GNOME" msgstr "Getting Things GNOME" msgid "Browse and create new tasks in GTG" msgstr "Parcourir et créer de nouvelles tâches dans GTG" #, python-format msgid "due: %s" msgstr "échéance : %s" #, python-format msgid "start: %s" msgstr "début : %s" #, python-format msgid "tags: %s" msgstr "étiquette : %s" msgid "Open task in Getting Things GNOME!" msgstr "Ouvrir la tâche dans Getting Things GNOME!" msgid "Delete" msgstr "Supprimer" msgid "Permanently remove this task" msgstr "Supprime cette tâche pour toujours" msgid "Mark Done" msgstr "Marquer comme réalisée" msgid "Mark this task as done" msgstr "Marque cette tâche comme réalisée" msgid "Dismiss" msgstr "Annuler" msgid "Mark this task as not to be done anymore" msgstr "Marque cette tâche comme n'étant plus à faire" msgid "Create Task" msgstr "Créer une tâche" msgid "Create new task in Getting Things GNOME" msgstr "Crée une nouvelle tâche dans Getting Things GNOME" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "Rechercher dans Devhelp" msgid "Empathy" msgstr "Empathy" msgid "Access to Empathy Contacts" msgstr "Accéder aux contacts Empathy" msgid "Busy" msgstr "Occupé" msgid "Not Available" msgstr "Non disponible" msgid "Invisible" msgstr "Invisible" msgid "Offline" msgstr "Déconnecté" msgid "Change Global Status To..." msgstr "Changer le statut global en..." msgid "Empathy Contacts" msgstr "Contacts Empathy" msgid "Empathy Account Status" msgstr "Statut du compte Empathy" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Activation alternative" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Astuce virgule" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Composition de commande" msgid "Mark Default Action" msgstr "Marquer l'action par défaut" msgid "Forget Object" msgstr "Oublier l'élément" msgid "Reset All" msgstr "Tout réinitialiser" msgid "Select Quit" msgstr "Sélectionner quitter" msgid "Select Selected File" msgstr "Sélectionner le fichier sélectionné" msgid "Select Selected Text" msgstr "Sélectionner le texte sélectionné" msgid "Show Help" msgstr "Afficher l'aide" msgid "Show Preferences" msgstr "Afficher les préférences" msgid "Switch to First Pane" msgstr "Basculer vers le premier panneau" msgid "Toggle Text Mode" msgstr "Basculer en mode texte" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Aucun résultat dans %(src)s pour « %(query)s »" msgid "No matches" msgstr "Aucun résultat" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Aucun résultat" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Rendre « %(action)s » par défaut pour « %(object)s »" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "Oublier « %s »" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Afficher l'interface principale" msgid "Show with Selection" msgstr "Afficher avec sélection" #. TRANS: Plugin info fields msgid "Description" msgstr "Description" msgid "Author" msgstr "Auteur" msgid "Version" msgstr "Version" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Le module Python « %s » est requis" msgid "Plugin could not be read due to an error:" msgstr "Le greffon n'a pas pu être lu à cause d'une erreur :" msgid "Content of" msgstr "Contenu de" #. TRANS: Plugin contents header msgid "Sources" msgstr "Sources" #. TRANS: Plugin contents header msgid "Actions" msgstr "Actions" #, python-format msgid "Using encrypted password storage: %s" msgstr "Utilisation d'un enregistrement de mot de passe chiffré : %s" #, python-format msgid "Using password storage: %s" msgstr "Utilisation d'un enregistrement de mot de passe : %s" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Configuration" msgid "Set username and password" msgstr "Configurer le nom d'utilisateur et le mot de passe" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Sélection d'un dossier" msgid "Reset all shortcuts to default values?" msgstr "Réinitialiser tous les raccourcis aux valeurs par défaut ?" msgid "Shortcut" msgstr "Raccourci" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "" "Christophe Benz \n" "Bruno Brouard " msgid "A free software (GPLv3+) launcher" msgstr "Un lanceur d'applications sous licence libre (GPLv3+)" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Ce programme est un logiciel libre ; vous pouvez le redistribuer et/ou\n" "le modifier au titre des clauses de la Licence Publique Générale GNU,\n" "telle que publiée par la Free Software Foundation ; soit la version 3\n" "de la Licence, ou (à votre discrétion) une version ultérieure quelconque.\n" "\n" "Ce programme est distribué dans l'espoir qu'il sera utile, mais SANS AUCUNE\n" "GARANTIE ; sans même une garantie implicite de COMMERCIABILITÉ ou DE\n" "CONFORMITÉ À UNE UTILISATION PARTICULIÈRE. Voir la Licence Publique " "Générale\n" "GNU pour plus de détails.\n" "\n" "Vous devriez avoir reçu un exemplaire de la Licence Publique Générale GNU " "avec\n" "ce programme ; si ce n'est pas le cas, consultez .\n" "\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Impossible de trouver une instance de Kupfer" #~ msgid "Compose Email" #~ msgstr "Composer un courriel" #~ msgid "Send in Email To..." #~ msgstr "Envoyer par courriel à..." #~ msgid "Type to search %s" #~ msgstr "Saisir pour rechercher dans %s" #~ msgid "No action" #~ msgstr "Aucune action" #~ msgid "GNOME Terminal Profiles" #~ msgstr "Profils du terminal GNOME" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Lancer les profils du terminal GNOME" #~ msgid "Multihead Support" #~ msgstr "Prise en charge multi-écrans" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Calculer les expressions commençant par « = »" #~ msgid "Epiphany Bookmarks" #~ msgstr "Marque-pages d'Epiphany" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Index des marque-pages d'Epiphany" #~ msgid "Include visited sites" #~ msgstr "Inclure les sites visités" #~ msgid "Selected File" #~ msgstr "Fichier sélectionné" #~ msgid "" #~ "Provides current nautilus selection, using Kupfer's Nautilus Extension" #~ msgstr "" #~ "Accéder à la sélection actuelle de nautilus grâce au greffon Nautilus de " #~ "Kupfer" #~ msgid "Selected File \"%s\"" #~ msgstr "Fichier sélectionné « %s »" #~ msgid "Selected Files" #~ msgstr "Fichiers sélectionnés" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Reprendre la lecture dans Rhythmbox" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Met Rhythmbox en pause" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Aller à la piste suivante dans Rhythmbox" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Aller à la piste précédente dans Rhythmbox" #~ msgid "Search the Web" #~ msgstr "Rechercher sur le Web" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Documents utilisés récemment dans Abiword" #~ msgid "Abiword Recent Items" #~ msgstr "Éléments récents d'Abiword" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "Interface avec le gestionnaire de paquets APT" #~ msgid "Installation method" #~ msgstr "Méthode d'installation" #~ msgid "Show Package Information" #~ msgstr "Afficher les informations du paquet" #~ msgid "Install" #~ msgstr "Installer" #~ msgid "Install package using the configured method" #~ msgstr "Installer le paquet suivant la méthode configurée" #~ msgid "Packages matching \"%s\"" #~ msgstr "Paquets correspondant à « %s »" #~ msgid "Search Package Name..." #~ msgstr "Rechercher un paquet par nom..." #~ msgid "Ascii & Unicode Icon Set" #~ msgstr "Ensemble d'icônes ASCII & unicode" #~ msgid "" #~ "Provides the Ascii and Unicode icon sets that use letters and symbols to " #~ "produce icons for the objects found in Kupfer." #~ msgstr "" #~ "Génère les ensembles d'icônes ASCII et unicode qui utilisent les lettres " #~ "et les symboles pour produire des icônes pour les objets trouvés dans " #~ "Kupfer." #~ msgid "Ascii" #~ msgstr "ASCII" #~ msgid "Unicode" #~ msgstr "Unicode" #~ msgid "Chromium Bookmarks" #~ msgstr "Marque-pages de Chromium" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Index des marque-pages de Chromium" #~ msgid "Claws Mail" #~ msgstr "Claws Mail" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Contacts et actions pour Claws Mail" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Composer un nouveau message dans Claws Mail" #~ msgid "Receive All Email" #~ msgstr "Relever tous les courriels" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "Relever les nouveaux messages pour tous les comptes dans Claws Mail" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Composer un message dans Claws Mail et joindre le fichier" #~ msgid "Claws Mail Address Book" #~ msgstr "Carnet d'adresses de Claws Mail" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Contacts depuis le carnet d'adresses de Claws Mail" #~ msgid "Configure a custom terminal emulator" #~ msgstr "Configurer un émulateur de terminal personnalisé" #~ msgid "Custom Theme" #~ msgstr "Thème personnalisé" #~ msgid "Use a custom color theme" #~ msgstr "Utiliser un thème de couleurs personnalisé" #~ msgid "Theme:" #~ msgstr "Thème :" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Contacts d'Evolution" #~ msgid "Compose a new message in Evolution" #~ msgstr "Composer un message dans Evolution" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Composer un message dans Evolution et joindre le fichier" #~ msgid "Evolution Address Book" #~ msgstr "Carnet d'adresses d'Evolution" #~ msgid "Filezilla" #~ msgstr "Filezilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Afficher les sites et gérer les adresses ftp par Filezilla" #~ msgid "Open Site with Filezilla" #~ msgstr "Ouvrir le site avec Filezilla" #~ msgid "Filezilla Sites" #~ msgstr "Sites Filezilla" #~ msgid "Sites from Filezilla" #~ msgstr "Sites de Filezilla" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Accéder aux contacts Gajim" #~ msgid "Free for Chat" #~ msgstr "Libre pour discuter" #~ msgid "Gajim Contacts" #~ msgstr "Contacts Gajim" #~ msgid "Gajim Account Status" #~ msgstr "Statut du compte Gajim" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Charger les contacts et composer un courriel dans Gmail" #~ msgid "Load contacts' pictures" #~ msgstr "Charger les images des contacts" #~ msgid "Load additional information" #~ msgstr "Charger des informations supplémentaires" #~ msgid "Work email" #~ msgstr "Courriel professionnel" #~ msgid "Home email" #~ msgstr "Courriel personnel" #~ msgid "Other email" #~ msgstr "Autre courriel" #~ msgid "Work address" #~ msgstr "Adresse professionnelle" #~ msgid "Home address" #~ msgstr "Adresse personnelle" #~ msgid "Other address" #~ msgstr "Autre adresse" #~ msgid "Car phone" #~ msgstr "Téléphone de voiture" #~ msgid "Fax" #~ msgstr "Fax" #~ msgid "Home phone" #~ msgstr "Téléphone du domicile" #~ msgid "Home fax" #~ msgstr "Fax du domicile" #~ msgid "Internal phone" #~ msgstr "Téléphone interne" #~ msgid "Mobile" #~ msgstr "Portable" #~ msgid "Other" #~ msgstr "Autre" #~ msgid "VOIP" #~ msgstr "VOIP" #~ msgid "Work phone" #~ msgstr "Téléphone professionnel" #~ msgid "Work fax" #~ msgstr "Fax professionnel" #~ msgid "Compose Email in Gmail" #~ msgstr "Composer un courriel dans Gmail" #~ msgid "Open web browser and compose new email in Gmail" #~ msgstr "Ouvrir le navigateur et composer un nouveau courriel dans Gmail" #~ msgid "Edit Contact in Gmail" #~ msgstr "Modifier les contacts dans Gmail" #~ msgid "Open web browser and edit contact in Gmail" #~ msgstr "Ouvrir le navigateur et modifier les contacts dans Gmail" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Contacts des services Google (Gmail)" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Afficher les albums et envoyer les fichiers vers Picasa" #~ msgid "Users to show: (,-separated)" #~ msgstr "Utilisateurs à afficher : (séparés par une virgule)" #~ msgid "Load user and album icons" #~ msgstr "Charger les icônes des utilisateurs et des albums" #~ msgid "Uploading Pictures" #~ msgstr "Envoyer des images" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Envoyer des images vers l'album Web Picasa" #~ msgid "Creating album:" #~ msgstr "Création de l'album :" #~ msgid "Album created by Kupfer" #~ msgstr "Album créé par Kupfer" #~ msgid "File:" #~ msgstr "Fichier :" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "Un album" #~ msgstr[1] "%(num)d albums" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "une photo" #~ msgstr[1] "%(num)s photos" #~ msgid "Upload to Picasa Album..." #~ msgstr "Envoyer dans l'album Picasa..." #~ msgid "Upload files to Picasa album" #~ msgstr "Envoyer les fichiers vers l'album Picasa" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Envoyer vers Picasa en tant que nouvel album" #~ msgid "Create album from selected local directory" #~ msgstr "Créer un album à partir du dossier local sélectionné" #~ msgid "Picasa Albums" #~ msgstr "Albums Picasa" #~ msgid "User albums in Picasa" #~ msgstr "Albums de l'utilisateur dans Picasa" #~ msgid "Google Search" #~ msgstr "Rechercher sur Google" #~ msgid "Search Google with results shown directly" #~ msgstr "Récupérer les résultats de Google et les afficher directement" #~ msgid "Show More Results For \"%s\"" #~ msgstr "Afficher plus de résultats pour « %s »" #~ msgid "%s total found" #~ msgstr "%s résultats trouvés au total" #~ msgid "Gwibber" #~ msgstr "Gwibber" #~ msgid "" #~ "Microblogging with Gwibber. Allows sending and receiving messages from " #~ "social networks like Twitter, Identi.ca etc. Requires the package " #~ "'gwibber-service'." #~ msgstr "" #~ "Micro-blogage avec Gwibber. Permet l'envoi et la réception de messages à " #~ "partir de réseaux sociaux comme Twitter, Identi.ca, etc. Nécessite le " #~ "paquet « gwibber-service »." #~ msgid "Maximum number of messages to show" #~ msgstr "Nombre maximum de messages à afficher" #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s sur %(service)s" #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s le %(when)s sur %(where)s" #~ msgid "Send Message" #~ msgstr "Envoyer un message" #~ msgid "Send message to all Gwibber accounts" #~ msgstr "Envoie un message vers tous les comptes Gwibber" #~ msgid "Send Message To..." #~ msgstr "Envoyer un message à..." #~ msgid "Send message to a Gwibber account" #~ msgstr "Envoie un message vers un compte Gwibber" #~ msgid "Send message to selected Gwibber account" #~ msgstr "Envoie un message vers le compte Gwibber sélectionné" #~ msgid "Reply..." #~ msgstr "Répondre..." #~ msgid "Delete Message" #~ msgstr "Supprimer un message" #~ msgid "Send Private Message..." #~ msgstr "Envoyer un message privé..." #~ msgid "Send direct message to user" #~ msgstr "Envoie un message direct à l'utilisateur" #~ msgid "Retweet" #~ msgstr "Renvoyer un tweet" #~ msgid "Retweet To..." #~ msgstr "Renvoyer un tweet à..." #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Renvoyer un tweet à tous les comptes dans Gwibber" #~ msgid "Retweet message to a Gwibber account" #~ msgstr "Renvoyer un tweet vers un compte Gwibber" #~ msgid "Open in Browser" #~ msgstr "Ouvrir dans le navigateur" #~ msgid "Open message in default web browser" #~ msgstr "Ouvre le message dans le navigateur Web par défaut" #~ msgid "Gwibber Accounts" #~ msgstr "Comptes Gwibber" #~ msgid "Accounts configured in Gwibber" #~ msgstr "Comptes configurés dans Gwibber" #~ msgid "Gwibber Messages" #~ msgstr "Messages Gwibber" #~ msgid "Recent messages received by Gwibber" #~ msgstr "Messages récents reçus par Gwibber" #~ msgid "Gwibber Messages for %s" #~ msgstr "Message Gwibber vers %s" #~ msgid "Gwibber Streams" #~ msgstr "Flux Gwibber" #~ msgid "Streams configured in Gwibber" #~ msgstr "Flux configurés dans Gwibber" #~ msgid "Gwibber Messages in %s" #~ msgstr "Messages Gwibber dans %s" #~ msgid "Gwibber (Simple)" #~ msgstr "Gwibber (simple)" #~ msgid "Send updates via the microblogging client Gwibber" #~ msgstr "Envoie des mises à jour via le client de micro-blogage Gwibber" #~ msgid "Send Update" #~ msgstr "Envoyer des mises à jour" #~ msgid "Unable to activate Gwibber service" #~ msgstr "Impossible d'activer le service Gwibber" #~ msgid "OpenOffice / LibreOffice" #~ msgstr "OpenOffice / LibreOffice" #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Documents récemment utilisés dans OpenOffice/LibreOffice" #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "Éléments récents OpenOffice/LibreOffice" #~ msgid "Opera Mail" #~ msgstr "Opera Mail" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Contacts et actions pour Opera Mail" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Composer un nouveau message dans Opera Mail" #~ msgid "Opera Mail Contacts" #~ msgstr "Contacts Opera Mail" #~ msgid "Contacts from Opera Mail" #~ msgstr "Contacts depuis Opera Mail" #~ msgid "Opera Bookmarks" #~ msgstr "Marque-pages d'Opera" #~ msgid "Index of Opera bookmarks" #~ msgstr "Liste des marque-pages Opera" #~ msgid "PuTTY Sessions" #~ msgstr "Sessions PuTTY" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Accès rapide aux sessions PuTTY" #~ msgid "Start Session" #~ msgstr "Démarrer la session" #~ msgid "reStructuredText" #~ msgstr "reStructuredText" #~ msgid "Render reStructuredText and show the result" #~ msgstr "Rendre avec reStructuredText et afficher le résultat" #~ msgid "View as HTML Document" #~ msgstr "Voir comme un document HTML" #~ msgid "System Services" #~ msgstr "Services système" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "" #~ "Démarre, arrête ou redémarre les services système via les scripts init" #~ msgid "Sudo-like Command" #~ msgstr "Commande de type sudo" #~ msgid "Start Service" #~ msgstr "Démarrer le service" #~ msgid "Stop Service" #~ msgstr "Arrêter le service" #~ msgid "%s Service" #~ msgstr "Service %s" #~ msgid "Show QRCode" #~ msgstr "Afficher le code QR" #~ msgid "Display text as QRCode in a window" #~ msgstr "Afficher du texte sous la forme de code QR dans une fenêtre" #~ msgid "Access to Skype contacts" #~ msgstr "Accéder aux contacts Skype" #~ msgid "Skype Me" #~ msgstr "Appelez moi" #~ msgid "Logged Out" #~ msgstr "Déconnecté" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Appeler" #~ msgid "Place a call to contact" #~ msgstr "Faire un appel vers un contact" #~ msgid "Skype Contacts" #~ msgstr "Contacts Skype" #~ msgid "Skype Statuses" #~ msgstr "Statuts Skype" #~ msgid "Tracker 0.6" #~ msgstr "Tracker 0.6" #~ msgid "Tracker tags" #~ msgstr "Étiquettes de Tracker" #~ msgid "Tracker Tags" #~ msgstr "Étiquettes de Tracker" #~ msgid "Browse Tracker's tags" #~ msgstr "Parcourir les étiquettes de Tracker" #~ msgid "Tag %s" #~ msgstr "Étiquette %s" #~ msgid "Objects tagged %s with Tracker" #~ msgstr "Éléments étiquetés %s avec Tracker" #~ msgid "Add Tag..." #~ msgstr "Ajouter une étiquette..." #~ msgid "Add tracker tag to file" #~ msgstr "Ajoute l'étiquette Tracker au fichier" #~ msgid "Remove Tag..." #~ msgstr "Retirer l'étiquette..." #~ msgid "Remove tracker tag from file" #~ msgstr "Retirer l'étiquette Tracker du fichier" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Volumes de l'historique de TrueCrypt" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "Volume TrueCrypt : %(file)s" #~ msgid "Mount Volume" #~ msgstr "Monter un volume" #~ msgid "Mount in Truecrypt" #~ msgstr "Monter avec Truecrypt" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Essaie de monter le fichier en tant que volume Truecrypt" #~ msgid "Dismount All Volumes" #~ msgstr "Démonter tous les volumes" #~ msgid "TrueCrypt Volumes" #~ msgstr "Volumes TrueCrypt" #~ msgid "Terminal Server Client" #~ msgstr "Terminal Server Client" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Session sauvegardée dans Terminal Server Client" #~ msgid "TSClient sessions" #~ msgstr "Sessions TSClient" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Sessions sauvegardées dans Terminal Server Client" #~ msgid "Vim" #~ msgstr "Vim" #~ msgid "Recently used documents in Vim" #~ msgstr "Documents utilisés récemment dans Vim" #~ msgid "Vim Recent Documents" #~ msgstr "Documents récents Vim" #~ msgid "Close (Save All)" #~ msgstr "Fermer (tout enregistrer)" #~ msgid "Send..." #~ msgstr "Envoyer..." #~ msgid "Send ex command" #~ msgstr "Envoyer une commande en mode ex" #~ msgid "Insert in Vim..." #~ msgstr "Insérer dans Vim..." #~ msgid "Active Vim Sessions" #~ msgstr "Sessions Vim actives" #~ msgid "Vim Session %s" #~ msgstr "Sessions Vim %s" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Marque-pages et actions pour Vinagre" #~ msgid "Start Vinagre Session" #~ msgstr "Démarrer une session Vinagre" #~ msgid "Vinagre Bookmarks" #~ msgstr "Marque-pages Vinagre" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "Contrôle les machines virtuelles VirtualBox. Supporte à la fois la " #~ "version de Sun et l'édition Open Source." #~ msgid "Force use CLI interface" #~ msgstr "Obliger l'utilisation de l'interface en ligne de commande" #~ msgid "Power On" #~ msgstr "Allumer" #~ msgid "Power On Headless" #~ msgstr "Allumer sans affichage" #~ msgid "Send Power Off Signal" #~ msgstr "Envoyer le signal d'extinction" #~ msgid "Reboot" #~ msgstr "Redémarrer" #~ msgid "Resume" #~ msgstr "Reprendre" #~ msgid "Save State" #~ msgstr "Sauvegarder l'état" #~ msgid "Power Off" #~ msgstr "Éteindre" #~ msgid "VirtualBox Machines" #~ msgstr "Machines VirtualBox" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "Accède aux pages stockées dans Zim - Un wiki pour le bureau" #~ msgid "Page names start with :colon" #~ msgstr "Les noms des pages commencent par « : » (deux points)" #~ msgid "Default page name for quick notes" #~ msgstr "Nom de la page par défaut pour les notes rapides" #~ msgid "Note %x %X" #~ msgstr "Note %x %X" #~ msgid "" #~ "Strftime tags can be used: %H - hour, %M - minutes, etc\n" #~ "Please check python documentation for details.\n" #~ "NOTE: comma will be replaced by _" #~ msgstr "" #~ "Des étiquettes strftime peuvent être utilisées : %H - heure, %M - " #~ "minutes, etc.\n" #~ "Consultez la documentation python pour plus de détails.\n" #~ "Note : les virgules seront remplacées par _" #~ msgid "Default namespace for quick notes" #~ msgstr "Espace de nom par défaut pour les notes rapides" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Page Zim du bloc-notes « %s »" #~ msgid "Create Zim Page" #~ msgstr "Créer une page Zim" #~ msgid "Create page in default notebook" #~ msgstr "Créer une page dans le bloc-notes par défaut" #~ msgid "Create Zim Page In..." #~ msgstr "Créer une page Zim dans..." #~ msgid "Insert QuickNote into Zim" #~ msgstr "Insérer des notes rapides dans Zim" #~ msgid "Quick note selected text into Zim notebook" #~ msgstr "" #~ "Créer une note rapide à partir du texte sélectionné dans les bloc-notes " #~ "de Zim" #~ msgid "Create Subpage..." #~ msgstr "Créer une sous-page..." #~ msgid "Zim Notebooks" #~ msgstr "Bloc-notes Zim" #~ msgid "Zim Pages" #~ msgstr "Pages Zim" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Pages stockées dans les bloc-notes de Zim" kupfer-328/po/gl.po000066400000000000000000001732471500175051100142550ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # Fran Diéguez , 2010. # Oscar Blanco , 2012. # msgid "" msgstr "" "Project-Id-Version: kupfer\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2012-08-10 17:37+0200\n" "Last-Translator: Oscar Blanco \n" "Language-Team: Galician \n" "Language: gl\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-Poedit-Language: Galician\n" "X-Generator: Gtranslator 2.91.5\n" msgid "User credentials" msgstr "Credenciais do usuario" msgid "_User:" msgstr "_Usuario:" msgid "_Password:" msgstr "C_ontrasinal:" msgid "_Change" msgstr "_Cambiar" msgid "Set Keyboard Shortcut" msgstr "Estabelecer o atallo do teclado" msgid "Please press desired key combination" msgstr "Prema a combinación de teclas desexada" msgid "Keybinding could not be bound" msgstr "Non foi posíbel ligar a combinación de teclas" msgid "Kupfer Preferences" msgstr "Preferencias de Kupfer" msgid "Start automatically on login" msgstr "Abrir automaticamente ao iniciar a sesión " msgid "Start" msgstr "Iniciar" msgid "Show icon in notification area" msgstr "Mostrar a icona na área de notificacións" msgid "Icon set:" msgstr "Conxunto de iconas:" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" msgid "Terminal emulator:" msgstr "Emulador da terminal:" msgid "Desktop Environment" msgstr "Contorno do escritorio" msgid "General" msgstr "Xeral" msgid "Global Keyboard Shortcuts" msgstr "Atallos de teclado globais" msgid "Reset" msgstr "Restabelecer" msgid "Browser Keyboard Shortcuts" msgstr "Atallos de teclado do explorador" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "Usar ordes dunha soa tecla (espazo, /, punto, coma, etc.)" msgid "Keyboard" msgstr "Teclado" msgid "Plugins" msgstr "Engadidos" msgid "Inclusion in Top Level Searches" msgstr "Incluír nas búsquedas de nivel superior" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "As fontes sinaladas teñen os seus obxetos incluidos nas búsquedas de nivel " "superior.\n" "Os contidos dunha fonte desmarcada só están dispoñibeis atopando o seu " "subcatálogo." msgid "Indexed Folders" msgstr "Cartafois indexados" msgid "Folders whose files are always available in the catalog." msgstr "Cartafois cuxos ficheiros están sempre dipoñibeis no catálogo." msgid "Catalog" msgstr "Catálogo" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Iniciador de aplicativos" msgid "Convenient command and access tool for applications and documents" msgstr "Ferramenta cómoda para controlar e acceder a aplicativos e documentos" msgid "Execute in Kupfer" msgstr "Executar en Kupfer" msgid "Saved Kupfer Command" msgstr "Gardouse a orde de Kupfer" #, python-format msgid "Could not to carry out '%s'" msgstr "Non foi posíbel executar «%s»" #, python-format msgid "\"%s\" produced a result" msgstr "«%s» xerou un resultado" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Non ten permisos para executar «%s» (non é executábel)" #, python-format msgid "Command in \"%s\" is not available" msgstr "A orde en «%s» non está dispoñíbel" #, python-format msgid "Keyboard relay is active for display %s" msgstr "A transmisión do teclado está activa para a pantalla %s" msgid "do not present main interface on launch" msgstr "non mostrar a interface principal ao iniciar" msgid "list available plugins" msgstr "lista de engadidos dispoñíbeis" msgid "enable debug info" msgstr "activar a información de depuración" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "executar plugin-helper" msgid "show usage help" msgstr "mostrar a axuda" msgid "show version information" msgstr "mostrar a información da versión" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Uso: kupfer [OPCIÓNS | FICHEIRO ...]" msgid "Available plugins:" msgstr "Engadidos dispoñíbeis:" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "Teclear para buscar" #, python-format msgid "%s is empty" msgstr "%s está baleiro" msgid "Text" msgstr "Texto" msgid "Run after Delay..." msgstr "Executar despois do atraso..." msgid "Perform command after a specified time interval" msgstr "Executar unha orde despois dun intervalo de tempo especificado" msgid "Multiple Objects" msgstr "Obxectos múltiples" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s obxecto" msgstr[1] "%s obxectos" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "descoñecido" msgid "Aim" msgstr "Aim" msgid "Google Talk" msgstr "Google Talk" msgid "ICQ" msgstr "ICQ" msgid "MSN" msgstr "MSN" msgid "QQ" msgstr "QQ" msgid "Yahoo" msgstr "Yahoo" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "%s non soporta esta operación" msgid "Can not be used with multiple objects" msgstr "Non se pode usar con múltiples obxetos" msgid "Open" msgstr "Abrir" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Non existe un aplicativo predefinido para %(file)s (%(type)s)" #, python-format msgid "Please use \"%s\"" msgstr "Use «%s»" msgid "Set Default Application..." msgstr "Estabelecer o aplicativo predefinido..." msgid "Open with default application" msgstr "Abrir co aplicativo predefinido" msgid "Reveal" msgstr "Mostrar" msgid "Open parent folder" msgstr "Abrir o cartafol pai" msgid "Open Terminal Here" msgstr "Abrir o terminal aquí" msgid "Open this location in a terminal" msgstr "Abrir esta localización no terminal" msgid "Run in Terminal" msgstr "Executar no terminal" msgid "Run (Execute)" msgstr "Executar" msgid "Run this program in a Terminal" msgstr "Executar este programa no terminal" msgid "Run this program" msgstr "Executar este programa" msgid "Go To" msgstr "Ir a" msgid "Open URL" msgstr "Abrir o URL" msgid "Open URL with default viewer" msgstr "Abrir o URL co visualizador predefinido" msgid "Launch" msgstr "Iniciar" msgid "Show application window" msgstr "Mostrar a xanela do aplicativo" msgid "Launch application" msgstr "Iniciar o aplicativo" msgid "Launch Again" msgstr "Iniciar outra vez" msgid "Launch another instance of this application" msgstr "Iniciar outra instancia deste aplicativo" msgid "Close" msgstr "Pechar" msgid "Attempt to close all application windows" msgstr "Tentar pechar todas as xanelas do aplicativo" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Executar" msgid "Perform command" msgstr "Executar a orde" msgid "(Empty Text)" msgstr "(Texto baleiro)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "«%(text)s»" msgstr[1] "(%(num)d liñas) «%(text)s»" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s e outros." #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Fonte recursiva de %(dir)s, (%(levels)d niveis)" #, python-format msgid "Directory source %s" msgstr "Directorio fonte %s" msgid "Home Folder" msgstr "Cartafol persoal" msgid "Catalog Index" msgstr "Índice do catálogo" msgid "An index of all available sources" msgstr "Un índice de todas as fontes dispoñíbeis" msgid "Root catalog" msgstr "Catálogo raíz" msgid "Please Configure Plugin" msgstr "Configurar o engadido" #, python-format msgid "Plugin %s is not configured" msgstr "O engadido %s non está configurado" #, python-format msgid "Invalid user credentials for %s" msgstr "As credenciais de usuario son incorrectas para %s" msgid "Applications" msgstr "Aplicativos" msgid "All applications and preferences" msgstr "Todos os aplicativos e preferencias" msgid "Applications for Desktop Environment" msgstr "Aplicativos para o contorno do escritorio" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "Abrir con…" msgid "Open with any application" msgstr "Abrir con calquera aplicativo" msgid "Set default application to open this file type" msgstr "Estabelecer o aplicativo predefinido para abrir este tipo de ficheiro" #, fuzzy msgid "Reset Associations" msgstr "Accións sobre os URL" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "Arquivadores profundos" msgid "Allow browsing inside compressed archive files" msgstr "Permitir a exploración dos ficheiros nos arquivos comprimidos" #, python-format msgid "Content of %s" msgstr "Contido de %s" msgid "Archive Manager" msgstr "Xestor de arquivadores" msgid "Use Archive Manager actions" msgstr "Usar as accións do Xestor de arquivadores" msgid "Compressed archive type for 'Create Archive In'" msgstr "Tipo de arquivo comprimido para «Crear un arquivo en»" msgid "Extract Here" msgstr "Extraer aquí" msgid "Extract compressed archive" msgstr "Extraer o arquivo comprimido" msgid "Create Archive" msgstr "Crear un arquivo" msgid "Create a compressed archive from folder" msgstr "Crear o arquivo comprimido dun cartafol" msgid "Create Archive In..." msgstr "Crear un arquivo en..." #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Arquivo" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "Controlar a reprodución e as listas de Audacious" msgid "Include songs in top level" msgstr "Incluír as cancións no nivel superior" msgid "Enqueue" msgstr "Na cola" msgid "Add track to the Audacious play queue" msgstr "Engadir unha pista á cola de reprodución de Audacious" msgid "Dequeue" msgstr "Retirar da cola" msgid "Remove track from the Audacious play queue" msgstr "Eliminar a pista da cola de reprodución de Audacious" msgid "Play" msgstr "Reproducir" msgid "Jump to track in Audacious" msgstr "Ir á pista en Audacious" msgid "Resume playback in Audacious" msgstr "Continuar a reprodución en Audacious" msgid "Pause" msgstr "Deter" msgid "Pause playback in Audacious" msgstr "Deter a reprodución en Audacious" msgid "Next" msgstr "Seguinte" msgid "Jump to next track in Audacious" msgstr "Ir á pista seguinte en Audacious" msgid "Previous" msgstr "Anterior" msgid "Jump to previous track in Audacious" msgstr "Ir á pista anterior en Audacious" msgid "Clear Queue" msgstr "Limpar a cola" msgid "Clear the Audacious play queue" msgstr "Limpar a cola de reprodución de Audacious" msgid "Shuffle" msgstr "Aleatorio" msgid "Toggle shuffle in Audacious" msgstr "Cambiar o modo aleatorio en Audacious" msgid "Repeat" msgstr "Repetir" msgid "Toggle repeat in Audacious" msgstr "Cambiar o modo reprodución en Audacious" msgid "Show Playing" msgstr "Mostrar a reprodución en curso" msgid "Tell which song is currently playing" msgstr "Mostrar que canción está en reprodución" msgid "Playlist" msgstr "Lista de reprodución" msgid "Calculator" msgstr "Calculadora" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "Calcular" msgid "Clipboards" msgstr "Portapapeis" msgid "Recent clipboards and clipboard proxy objects" msgstr "Portapapeis recentes e obxetos proxy do portapapeis" msgid "Number of recent clipboards to remember" msgstr "Número de portapapeis recentes que lembrar" msgid "Include selected text in clipboard history" msgstr "Incluir o texto seleccionado no historial do portapapeis" msgid "Copy selected text to primary clipboard" msgstr "Copiar o texto seleccionado ao portapapeis primario" msgid "Selected Text" msgstr "Texto seleccionado" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Portapapeis «%(desc)s»" msgstr[1] "Portapapeis con %(num)d liñas «%(desc)s»" msgid "Clipboard Text" msgstr "Texto do portapapeis" msgid "Clipboard File" msgstr "Ficheiro do portapapeis" msgid "Clipboard Files" msgstr "Ficheiros do portapapeis" msgid "Clear" msgstr "Limpar" msgid "Remove all recent clipboards" msgstr "Eliminar os elementos recentes do portapeis" msgid "Shell Commands" msgstr "Ordes da Shell" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Executar programas de liña de comandos. As accións marcadas co símbolo «%s» " "executaranse nunha subshell." msgid "Run (Get Output)" msgstr "Executar (obter a información de saída)" msgid "Run program and return its output" msgstr "Executar o programa e mostrar a información de saída" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "Enviar a un comando…" msgid "Run program with object as an additional parameter" msgstr "Executar programa cun obxeto como parámetro adicional" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "Redirixir a un comando…" msgid "Run program and supply text on the standard input" msgstr "Executar o programa e proporcionar texto na saída estándar" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "Filtrar a través dun comando…" msgid "Run command-line programs" msgstr "Executar programas de liña de comandos" msgid "GTK+" msgstr "GTK+" msgid "GNOME Terminal" msgstr "Terminal de GNOME" msgid "XFCE Terminal" msgstr "Terminal de XFCE" msgid "LXTerminal" msgstr "LXTerminal" msgid "X Terminal" msgstr "Terminal X" msgid "Urxvt" msgstr "Urxvt" msgid "Konsole" msgstr "Konsole" msgid "Save As..." msgstr "Gardar como..." #, fuzzy msgid "Restart Kupfer" msgstr "Reiniciar o servizo" msgid "Quit" msgstr "Saír" msgid "Quit Kupfer" msgstr "Saír de Kupfer" msgid "About Kupfer" msgstr "Sobre Kupfer" msgid "Show information about Kupfer authors and license" msgstr "Mostrar a información sobre os autores e a licenza de Kupfer" msgid "Kupfer Help" msgstr "Axuda de Kupfer" msgid "Get help with Kupfer" msgstr "Obter axuda con Kupfer" msgid "Show preferences window for Kupfer" msgstr "Mostrar a xanela de preferencias de Kupfer" msgid "Search Contents" msgstr "Contidos da busca" msgid "Search inside this catalog" msgstr "Buscar neste catálogo" msgid "Copy" msgstr "Copiar" msgid "Copy to clipboard" msgstr "Copiar ao portapapeis" msgid "Rescan" msgstr "Escanear outra vez" msgid "Force reindex of this source" msgstr "Forzar a reindexación desta fonte" msgid "Last Command" msgstr "Última orde" msgid "Internal Kupfer Objects" msgstr "Obxectos internos de Kupfer" msgid "Last Result" msgstr "Último resultado" msgid "Command Results" msgstr "Resultados da orde" msgid "Custom Terminal" msgstr "Terminal personalizada" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Orde" msgid "Execute flag" msgstr "Executar opción" msgid "Default Email Client" msgstr "Cliente de correo-e predefinido" msgid "Compose email using the system's default mailto: handler" msgstr "" "Escribir un correo-e usando o xestor de correo predefinido no sistema: " "manexador" #, fuzzy msgid "Compose Email To" msgstr "Escribir un correo-e" msgid "Dictionary" msgstr "Dicionario" msgid "Look up word in dictionary" msgstr "Buscar unha palabra no dicionario" msgid "Look Up" msgstr "Buscar" msgid "Documents" msgstr "Documentos" msgid "Recently used documents and bookmarked folders" msgstr "Documentos usados recentemente e cartafoles marcados" msgid "Max recent document days" msgstr "Número máximo de días para os documentos recentes" msgid "Recent Items" msgstr "Elementos recentes" msgid "Recently used documents" msgstr "Documentos usados recentemente" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "Documentos %s" #, python-format msgid "Recently used documents for %s" msgstr "Documentos usados recentemente por %s" msgid "Places" msgstr "Lugares" msgid "Bookmarked folders" msgstr "Cartafoles marcados" msgid "DuckDuckGo Search" msgstr "Búsqueda DuckDuckGo" msgid "Search the web securely with DuckDuckGo" msgstr "Buscar con seguridade na web con DuckDuckGo" msgid "Favorites" msgstr "Favoritos" msgid "Mark commonly used items and store objects for later use" msgstr "" "Marcar os elementos usados habitualmente e gardar os obxectos para usalos " "máis tarde" msgid "Shelf of \"Favorite\" items" msgstr "Andel de «Favoritos»" msgid "Add to Favorites" msgstr "Engadir aos favoritos" msgid "Add item to favorites shelf" msgstr "Engadir un elemento ao andel de favoritos" msgid "Remove from Favorites" msgstr "Eliminar dos favoritos" msgid "Remove item from favorites shelf" msgstr "Eliminar o elemento do andel de favoritos" msgid "File Actions" msgstr "Accións sobre os ficheiros" msgid "More file actions" msgstr "Máis accións sobre os ficheiros" msgid "Move To..." msgstr "Mover a..." msgid "Move file to new location" msgstr "Mover o ficheiro a unha nova localización" msgid "Rename To..." msgstr "Renomear como..." msgid "Copy To..." msgstr "Copiar a…" msgid "Copy file to a chosen location" msgstr "Copiar o ficheiro á localización escollida" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "Glob" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "Accións prioritarias" msgid "Tools to work with commands as objects" msgstr "Ferramentas para traballar con ordes e obxectos" msgid "Select in Kupfer" msgstr "Seleccionar en Kupfer" #, python-format msgid "Result of %s (%s)" msgstr "Resultado de %s (%s)" msgid "Run (Take Result)" msgstr "Executar (gardar o resultado)" msgid "Take the command result as a proxy object" msgstr "Usar o resultado da orde como un obxecto proxy" msgid "Run (Discard Result)" msgstr "Executar (descartar o resultado)" msgid "Image Tools" msgstr "Ferramentas de imaxe" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Ferramentas para a transformación de imaxes" msgid "Scale..." msgstr "Escalar…" msgid "Scale image to fit inside given pixel measure(s)" msgstr "Escalar a imaxe para axustala ás dimensións indicadas" msgid "Rotate Clockwise" msgstr "Rotar cara á dereita" msgid "Rotate Counter-Clockwise" msgstr "Rotar cara á esquerda" msgid "Autorotate" msgstr "Rotación automática" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "Rotar a imaxe JPEG (in situ) segundo os seus metadatos EXIF" msgid "Kupfer Plugins" msgstr "Engadidos de Kupfer" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Acceder á lista de engadidos de Kupfer" msgid "Show Information" msgstr "Mostrar a información" msgid "Show Source Code" msgstr "Mostrar o código fonte" msgid "enabled" msgstr "activado" msgid "disabled" msgstr "desactivado" msgid "Notes" msgstr "Notas" msgid "Gnote or Tomboy notes" msgstr "Notas de GNote ou Tomboy" msgid "Work with application" msgstr "Traballar con un aplicativo" msgid "Open with notes application" msgstr "Abrir co aplicativo de notas" msgid "Append to Note..." msgstr "Anexar á nota..." msgid "Add text to existing note" msgstr "Engadir un texto a unha nota existente" msgid "Create Note" msgstr "Crear unha nota" msgid "Create a new note from this text" msgstr "Crear unha nota nova con este texto" msgid "Get Note Search Results..." msgstr "Buscar nas notas..." msgid "Show search results for this query" msgstr "Mostrar os resultados da busca desta consulta" #, python-format msgid "today, %s" msgstr "hoxe, %s" #, python-format msgid "yesterday, %s" msgstr "onte, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Última actualización %s" msgid "Quicksilver Icons" msgstr "Iconas Quicksilver" msgid "Quick Image Viewer" msgstr "Visor rápido de imaxes" msgid "View Image" msgstr "Ver imaxe" msgid "GNU Screen" msgstr "GNU Screen" msgid "Active GNU Screen sessions" msgstr "Activar as sesións de GNU Screen" msgid "Attached" msgstr "Anexado" msgid "Detached" msgstr "Desanexado" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "%(status)s sesión (%(pid)s) creada o %(time)s" msgid "Screen Sessions" msgstr "Sesións de Screen" msgid "Attach" msgstr "Anexar" msgid "Send Keys" msgstr "Enviar teclas" msgid "Send synthetic keyboard events using xautomation" msgstr "Enviar eventos sintéticos de teclado usando xautomation" msgid "Paste to Foreground Window" msgstr "Pegar na xanela en primeiro plano" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "Copiar ao portapapeis e enviar Ctrl+V a xanela en primeiro plano" msgid "Send keys to foreground window" msgstr "Enviar teclas a xanela en primeiro plano" msgid "Type Text" msgstr "Escribir texto" msgid "Type the text to foreground window" msgstr "Escribir o texto na xanela en primeiro plano" msgid "GNOME Session Management" msgstr "Xestión de sesións de GNOME" msgid "Special items and actions for GNOME environment" msgstr "Elementos e accións especiais para o contorno de GNOME" msgid "Log Out..." msgstr "Terminar a sesión..." msgid "Log out or change user" msgstr "Terminar a sesión ou cambiar de usuario" msgid "Shut Down..." msgstr "Apagar..." msgid "Shut down, restart or suspend computer" msgstr "Apagar, reiniciar ou suspender o computador" msgid "Lock Screen" msgstr "Bloquear a pantalla" msgid "Enable screensaver and lock" msgstr "Activar o salvapantallas e bloquear" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "Xestión de sesións de XFCE" msgid "Special items and actions for XFCE environment" msgstr "Elementos e accións especiais para o contorno de XFCE" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "Servidores SSH" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "Engade os servidores SSH encontrados en ~/.ssh/config." msgid "SSH host" msgstr "Servidor SSH" msgid "Connect" msgstr "Conectar" msgid "Connect to SSH host" msgstr "Conectar co servidor SSH" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "Servidores SSH como os especificados en ~/.ssh/config" msgid "No D-Bus connection to desktop session" msgstr "Non hai conexión D-Bus coa sesión do escritorio" msgid "GNOME Keyring" msgstr "Depósito de claves de GNOME" msgid "KWallet" msgstr "KWallet" msgid "Unencrypted File" msgstr "Ficheiro non cifrado" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "A orde en «%s» non está dispoñíbel" msgid "Document Templates" msgstr "Modelos de documentos" msgid "Create new documents from your templates" msgstr "Crear un novo documento a partir de un modelo" #, python-format msgid "%s template" msgstr "Modelo %s" msgid "Empty File" msgstr "Ficheiro baleiro" msgid "New Folder" msgstr "Novo cartafol" msgid "Create New Document..." msgstr "Crear un novo documento..." msgid "Create a new document from template" msgstr "Crear un novo documento con un modelo" msgid "Create Document In..." msgstr "Crear un documento en..." msgid "Textfiles" msgstr "Ficheiros de texto" msgid "Append To..." msgstr "Anexar a..." msgid "Append..." msgstr "Anexar..." msgid "Write To..." msgstr "Escribir en…" msgid "Get Text Contents" msgstr "Obter os contidos de texto" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "Accións do xestor de ficheiros Thunar" msgid "Select in File Manager" msgstr "Seleccionar un xestor de ficheiros" msgid "Show Properties" msgstr "Mostrar as propiedades" msgid "Show information about file in file manager" msgstr "Mostrar a información do ficheiro no xestor de ficheiros" msgid "Send To..." msgstr "Enviar a..." msgid "Symlink In..." msgstr "Crear unha ligazón simbólica en…" msgid "Create a symlink to file in a chosen location" msgstr "Crear unha ligazón simbólica a un ficheiro na ubicación elixida" msgid "Empty Trash" msgstr "Baleirar o lixo" msgid "Thunar Send To Objects" msgstr "Enviar a Obxectos Thunar" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Contactos e accións de Thunderbird/Icedove" msgid "Compose New Email" msgstr "Escribir un novo correo-e" msgid "Compose a new message in Thunderbird" msgstr "Escribir unha nova mensaxe en Thunderbird" #, fuzzy msgid "Attach in Email To..." msgstr "Enviar un correo-e a…" #, fuzzy msgid "Compose Email With" msgstr "Escribir un correo-e" #, fuzzy msgid "Compose a new message using the text as body" msgstr "Escribir unha nova mensaxe en Thunderbird" msgid "Thunderbird Address Book" msgstr "Axenda de Thunderbird" msgid "Contacts from Thunderbird Address Book" msgstr "Contactos da axenda de Thunderbird" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Arriba" msgid "Show running tasks and allow sending signals to them" msgstr "Mostrar as tarefas en execución e permitir que se lle manden sinais" msgid "Sort Order" msgstr "Ordenación" msgid "Commandline" msgstr "Liña de ordes" msgid "CPU usage (descending)" msgstr "Uso da CPU (descendente)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Uso da memoria (descendente)" msgid "Send Signal..." msgstr "Enviar unha sinal..." msgid "Signals" msgstr "Sinais" msgid "Running Tasks" msgstr "Tarefas en execución" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% tempo: %(time)s" msgid "Running tasks for current user" msgstr "Tarefas en execución do usuario actual" msgid "Trash" msgstr "Lixo" msgid "Access trash contents" msgstr "Acceder aos contidos do lixo" msgid "Move to Trash" msgstr "Mover ao lixo" msgid "Move this file to trash" msgstr "Mover este ficheiro ao lixo" msgid "Restore" msgstr "Restabelecer" msgid "Move file back to original location" msgstr "Mover o ficheiro á localización orixinal" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "O lixo está baleiro" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "Hai un ficheiro no lixo" msgstr[1] "Hai %(num)s ficheiros no lixo" msgid "Triggers" msgstr "Disparadores" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Asignar combinacións globais de teclas (disparadores) aos obxectos creados " "con «Escribir unha orde»." msgid "Add Trigger..." msgstr "Engadir un disparador..." msgid "Remove Trigger" msgstr "Eliminar o disparador" msgid "URL Actions" msgstr "Accións sobre os URL" msgid "Download and Open" msgstr "Descargar e abrir" msgid "Download To..." msgstr "Descargar en…" msgid "Download URL to a chosen location" msgstr "Descargar un URL nunha localización escollida" msgid "Wikipedia" msgstr "Wikipedia" msgid "Search in Wikipedia" msgstr "Buscar na Wikipedia" msgid "Wikipedia language" msgstr "Idioma da Wikipedia" #. TRANS: Default wikipedia language code msgid "en" msgstr "gl" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Buscar este termo en %s.wikipedia.org" msgid "Window List" msgstr "Lista de xanelas" msgid "All windows on all workspaces" msgstr "Todas as xanelas en todos os espazos de traballo" msgid "Activate" msgstr "Activación" msgid "Shade" msgstr "Pregar" msgid "Unshade" msgstr "Despregar" msgid "Minimize" msgstr "Minimizar" msgid "Unminimize" msgstr "Restabelecer" msgid "Maximize" msgstr "Maximizar" msgid "Unmaximize" msgstr "Restabelecer" msgid "Maximize Vertically" msgstr "Maximizar verticalmente" msgid "Unmaximize Vertically" msgstr "Restabelecer verticalmente" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Xanela no %(wkspc)s" msgid "Frontmost Window" msgstr "Xanela en primeiro plano" msgid "Next Window" msgstr "Seguinte xanela" msgid "Jump to this window's workspace and focus" msgstr "Saltar ao espazo de traballo desta xanela e focalizar" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "%d xanela" msgstr[1] "%d xanelas" msgid "Active workspace" msgstr "Espazo de traballo activo" msgid "Jump to this workspace" msgstr "Saltar a este espazo de traballo" msgid "Workspaces" msgstr "Espazos de traballo" msgid "Volumes and Disks" msgstr "Volumes e discos" msgid "Mounted volumes and disks" msgstr "Volumes e discos montados" #, python-format msgid "Volume mounted at %s" msgstr "Volume montado en %s" msgid "Unmount" msgstr "Desmontar" msgid "Unmount this volume" msgstr "Desmontar este volume" msgid "Eject" msgstr "Expulsar" msgid "Unmount and eject this media" msgstr "Desmontar e expulsar este medio" msgid "Show Text" msgstr "Mostrar o texto" msgid "Display text in a window" msgstr "Mostrar o texto nunha xanela" msgid "Large Type" msgstr "Tipo grande" msgid "Show Notification" msgstr "Mostrar a notificación" msgid "Tracker" msgstr "Tracker" msgid "Tracker desktop search integration" msgstr "Integración co aplicativo de buscas de escritorio Tracker" msgid "Search in Tracker" msgstr "Buscar en Tracker" msgid "Open Tracker Search Tool and search for this term" msgstr "Abrir Tracker e buscar este termo" msgid "Get Tracker Results..." msgstr "Obter os resultados de Tracker…" msgid "Show Tracker results for query" msgstr "Mostrar os resultados da consulta en Tracker" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "Resultados para «%s»" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "Localizar ficheiros" msgid "Search filesystem using locate" msgstr "Buscar no sistema de ficheiros usando «locate»" msgid "Ignore case distinctions when searching files" msgstr "" "ignorar a diferenciación entre maiúsc./minúsc. cando se busquen ficheiros" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Marcadores de Firefox" msgid "Index of Firefox bookmarks" msgstr "Índice dos marcadores de Firefox" #, fuzzy msgid "Firefox Keywords" msgstr "Marcadores de Firefox" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "Buscar na web con motores OpenSearch" msgid "Search With..." msgstr "Buscar con…" msgid "Search For..." msgstr "Buscar…" #, fuzzy msgid "Search Terms" msgstr "Motores de busca" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Use «%s»" #, fuzzy msgid "Resume playback" msgstr "Continuar a reprodución en Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Seguinte" #, fuzzy msgid "Skip to next track" msgstr "Ir á pista seguinte en Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Anterior" #, fuzzy msgid "Skip to previous track" msgstr "Ir á pista anterior en Audacious" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "Acceder aos contactos de Pidgin" msgid "Show offline contacts" msgstr "Mostrar os contactos desconectados" msgid "Open Chat" msgstr "Abrir unha conversa" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d caracter)" msgstr[1] "%s (%d caracteres)" msgid "Send Message..." msgstr "Enviar unha mensaxe..." msgid "Available" msgstr "Dispoñíbel" msgid "Away" msgstr "Ausente" msgid "Pidgin Contacts" msgstr "Contactos de Pidgin" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Abreviar as ligazóns" msgid "Create short aliases of long URLs" msgstr "Crear abreviaturas para URLs longos" msgid "Error" msgstr "Erro" msgid "Shorten With..." msgstr "Abreviar con..." msgid "Services" msgstr "Servizos" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "Reproducir, poñer as pistas na cola e explorar a biblioteca da música" msgid "Include artists in top level" msgstr "Incluír os artistas no nivel superior" msgid "Include albums in top level" msgstr "Incluír os álbums no nivel superior" msgid "Play tracks in Rhythmbox" msgstr "Reproducir as pistas en Rhythmbox" msgid "Add tracks to the play queue" msgstr "Engadir as pistas á cola de reprodución" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "por %(artist)s de %(album)s" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "por %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Pistas por %s" msgid "Albums" msgstr "Álbums" msgid "Music albums in Rhythmbox Library" msgstr "Álbums musicais na biblioteca de Rhythmbox" msgid "Artists" msgstr "Artistas" msgid "Music artists in Rhythmbox Library" msgstr "Artistas musicais na biblioteca de Rhythmbox" msgid "Songs" msgstr "Cancións" msgid "Songs in Rhythmbox library" msgstr "Cancións da biblioteca de Rhythmbox" msgid "Getting Things GNOME" msgstr "Getting Things GNOME" msgid "Browse and create new tasks in GTG" msgstr "Explorar e crear novas tarefas en GTG" #, python-format msgid "due: %s" msgstr "límite: %s" #, python-format msgid "start: %s" msgstr "iniciar: %s" #, python-format msgid "tags: %s" msgstr "etiquetas: %s" msgid "Open task in Getting Things GNOME!" msgstr "Abrir a tarefa en Getting Things GNOME" msgid "Delete" msgstr "Borrar" msgid "Permanently remove this task" msgstr "Eliminar esta tarefa permanentemente" msgid "Mark Done" msgstr "Marcar como feita" msgid "Mark this task as done" msgstr "Marcar esta tarefa como feita" msgid "Dismiss" msgstr "Ignorar" msgid "Mark this task as not to be done anymore" msgstr "Marcar esta tarefa para non ser feita máis" msgid "Create Task" msgstr "Crear unha tarefa" msgid "Create new task in Getting Things GNOME" msgstr "Crear unha tarefa nova en Getting Things GNOME" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "Buscar en Devhelp" msgid "Empathy" msgstr "Empathy" msgid "Access to Empathy Contacts" msgstr "Acceder aos contactos de Empathy" msgid "Busy" msgstr "Ocupado" msgid "Not Available" msgstr "Non dispoñíbel" msgid "Invisible" msgstr "Invisíbel" msgid "Offline" msgstr "Desconectado" msgid "Change Global Status To..." msgstr "Cambiar o estado global a..." msgid "Empathy Contacts" msgstr "Contactos de Empathy" msgid "Empathy Account Status" msgstr "Estado da conta de Empathy" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Activación alternativa" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Truco da coma" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Escribir unha orde" msgid "Mark Default Action" msgstr "Marcar a acción predefinida" msgid "Forget Object" msgstr "Esquecer obxeto" msgid "Reset All" msgstr "Restabelecer todo" msgid "Select Quit" msgstr "Seleccionar «Saír»" msgid "Select Selected File" msgstr "Seleccionar «Ficheiro seleccionado»" msgid "Select Selected Text" msgstr "Seleccionar «Texto seleccionado»" msgid "Show Help" msgstr "Mostrar a axuda" msgid "Show Preferences" msgstr "Mostrar as preferencias" msgid "Switch to First Pane" msgstr "Cambiar ao primeiro panel" msgid "Toggle Text Mode" msgstr "Alternar o «Modo texto»" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Non hai resultados en %(src)s para «%(query)s»" msgid "No matches" msgstr "Non hai resultados" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Non hai resultados" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Facer «%(action)s» predefinida para «%(object)s»" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "Esquecerse de «%s»" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Mostrar a interface principal" msgid "Show with Selection" msgstr "Mostrar coa selección" #. TRANS: Plugin info fields msgid "Description" msgstr "Descrición" msgid "Author" msgstr "Autor" msgid "Version" msgstr "Vesión" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Precísase o módulo Python «%s»" msgid "Plugin could not be read due to an error:" msgstr "Non foi posíbel ler o engadido por mor dun erro:" msgid "Content of" msgstr "Contido de" #. TRANS: Plugin contents header msgid "Sources" msgstr "Fontes" #. TRANS: Plugin contents header msgid "Actions" msgstr "Accións" #, python-format msgid "Using encrypted password storage: %s" msgstr "Usándose almacenamento de contrasinais cifrado: %s" #, python-format msgid "Using password storage: %s" msgstr "Usándose almacenamento de contrasinais: %s" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Configuración" msgid "Set username and password" msgstr "Estabelecer o nome do usuario e o contrasinal" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Escoller un directorio" msgid "Reset all shortcuts to default values?" msgstr "" "Desexa restabelecer os valores predefinidos de todos os atallos do teclado?" msgid "Shortcut" msgstr "Atallo" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "Marcos Lans - marcoslansgarza@gmail.com, 2010;" msgid "A free software (GPLv3+) launcher" msgstr "Un iniciador de aplicativos libre (GPLv3+)" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Este programa é software libre, vostede pode redistribuílo e/ou modificalo\n" "baixo os termos da Licenza Pública Xeral de GNU publicada pola Free\n" "Software Foundation, tanto a versión 3 como as posteriores.\n" "\n" "Este programa distribúese coa esperanza de que lle sexa útil, pero\n" "SEN GARANTÍA NINGUNHA, incluso sen a garantía de MERCANTIBILIDADE\n" "ou ADECUACIÓN A UN PROPÓSITO EN PARTICULAR. Vexa a Licenza \n" "Pública Xeral para ter máis detalles.\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Non foi posíbel encontrar un Kupfer en execución" #~ msgid "Compose Email" #~ msgstr "Escribir un correo-e" #~ msgid "Send in Email To..." #~ msgstr "Enviar un correo-e a…" #~ msgid "Type to search %s" #~ msgstr "Teclear para buscar %s" #~ msgid "No action" #~ msgstr "Sen acción" #~ msgid "GNOME Terminal Profiles" #~ msgstr "Perfís do terminal de GNOME" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Iniciar os perfís do terminal de GNOME" #~ msgid "Multihead Support" #~ msgstr "Soporte de múltiples monitores" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Calcular as expresións que comezan con «=»" #~ msgid "Epiphany Bookmarks" #~ msgstr "Marcadores de Epiphany" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Índice dos marcadores de Epiphany" #~ msgid "Include visited sites" #~ msgstr "Incluír os sitios visitados" #~ msgid "Firefox tag" #~ msgstr "Etiqueta de Firefox" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Continuar a reprodución en Rhythmbox" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Deter a reprodución en Rhythmbox" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Saltar á pista seguinte en Rhythmbox" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Saltar á pista anterior en Rhythmbox" #~ msgid "Search the Web" #~ msgstr "Buscar na web" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Documentos usados recentemente en Abiword" #~ msgid "Abiword Recent Items" #~ msgstr "Elementos recentes de Abiword" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "Interface co xestor de paquetes APT" #~ msgid "Installation method" #~ msgstr "Método de instalación" #~ msgid "Show Package Information" #~ msgstr "Mostrar a información do paquete" #~ msgid "Install" #~ msgstr "Instalar" #~ msgid "Install package using the configured method" #~ msgstr "Instalar o paquete usando o método configurado" #~ msgid "Packages matching \"%s\"" #~ msgstr "Paquetes coincidentes con «%s»" #~ msgid "Search Package Name..." #~ msgstr "Buscar o paquete polo nome..." #~ msgid "Ascii & Unicode Icon Set" #~ msgstr "Conxunto de iconas ASCII e Unicode" #~ msgid "" #~ "Provides the Ascii and Unicode icon sets that use letters and symbols to " #~ "produce icons for the objects found in Kupfer." #~ msgstr "" #~ "Forneza o conxunto de iconas ASCII e Unicode que usan letras e simbolos " #~ "para producir iconas para os obxetos atopados en Kupfer." #~ msgid "Ascii" #~ msgstr "ASCII" #~ msgid "Unicode" #~ msgstr "Unicode" #~ msgid "Chromium Bookmarks" #~ msgstr "Marcadores de Chromium" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Índice dos marcadores de Chromium" #~ msgid "Claws Mail" #~ msgstr "Claws Mail" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Contactos e accións de Claws Mail" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Escribir unha nova mensaxe en Claws Mail" #~ msgid "Receive All Email" #~ msgstr "Recibir todos os correos-e" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "Recibir as novas mensaxes de todas as contas de ClawsMail" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Escribir unha nova mensaxe en Claws Mail e anexarlle un ficheiro" #~ msgid "Claws Mail Address Book" #~ msgstr "Axenda de enderezos de Claws Mail" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Contactos da axenda de enderezos de Claws Mail" #~ msgid "Configure a custom terminal emulator" #~ msgstr "Configurar un emulador de terminal personalizada" #~ msgid "Custom Theme" #~ msgstr "Tema personalizado" #~ msgid "Use a custom color theme" #~ msgstr "Usar un tema de cor personalizado" #~ msgid "Theme:" #~ msgstr "Tema:" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Contactos de Evolution" #~ msgid "Compose a new message in Evolution" #~ msgstr "Escribir unha nova mensaxe en Evolution" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Escribir unha nova mensaxe en Evolution e anexarlle un ficheiro" #~ msgid "Evolution Address Book" #~ msgstr "Axenda de enderezos de Evolution" #~ msgid "Filezilla" #~ msgstr "Filezilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Mostrar os sitios e manexar os enderezos ftp con Filezilla" #~ msgid "Open Site with Filezilla" #~ msgstr "Abrir un sitio web con Filezilla" #~ msgid "Filezilla Sites" #~ msgstr "Sitios web de Filezilla" #~ msgid "Sites from Filezilla" #~ msgstr "Sitios web de Filezilla" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Acceder aos contactos de Gajim" #~ msgid "Free for Chat" #~ msgstr "Dispoñíbel para conversar" #~ msgid "Gajim Contacts" #~ msgstr "Contactos de Gajim" #~ msgid "Gajim Account Status" #~ msgstr "Estado da conta de Gajim" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Cargar os contactos e escribir un novo correo-e en Gmail" #~ msgid "Load contacts' pictures" #~ msgstr "Cargar as imaxes dos contactos" #~ msgid "Load additional information" #~ msgstr "Cargar información adicional" #~ msgid "Work email" #~ msgstr "Correo-e do traballo" #~ msgid "Home email" #~ msgstr "Correo-e persoal" #~ msgid "Other email" #~ msgstr "Outro correo-e" #~ msgid "Work address" #~ msgstr "Enderezo do traballo" #~ msgid "Home address" #~ msgstr "Enderezo persoal" #~ msgid "Other address" #~ msgstr "Outro enderezo" #~ msgid "Car phone" #~ msgstr "Teléfono do coche" #~ msgid "Fax" #~ msgstr "Fax" #~ msgid "Home phone" #~ msgstr "Teléfono persoal" #~ msgid "Home fax" #~ msgstr "Fax persoal" #~ msgid "Internal phone" #~ msgstr "Teléfono interno" #~ msgid "Mobile" #~ msgstr "Móbil" #~ msgid "Other" #~ msgstr "Outro" #~ msgid "VOIP" #~ msgstr "VOIP" #~ msgid "Work phone" #~ msgstr "Teléfono do traballo" #~ msgid "Work fax" #~ msgstr "Fax do traballo" #~ msgid "Compose Email in Gmail" #~ msgstr "Redactar un correo-e en Gmail" #~ msgid "Open web browser and compose new email in Gmail" #~ msgstr "Abrir o navegador web e redactar un novo correo-e en Gmail" #~ msgid "Edit Contact in Gmail" #~ msgstr "Editar contacto en Gmail" #~ msgid "Open web browser and edit contact in Gmail" #~ msgstr "Abrir o navegador web e editar contacto en Gmail" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Contactos dos servizos de Google (Gmail)" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Mostrar os álbums e enviar os ficheiros a Picasa" #~ msgid "Users to show: (,-separated)" #~ msgstr "Usuarios para mostrar (separados por comas):" #~ msgid "Load user and album icons" #~ msgstr "Cargar as iconas do usuario e do álbum" #~ msgid "Uploading Pictures" #~ msgstr "Enviando as imaxes" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Enviando as imaxes ao álbum web de Picasa" #~ msgid "Creating album:" #~ msgstr "Creando un álbum:" #~ msgid "Album created by Kupfer" #~ msgstr "Álbum creado por Kupfer" #~ msgid "File:" #~ msgstr "Ficheiro:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "Un álbum" #~ msgstr[1] "%(num)d álbums" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "Unha fotografía" #~ msgstr[1] "%(num)s fotografías" #~ msgid "Upload to Picasa Album..." #~ msgstr "Enviar a un álbum de Picasa..." #~ msgid "Upload files to Picasa album" #~ msgstr "Enviar os ficheiros a un álbum de Picasa" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Enviar a Picasa como un novo álbum" #~ msgid "Create album from selected local directory" #~ msgstr "Crear un álbum desde o directorio local seleccionado" #~ msgid "Picasa Albums" #~ msgstr "Álbums de Picasa" #~ msgid "User albums in Picasa" #~ msgstr "Álbums do usuario en Picasa" #~ msgid "Google Search" #~ msgstr "Buscar en Google" #~ msgid "Search Google with results shown directly" #~ msgstr "Buscar en Google mostrando os resultados directamente" #~ msgid "Show More Results For \"%s\"" #~ msgstr "Mostrar máis resultados para «%s»" #~ msgid "%s total found" #~ msgstr "%s encontrados en total" #~ msgid "Gwibber" #~ msgstr "Gwibber" #~ msgid "" #~ "Microblogging with Gwibber. Allows sending and receiving messages from " #~ "social networks like Twitter, Identi.ca etc. Requires the package " #~ "'gwibber-service'." #~ msgstr "" #~ "Microblogging con Gwibber. Permite enviar e recibir mensaxes de redes " #~ "sociais como Twitter, Identi.ca etc. Require o paquete «gwibber-service»." #~ msgid "Maximum number of messages to show" #~ msgstr "Número máximo de mensaxes a mostrar" #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s en %(service)s" #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s en %(where)s" #~ msgid "Send Message" #~ msgstr "Enviar unha mensaxe" #~ msgid "Send message to all Gwibber accounts" #~ msgstr "Enviar a mensaxe a todas as contas de Gwibber" #~ msgid "Send Message To..." #~ msgstr "Enviar unha mensaxe a…" #~ msgid "Send message to a Gwibber account" #~ msgstr "Enviar a mensaxe a unha conta de Gwibber" #~ msgid "Send message to selected Gwibber account" #~ msgstr "Enviar a mensaxe a conta de Gwibber seleccionada" #~ msgid "Reply..." #~ msgstr "Responder…" #~ msgid "Delete Message" #~ msgstr "Eliminar a mensaxe" #~ msgid "Send Private Message..." #~ msgstr "Enviar unha mensaxe privada..." #~ msgid "Send direct message to user" #~ msgstr "Enviar unha mensaxe directa o usuario" #~ msgid "Retweet" #~ msgstr "Retwitear" #~ msgid "Retweet To..." #~ msgstr "Retwitear a…" #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Retwitear a mensaxe a todas as contas de Gwibber" #~ msgid "Retweet message to a Gwibber account" #~ msgstr "Retwitear a mensaxe a unha conta de Gwibber" #~ msgid "Open in Browser" #~ msgstr "Abrir no navegador" #~ msgid "Open message in default web browser" #~ msgstr "Abrir a mensaxe co navegador web predefinido" #~ msgid "Gwibber Accounts" #~ msgstr "Contas de Gwibber" #~ msgid "Accounts configured in Gwibber" #~ msgstr "Contas configuradas en Gwibber" #~ msgid "Gwibber Messages" #~ msgstr "Mensaxes de Gwibber" #~ msgid "Recent messages received by Gwibber" #~ msgstr "Mensaxes recentes recibidas por Gwibber" #~ msgid "Gwibber Messages for %s" #~ msgstr "Mensaxes de Gwibber para %s" #~ msgid "Gwibber Streams" #~ msgstr "Canles de Gwibber" #~ msgid "Streams configured in Gwibber" #~ msgstr "Canles configuradas en Gwibber" #~ msgid "Gwibber Messages in %s" #~ msgstr "Mensaxes de Gwibber en %s" #~ msgid "Gwibber (Simple)" #~ msgstr "Gwibber (Simple)" #~ msgid "Send updates via the microblogging client Gwibber" #~ msgstr "Enviar actualizacións a través do cliente de microblogging Gwibber" #~ msgid "Send Update" #~ msgstr "Enviar actualización" #~ msgid "Unable to activate Gwibber service" #~ msgstr "Non foi posíbel activar o servizo de Gwibber" #~ msgid "OpenOffice / LibreOffice" #~ msgstr "OpenOffice / LibreOffice" #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Documentos usados recentemente en OpenOffice/LibreOffice" #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "Elementos recentes de OpenOffice/LibreOffice" #~ msgid "Opera Mail" #~ msgstr "Opera Mail" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Contactos e accións de Opera Mail" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Escribir un novo correo-e en Opera Mail" #~ msgid "Opera Mail Contacts" #~ msgstr "Contactos de Opera Mail" #~ msgid "Contacts from Opera Mail" #~ msgstr "Contactos de Opera Mail" #~ msgid "Opera Bookmarks" #~ msgstr "Marcadores de Opera" #~ msgid "Index of Opera bookmarks" #~ msgstr "Índice dos marcadores de Opera" #~ msgid "PuTTY Sessions" #~ msgstr "Sesións de PuTTY" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Acceso rápido ás sesións de PuTTY" #~ msgid "Start Session" #~ msgstr "Iniciar unha sesión" #~ msgid "reStructuredText" #~ msgstr "TextoRestructurado" #~ msgid "Render reStructuredText and show the result" #~ msgstr "Renderizar TextoRestructurado e mostrar o resultado" #~ msgid "View as HTML Document" #~ msgstr "Ver como documento HTML" #~ msgid "System Services" #~ msgstr "Servizos do sistema" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "" #~ "Iniciar, parar ou reiniciar os servizos do sistema mediante os scripts de " #~ "init" #~ msgid "Sudo-like Command" #~ msgstr "Ordes do tipo sudo" #~ msgid "Start Service" #~ msgstr "Iniciar o servizo" #~ msgid "Stop Service" #~ msgstr "Parar o servizo" #~ msgid "%s Service" #~ msgstr "Servizo %s" #~ msgid "Show QRCode" #~ msgstr "Mostrar o código QR" #~ msgid "Display text as QRCode in a window" #~ msgstr "Mostrar o texto como código QR nunha xanela" #~ msgid "Access to Skype contacts" #~ msgstr "Acceder aos contactos de Skype" #~ msgid "Skype Me" #~ msgstr "Skypéame" #~ msgid "Logged Out" #~ msgstr "Sesión finalizada" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Chamar" #~ msgid "Place a call to contact" #~ msgstr "Chamar ao contacto" #~ msgid "Skype Contacts" #~ msgstr "Contactos de Skype" #~ msgid "Skype Statuses" #~ msgstr "Estados de Skype" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Volumes do histórico de TrueCrypt" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "Volume de TrueCrypt: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Montar o volume" #~ msgid "Mount in Truecrypt" #~ msgstr "Montar en TrueCrypt" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Tentar montar o ficheiro como un volume de TrueCrypt" #~ msgid "Dismount All Volumes" #~ msgstr "Desmontar todos os volumes" #~ msgid "TrueCrypt Volumes" #~ msgstr "Volumes de TrueCrypt" #~ msgid "Terminal Server Client" #~ msgstr "Terminal Server Client" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Sesión gardada en Terminal Server Client" #~ msgid "TSClient sessions" #~ msgstr "Sesións de TSClient" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Sesións gardadas en Terminal Server Client" #~ msgid "Vim" #~ msgstr "Vim" #~ msgid "Recently used documents in Vim" #~ msgstr "Documentos usados recentemente en Vim" #~ msgid "Vim Recent Documents" #~ msgstr "Documentos recentes de Vim" #~ msgid "Close (Save All)" #~ msgstr "Pechar (gardar todo)" #~ msgid "Send..." #~ msgstr "Enviar…" #~ msgid "Send ex command" #~ msgstr "Enviar comando «ex»" #~ msgid "Insert in Vim..." #~ msgstr "Inserir en Vim…" #~ msgid "Active Vim Sessions" #~ msgstr "Sesións activas de Vim" #~ msgid "Vim Session %s" #~ msgstr "Sesión %s de Vim" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Marcadores e accións de Vinagre" #~ msgid "Start Vinagre Session" #~ msgstr "Iniciar unha sesión de Vinagre" #~ msgid "Vinagre Bookmarks" #~ msgstr "Marcadores de Vinagre" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "Controlar as máquinas virtuais de VirtualBox, compatíbel tanto coa " #~ "VirtualBox de Sun como coa edición de fontes abertas." #~ msgid "Force use CLI interface" #~ msgstr "Forzar o uso da interface CLI" #~ msgid "Power On" #~ msgstr "Acender" #~ msgid "Power On Headless" #~ msgstr "Encender «Headless»" #~ msgid "Send Power Off Signal" #~ msgstr "Enviar a sinal de apagado" #~ msgid "Reboot" #~ msgstr "Reiniciar" #~ msgid "Resume" #~ msgstr "Continuar" #~ msgid "Save State" #~ msgstr "Gardar o estado" #~ msgid "Power Off" #~ msgstr "Apagar" #~ msgid "VirtualBox Machines" #~ msgstr "Máquinas de VirtualBox" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "" #~ "Acceder ás páxinas gardadas en Zim - Unha wiki de escritorio e un " #~ "esquematizador" #~ msgid "Page names start with :colon" #~ msgstr "Os nomes de páxinas comezan con :(dous puntos)" #~ msgid "Default page name for quick notes" #~ msgstr "Nome de páxina predefinido para as notas rápidas" #~ msgid "Note %x %X" #~ msgstr "Nota %x %X" #~ msgid "" #~ "Strftime tags can be used: %H - hour, %M - minutes, etc\n" #~ "Please check python documentation for details.\n" #~ "NOTE: comma will be replaced by _" #~ msgstr "" #~ "Pódense usar etiquetas «strftime»: %H - hora, %M - minutos, etc\n" #~ "Consulte a documentación de Python para obter máis detalles.\n" #~ "Nota: as comas reemplazaranse por «_»" #~ msgid "Default namespace for quick notes" #~ msgstr "Espazo de nomes predefinido para as notas rápidas" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Páxina Zim do caderno de notas «%s»" #~ msgid "Create Zim Page" #~ msgstr "Crear unha páxina Zim" #~ msgid "Create page in default notebook" #~ msgstr "Crear unha páxina no caderno de notas predefinido" #~ msgid "Create Zim Page In..." #~ msgstr "Crear unha páxina Zim en..." #~ msgid "Insert QuickNote into Zim" #~ msgstr "Inserir nota rápida en Zim" #~ msgid "Quick note selected text into Zim notebook" #~ msgstr "Nota rápida seleccionada no caderno de notas Zim" #~ msgid "Create Subpage..." #~ msgstr "Crear unha subpáxina..." #~ msgid "Zim Notebooks" #~ msgstr "Caderno de notas de Zim" #~ msgid "Zim Pages" #~ msgstr "Páxinas Zim" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Páxinas gardadas no caderno de notas de Zim" #~ msgid "Selected Text \"%s\"" #~ msgstr "Texto seleccionado «%s»" #~ msgid "Recent clipboards" #~ msgstr "Portapapeis recentes" #~ msgid "Include recent selections" #~ msgstr "Incluír as seleccións recentes" #~ msgid "" #~ "Provides current nautilus selection, using Kupfer's Nautilus Extension" #~ msgstr "" #~ "Proporciona a selección actual do nautilus usando a extensión para " #~ "nautilus de Kupfer" #~ msgid "Selected File \"%s\"" #~ msgstr "Ficheiro seleccionado «%s»" #~ msgid "Selected Files" #~ msgstr "Ficheiros seleccionados" #~ msgid "Translate text with Google Translate" #~ msgstr "Traducir un texto con Google Translate" #~ msgid "Google Translate connection timed out" #~ msgstr "A conexión con Google Translate expirou" #~ msgid "Error connecting to Google Translate" #~ msgstr "Produciuse un erro na conexión con Google Translate" #~ msgid "Translate To..." #~ msgstr "Traducir a…" #~ msgid "Translate into %s" #~ msgstr "Traducir a %s" #~ msgid "Languages" #~ msgstr "Idiomas" #~ msgid "Show translated page in browser" #~ msgstr "Mostrar no navegador a páxina traducida" #~ msgid "Show Translation To..." #~ msgstr "Mostrar a tradución en..." #~ msgid "Show translation in browser" #~ msgstr "Mostrar a tradución no navegador" #~ msgid "Tracker 0.6" #~ msgstr "Tracker 0.6" #~ msgid "Tracker tags" #~ msgstr "Etiquetas de Tracker" #~ msgid "Tracker Tags" #~ msgstr "Etiquetas de Tracker" #~ msgid "Browse Tracker's tags" #~ msgstr "Examinar as etiquetas de Tracker" #~ msgid "Tag %s" #~ msgstr "Etiqueta %s" #~ msgid "Objects tagged %s with Tracker" #~ msgstr "Obxectos etiquetados %s con Tracker" #~ msgid "Add Tag..." #~ msgstr "Engadir unha etiqueta..." #~ msgid "Add tracker tag to file" #~ msgstr "Engadir unha etiqueta de tracker ao ficheiro" #~ msgid "Remove Tag..." #~ msgstr "Eliminar a etiqueta..." #~ msgid "Remove tracker tag from file" #~ msgstr "Eliminar a etiqueta de tracker do ficheiro" #~ msgid "Directories" #~ msgstr "Directorios" #~ msgid "Interface" #~ msgstr "Interface" #~ msgid "Hide Kupfer when focus is lost" #~ msgstr "Ocultar Kupfer cando non teña o foco" #~ msgid "" #~ "Tick the box next to a source to make sure its objects are exported to " #~ "the top level of the catalog. An unticked source's contents are only " #~ "available by locating its subcatalog and entering it.\n" #~ "\n" #~ "Note: Kupfer is an integrator, not an indexer itself. Kupfer is not " #~ "designed to carry a catalog larger than a couple of thousand objects, and " #~ "may become slow if overly large subcatalogs are included in the top level." #~ msgstr "" #~ "Marque o cadro dunha fonte para que os seus obxectos se exporten ao nivel " #~ "superior do catálogo. Os contidos dunha fonte sen seleccionar unicamente " #~ "estarán dispoñíbeis localizando o seu subcatálogo e introducíndoo.\n" #~ "\n" #~ "Nota: Kupfer é un integrador, non un indexador. Non está deseñado para " #~ "manexar catálogos maiores de un par de miles de obxectos e pode resultar " #~ "moi lento se subcatálogos grandes son incluídos no nivel superior." #~ msgid "Text Matches" #~ msgstr "Resultados para o texto" #~ msgid "noun" #~ msgstr "substantivo" #~ msgid "verb" #~ msgstr "verbo" #~ msgid "adjective" #~ msgstr "adxectivo" #~ msgid "Twitter" #~ msgstr "Twitter" #~ msgid "Microblogging with Twitter: send updates and show friends' tweets" #~ msgstr "" #~ "Microblogueo con Twitter: enviar actualizacións e mostrar os tweets dos " #~ "amigos" #~ msgid "Load friends' pictures" #~ msgstr "Cargar as imaxes dos amigos" #~ msgid "Load friends' public tweets" #~ msgstr "Cargar os tweets públicos dos amigos" #~ msgid "Load timeline" #~ msgstr "Cargar a liña de tempo" #~ msgid "Post Update to Twitter" #~ msgstr "Publicar a actualización no Twitter" #~ msgid "Twitter Timeline" #~ msgstr "Liña de tempo de Twitter" #~ msgid "Twitter Friends" #~ msgstr "Amigos de Twitter" #~ msgid "Timeline for %s" #~ msgstr "Liña de tempo de %s" #~ msgid "OpenOffice" #~ msgstr "OpenOffice" #~ msgid "Preferred terminal" #~ msgstr "Terminal preferido" #~ msgid "" #~ "The preferred terminal emulator. It's used to launch the SSH sessions." #~ msgstr "" #~ "O emulador de terminal preferido. Úsase para iniciar as sesións SSH." #~ msgid "" #~ "The flag which makes the terminal execute everything following it inside " #~ "the terminal (e.g. '-x' for gnome-terminal and terminal, '-e' for konsole " #~ "and urxvt)." #~ msgstr "" #~ "A opción que fai que o terminal execute todas as instrucións que lle " #~ "siguen no propio terminal. (p.e. '-x' para gnome-terminal e terminal, '-" #~ "e' para konsole e urxvt)." #~ msgid "Tracker 0.8" #~ msgstr "Tracker 0.8" kupfer-328/po/hu.po000066400000000000000000001721611500175051100142610ustar00rootroot00000000000000# Hungarian translations for the kupfer package # Copyright (C) 2009--2011 Ulrik Sverdrup # Hungarian translation by SanskritFritz (gmail) # This file is distributed under the same license as the kupfer package. (GPLv3) # # Reviewed and fixed by Balázs Úr, 2013-04-01 # # Balázs Úr , 2013. msgid "" msgstr "" "Project-Id-Version: kupfer\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2013-04-01 22:49+0200\n" "Last-Translator: Balázs Úr \n" "Language-Team: Hungarian \n" "Language: Hungarian\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: Lokalize 1.2\n" msgid "User credentials" msgstr "Felhasználói hitelesítési adatok" msgid "_User:" msgstr "_Felhasználó:" msgid "_Password:" msgstr "_Jelszó:" msgid "_Change" msgstr "_Módosítás" msgid "Set Keyboard Shortcut" msgstr "Gyorsbillentyű beállítása" msgid "Please press desired key combination" msgstr "Nyomja le a kívánt billentyűkombinációt" msgid "Keybinding could not be bound" msgstr "A billentyűparancs nem köthető" msgid "Kupfer Preferences" msgstr "Kupfer beállítások" msgid "Start automatically on login" msgstr "Automatikus indulás bejelentkezéskor" msgid "Start" msgstr "Indítás" msgid "Show icon in notification area" msgstr "Ikon megjelenítése az értesítési területen" msgid "Icon set:" msgstr "Ikonkészlet:" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" msgid "Terminal emulator:" msgstr "Terminál emulátor:" msgid "Desktop Environment" msgstr "Asztali környezet" msgid "General" msgstr "Általános" msgid "Global Keyboard Shortcuts" msgstr "Globális gyorsbillentyűk" msgid "Reset" msgstr "Visszaállítás" msgid "Browser Keyboard Shortcuts" msgstr "Böngésző gyorsbillentyűk" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "Egyszerű billentyűparancsok használata (Szóköz, /, pont, vessző stb.)" msgid "Keyboard" msgstr "Billentyűzet" msgid "Plugins" msgstr "Bővítmények" msgid "Inclusion in Top Level Searches" msgstr "Tartalmazza a legfelső szintű kereséseket" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "A kijelölt források objektumai benne lesznek a legfelső szintű " "keresésekben.\n" "A többi forrás tartalma csak az alkatalógus kiválasztásakor lesz elérhető." msgid "Indexed Folders" msgstr "Indexelt mappák" msgid "Folders whose files are always available in the catalog." msgstr "Mappák, amelyek fájljai mindig elérhetők lesznek a katalógusban." msgid "Catalog" msgstr "Katalógus" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Alkalmazásindító" msgid "Convenient command and access tool for applications and documents" msgstr "" "Kényelmes parancs és hozzáférési eszköz az alkalmazásokhoz és dokumentumokhoz" msgid "Execute in Kupfer" msgstr "Végrehajtás a Kupferben" msgid "Saved Kupfer Command" msgstr "Mentett Kupfer parancs" #, python-format msgid "Could not to carry out '%s'" msgstr "Nem hajtható végre: „%s”" #, python-format msgid "\"%s\" produced a result" msgstr "„%s” eredményt adott" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Nincs jogosultság „%s” futtatására (nem végrehajtható)" #, python-format msgid "Command in \"%s\" is not available" msgstr "A parancs nem érhető el ebben: „%s”" #, python-format msgid "Keyboard relay is active for display %s" msgstr "A billentyű-továbbítás aktív a(z) %s képernyőnek" msgid "do not present main interface on launch" msgstr "ne jelenjen meg a fő felület induláskor" msgid "list available plugins" msgstr "elérhető bővítmények listázása" msgid "enable debug info" msgstr "hibakeresési információk engedélyezése" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "bővítménysegéd futtatása" msgid "show usage help" msgstr "használatai súgó megjelenítése" msgid "show version information" msgstr "verzióinformációk megjelenítése" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Használat: kupfer [ KAPCSOLÓK | FÁJL … ]" msgid "Available plugins:" msgstr "Elérhető bővítmények:" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "Gépeljen a kereséshez" #, python-format msgid "%s is empty" msgstr "%s üres" msgid "Text" msgstr "Szöveg" msgid "Run after Delay..." msgstr "Futtatás késleltetés után…" msgid "Perform command after a specified time interval" msgstr "Parancs végrehajtása egy megadott időtartam után" msgid "Multiple Objects" msgstr "Több objektum" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s objektum" msgstr[1] "%s objektum" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "ismeretlen" msgid "Aim" msgstr "Aim" msgid "Google Talk" msgstr "Google Talk" msgid "ICQ" msgstr "ICQ" msgid "MSN" msgstr "MSN" msgid "QQ" msgstr "QQ" msgid "Yahoo" msgstr "Yahoo" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "%s nem támogatja ezt a műveletet" msgid "Can not be used with multiple objects" msgstr "Nem használható több objektummal" msgid "Open" msgstr "Megnyitás" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Nincs alapértelmezett alkalmazás ehhez: %(file)s (%(type)s)" #, python-format msgid "Please use \"%s\"" msgstr "Kérem használja ezt: „%s”" msgid "Set Default Application..." msgstr "Alapértelmezett alkalmazás beállítása…" msgid "Open with default application" msgstr "Megnyitás az alapértelmezett alkalmazással" msgid "Reveal" msgstr "Felfedés" msgid "Open parent folder" msgstr "Szülőmappa megnyitása" msgid "Open Terminal Here" msgstr "Terminál megnyitása itt" msgid "Open this location in a terminal" msgstr "A hely megnyitása a terminálban" msgid "Run in Terminal" msgstr "Futtatás terminálban" msgid "Run (Execute)" msgstr "Futtatás (végrehajtás)" msgid "Run this program in a Terminal" msgstr "A program futtatása terminálban" msgid "Run this program" msgstr "A program futtatása" msgid "Go To" msgstr "Ugrás" msgid "Open URL" msgstr "URL megnyitása" msgid "Open URL with default viewer" msgstr "URL megnyitása az alapértelmezett megjelenítővel" msgid "Launch" msgstr "Indítás" msgid "Show application window" msgstr "Alkalmazásablak megjelenítése" msgid "Launch application" msgstr "Alkalmazás indítása" msgid "Launch Again" msgstr "Indítás újra" msgid "Launch another instance of this application" msgstr "Az alkalmazás még egy példányának indítása" msgid "Close" msgstr "Bezárás" msgid "Attempt to close all application windows" msgstr "Kísérlet minden alkalmazásablak bezárására" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Futtatás" msgid "Perform command" msgstr "Parancs végrehajtása" msgid "(Empty Text)" msgstr "(Üres szöveg)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "„%(text)s”" msgstr[1] "(%(num)d sor) „%(text)s”" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s et. al." #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "%(dir)s rekurzív forrása, (%(levels)d szint)" #, python-format msgid "Directory source %s" msgstr "Könyvtár forrás %s" msgid "Home Folder" msgstr "Saját mappa" msgid "Catalog Index" msgstr "Katalógus-index" msgid "An index of all available sources" msgstr "Az összes elérhető forrás indexe" msgid "Root catalog" msgstr "Gyökérkatalógus" msgid "Please Configure Plugin" msgstr "Kérem állítsa be a bővítményt" #, python-format msgid "Plugin %s is not configured" msgstr "A(z) %s bővítmény nincs beállítva" #, python-format msgid "Invalid user credentials for %s" msgstr "Érvénytelen felhasználói hitelesítési adatok ehhez: %s" msgid "Applications" msgstr "Alkalmazások" msgid "All applications and preferences" msgstr "Minden alkalmazás és beállítás" msgid "Applications for Desktop Environment" msgstr "Alkalmazások az asztali környezethez" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "Megnyitás ezzel…" msgid "Open with any application" msgstr "Megnyitás bármely alkalmazással" msgid "Set default application to open this file type" msgstr "Alapértelmezett alkalmazás beállítása ezen fájltípus megnyitásához" #, fuzzy msgid "Reset Associations" msgstr "URL műveletek" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "Mély archívumok" msgid "Allow browsing inside compressed archive files" msgstr "Lehetővé teszi a tömörített archívumfájlokon belüli böngészést" #, python-format msgid "Content of %s" msgstr "%s tartalma" msgid "Archive Manager" msgstr "Archívumkezelő" msgid "Use Archive Manager actions" msgstr "Archívumkezelő műveleteinek használata" msgid "Compressed archive type for 'Create Archive In'" msgstr "Tömörített archívumtípus az „Archívum létrehozása ebben” parancshoz" msgid "Extract Here" msgstr "Kibontás ide" msgid "Extract compressed archive" msgstr "Tömörített archívum kibontása" msgid "Create Archive" msgstr "Archívum létrehozása" msgid "Create a compressed archive from folder" msgstr "Tömörített archívum létrehozása a mappából" msgid "Create Archive In..." msgstr "Archívum létrehozása ebben…" #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Archívum" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "Audacious lejátszás és lejátszólista vezérlése" msgid "Include songs in top level" msgstr "Dalok láthatók a felső szinten is" msgid "Enqueue" msgstr "Sorba állítás" msgid "Add track to the Audacious play queue" msgstr "Szám hozzáadása az Audacious lejátszási sorához" msgid "Dequeue" msgstr "Kivétel a sorból" msgid "Remove track from the Audacious play queue" msgstr "Szám eltávolítása az Audacious lejátszási sorából" msgid "Play" msgstr "Lejátszás" msgid "Jump to track in Audacious" msgstr "Számhoz ugrás az Audaciousban" msgid "Resume playback in Audacious" msgstr "Lejátszás folytatása az Audaciousban" msgid "Pause" msgstr "Szünet" msgid "Pause playback in Audacious" msgstr "Lejátszás szüneteltetése az Audaciousban" msgid "Next" msgstr "Következő" msgid "Jump to next track in Audacious" msgstr "Ugrás a következő számhoz az Audaciousban" msgid "Previous" msgstr "Előző" msgid "Jump to previous track in Audacious" msgstr "Ugrás az előző számhoz az Audaciousban" msgid "Clear Queue" msgstr "Sor törlése" msgid "Clear the Audacious play queue" msgstr "Az Audacious lejátszási sorának törlése" msgid "Shuffle" msgstr "Keverés" msgid "Toggle shuffle in Audacious" msgstr "Keverés váltása az Audaciousban" msgid "Repeat" msgstr "Ismétlés" msgid "Toggle repeat in Audacious" msgstr "Ismétlés váltása az Audaciousban" msgid "Show Playing" msgstr "Lejátszás megjelenítése" msgid "Tell which song is currently playing" msgstr "Megmondja, hogy jelenleg melyik szám szól" msgid "Playlist" msgstr "Lejátszólista" msgid "Calculator" msgstr "Számológép" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "Számítás" msgid "Clipboards" msgstr "Vágólapok" msgid "Recent clipboards and clipboard proxy objects" msgstr "Legutóbbi vágólapok és vágólap proxy objektumok" msgid "Number of recent clipboards to remember" msgstr "A megjegyzendő legutóbbi vágólapok száma" msgid "Include selected text in clipboard history" msgstr "A kijelölt szöveg felvétele a vágólap előzménybe" msgid "Copy selected text to primary clipboard" msgstr "A kijelölt szöveg másolása az elsődleges vágólapra" msgid "Selected Text" msgstr "Kijelölt szöveg" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "„%(desc)s” vágólap" msgstr[1] "„%(desc)s” vágólap %(num)d sorral" msgid "Clipboard Text" msgstr "Vágólap szöveg" msgid "Clipboard File" msgstr "Vágólap fájl" msgid "Clipboard Files" msgstr "Vágólap fájlok" msgid "Clear" msgstr "Törlés" msgid "Remove all recent clipboards" msgstr "Minden legutóbbi vágólap eltávolítása" msgid "Shell Commands" msgstr "Héjparancsok" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Parancssoros programok futtatása. A(z) %s szimbólummal jelölt műveletek az " "alhéjban futnak." msgid "Run (Get Output)" msgstr "Futtatás (eredmény elkapása)" msgid "Run program and return its output" msgstr "Program futtatása a kimenet visszaadásával" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "Átadás a parancsnak…" msgid "Run program with object as an additional parameter" msgstr "Program futtatása objektummal mint további paraméterrel" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "Írás a parancsnak…" msgid "Run program and supply text on the standard input" msgstr "Program futtatása és szöveg megadása az alapértelmezett bemeneten" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "Szűrés parancson keresztül…" msgid "Run command-line programs" msgstr "Parancssoros programok futtatása" msgid "GTK+" msgstr "GTK+" msgid "GNOME Terminal" msgstr "GNOME Terminál" msgid "XFCE Terminal" msgstr "XFCE Terminál" msgid "LXTerminal" msgstr "LXTerminal" msgid "X Terminal" msgstr "X Terminál" msgid "Urxvt" msgstr "Urxvt" msgid "Konsole" msgstr "Konsole" msgid "Save As..." msgstr "Mentés másként…" #, fuzzy msgid "Restart Kupfer" msgstr "Szolgáltatás újraindítása" msgid "Quit" msgstr "Kilépés" msgid "Quit Kupfer" msgstr "Kilépés a Kupferből" msgid "About Kupfer" msgstr "A Kupfer névjegye" msgid "Show information about Kupfer authors and license" msgstr "Információk megjelenítése a Kupfer szerzőiről és a licencről" msgid "Kupfer Help" msgstr "Kupfer súgó" msgid "Get help with Kupfer" msgstr "Segítség a Kupfer használatához" msgid "Show preferences window for Kupfer" msgstr "A Kupfer beállítások ablakának megjelenítése" msgid "Search Contents" msgstr "Tartalmak keresése" msgid "Search inside this catalog" msgstr "Keresés ebben a katalógusban" msgid "Copy" msgstr "Másolás" msgid "Copy to clipboard" msgstr "Másolás a vágólapra" msgid "Rescan" msgstr "Újrakeresés" msgid "Force reindex of this source" msgstr "A forrás újraindexelésének erőltetése" msgid "Last Command" msgstr "Utolsó parancs" msgid "Internal Kupfer Objects" msgstr "Belső Kupfer objektumok" msgid "Last Result" msgstr "Utolsó eredmény" msgid "Command Results" msgstr "Parancs eredményei" msgid "Custom Terminal" msgstr "Egyéni terminál" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Parancs" msgid "Execute flag" msgstr "Végrehajtás zászló" msgid "Default Email Client" msgstr "Alapértelmezett e-mail kliens" msgid "Compose email using the system's default mailto: handler" msgstr "" "Levél írása a rendszer alapértelmezett „mailto:” kezelőjének használatával" #, fuzzy msgid "Compose Email To" msgstr "Levél írása" msgid "Dictionary" msgstr "Szótár" msgid "Look up word in dictionary" msgstr "Szó keresése a szótárban" msgid "Look Up" msgstr "Keresés" msgid "Documents" msgstr "Dokumentumok" msgid "Recently used documents and bookmarked folders" msgstr "Nemrég használt dokumentumok és könyvjelzővel jelölt mappák" msgid "Max recent document days" msgstr "Nemrég használt dokumentum maximális napjai" msgid "Recent Items" msgstr "Legutóbbi elemek" msgid "Recently used documents" msgstr "Nemrég használt dokumentumok" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "%s dokumentum" #, python-format msgid "Recently used documents for %s" msgstr "Nemrég használt dokumentumok ehhez: %s" msgid "Places" msgstr "Helyek" msgid "Bookmarked folders" msgstr "Könyvjelzővel jelölt mappák" msgid "DuckDuckGo Search" msgstr "DuckDuckGo keresés" msgid "Search the web securely with DuckDuckGo" msgstr "Keresés a világhálón biztonságosan a DuckDuckGo szolgáltatással" msgid "Favorites" msgstr "Kedvencek" msgid "Mark commonly used items and store objects for later use" msgstr "" "Gyakran használt elemek megjelölése és objektumok tárolása későbbi " "felhasználásra" msgid "Shelf of \"Favorite\" items" msgstr "A „kedvenc” elemek polca" msgid "Add to Favorites" msgstr "Hozzáadás a kedvencekhez" msgid "Add item to favorites shelf" msgstr "Elem hozzáadása a kedvencek polcára" msgid "Remove from Favorites" msgstr "Eltávolítás a kedvencek közül" msgid "Remove item from favorites shelf" msgstr "Elem eltávolítása a kedvencek polcáról" msgid "File Actions" msgstr "Fájlműveletek" msgid "More file actions" msgstr "További fájlműveletek" msgid "Move To..." msgstr "Áthelyezés ide…" msgid "Move file to new location" msgstr "Fájl áthelyezése új helyre" msgid "Rename To..." msgstr "Átnevezés erre…" msgid "Copy To..." msgstr "Másolás ide…" msgid "Copy file to a chosen location" msgstr "Fájl másolása a kiválasztott helyre" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "Minta" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "Magasabb rendű műveletek" msgid "Tools to work with commands as objects" msgstr "Eszközök, amelyek parancsokat objektumokként használnak" msgid "Select in Kupfer" msgstr "Kijelölés a Kupferben" #, python-format msgid "Result of %s (%s)" msgstr "%s eredménye (%s)" msgid "Run (Take Result)" msgstr "Futtatás (eredmény átvétele)" msgid "Take the command result as a proxy object" msgstr "A parancs eredményének átvétele proxy objektumként" msgid "Run (Discard Result)" msgstr "Futtatás (eredmény eldobása)" msgid "Image Tools" msgstr "Képeszközök" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Képátalakítási eszközök" msgid "Scale..." msgstr "Méretezés…" msgid "Scale image to fit inside given pixel measure(s)" msgstr "Kép méretezése a belül megadott képpontméretekre való illesztésre" msgid "Rotate Clockwise" msgstr "Forgatás az óra járásával egyező irányba" msgid "Rotate Counter-Clockwise" msgstr "Forgatás az óra járásával ellentétes irányba" msgid "Autorotate" msgstr "Automatikus forgatás" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "JPEG képek forgatása (helyben) az EXIF metaadatok alapján" msgid "Kupfer Plugins" msgstr "Kupfer bővítmények" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Hozzáférés a Kupfer bővítménylistájához a Kupferben" msgid "Show Information" msgstr "Információk megjelenítése" msgid "Show Source Code" msgstr "Forráskód megjelenítése" msgid "enabled" msgstr "engedélyezve" msgid "disabled" msgstr "letiltva" msgid "Notes" msgstr "Jegyzetek" msgid "Gnote or Tomboy notes" msgstr "Gnote vagy Tomboy jegyzetek" msgid "Work with application" msgstr "Munka az alkalmazással" msgid "Open with notes application" msgstr "Megnyitás jegyzetelő alkalmazással" msgid "Append to Note..." msgstr "Hozzáfűzés a jegyzethez…" msgid "Add text to existing note" msgstr "Szöveg hozzáadása meglévő jegyzethez" msgid "Create Note" msgstr "Jegyzet létrehozása" msgid "Create a new note from this text" msgstr "Új jegyzet létrehozása ebből a szövegből" msgid "Get Note Search Results..." msgstr "Jegyzetkeresési eredmények megszerzése…" msgid "Show search results for this query" msgstr "A lekérdezés keresési eredményeinek megjelenítése" #, python-format msgid "today, %s" msgstr "ma, %s" #, python-format msgid "yesterday, %s" msgstr "tegnap, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Utoljára frissítve %s" msgid "Quicksilver Icons" msgstr "Quicksilver ikonok" msgid "Quick Image Viewer" msgstr "Gyors képnézegető" msgid "View Image" msgstr "Kép megtekintése" msgid "GNU Screen" msgstr "GNU Screen" msgid "Active GNU Screen sessions" msgstr "Aktív GNU Screen munkamenetek" msgid "Attached" msgstr "Csatolva" msgid "Detached" msgstr "Leválasztva" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "%(status)s munkamenet (%(pid)s) létrehozva: %(time)s" msgid "Screen Sessions" msgstr "Screen munkamenetek" msgid "Attach" msgstr "Csatolás" msgid "Send Keys" msgstr "Billentyűk küldése" msgid "Send synthetic keyboard events using xautomation" msgstr "" "Szintetikus billentyűzet események küldése az xautomation használatával" msgid "Paste to Foreground Window" msgstr "Beillesztés a legelső ablakba" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "Másolás a vágólapra és Ctrl+V küldése a legelső ablaknak" msgid "Send keys to foreground window" msgstr "Billentyűk küldése a legelső ablaknak" msgid "Type Text" msgstr "Szöveg begépelése" msgid "Type the text to foreground window" msgstr "Szöveg begépelése a legelső ablakba" msgid "GNOME Session Management" msgstr "GNOME munkamenet-kezelés" msgid "Special items and actions for GNOME environment" msgstr "Speciális elemek és műveletek a GNOME környezethez" msgid "Log Out..." msgstr "Kijelentkezés…" msgid "Log out or change user" msgstr "Kijelentkezés vagy felhasználóváltás" msgid "Shut Down..." msgstr "Leállítás…" msgid "Shut down, restart or suspend computer" msgstr "Leállítás, újraindítás vagy a számítógép felfüggesztése" msgid "Lock Screen" msgstr "Képernyő zárolása" msgid "Enable screensaver and lock" msgstr "Képernyővédő engedélyezése és zárolás" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "XFCE munkamenet-kezelés" msgid "Special items and actions for XFCE environment" msgstr "Speciális elemek és műveletek az XFCE környezethez" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "SSH gépek" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "Hozzáadja a ~/.ssh/config helyen található SSH gépeket." msgid "SSH host" msgstr "SSH gép" msgid "Connect" msgstr "Kapcsolódás" msgid "Connect to SSH host" msgstr "Kapcsolódás SSH géphez" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "SSH gépek a ~/.ssh/config helyen megadottak szerint" msgid "No D-Bus connection to desktop session" msgstr "Nincs D-Bus kapcsolat az asztali munkamenettel" msgid "GNOME Keyring" msgstr "GNOME kulcstartó" msgid "KWallet" msgstr "KWallet" msgid "Unencrypted File" msgstr "Titkosítatlan fájl" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "A parancs nem érhető el ebben: „%s”" msgid "Document Templates" msgstr "Dokumentumsablonok" msgid "Create new documents from your templates" msgstr "Új dokumentumok létrehozása sablonokból" #, python-format msgid "%s template" msgstr "%s sablon" msgid "Empty File" msgstr "Üres fájl" msgid "New Folder" msgstr "Új mappa" msgid "Create New Document..." msgstr "Új dokumentum létrehozása…" msgid "Create a new document from template" msgstr "Új dokumentum létrehozása sablonból" msgid "Create Document In..." msgstr "Dokumentum létrehozása itt…" msgid "Textfiles" msgstr "Szövegfájlok" msgid "Append To..." msgstr "Hozzáfűzés ehhez…" msgid "Append..." msgstr "Hozzáfűzés…" msgid "Write To..." msgstr "Írás ide…" msgid "Get Text Contents" msgstr "Szöveg tartalmának megszerzése" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "Thunar fájlkezelő műveletek" msgid "Select in File Manager" msgstr "Kijelölés a fájlkezelőben" msgid "Show Properties" msgstr "Tulajdonságok megjelenítése" msgid "Show information about file in file manager" msgstr "A fájl információinak megjelenítése a fájlkezelőben" msgid "Send To..." msgstr "Küldés ide…" msgid "Symlink In..." msgstr "Szimbolikus link ebben…" msgid "Create a symlink to file in a chosen location" msgstr "Szimbolikus link létrehozása a fájlra a kiválasztott helyen" msgid "Empty Trash" msgstr "Kuka ürítése" msgid "Thunar Send To Objects" msgstr "Thunar „küldés ide” objektumok" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Thunderbird/Icedove partnerek és műveletek" msgid "Compose New Email" msgstr "Új levél írása" msgid "Compose a new message in Thunderbird" msgstr "Új üzenet írása a Thunderbirdben" #, fuzzy msgid "Attach in Email To..." msgstr "Küldés levélben…" #, fuzzy msgid "Compose Email With" msgstr "Levél írása" #, fuzzy msgid "Compose a new message using the text as body" msgstr "Új üzenet írása a Thunderbirdben" msgid "Thunderbird Address Book" msgstr "Thunderbird címjegyzék" msgid "Contacts from Thunderbird Address Book" msgstr "Partnerek a Thunderbird címjegyzékből" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Top" msgid "Show running tasks and allow sending signals to them" msgstr "Futó feladatok megjelenítése és szignálok küldésének lehetővé tétele" msgid "Sort Order" msgstr "Rendezési sorrend" msgid "Commandline" msgstr "Parancssor" msgid "CPU usage (descending)" msgstr "CPU használat (csökkenő)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Memóriahasználat (csökkenő)" msgid "Send Signal..." msgstr "Szignál küldése…" msgid "Signals" msgstr "Szignálok" msgid "Running Tasks" msgstr "Futó feladatok" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% idő: %(time)s" msgid "Running tasks for current user" msgstr "A jelenlegi felhasználó futó feladatai" msgid "Trash" msgstr "Kuka" msgid "Access trash contents" msgstr "Hozzáférés a kuka tartalmához" msgid "Move to Trash" msgstr "Áthelyezés a Kukába" msgid "Move this file to trash" msgstr "A fájl áthelyezése a Kukába" msgid "Restore" msgstr "Visszaállítás" msgid "Move file back to original location" msgstr "A fájl visszaállítása az eredeti helyére" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "A kuka üres" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "A kukában egy fájl van" msgstr[1] "A kukában %(num)s fájl van" msgid "Triggers" msgstr "Aktiválók" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Globális gyorsbillentyűk (aktiválók) hozzárendelése a „Parancs " "összeállítása” művelettel létrehozott objektumokhoz." msgid "Add Trigger..." msgstr "Aktiváló hozzáadása…" msgid "Remove Trigger" msgstr "Aktiváló eltávolítása" msgid "URL Actions" msgstr "URL műveletek" msgid "Download and Open" msgstr "Letöltés és megnyitás" msgid "Download To..." msgstr "Letöltés ide…" msgid "Download URL to a chosen location" msgstr "URL letöltése egy kiválasztott helyre" msgid "Wikipedia" msgstr "Wikipédia" msgid "Search in Wikipedia" msgstr "Keresés a Wikipédián" msgid "Wikipedia language" msgstr "Wikipédia nyelv" #. TRANS: Default wikipedia language code msgid "en" msgstr "hu" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "A kifejezés keresése a %s.wikipedia.org oldalon" msgid "Window List" msgstr "Ablaklista" msgid "All windows on all workspaces" msgstr "Minden ablak az összes munkaterületen" msgid "Activate" msgstr "Aktiválás" msgid "Shade" msgstr "Felgördítés" msgid "Unshade" msgstr "Legördítés" msgid "Minimize" msgstr "Minimalizálás" msgid "Unminimize" msgstr "Minimalizálás megszüntetése" msgid "Maximize" msgstr "Maximalizálás" msgid "Unmaximize" msgstr "Maximalizálás megszüntetése" msgid "Maximize Vertically" msgstr "Függőleges maximalizálás" msgid "Unmaximize Vertically" msgstr "Függőleges maximalizálás megszüntetése" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Ablak itt: %(wkspc)s" msgid "Frontmost Window" msgstr "Legelső ablak" msgid "Next Window" msgstr "Következő ablak" msgid "Jump to this window's workspace and focus" msgstr "Ugrás az ablak munkaterületére és fókusz" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "%d ablak" msgstr[1] "%d ablak" msgid "Active workspace" msgstr "Aktív munkaterület" msgid "Jump to this workspace" msgstr "Ugrás erre a munkaterületre" msgid "Workspaces" msgstr "Munkaterületek" msgid "Volumes and Disks" msgstr "Kötetek és lemezek" msgid "Mounted volumes and disks" msgstr "Csatolt kötetek és lemezek" #, python-format msgid "Volume mounted at %s" msgstr "A kötet ide van csatolva: %s" msgid "Unmount" msgstr "Leválasztás" msgid "Unmount this volume" msgstr "A kötet leválasztása" msgid "Eject" msgstr "Kiadás" msgid "Unmount and eject this media" msgstr "Az adathordozó leválasztása és kiadása" msgid "Show Text" msgstr "Szöveg megjelenítése" msgid "Display text in a window" msgstr "Szöveg megjelenítése egy ablakban" msgid "Large Type" msgstr "Nagy típus" msgid "Show Notification" msgstr "Értesítés megjelenítése" msgid "Tracker" msgstr "Tracker" msgid "Tracker desktop search integration" msgstr "Tracker asztali kereső integráció" msgid "Search in Tracker" msgstr "Keresés a Trackerben" msgid "Open Tracker Search Tool and search for this term" msgstr "Tracker keresőeszköz megnyitása és keresés erre a kifejezésre" msgid "Get Tracker Results..." msgstr "Tracker eredményeinek megszerzése…" msgid "Show Tracker results for query" msgstr "A Tracker eredményeinek megjelenítése a lekérdezéshez" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "„%s” keresési eredményei" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "Fájlok keresése" msgid "Search filesystem using locate" msgstr "Keresés a fájlrendszerben a locate használatával" msgid "Ignore case distinctions when searching files" msgstr "Kis- és nagybetűk megkülönböztetésének mellőzése fájlok keresésekor" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Firefox könyvjelzők" msgid "Index of Firefox bookmarks" msgstr "Firefox könyvjelzők indexe" #, fuzzy msgid "Firefox Keywords" msgstr "Firefox könyvjelzők" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "Keresés a világhálón az OpenSearch keresőmotorokkal" msgid "Search With..." msgstr "Keresés ezzel…" msgid "Search For..." msgstr "Keresés erre…" #, fuzzy msgid "Search Terms" msgstr "Keresőmotorok" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Kérem használja ezt: „%s”" #, fuzzy msgid "Resume playback" msgstr "Lejátszás folytatása az Audaciousban" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Következő" #, fuzzy msgid "Skip to next track" msgstr "Ugrás a következő számhoz az Audaciousban" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Előző" #, fuzzy msgid "Skip to previous track" msgstr "Ugrás az előző számhoz az Audaciousban" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "Hozzáférés a Pidgin partnerekhez" msgid "Show offline contacts" msgstr "Kilépett partnerek megjelenítése" msgid "Open Chat" msgstr "Csevegés megnyitása" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d karakter)" msgstr[1] "%s (%d karakter)" msgid "Send Message..." msgstr "Üzenet küldése…" msgid "Available" msgstr "Elérhető" msgid "Away" msgstr "Távol" msgid "Pidgin Contacts" msgstr "Pidgin partnerek" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Linkek rövidítése" msgid "Create short aliases of long URLs" msgstr "Hosszú URL-ek rövid álnevének létrehozása" msgid "Error" msgstr "Hiba" msgid "Shorten With..." msgstr "Rövidítés ezzel…" msgid "Services" msgstr "Szolgáltatások" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "Számok lejátszása és sorba állítása és a zenekönyvtár böngészése" msgid "Include artists in top level" msgstr "Előadók láthatók a felső szinten is" msgid "Include albums in top level" msgstr "Albumok láthatók a felső szinten is" msgid "Play tracks in Rhythmbox" msgstr "Számok lejátszása a Rhythmboxban" msgid "Add tracks to the play queue" msgstr "Számok hozzáadása a lejátszási sorhoz" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "%(artist)s - %(album)s" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "%s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "%s számai" msgid "Albums" msgstr "Albumok" msgid "Music albums in Rhythmbox Library" msgstr "Zene albumok a Rhythmbox könyvtárban" msgid "Artists" msgstr "Előadók" msgid "Music artists in Rhythmbox Library" msgstr "Zene előadók a Rhythmbox könyvtárban" msgid "Songs" msgstr "Dalok" msgid "Songs in Rhythmbox library" msgstr "Dalok a Rhythmbox könyvtárban" msgid "Getting Things GNOME" msgstr "Getting Things GNOME" msgid "Browse and create new tasks in GTG" msgstr "Böngészés és új feladatok létrehozása a GTG-ben" #, python-format msgid "due: %s" msgstr "határidő: %s" #, python-format msgid "start: %s" msgstr "kezdés: %s" #, python-format msgid "tags: %s" msgstr "címkék: %s" msgid "Open task in Getting Things GNOME!" msgstr "Feladat megnyitása a „Getting Things GNOME!”-ban" msgid "Delete" msgstr "Törlés" msgid "Permanently remove this task" msgstr "Feladat végleges eltávolítása" msgid "Mark Done" msgstr "Készre jelölés" msgid "Mark this task as done" msgstr "A feladat készre jelölése" msgid "Dismiss" msgstr "Eltüntetés" msgid "Mark this task as not to be done anymore" msgstr "Feladat megjelölése „többé nem kell elvégezni”-ként" msgid "Create Task" msgstr "Feladat létrehozása" msgid "Create new task in Getting Things GNOME" msgstr "Feladat létrehozása a „Getting Things GNOME”-ban" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "Keresés a Devhelpben" msgid "Empathy" msgstr "Empathy" msgid "Access to Empathy Contacts" msgstr "Hozzáférés az Empathy partnerekhez" msgid "Busy" msgstr "Elfoglalt" msgid "Not Available" msgstr "Nem érhető el" msgid "Invisible" msgstr "Láthatatlan" msgid "Offline" msgstr "Kilépett" msgid "Change Global Status To..." msgstr "Globális állapot megváltoztatása…" msgid "Empathy Contacts" msgstr "Empathy partnerek" msgid "Empathy Account Status" msgstr "Empathy fiók állapot" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Alternatív aktiválása" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Vesszőtrükk" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Parancs összeállítása" msgid "Mark Default Action" msgstr "Alapértelmezett művelet jelölése" msgid "Forget Object" msgstr "Objektum elfelejtése" msgid "Reset All" msgstr "Összes visszaállítása" msgid "Select Quit" msgstr "Kilépés kiválasztása" msgid "Select Selected File" msgstr "Kijelölt fájl kiválasztása" msgid "Select Selected Text" msgstr "Kijelölt szöveg kiválasztása" msgid "Show Help" msgstr "Súgó megjelenítése" msgid "Show Preferences" msgstr "Beállítások megjelenítése" msgid "Switch to First Pane" msgstr "Váltás az első ablaktáblára" msgid "Toggle Text Mode" msgstr "Szöveges mód váltása" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Nincs találat ebben: %(src)s erre: „%(query)s”" msgid "No matches" msgstr "Nincs találat" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Nincs találat" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Legyen „%(action)s” az alapértelmezett ehhez: „%(object)s”" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "Felejtse el ezt: „%s”" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Fő felület megjelenítése" msgid "Show with Selection" msgstr "Megjelenítés a kijelöléssel" #. TRANS: Plugin info fields msgid "Description" msgstr "Leírás" msgid "Author" msgstr "Szerző" msgid "Version" msgstr "Verzió" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "A(z) „%s” Python modul szükséges" msgid "Plugin could not be read due to an error:" msgstr "A bővítmény nem olvasható valamilyen hiba miatt:" msgid "Content of" msgstr "Tartalom" #. TRANS: Plugin contents header msgid "Sources" msgstr "Források" #. TRANS: Plugin contents header msgid "Actions" msgstr "Műveletek" #, python-format msgid "Using encrypted password storage: %s" msgstr "Titkosított jelszótároló használata: %s" #, python-format msgid "Using password storage: %s" msgstr "Jelszótároló használata: %s" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Beállítások" msgid "Set username and password" msgstr "Felhasználónév és jelszó beállítása" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Válasszon könyvtárat" msgid "Reset all shortcuts to default values?" msgstr "Visszaállít minden gyorsbillentyűt az alapértelmezett értékre?" msgid "Shortcut" msgstr "Gyorsbillentyű" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "" "SanskritFritz \n" "Úr Balázs " msgid "A free software (GPLv3+) launcher" msgstr "Szabad szoftver (GPLv3+) indító" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Ez a program szabad szoftver; terjeszthető illetve módosítható a\n" "Free Software Foundation által kiadott GNU General Public License\n" "dokumentumában leírtak; akár a licenc 3-as, akár (tetszőleges) későbbi\n" "változata szerint.\n" "\n" "Ez a program abban a reményben kerül közreadásra, hogy hasznos lesz,\n" "de minden egyéb GARANCIA NÉLKÜL, az ELADHATÓSÁGRA vagy VALAMELY CÉLRA\n" "VALÓ ALKALMAZHATÓSÁGRA való származtatott garanciát is beleértve.\n" "További részleteket a GNU General Public License tartalmaz.\n" "\n" "A felhasználónak a programmal együtt meg kell kapnia a GNU General\n" "Public License egy példányát; ha mégsem kapta meg, akkor\n" "tekintse meg a oldalon.\n" "\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Nem található futó Kupfer" #~ msgid "Compose Email" #~ msgstr "Levél írása" #~ msgid "Send in Email To..." #~ msgstr "Küldés levélben…" #~ msgid "Type to search %s" #~ msgstr "Gépeljen %s kereséséhez" #~ msgid "No action" #~ msgstr "Nincs művelet" #~ msgid "GNOME Terminal Profiles" #~ msgstr "GNOME terminál profilok" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "GNOME terminálprofilok indítása" #~ msgid "Multihead Support" #~ msgstr "Több kijelző támogatása" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Az „=” jellel kezdődő kifejezések számítása" #~ msgid "Epiphany Bookmarks" #~ msgstr "Epiphany könyvjelzők" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Epiphany könyvjelzők indexe" #~ msgid "Include visited sites" #~ msgstr "A látogatott oldalak is" #~| msgid "Firefox Bookmarks" #~ msgid "Firefox tag" #~ msgstr "Firefox címke" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Lejátszás folytatása a Rhythmboxban" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Lejátszás szüneteltetése a Rhythmboxban" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Ugrás a következő számra a Rhythmboxban" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Ugrás az előző számra a Rhythmboxban" #~ msgid "Search the Web" #~ msgstr "Keresés a világhálón" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Nemrég használt dokumentumok az Abiwordben" #~ msgid "Abiword Recent Items" #~ msgstr "Legutóbbi elemek az Abiwordben" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "Felület az APT csomagkezelővel" #~ msgid "Installation method" #~ msgstr "Telepítési mód" #~ msgid "Show Package Information" #~ msgstr "Csomaginformációk megjelenítése" #~ msgid "Install" #~ msgstr "Telepítés" #~ msgid "Install package using the configured method" #~ msgstr "Csomag telepítése a beállított módon" #~ msgid "Packages matching \"%s\"" #~ msgstr "Erre illeszkedő csomagok: „%s”" #~ msgid "Search Package Name..." #~ msgstr "Csomagnév keresése…" #~ msgid "Ascii & Unicode Icon Set" #~ msgstr "Ascii és Unicode ikonkészlet" #~ msgid "" #~ "Provides the Ascii and Unicode icon sets that use letters and symbols to " #~ "produce icons for the objects found in Kupfer." #~ msgstr "" #~ "Az Ascii és Unicode ikonkészlet biztosítja, amelyek betűket és " #~ "szimbólumokat használnak ikonok készítéséhez a Kupferben található " #~ "objektumokhoz." #~ msgid "Ascii" #~ msgstr "Ascii" #~ msgid "Unicode" #~ msgstr "Unicode" #~ msgid "Chromium Bookmarks" #~ msgstr "Chromium könyvjelzők" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Chromium könyvjelzők indexe" #~ msgid "Claws Mail" #~ msgstr "Claws Mail" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Claws Mail címtár és műveletek" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Új levél írása a Claws Mailben" #~ msgid "Receive All Email" #~ msgstr "Minden levél fogadása" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "Új üzenetek fogadása a Claws Mail minden fiókjába" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Új üzenet írása és fájl csatolása a Claws Mailben" #~ msgid "Claws Mail Address Book" #~ msgstr "Claws Mail címjegyzék" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Partnerek a Claws Mail címjegyzékéből" #~ msgid "Configure a custom terminal emulator" #~ msgstr "Egyéni terminálemulátor beállítása" #~ msgid "Custom Theme" #~ msgstr "Egyéni téma" #~ msgid "Use a custom color theme" #~ msgstr "Egyéni színtéma használata" #~ msgid "Theme:" #~ msgstr "Téma:" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Evolution partnerek" #~ msgid "Compose a new message in Evolution" #~ msgstr "Új üzenet írása az Evolutionben" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Új üzenet írása és fájl csatolása az Evolutionben" #~ msgid "Evolution Address Book" #~ msgstr "Evolution címjegyzék" #~ msgid "Filezilla" #~ msgstr "Filezilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Oldalak megjelenítése és FTP-címek kezelése a Filezillával" #~ msgid "Open Site with Filezilla" #~ msgstr "Oldal megnyitása a Filezillával" #~ msgid "Filezilla Sites" #~ msgstr "Filezilla oldalak" #~ msgid "Sites from Filezilla" #~ msgstr "Oldalak a Filezillából" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Hozzáférés a Gajim partnerekhez" #~ msgid "Free for Chat" #~ msgstr "Csevegésre kész" #~ msgid "Gajim Contacts" #~ msgstr "Gajim partnerek" #~ msgid "Gajim Account Status" #~ msgstr "Gajim fiók állapot" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Partnerek betöltése és új levél írása Gmailben" #~ msgid "Load contacts' pictures" #~ msgstr "Partnerek képeinek betöltése" #~| msgid "show version information" #~ msgid "Load additional information" #~ msgstr "További információk betöltése" #~ msgid "Work email" #~ msgstr "Munkahelyi e-mail" #~| msgid "Compose Email" #~ msgid "Home email" #~ msgstr "Otthoni e-mail" #~ msgid "Other email" #~ msgstr "Egyéb e-mail" #~| msgid "Workspaces" #~ msgid "Work address" #~ msgstr "Munkahelyi cím" #~| msgid "Home Folder" #~ msgid "Home address" #~ msgstr "Otthoni cím" #~ msgid "Other address" #~ msgstr "Egyéb cím" #~ msgid "Car phone" #~ msgstr "Autótelefon" #~ msgid "Fax" #~ msgstr "Fax" #~| msgid "Home Folder" #~ msgid "Home phone" #~ msgstr "Otthoni telefon" #~ msgid "Home fax" #~ msgstr "Otthoni fax" #~ msgid "Internal phone" #~ msgstr "Belső telefon" #~ msgid "Mobile" #~ msgstr "Mobiltelefon" #~ msgid "Other" #~ msgstr "Egyéb" #~ msgid "VOIP" #~ msgstr "VOIP" #~| msgid "Workspaces" #~ msgid "Work phone" #~ msgstr "Munkahelyi telefon" #~ msgid "Work fax" #~ msgstr "Munkahelyi fax" #~ msgid "Compose Email in Gmail" #~ msgstr "Levél írása a Gmailben" #~ msgid "Open web browser and compose new email in Gmail" #~ msgstr "Webböngésző megnyitása és új levél írása a Gmailben" #~ msgid "Edit Contact in Gmail" #~ msgstr "Partner szerkesztése a Gmailben" #~| msgid "Open web browser and compose new email in Gmail" #~ msgid "Open web browser and edit contact in Gmail" #~ msgstr "Webböngésző megnyitása és partner szerkesztése a Gmailben" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Partnerek a Google szolgáltatásokból (Gmail)" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Albumok megjelenítése és fájlok feltöltése a Picasára" #~ msgid "Users to show: (,-separated)" #~ msgstr "Megjelenítendő felhasználók: (vesszővel elválasztva)" #~ msgid "Load user and album icons" #~ msgstr "Felhasználó és album ikonok betöltése" #~ msgid "Uploading Pictures" #~ msgstr "Képek feltöltése" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Képek feltöltése a Picasa webalbumba" #~ msgid "Creating album:" #~ msgstr "Album létrehozása:" #~ msgid "Album created by Kupfer" #~ msgstr "Kupfer által létrehozott album" #~ msgid "File:" #~ msgstr "Fájl:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "Egy album" #~ msgstr[1] "%(num)d album" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "egy fénykép" #~ msgstr[1] "%(num)s fénykép" #~ msgid "Upload to Picasa Album..." #~ msgstr "Feltöltés a Picasa albumba…" #~ msgid "Upload files to Picasa album" #~ msgstr "Fájlok feltöltése a Picasa albumba" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Feltöltés a Picasára új albumként" #~ msgid "Create album from selected local directory" #~ msgstr "Album létrehozása a kijelölt helyi könyvtárból" #~ msgid "Picasa Albums" #~ msgstr "Picasa albumok" #~ msgid "User albums in Picasa" #~ msgstr "Felhasználói albumok a Picasában" #~ msgid "Google Search" #~ msgstr "Google keresés" #~ msgid "Search Google with results shown directly" #~ msgstr "Google keresés a közvetlenül megjelenített eredményekkel" #~ msgid "Show More Results For \"%s\"" #~ msgstr "További eredmények megjelenítése ehhez: „%s”" #~ msgid "%s total found" #~ msgstr "%s találat összesen" #~ msgid "Gwibber" #~ msgstr "Gwibber" #~ msgid "" #~ "Microblogging with Gwibber. Allows sending and receiving messages from " #~ "social networks like Twitter, Identi.ca etc. Requires the package " #~ "'gwibber-service'." #~ msgstr "" #~ "Mikroblogolás a Gwibberrel. Lehetővé teszi üzenetek küldését és fogadását " #~ "a közösségi hálózatokról mint a Twitter, Identi.ca, stb. A „gwibber-" #~ "service” csomag szükséges hozzá." #~ msgid "Maximum number of messages to show" #~ msgstr "Megjelenítendő üzenetek maximális száma" #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s - %(service)s" #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s - %(where)s" #~ msgid "Send Message" #~ msgstr "Üzenet küldése" #~ msgid "Send message to all Gwibber accounts" #~ msgstr "Üzenet küldése minden Gwibber fiókra" #~ msgid "Send Message To..." #~ msgstr "Üzenet küldése…" #~ msgid "Send message to a Gwibber account" #~ msgstr "Üzenet küldése egy Gwibber fiókra" #~ msgid "Send message to selected Gwibber account" #~ msgstr "Üzenet küldése a kijelölt Gwibber fiókra" #~ msgid "Reply..." #~ msgstr "Válasz…" #~ msgid "Delete Message" #~ msgstr "Üzenet törlése" #~ msgid "Send Private Message..." #~ msgstr "Magánüzenet küldése…" #~ msgid "Send direct message to user" #~ msgstr "Közvetlen üzenet küldése a felhasználónak" #~ msgid "Retweet" #~ msgstr "Újratweetelés" #~ msgid "Retweet To..." #~ msgstr "Újratweetelés…" #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Üzenet újratweetelése minden Gwibber fiókra" #~ msgid "Retweet message to a Gwibber account" #~ msgstr "Üzenet újratweetelése egy Gwibber fiókra" #~ msgid "Open in Browser" #~ msgstr "Megnyitás böngészőben" #~ msgid "Open message in default web browser" #~ msgstr "Üzenet megnyitása az alapértelmezett webböngészőben" #~ msgid "Gwibber Accounts" #~ msgstr "Gwibber fiókok" #~ msgid "Accounts configured in Gwibber" #~ msgstr "A Gwibberben beállított fiókok" #~ msgid "Gwibber Messages" #~ msgstr "Gwibber üzenetek" #~ msgid "Recent messages received by Gwibber" #~ msgstr "A Gwibberrel legutóbb fogadott üzenetek" #~ msgid "Gwibber Messages for %s" #~ msgstr "Gwibber üzenetek ehhez: %s" #~ msgid "Gwibber Streams" #~ msgstr "Gwibber folyamok" #~ msgid "Streams configured in Gwibber" #~ msgstr "A Gwibberben beállított folyamok" #~ msgid "Gwibber Messages in %s" #~ msgstr "Gwibber üzenetek ebben: %s" #~ msgid "Gwibber (Simple)" #~ msgstr "Gwibber (egyszerű)" #~ msgid "Send updates via the microblogging client Gwibber" #~ msgstr "Frissítések küldése a Gwibber mikroblogoló kliensen keresztül" #~ msgid "Send Update" #~ msgstr "Frissítés küldése" #~ msgid "Unable to activate Gwibber service" #~ msgstr "Nem aktiválható a Gwibber szolgáltatás" #~ msgid "OpenOffice / LibreOffice" #~ msgstr "OpenOffice / LibreOffice" #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Legutóbb használt dokumentumok az OpenOffice-ban/LibreOffice-ban" #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "OpenOffice/LibreOffice legutóbbi elemek" #~ msgid "Opera Mail" #~ msgstr "Opera Mail" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Opera Mail partnerek és műveletek" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Új üzenet írása az Opera Mailben" #~ msgid "Opera Mail Contacts" #~ msgstr "Opera Mail partnerek" #~ msgid "Contacts from Opera Mail" #~ msgstr "Partnerek az Opera Mailből" #~ msgid "Opera Bookmarks" #~ msgstr "Opera könyvjelzők" #~ msgid "Index of Opera bookmarks" #~ msgstr "Opera könyvjelzők indexe" #~ msgid "PuTTY Sessions" #~ msgstr "PuTTY munkamenetek" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Gyors hozzáférés a PuTTY munkamenetekhez" #~ msgid "Start Session" #~ msgstr "Munkamenet indítása" #~ msgid "reStructuredText" #~ msgstr "reStructuredText" #~ msgid "Render reStructuredText and show the result" #~ msgstr "reStructuredText renderelése és az eredmény megjelenítése" #~ msgid "View as HTML Document" #~ msgstr "Megtekintés HTML dokumentumként" #~ msgid "System Services" #~ msgstr "Rendszerszolgáltatások" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "" #~ "Rendszerszolgáltatások indítása, leállítása vagy újraindítása az init " #~ "parancsfájlokkal" #~ msgid "Sudo-like Command" #~ msgstr "Sudo-szerű parancs" #~ msgid "Start Service" #~ msgstr "Szolgáltatás indítása" #~ msgid "Stop Service" #~ msgstr "Szolgáltatás leállítása" #~ msgid "%s Service" #~ msgstr "%s szolgáltatás" #~ msgid "Show QRCode" #~ msgstr "QRCode megjelenítése" #~ msgid "Display text as QRCode in a window" #~ msgstr "Szöveg megjelenítése QRCode-ként egy ablakban" #~ msgid "Access to Skype contacts" #~ msgstr "Hozzáférés a Skype partnerekhez" #~ msgid "Skype Me" #~ msgstr "Skype Me" #~ msgid "Logged Out" #~ msgstr "Kijelentkezve" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Hívás" #~ msgid "Place a call to contact" #~ msgstr "Partner hívása" #~ msgid "Skype Contacts" #~ msgstr "Skype partnerek" #~ msgid "Skype Statuses" #~ msgstr "Skype állapotok" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Kötetek a TrueCrypt előzményeiből" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "TrueCrypt kötet: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Kötet csatolása" #~ msgid "Mount in Truecrypt" #~ msgstr "Csatolás a TrueCryptben" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Fájl csatolásának próbája TrueCrypt kötetként" #~ msgid "Dismount All Volumes" #~ msgstr "Minden kötet leválasztása" #~ msgid "TrueCrypt Volumes" #~ msgstr "TrueCrypt kötetek" #~ msgid "Terminal Server Client" #~ msgstr "Terminálkiszolgáló kliens" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "A terminálkiszolgáló kliensben elmentett munkamenet" #~ msgid "TSClient sessions" #~ msgstr "TSClient munkamenetek" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "A terminálkiszolgáló kliensben elmentett munkamenetek" #~ msgid "Vim" #~ msgstr "Vim" #~ msgid "Recently used documents in Vim" #~ msgstr "Nemrég használt dokumentumok a Vim-ben" #~ msgid "Vim Recent Documents" #~ msgstr "Vim legutóbbi dokumentumok" #~ msgid "Close (Save All)" #~ msgstr "Bezárás (Összes mentése)" #~| msgid "Send To..." #~ msgid "Send..." #~ msgstr "Küldés…" #~| msgid "Saved Kupfer Command" #~ msgid "Send ex command" #~ msgstr "Ex parancs küldése" #~ msgid "Insert in Vim..." #~ msgstr "Beszúrás a Vim-be…" #~| msgid "Active GNU Screen sessions" #~ msgid "Active Vim Sessions" #~ msgstr "Aktív Vim munkamenetek" #~| msgid "PuTTY Sessions" #~ msgid "Vim Session %s" #~ msgstr "Vim munkamenet %s" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Vinagre könyvjelzők és műveletek" #~ msgid "Start Vinagre Session" #~ msgstr "Vinagre munkamenet indítása" #~ msgid "Vinagre Bookmarks" #~ msgstr "Vinagre könyvjelzők" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "VirtualBox virtuális gépek vezérlése. Támogatja a Sun Virtualboxot és a " #~ "nyílt forrású változatot is." #~ msgid "Force use CLI interface" #~ msgstr "Parancssori felület használatának erőltetése" #~ msgid "Power On" #~ msgstr "Bekapcsolás" #~ msgid "Power On Headless" #~ msgstr "Bekapcsolás felület nélkül" #~ msgid "Send Power Off Signal" #~ msgstr "Kikapcsolás szignál küldése" #~ msgid "Reboot" #~ msgstr "Újraindítás" #~ msgid "Resume" #~ msgstr "Folytatás" #~ msgid "Save State" #~ msgstr "Állapot mentése" #~ msgid "Power Off" #~ msgstr "Kikapcsolás" #~ msgid "VirtualBox Machines" #~ msgstr "VirtualBox gépek" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "" #~ "Hozzáférés a „Zim - egy asztali Wiki és vázlatkészítőben” tárolt " #~ "oldalakhoz" #~ msgid "Page names start with :colon" #~ msgstr "Az oldalak neve :colon-nal kezdődik" #~ msgid "Default page name for quick notes" #~ msgstr "Alapértelmezett oldalnév a gyors jegyzetekhez" #~ msgid "Note %x %X" #~ msgstr "Jegyzet %x %X" #~ msgid "" #~ "Strftime tags can be used: %H - hour, %M - minutes, etc\n" #~ "Please check python documentation for details.\n" #~ "NOTE: comma will be replaced by _" #~ msgstr "" #~ "Az strftime címkék használhatók: %H - óra, %M - perc, stb.\n" #~ "Nézze meg a python dokumentációját a részletekért.\n" #~ "MEGJEGYZÉS: a vessző _ jellel lesz helyettesítve" #~ msgid "Default namespace for quick notes" #~ msgstr "Alapértelmezett névtér a gyors jegyzetekhez" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Zim oldal a(z) „%s” jegyzettömbből" #~ msgid "Create Zim Page" #~ msgstr "Zim oldal létrehozása" #~ msgid "Create page in default notebook" #~ msgstr "Oldal létrehozása az alapértelmezett jegyzettömbben" #~ msgid "Create Zim Page In..." #~ msgstr "Zim oldal létrehozása itt…" #~ msgid "Insert QuickNote into Zim" #~ msgstr "QuickNote beszúrása a Zimbe" #~ msgid "Quick note selected text into Zim notebook" #~ msgstr "Gyors jegyzet a kijelölt szövegből a Zim jegyzettömbbe" #~ msgid "Create Subpage..." #~ msgstr "Aloldal létrehozása…" #~ msgid "Zim Notebooks" #~ msgstr "Zim jegyzettömbök" #~ msgid "Zim Pages" #~ msgstr "Zim oldalak" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Zim jegyzettömbben tárolt oldalak" #~ msgid "run keyboard shortcut relay service on this display" #~ msgstr "Billentyűtovábbító szolgáltatás engedélyezése ezen a képernyőn" #~ msgid "Selected Text \"%s\"" #~ msgstr "Kijelölt szöveg \"%s\"" #~ msgid "Recent clipboards" #~ msgstr "Legutóbbi vágólap-tartalmak" #~ msgid "Include recent selections" #~ msgstr "Legutolsó kijelölések beleszámítása" #~ msgid "" #~ "Provides current nautilus selection, using Kupfer's Nautilus Extension" #~ msgstr "" #~ "Hozzáférés a Nautilusban kiválasztott elemhez, a Kupfer Nautilus " #~ "kiegészítő segítségével" #~ msgid "Selected File \"%s\"" #~ msgstr "Kiválasztott fájl \"%s\"" #~ msgid "Selected Files" #~ msgstr "Kiválasztott fájlok" #~ msgid "Translate text with Google Translate" #~ msgstr "Szöveg lefordítása Google fordítóval" #~ msgid "Google Translate connection timed out" #~ msgstr "Google fordítóval a kapcsolat megszakadt" #~ msgid "Error connecting to Google Translate" #~ msgstr "Nem sikerült kapcsolódni a Google fordítóhoz" #~ msgid "Translate To..." #~ msgstr "Fordítás..." #~ msgid "Translate into %s" #~ msgstr "Fordítás %s-ra" #~ msgid "Languages" #~ msgstr "Nyelvek" #~ msgid "Show translated page in browser" #~ msgstr "A lefordított szöveg megjelenítése böngészőben" #~ msgid "Show Translation To..." #~ msgstr "Szöveg lefordítása erre..." #~ msgid "Show translation in browser" #~ msgstr "Fordítás megjelenítése böngészőben" #~ msgid "Tracker 0.6" #~ msgstr "Tracker 0.6" #~ msgid "Tracker tags" #~ msgstr "Tracker cimkék" #~ msgid "Tracker Tags" #~ msgstr "Tracker cimkék" #~ msgid "Browse Tracker's tags" #~ msgstr "Tracker cimkék böngészése" #~ msgid "Tag %s" #~ msgstr "%s cimke" #~ msgid "Objects tagged %s with Tracker" #~ msgstr "Elemek, Tracker-ben %s cimkével" #~ msgid "Add Tag..." #~ msgstr "Cimke hozzáadása..." #~ msgid "Add tracker tag to file" #~ msgstr "Tracker cimke hozzáadása fájlhoz" #~ msgid "Remove Tag..." #~ msgstr "Cimke eltávolítása..." #~ msgid "Remove tracker tag from file" #~ msgstr "Cimke eltávolítása fájlból" kupfer-328/po/intltool000077500000000000000000000001031500175051100150610ustar00rootroot00000000000000#!/bin/sh XGETTEXT_ARGS="--no-location" exec intltool-update "$@" kupfer-328/po/it.po000066400000000000000000001626721500175051100142670ustar00rootroot00000000000000# Italian translation for the kupfer package # Copyright (C) 2009 Ulrik Sverdrup # This file is distributed under the same license as the kupfer package. (GPLv3) # # Andrea Zagli , 2009. # Francesco Marella , 2010. #Albano Battistella , 2020. # msgid "" msgstr "" "Project-Id-Version: kupfer beta\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2021-01-20 16:33+0100\n" "Last-Translator: Albano Battistella \n" "Language-Team: Italian \n" "Language: 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" msgid "User credentials" msgstr "Credenziali utente" msgid "_User:" msgstr "_Utente:" msgid "_Password:" msgstr "_Password:" msgid "_Change" msgstr "_Cambia" msgid "Set Keyboard Shortcut" msgstr "Impostazione scorciatoia da tastiera" msgid "Please press desired key combination" msgstr "Premere la combinazione di tasti desiderata" msgid "Keybinding could not be bound" msgstr "L'associazione di tasti non può essere associata" msgid "Kupfer Preferences" msgstr "Preferenze di Kupfer" msgid "Start automatically on login" msgstr "Avvia automaticamente all'accesso" msgid "Start" msgstr "Avvio" msgid "Show icon in notification area" msgstr "Mostrare l'icona nell'area di notifica" msgid "Icon set:" msgstr "Set Icone:" msgid "Large Icon Size:" msgstr "Dimensione icona grande:" msgid "Small Icon Size:" msgstr "Dimensione icona piccola:" msgid "Terminal emulator:" msgstr "Emulatore di terminale:" msgid "Desktop Environment" msgstr "Ambiente Desktop" msgid "General" msgstr "Generale" msgid "Global Keyboard Shortcuts" msgstr "Scorciatoie da tastiera globali" msgid "Reset" msgstr "Ripristina" msgid "Browser Keyboard Shortcuts" msgstr "Scorciatoie da tastiera del browser" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "" "Usa pressione di singoli tasti per i comandi (Spazio, /, punto, virgola ecc.)" msgid "Keyboard" msgstr "Tastiera" msgid "Plugins" msgstr "Plugin" msgid "Inclusion in Top Level Searches" msgstr "Inclusione nelle ricerche di primo livello" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "Le sorgenti contrassegnate hanno i loro oggetti inclusi nelle ricerche di primo livello.\n" "I contenuti di una fonte non contrassegnata sono disponibili solo individuando il relativo sottocatalogo." msgid "Indexed Folders" msgstr "Cartelle indicizzate" msgid "Folders whose files are always available in the catalog." msgstr "Cartelle i cui file sono sempre disponibili nel catalogo." msgid "Catalog" msgstr "Catalogo" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Lanciatore di applicazioni" msgid "Convenient command and access tool for applications and documents" msgstr "Comodo comando e strumento di accesso per applicazioni e documenti" msgid "Execute in Kupfer" msgstr "Esegui in Kupfer" msgid "Saved Kupfer Command" msgstr "Comando salvato" #, python-format msgid "Could not to carry out '%s'" msgstr "Impossibile eseguire \"%s\"" #, python-format msgid "\"%s\" produced a result" msgstr "\"%s\" ha prodotto un risultato" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Permessi insufficienti per eseguire \"%s\" (non eseguibile)" #, python-format msgid "Command in \"%s\" is not available" msgstr "Comando in \"%s\" non è disponibile" #, python-format msgid "Keyboard relay is active for display %s" msgstr "" msgid "do not present main interface on launch" msgstr "non presentare l'interfaccia principale all'avvio" msgid "list available plugins" msgstr "elenca i plugin disponibili" msgid "enable debug info" msgstr "abilita informazioni di debug" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "eseguire il plugin helper" msgid "show usage help" msgstr "mostra l'aiuto per l'uso" msgid "show version information" msgstr "mostra informazioni sulla versione" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Utilizzo: kupfer [ OPTIONS | FILE ... ]" msgid "Available plugins:" msgstr "Plugin disponibili:" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "Digita per cercare" #, python-format msgid "%s is empty" msgstr "%s è vuoto" msgid "Text" msgstr "Testo" msgid "Run after Delay..." msgstr "Eseguire dopo un ritardo..." msgid "Perform command after a specified time interval" msgstr "Eseguire comando dopo un intervallo di tempo specificato" msgid "Multiple Objects" msgstr "Oggetti multipli" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s oggetto" msgstr[1] "%s oggetti" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "Sconosciuto" #, fuzzy msgid "Aim" msgstr "Vim" #, fuzzy msgid "Google Talk" msgstr "Google Translate" msgid "ICQ" msgstr "" msgid "MSN" msgstr "" msgid "QQ" msgstr "" msgid "Yahoo" msgstr "" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "%s non supporta questa operazione" msgid "Can not be used with multiple objects" msgstr "Non può essere utilizzato con più oggetti" msgid "Open" msgstr "Apri" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Nessuna applicazione predefinita per %(file)s (%(type)s)" #, fuzzy, python-format msgid "Please use \"%s\"" msgstr "File selezionato \"%s\"" msgid "Set Default Application..." msgstr "Imposta applicazione predefinita..." msgid "Open with default application" msgstr "Apri con applicazione predefinita" msgid "Reveal" msgstr "Rivela" msgid "Open parent folder" msgstr "Apre la cartella superiore" msgid "Open Terminal Here" msgstr "Apri terminale qui" msgid "Open this location in a terminal" msgstr "Apre questa posizione in un terminale" msgid "Run in Terminal" msgstr "Esegui nel terminale" msgid "Run (Execute)" msgstr "Esegui" msgid "Run this program in a Terminal" msgstr "Esegue questo programma in un terminale" msgid "Run this program" msgstr "Esegue questo programma" msgid "Go To" msgstr "Vai a" msgid "Open URL" msgstr "Apri URL" msgid "Open URL with default viewer" msgstr "Apre URL con visualizzatore predefinito" msgid "Launch" msgstr "Lancia" msgid "Show application window" msgstr "Mostra finestra applicazione" msgid "Launch application" msgstr "Lancia applicazione" msgid "Launch Again" msgstr "Lancia di nuovo" msgid "Launch another instance of this application" msgstr "Lancia un'altra istanza di questa applicazione" msgid "Close" msgstr "Chiudi" msgid "Attempt to close all application windows" msgstr "Tenta di chiudere tutte le finestre dell'applicazione" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Esegui" msgid "Perform command" msgstr "Esegui comando" msgid "(Empty Text)" msgstr "(File vuoto)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "\"%(text)s\"" msgstr[1] "(%(num)d righe) \"%(text)s\"" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s et. al." #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Sorgente ricorsiva di %(dir)s, (%(levels)d livelli)" #, python-format msgid "Directory source %s" msgstr "Directory sorgente «%s»" msgid "Home Folder" msgstr "Cartella home" msgid "Catalog Index" msgstr "Indice del catalogo" msgid "An index of all available sources" msgstr "Un indice di tutte le sorgenti disponibili" msgid "Root catalog" msgstr "Catalogo radice" msgid "Please Configure Plugin" msgstr "Configura il plugin" #, python-format msgid "Plugin %s is not configured" msgstr "Il plugin %s non è configurato" #, python-format msgid "Invalid user credentials for %s" msgstr "Credenziali utente non valide per %s" msgid "Applications" msgstr "Applicazioni" msgid "All applications and preferences" msgstr "Tutte le applicazioni e le preferenze" msgid "Applications for Desktop Environment" msgstr "Applicazioni per l'ambiente desktop" msgid "Use Desktop Filter" msgstr "Usa Filtro Desktop" msgid "Open With..." msgstr "Apri con..." msgid "Open with any application" msgstr "Apre con qualsiasi applicazione" msgid "Set default application to open this file type" msgstr "Imposta l'applicazione predefinita per questo tipo di file" msgid "Reset Associations" msgstr "Reimposta associazioni" msgid "Reset program associations for files of this type." msgstr "Reimposta le associazioni del programma per i file di questo tipo." msgid "Deep Archives" msgstr "Azioni su archivi" msgid "Allow browsing inside compressed archive files" msgstr "Permette la navigazione all'interno di archivi compressi" #, python-format msgid "Content of %s" msgstr "Contenuto di %s" #, fuzzy msgid "Archive Manager" msgstr "Archivio" #, fuzzy msgid "Use Archive Manager actions" msgstr "Azioni di Thunar" msgid "Compressed archive type for 'Create Archive In'" msgstr "Formato archivio compresso per 'Crea archivio in'" msgid "Extract Here" msgstr "Estrai qui" msgid "Extract compressed archive" msgstr "Estrae l'archivio compresso" msgid "Create Archive" msgstr "Crea archivio" msgid "Create a compressed archive from folder" msgstr "Crea un archivio compresso dalla cartella" msgid "Create Archive In..." msgstr "Crea archivio in..." #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Archivio" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "Controlla la riproduzione e la scaletta di Audacious" msgid "Include songs in top level" msgstr "Includere le canzoni nel livello principale" msgid "Enqueue" msgstr "Accoda" msgid "Add track to the Audacious play queue" msgstr "Aggiunge la traccia alla coda di riproduzione di Audacious" msgid "Dequeue" msgstr "Togli dalla coda" msgid "Remove track from the Audacious play queue" msgstr "Rimuove tracce dalla coda di riproduzione di Audacious" msgid "Play" msgstr "Riproduci" msgid "Jump to track in Audacious" msgstr "Salta alla traccia successiva in Audacious" msgid "Resume playback in Audacious" msgstr "Riprende la riproduzione in Audacious" msgid "Pause" msgstr "Pausa" msgid "Pause playback in Audacious" msgstr "Mette in pausa la riproduzione in Audacious" msgid "Next" msgstr "Successiva" msgid "Jump to next track in Audacious" msgstr "Salta alla traccia successiva in Audacious" msgid "Previous" msgstr "Precedente" msgid "Jump to previous track in Audacious" msgstr "Salta alla traccia precedente in Audacious" msgid "Clear Queue" msgstr "Cancella coda" msgid "Clear the Audacious play queue" msgstr "Cancella la coda di riproduzione di Audacious" msgid "Shuffle" msgstr "Mischia" msgid "Toggle shuffle in Audacious" msgstr "Attiva/disattiva mischia in Audacious" msgid "Repeat" msgstr "Ripeti" msgid "Toggle repeat in Audacious" msgstr "Attiva/Disattiva ripeti in Audacious" msgid "Show Playing" msgstr "Mostra riproduzione" msgid "Tell which song is currently playing" msgstr "Mostra quale canzone è attualmente riprodotta" msgid "Playlist" msgstr "Scaletta" msgid "Calculator" msgstr "Calcolatrice" msgid "Calculate mathematical expressions" msgstr "Calcola espressioni matematiche" msgid "Calculate" msgstr "Calcola" msgid "Clipboards" msgstr "Appunti" msgid "Recent clipboards and clipboard proxy objects" msgstr "Appunti recenti e oggetti proxy negli appunti" msgid "Number of recent clipboards to remember" msgstr "Numero di appunti recenti da ricordare" msgid "Include selected text in clipboard history" msgstr "Includi il testo selezionato nella cronologia degli appunti" msgid "Copy selected text to primary clipboard" msgstr "Copia il testo selezionato negli appunti principali" msgid "Selected Text" msgstr "Testo selezionato" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Appunti \"%(desc)s\"" msgstr[1] "Appunti con %(num)d righe \"%(desc)s\"" msgid "Clipboard Text" msgstr "Testo appunti" msgid "Clipboard File" msgstr "Appunto File" msgid "Clipboard Files" msgstr "Appunti FIle" msgid "Clear" msgstr "Cancella" msgid "Remove all recent clipboards" msgstr "Rimuovi tutti gli appunti recenti" msgid "Shell Commands" msgstr "Comandi della shell" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Esegui programmi da riga di comando. Le azioni contrassegnate con il simbolo %s vengono eseguite in " "subshell." msgid "Run (Get Output)" msgstr "Esegui (con output)" msgid "Run program and return its output" msgstr "Esegui il programma e ritorna il suo risultato" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "Passa al comando..." msgid "Run program with object as an additional parameter" msgstr "Esegui il programma con oggetto come parametro aggiuntivo" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "Scrivi Comando... " msgid "Run program and supply text on the standard input" msgstr "Eseguire il programma e fornire il testo sullo standard input" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "Filtra tramite il Comando..." msgid "Run command-line programs" msgstr "Esegue programmi a riga di comando" msgid "GTK+" msgstr "" msgid "GNOME Terminal" msgstr "Terminale di GNOME" msgid "XFCE Terminal" msgstr "TerminaleXFCE" msgid "LXTerminal" msgstr "Terminale LX" #, fuzzy msgid "X Terminal" msgstr "Terminale X" msgid "Urxvt" msgstr "" msgid "Konsole" msgstr "" msgid "Save As..." msgstr "Salva come..." msgid "Restart Kupfer" msgstr "Riavvia Kupfer" msgid "Quit" msgstr "Esci" msgid "Quit Kupfer" msgstr "Esce da Kupfer" msgid "About Kupfer" msgstr "Informazioni su Kupfer" msgid "Show information about Kupfer authors and license" msgstr "Mostra informazioni sugli autori di Kupfer e sulla licenza" msgid "Kupfer Help" msgstr "Aiuto di Kupfer" msgid "Get help with Kupfer" msgstr "Ottieni aiuto su Kupfer" msgid "Show preferences window for Kupfer" msgstr "Mostra la finestra delle preferenze di Kupfer" msgid "Search Contents" msgstr "Cerca contenuto" msgid "Search inside this catalog" msgstr "Cerca all'interno del catalogo" msgid "Copy" msgstr "Copia" msgid "Copy to clipboard" msgstr "Copia negli appunti" msgid "Rescan" msgstr "Nuova scansione" msgid "Force reindex of this source" msgstr "Forza la re-indicizzazione di questa sorgente" msgid "Last Command" msgstr "Ultimo comando" msgid "Internal Kupfer Objects" msgstr "Oggetti interni a Kupfer" msgid "Last Result" msgstr "Ultimo risultato" msgid "Command Results" msgstr "Risultati comando" msgid "Custom Terminal" msgstr "Terminale personalizzato" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" "Configura un emulatore di terminale personalizzato.\n" "\n" "Il plugin aggiunge un'altra alternativa al terminale (selezionalo nella pagina principale)." msgid "Command" msgstr "Comando" msgid "Execute flag" msgstr "Flag esecuzione" msgid "Default Email Client" msgstr "Client email predefinito" msgid "Compose email using the system's default mailto: handler" msgstr "" "Compone nuovo messaggio di posta usando il gestore di posta predefinito" msgid "Compose Email To" msgstr "Componi nuovo messaggio di posta" msgid "Dictionary" msgstr "Dizionario" msgid "Look up word in dictionary" msgstr "Cerca una parola nel dizionario" msgid "Look Up" msgstr "Cerca" msgid "Documents" msgstr "Documenti" msgid "Recently used documents and bookmarked folders" msgstr "Documenti utilizzati recentemente e cartelle aggiunte ai preferiti" msgid "Max recent document days" msgstr "Giorni massimi dei documenti recenti" msgid "Recent Items" msgstr "Voci recenti" msgid "Recently used documents" msgstr "Documenti utilizzati recentemente" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "Documenti %s" #, python-format msgid "Recently used documents for %s" msgstr "Documenti utilizzati recentemente per %s" msgid "Places" msgstr "Risorse" msgid "Bookmarked folders" msgstr "Cartelle aggiunte ai segnalibri" msgid "DuckDuckGo Search" msgstr "Cerca con DuckDuckGo" msgid "Search the web securely with DuckDuckGo" msgstr "Cerca nel web in sicurezza con DuckDuckGo" msgid "Favorites" msgstr "Preferiti" msgid "Mark commonly used items and store objects for later use" msgstr "Segna elementi usati comunemente e archivia oggetti per un utilizzo futuro" msgid "Shelf of \"Favorite\" items" msgstr "Lista di voci preferite" msgid "Add to Favorites" msgstr "Aggiungi ai preferiti" msgid "Add item to favorites shelf" msgstr "Aggiunge la voce alla lista dei preferiti" msgid "Remove from Favorites" msgstr "Rimuovi dai preferiti" msgid "Remove item from favorites shelf" msgstr "Rimuove la voce dalla lista dei preferiti" msgid "File Actions" msgstr "Azioni su file" msgid "More file actions" msgstr "Altre azioni su file" msgid "Move To..." msgstr "Sposta in..." msgid "Move file to new location" msgstr "Sposta il file in una nuova posizione" msgid "Rename To..." msgstr "Rinomina in..." msgid "Copy To..." msgstr "Copia in..." msgid "Copy file to a chosen location" msgstr "Copia il file in una nuova posizione" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "" msgid "Select objects using '*' and '?' as wildcards." msgstr "Seleziona gli oggetti usando '*' e '?' come caratteri jolly." msgid "Higher-order Actions" msgstr "Azioni Higher-order" msgid "Tools to work with commands as objects" msgstr "Strumenti per lavorare con comandi e oggetti" msgid "Select in Kupfer" msgstr "Seleziona in Kupfer" #, python-format msgid "Result of %s (%s)" msgstr "Risultati per %s (%s)" msgid "Run (Take Result)" msgstr "Esegui (Usa risultati)" msgid "Take the command result as a proxy object" msgstr "Usa il risultato del comando come un oggetto proxy" msgid "Run (Discard Result)" msgstr "Esegui (Scarta risultati)" msgid "Image Tools" msgstr "Strumenti per immagini" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Strumenti per la trasformazione delle immagini" msgid "Scale..." msgstr "Scala..." msgid "Scale image to fit inside given pixel measure(s)" msgstr "Scala immagine per adattarla alle dimensioni fornite in pixel" msgid "Rotate Clockwise" msgstr "Rotazione oraria" msgid "Rotate Counter-Clockwise" msgstr "Rotazione anti-oraria" msgid "Autorotate" msgstr "Rotazione automatica" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "Ruota immagine JPEG in base ai metadati EXIF associati" msgid "Kupfer Plugins" msgstr "Plugin" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Accede alla lista di plugin" msgid "Show Information" msgstr "Mostra informazioni" msgid "Show Source Code" msgstr "Mostra codice sorgente" msgid "enabled" msgstr "abilitato" msgid "disabled" msgstr "disabilitato" msgid "Notes" msgstr "Note" msgid "Gnote or Tomboy notes" msgstr "Note di Gnote o Tomboy" msgid "Work with application" msgstr "Utilizza l'applicazione" msgid "Open with notes application" msgstr "Apre note con l'applicazione" msgid "Append to Note..." msgstr "Aggiungi alle note..." msgid "Add text to existing note" msgstr "Aggiunge testo a una nota esistente" msgid "Create Note" msgstr "Crea nota" msgid "Create a new note from this text" msgstr "Crea una nuova nota dal testo" msgid "Get Note Search Results..." msgstr "Recupero risultati di Note..." msgid "Show search results for this query" msgstr "Mostra i risultati della ricerca per l'interrogazione" #, python-format msgid "today, %s" msgstr "oggi, %s" #, python-format msgid "yesterday, %s" msgstr "ieri, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Ultimo aggiornamento %s" msgid "Quicksilver Icons" msgstr "Icone Quicksilver" msgid "Quick Image Viewer" msgstr "Visualizzatore rapido di immagini" msgid "View Image" msgstr "Guarda immagine" msgid "GNU Screen" msgstr "GNU Screen" msgid "Active GNU Screen sessions" msgstr "Sessioni attive di GNU Screen" msgid "Attached" msgstr "Attaccato" msgid "Detached" msgstr "Separato" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "Sessione %(status)s (%(pid)s) creata %(time)s" msgid "Screen Sessions" msgstr "Sessioni di Screen" msgid "Attach" msgstr "Attacca" msgid "Send Keys" msgstr "Invia Chiave" msgid "Send synthetic keyboard events using xautomation" msgstr "Invia eventi di tastiera sintetica utilizzando xautomation" msgid "Paste to Foreground Window" msgstr "Incolla nella finestra in primo piano" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "Copia negli appunti e invia Ctrl+V alla finestra in primo piano" msgid "Send keys to foreground window" msgstr "Invia le chiavi alla finestra in primo piano" msgid "Type Text" msgstr "Digita Testo" msgid "Type the text to foreground window" msgstr "Digita il testo nella finestra in primo piano" msgid "GNOME Session Management" msgstr "Gestore sessioni di GNOME" msgid "Special items and actions for GNOME environment" msgstr "Voci speciali e azioni per l'ambiente GNOME" msgid "Log Out..." msgstr "Uscita..." msgid "Log out or change user" msgstr "Esce o cambia utente" msgid "Shut Down..." msgstr "Arresto..." msgid "Shut down, restart or suspend computer" msgstr "Arresta, riavvia o sospende il computer" msgid "Lock Screen" msgstr "Blocca lo schermo" msgid "Enable screensaver and lock" msgstr "Abilita il salvaschermo e blocca" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "Gestore di sessione XFCE" msgid "Special items and actions for XFCE environment" msgstr "Voci speciali e azioni per l'ambiente XFCE" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "Host SSH" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "Aggiunge gli host SSH trovati in ~/.ssh/config." msgid "SSH host" msgstr "Host SSH" msgid "Connect" msgstr "Connetti" msgid "Connect to SSH host" msgstr "Connette a host SSH" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "Host SSH come specificato in ~/.ssh/config" msgid "No D-Bus connection to desktop session" msgstr "Connessione D-Bus alla sessione assente" msgid "GNOME Keyring" msgstr "Portachiavi GNOME" msgid "KWallet" msgstr "" msgid "Unencrypted File" msgstr "File non crittografato" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "Comando in \"%s\" non è disponibile" msgid "Document Templates" msgstr "Modelli di documento" msgid "Create new documents from your templates" msgstr "Crea nuovi documenti dai modelli" #, python-format msgid "%s template" msgstr "%s modello" msgid "Empty File" msgstr "File vuoto" msgid "New Folder" msgstr "Nuova cartella" msgid "Create New Document..." msgstr "Crea nuovo documento..." msgid "Create a new document from template" msgstr "Crea un nuovo documento da modello" msgid "Create Document In..." msgstr "Crea nuovo documento in..." msgid "Textfiles" msgstr "File di testo" msgid "Append To..." msgstr "Aggiungi a..." msgid "Append..." msgstr "Aggiungi..." msgid "Write To..." msgstr "Scrivi in... " msgid "Get Text Contents" msgstr "Cerca contenuto" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "Azioni di Thunar" msgid "Select in File Manager" msgstr "Seleziona nell'esploratore file" msgid "Show Properties" msgstr "Mostra proprietà" msgid "Show information about file in file manager" msgstr "Mostra informazioni sul file nell'esploratore file" msgid "Send To..." msgstr "Invia a..." msgid "Symlink In..." msgstr "" #, fuzzy msgid "Create a symlink to file in a chosen location" msgstr "Copia il file in una nuova posizione" msgid "Empty Trash" msgstr "Svuota cestino" msgid "Thunar Send To Objects" msgstr "Thunar Invia ad oggetti" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Contatti e azioni di Thunderbird/Icedove" msgid "Compose New Email" msgstr "Componi nuovo messaggio di posta" msgid "Compose a new message in Thunderbird" msgstr "Compone un nuovo messaggio di posta in Thunderbird" #, fuzzy msgid "Attach in Email To..." msgstr "Invia con messaggio di posta a..." #, fuzzy msgid "Compose Email With" msgstr "Componi nuovo messaggio di posta" #, fuzzy msgid "Compose a new message using the text as body" msgstr "Compone un nuovo messaggio di posta in Thunderbird" msgid "Thunderbird Address Book" msgstr "Rubrica indirizzi di Thunderbird" msgid "Contacts from Thunderbird Address Book" msgstr "Contatti dalla rubrica indirizzi di Thunderbird" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Top" msgid "Show running tasks and allow sending signals to them" msgstr "Mostra i processi in esecuzione e permette di inviare segnali" msgid "Sort Order" msgstr "Ordina per" msgid "Commandline" msgstr "Riga di comando" msgid "CPU usage (descending)" msgstr "Utilizzo CPU (discendente)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Utilizzo di memoria (discendente)" msgid "Send Signal..." msgstr "Invia segnale..." msgid "Signals" msgstr "Segnali" msgid "Running Tasks" msgstr "Processi in esecuzione" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% tempo: %(time)s" msgid "Running tasks for current user" msgstr "Processi in esecuzione per l'utente corrente" msgid "Trash" msgstr "Cestino" msgid "Access trash contents" msgstr "Accede al contenuto del cestino" msgid "Move to Trash" msgstr "Sposta nel cestino" msgid "Move this file to trash" msgstr "Sposta questo file nel cestino" msgid "Restore" msgstr "Ripristina" msgid "Move file back to original location" msgstr "Sposta il file nella posizione originale" msgid "" "Could not delete files:\n" " " msgstr "" "Impossibile eliminare i file:\n" " " msgid "Trash is empty" msgstr "Il cestino è vuoto" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "Il cestino contiene un file" msgstr[1] "Il cestino contiene %(num)s file" msgid "Triggers" msgstr "Trigger" #, fuzzy msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Assegna associazione tasti globale (trigger) a oggetti creati con 'Componi " "comando' (Ctrl+Invio)." msgid "Add Trigger..." msgstr "Aggiungi trigger..." msgid "Remove Trigger" msgstr "Rimuovi trigger" msgid "URL Actions" msgstr "Azioni su URL" msgid "Download and Open" msgstr "Scarica e apri" msgid "Download To..." msgstr "Scarica in..." msgid "Download URL to a chosen location" msgstr "Copia i file in una nuova posizione" msgid "Wikipedia" msgstr "Wikipedia" msgid "Search in Wikipedia" msgstr "Cerca in Wikipedia" msgid "Wikipedia language" msgstr "Lingua di Wikipedia" #. TRANS: Default wikipedia language code msgid "en" msgstr "it" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Cerca questo termine in %s.wikipedia.org" msgid "Window List" msgstr "Elenco finestre" msgid "All windows on all workspaces" msgstr "Tutte le finestre in tutti gli spazi di lavoro" msgid "Activate" msgstr "Attiva" msgid "Shade" msgstr "Arrotola" msgid "Unshade" msgstr "Srotola" msgid "Minimize" msgstr "Minimizza" msgid "Unminimize" msgstr "Deminimizza" msgid "Maximize" msgstr "Massimizza" msgid "Unmaximize" msgstr "Demassimizza" msgid "Maximize Vertically" msgstr "Massimizza verticalmente" msgid "Unmaximize Vertically" msgstr "Demassimizza verticalmente" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Finestra in %(wkspc)s" msgid "Frontmost Window" msgstr "Finestra in primo piano" msgid "Next Window" msgstr "Prossima finestra" msgid "Jump to this window's workspace and focus" msgstr "Salta nello spazio di lavoro di questa finestra e dà il focus" #, fuzzy, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "Prossima finestra" msgstr[1] "Prossima finestra" #, fuzzy msgid "Active workspace" msgstr "Salta in questo spazio di lavoro" msgid "Jump to this workspace" msgstr "Salta in questo spazio di lavoro" msgid "Workspaces" msgstr "Spazi di lavoro" msgid "Volumes and Disks" msgstr "Volumi e dischi" msgid "Mounted volumes and disks" msgstr "Volumi e dischi montati" #, python-format msgid "Volume mounted at %s" msgstr "Volume montato su «%s»" msgid "Unmount" msgstr "Smonta" msgid "Unmount this volume" msgstr "Smonta questo volume" msgid "Eject" msgstr "Espelli" msgid "Unmount and eject this media" msgstr "Smonta ed espelle questo supporto" msgid "Show Text" msgstr "Mostra testo" msgid "Display text in a window" msgstr "Mostra testo in finestra" msgid "Large Type" msgstr "Carattere grande" msgid "Show Notification" msgstr "Mostrare notifiche" #, fuzzy msgid "Tracker" msgstr "Tracker 0.6" msgid "Tracker desktop search integration" msgstr "Integrazione con Tracker, ricerca scrivania" msgid "Search in Tracker" msgstr "Cerca in Tracker" msgid "Open Tracker Search Tool and search for this term" msgstr "Apre lo strumento di ricerca Tracker e cerca questo termine" msgid "Get Tracker Results..." msgstr "Recupero risultati di Tracker..." msgid "Show Tracker results for query" msgstr "Mostra i risultati di Tracker per l'interrogazione" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "Risultati per \"%s\"" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "Uso '?' prefisso per ottenere risultati di testo completo" msgid "Locate Files" msgstr "Trova file" msgid "Search filesystem using locate" msgstr "Cerca nel filesystem con locate" msgid "Ignore case distinctions when searching files" msgstr "Ignorare distinzione tra maiuscole/minuscole durante la ricerca dei file" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Segnalibri di Firefox" msgid "Index of Firefox bookmarks" msgstr "Indice dei segnalibri di Firefox" #, fuzzy msgid "Firefox Keywords" msgstr "Segnalibri di Firefox" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "Ricerca nel web con OpenSearch" msgid "Search With..." msgstr "Ricerca con..." msgid "Search For..." msgstr "Cerca contenuto..." #, fuzzy msgid "Search Terms" msgstr "Motori di ricerca" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "File selezionato \"%s\"" #, fuzzy msgid "Resume playback" msgstr "Riprende la riproduzione in Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Successiva" #, fuzzy msgid "Skip to next track" msgstr "Salta alla traccia successiva in Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Precedente" #, fuzzy msgid "Skip to previous track" msgstr "Salta alla traccia precedente in Audacious" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr " Ferma (%s)" msgid "Stop playback" msgstr "Ferma riprodizione" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "Accedi ai contatti di Pidgin" msgid "Show offline contacts" msgstr "Mostrare i contatti non in linea" msgid "Open Chat" msgstr "Apri chat" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d carattere)" msgstr[1] "%s (%d caratteri)" msgid "Send Message..." msgstr "Invia messaggio..." msgid "Available" msgstr "Disponibile" msgid "Away" msgstr "Assente" msgid "Pidgin Contacts" msgstr "Contatti Pidgin" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Abbrevia collegamenti" msgid "Create short aliases of long URLs" msgstr "Crea alias brevi per URL lunghi" msgid "Error" msgstr "Errore" msgid "Shorten With..." msgstr "Abbrevia con..." msgid "Services" msgstr "Servizi" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "Riproduce, accoda tracce e sfoglia la libreria musicale" msgid "Include artists in top level" msgstr "Includere gli artisti nel livello principale" msgid "Include albums in top level" msgstr "Includere gli album nel livello principale" msgid "Play tracks in Rhythmbox" msgstr "Riproduce tracce in Rhythmbox" msgid "Add tracks to the play queue" msgstr "Aggiunge tracce alla coda di riproduzione" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "di %(artist)s da %(album)s" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "di %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Traccia da %s" msgid "Albums" msgstr "Album" msgid "Music albums in Rhythmbox Library" msgstr "Album musicali nella libreria di Rhythmbox" msgid "Artists" msgstr "Artisti" msgid "Music artists in Rhythmbox Library" msgstr "Artisti musicali nella libreria di Rhythmbox" msgid "Songs" msgstr "Canzoni" msgid "Songs in Rhythmbox library" msgstr "Canzoni nella libreria di Rhythmbox" msgid "Getting Things GNOME" msgstr "Getting Things GNOME" msgid "Browse and create new tasks in GTG" msgstr "Sfoglia e crea nuove attività in GTG" #, python-format msgid "due: %s" msgstr "da completare il: %s" #, python-format msgid "start: %s" msgstr "inizia il: %s" #, python-format msgid "tags: %s" msgstr "etichette: %s" msgid "Open task in Getting Things GNOME!" msgstr "Apri l'attività in Getting Things GNOME!" msgid "Delete" msgstr "Elimina" msgid "Permanently remove this task" msgstr "Elimina definitivamente questa attività" msgid "Mark Done" msgstr "Marca completa" msgid "Mark this task as done" msgstr "Marca questa attività completa" msgid "Dismiss" msgstr "Rimuovi" msgid "Mark this task as not to be done anymore" msgstr "Marca questa attività come non più da completare" msgid "Create Task" msgstr "Crea attività" msgid "Create new task in Getting Things GNOME" msgstr "Crea una nuova attività in Getting Things GNOME" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "Cerca in Devhelp" msgid "Empathy" msgstr "Empathy" msgid "Access to Empathy Contacts" msgstr "Accede ai contatti di Empathy" msgid "Busy" msgstr "Occupato" msgid "Not Available" msgstr "Non disponibile" msgid "Invisible" msgstr "Invisibile" msgid "Offline" msgstr "Fuori rete" msgid "Change Global Status To..." msgstr "Cambia stato globale in..." msgid "Empathy Contacts" msgstr "Contatti di Empathy" msgid "Empathy Account Status" msgstr "Stato account Empathy" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Attivazione alternativa" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Posiziona selezione in pila" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Comando Componi" msgid "Mark Default Action" msgstr "Contrassegna azione predefinita" msgid "Forget Object" msgstr "Dimentica Oggetto" msgid "Reset All" msgstr "Ripristina tutto" msgid "Select Quit" msgstr "Seleziona Esci" msgid "Select Selected File" msgstr "Seleziona file selezionato" msgid "Select Selected Text" msgstr "Seleziona testo selezionato" msgid "Show Help" msgstr "Mostra aiuto" msgid "Show Preferences" msgstr "Mostra preferenze" msgid "Switch to First Pane" msgstr "Passa al primo riquadro" msgid "Toggle Text Mode" msgstr "Attiva/Disattiva modalità testo" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Nessuna corrispondenza in %(src)s per \"%(query)s\"" msgid "No matches" msgstr "Nessuna corrispondenza" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Nessuna corrispondenza" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Mostra interfaccia" msgid "Show with Selection" msgstr "Mostra con selezione" #. TRANS: Plugin info fields msgid "Description" msgstr "Descrizione" msgid "Author" msgstr "Autore" msgid "Version" msgstr "Versione" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Il modulo Python \"%s\" è necessario" msgid "Plugin could not be read due to an error:" msgstr "Il plugin non può essere letto a causa di un errore:" msgid "Content of" msgstr "Contenuto di" #. TRANS: Plugin contents header msgid "Sources" msgstr "Sorgenti" #. TRANS: Plugin contents header msgid "Actions" msgstr "Azioni" #, python-format msgid "Using encrypted password storage: %s" msgstr "Utilizzo dell'archiviazione password crittografata: %s" #, python-format msgid "Using password storage: %s" msgstr "Utilizzo dell'archiviazione password: %s" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Configurazione" msgid "Set username and password" msgstr "Imposta nome utente e password" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Scegli una cartella" msgid "Reset all shortcuts to default values?" msgstr "Reimpostare tutti i collegamenti ai valori predefiniti?" msgid "Shortcut" msgstr "Collegamento" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "" "Andrea Zagli \n" "Francesco Marella " msgid "A free software (GPLv3+) launcher" msgstr "Un lanciatore software libero (GPLv3+)" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Questo programma è software libero, lo si può redistribuire e/o modificare\n" "in base ai termini della Licenza Pubblica Generale GNU (GNU GPL) come\n" "pubblicata dalla Free Software Foundation versione 3 o (a proprio\n" "piacimento) successiva.\n" "\n" "Questo programma è distribuito nella speranza che sia utile, ma SENZA " "ALCUNA\n" "GARANZIA, comprese anche la garanzia implicita di VENDIBILITÀ e di\n" "ADEGUATEZZA AD UN PARTICOLARE SCOPO. Vedere la Licenza Pubblica Generale " "GNU\n" "per maggiori dettagli.\n" "\n" "Insieme a questo programma dovrebbe essere stata fornita anche una copia\n" "della Licenza Pubblica Generale GNU. In caso contrario vedere .\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Impossibile trovare Kupfer in esecuzione" #~ msgid "Compose Email" #~ msgstr "Componi nuovo messaggio di posta" #~ msgid "Send in Email To..." #~ msgstr "Invia con messaggio di posta a..." #~ msgid "Type to search %s" #~ msgstr "Digita per cercare in %s" #~ msgid "No action" #~ msgstr "Nessuna azione" #~ msgid "GNOME Terminal Profiles" #~ msgstr "Profili del Terminale di GNOME" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Lancia profili del Terminale di GNOME" #~ msgid "Selected Text \"%s\"" #~ msgstr "Testo selezionato «%s»" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Calcola espressioni che iniziano con '='" #~ msgid "Recent clipboards" #~ msgstr "Appunti recenti" #~ msgid "Include recent selections" #~ msgstr "Includere selezioni recenti" #~ msgid "Epiphany Bookmarks" #~ msgstr "Segnalibri di Epiphany" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Indice dei segnalibri di Epiphany" #~ msgid "Include visited sites" #~ msgstr "Includere i siti visitati" #~ msgid "" #~ "Provides current nautilus selection, using Kupfer's Nautilus Extension" #~ msgstr "" #~ "Fornisce la selezione corrente in nautilus, usando l'estensione per " #~ "Nautilus di Kupfer" #~ msgid "Selected File \"%s\"" #~ msgstr "File selezionato \"%s\"" #~ msgid "Selected Files" #~ msgstr "File selezionati" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Riprende la riproduzione in Rhythmbox" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Mette in pausa la riproduzione in Rhythmbox" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Salta alla traccia successiva in Rhythmbox" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Salta alla traccia precedente in Rhythmbox" #~ msgid "Search the Web" #~ msgstr "Cerca sul web" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Documenti utilizzati recentemente in Abiword" #~ msgid "Abiword Recent Items" #~ msgstr "Voci recenti di Abiword" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "Interfaccia per il gestore di pacchetti APT" #~ msgid "Installation method" #~ msgstr "Metodo di installazione" #~ msgid "Show Package Information" #~ msgstr "Mostra informazioni sul pacchetto" #~ msgid "Install" #~ msgstr "Installa" #~ msgid "Install package using the configured method" #~ msgstr "Installa il pacchetto utilizzando il metodo configurato" #~ msgid "Packages matching \"%s\"" #~ msgstr "Pacchetti per \"%s\"" #~ msgid "Search Package Name..." #~ msgstr "Cerca per nome pacchetto..." #~ msgid "Chromium Bookmarks" #~ msgstr "Segnalibri di Chromium" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Indice dei segnalibri di Chromium" #~ msgid "Claws Mail" #~ msgstr "Claws Mail" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Contatti e azioni di Claws Mail" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Compone nuovo messaggio di posta con Claws Mail" #~ msgid "Receive All Email" #~ msgstr "Ricevi tutti i messaggi di posta" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "Riceve nuovi messaggi di posta per tutti gli account con ClawsMail" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Compone nuovo messaggio di posta con Claws Mail e allega file" #~ msgid "Claws Mail Address Book" #~ msgstr "Rubrica indirizzi di Claws Mail" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Contatti dalla rubrica indirizzi di Claws Mail" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Contatti Evolution" #~ msgid "Compose a new message in Evolution" #~ msgstr "Componi nuovo messaggio in Evolution" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Compone nuovo messaggio in Evolution e allega file" #~ msgid "Evolution Address Book" #~ msgstr "Rubrica indirizzi di Evolution" #~ msgid "Filezilla" #~ msgstr "Filezilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Mostra siti e gestisce indirizzi ftp con Filezilla" #~ msgid "Open Site with Filezilla" #~ msgstr "Apre il sito con Filezilla" #~ msgid "Filezilla Sites" #~ msgstr "Siti Filezilla" #~ msgid "Sites from Filezilla" #~ msgstr "Siti di Filezilla" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Accede ai contatti Gajim" #~ msgid "Free for Chat" #~ msgstr "Disponibile alla chat" #~ msgid "Gajim Contacts" #~ msgstr "Contatti Gajim" #~ msgid "Gajim Account Status" #~ msgstr "Stato account Gajim" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Carica contatti e compone un nuovo messaggio di posta in Gmail" #~ msgid "Load contacts' pictures" #~ msgstr "Caricare immagini dei contatti" #~ msgid "Compose Email in GMail" #~ msgstr "Componi nuovo messaggio di posta in GMail" #~ msgid "Open web browser and compose new email in GMail" #~ msgstr "" #~ "Apre il browser web per comporre un nuovo messaggio di posta in GMail" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Contatti dai servizi Google (Gmail)" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Mostra album e carica file in Picasa" #~ msgid "Users to show: (,-separated)" #~ msgstr "Utenti da mostrare: (separati con virgola)" #~ msgid "Load user and album icons" #~ msgstr "Caricare gli utenti e le icone degli album" #~ msgid "Uploading Pictures" #~ msgstr "Caricamento immagini" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Carica foto in Picasa Web Album" #~ msgid "Creating album:" #~ msgstr "Creazione album:" #~ msgid "Album created by Kupfer" #~ msgstr "Album creati da Kupfer" #~ msgid "File:" #~ msgstr "File:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "Un album" #~ msgstr[1] "%(num)d album" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "una foto" #~ msgstr[1] "%(num)s foto" #~ msgid "Upload to Picasa Album..." #~ msgstr "Carica nell'album Picasa..." #~ msgid "Upload files to Picasa album" #~ msgstr "Carica file in un album Picasa" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Carica in Picasa come nuovo album" #~ msgid "Create album from selected local directory" #~ msgstr "Crea album dalle cartelle locali selezionate" #~ msgid "Picasa Albums" #~ msgstr "Album di picasa" #~ msgid "User albums in Picasa" #~ msgstr "Album dell'utente in Picasa" #~ msgid "Search Google with results shown directly" #~ msgstr "Cerca con Google con risultati mostrati direttamente" #~ msgid "Show More Results For \"%s\"" #~ msgstr "Mostra più risultati per \"%s\"" #~ msgid "%s total found" #~ msgstr "%s trovati in totale" #~ msgid "Translate text with Google Translate" #~ msgstr "Traduce testo con Google Translate" #~ msgid "Google Translate connection timed out" #~ msgstr "Connessione a Google Translate scaduta" #~ msgid "Error connecting to Google Translate" #~ msgstr "Errore di connessione a Google Translate" #~ msgid "Translate To..." #~ msgstr "Traduci..." #~ msgid "Translate into %s" #~ msgstr "Traduci in %s" #~ msgid "Languages" #~ msgstr "Lingue" #~ msgid "Show translated page in browser" #~ msgstr "Mostra la pagina tradotta in finestra" #~ msgid "Show Translation To..." #~ msgstr "Mostra traduzione in..." #~ msgid "Show translation in browser" #~ msgstr "Mostra la traduzione nel browser" #, fuzzy #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s %(when)s" #, fuzzy #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s" #~ msgid "Send Message" #~ msgstr "Invia messaggio" #~ msgid "Send Message To..." #~ msgstr "Invia messaggio a..." #~ msgid "Reply..." #~ msgstr "Rispondi..." #~ msgid "Delete Message" #~ msgstr "Cancella Messaggio" #~ msgid "Send Private Message..." #~ msgstr "Invia Messaggio Privato" #~ msgid "Send direct message to user" #~ msgstr "Invia messaggio diretto ad un utente" #~ msgid "Retweet To..." #~ msgstr "Ritwetta a..." #, fuzzy #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Riceve nuovi messaggi di posta per tutti gli account con ClawsMail" #, fuzzy #~ msgid "Open in Browser" #~ msgstr "Apre la cartella superiore" #, fuzzy #~ msgid "Open message in default web browser" #~ msgstr "Apre URL con visualizzatore predefinito" #, fuzzy #~ msgid "Gwibber Accounts" #~ msgstr "Stato account Gajim" #, fuzzy #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Documenti utilizzati recentemente in OpenOffice" #, fuzzy #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "Voci recenti OpenOffice" #~ msgid "Opera Bookmarks" #~ msgstr "Segnalibri di Opera" #~ msgid "Index of Opera bookmarks" #~ msgstr "Indice dei segnalibri di Opera" #~ msgid "Opera Mail" #~ msgstr "Opera Mail" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Contatti e azioni di Opera Mail" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Compone nuovo messaggio di posta con Opera Mail" #~ msgid "Opera Mail Contacts" #~ msgstr "Contatti Opera Mail" #~ msgid "Contacts from Opera Mail" #~ msgstr "Contatti dalla rubrica indirizzi di Opera Mail" #~ msgid "PuTTY Sessions" #~ msgstr "Sessioni di PuTTY" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Accesso veloce alle sessioni PuTTY" #~ msgid "Start Session" #~ msgstr "Avvia sessione" #~ msgid "reStructuredText" #~ msgstr "reStructuredText" #~ msgid "Render reStructuredText and show the result" #~ msgstr "Genera reStructuredText e mostra il risultato" #~ msgid "View as HTML Document" #~ msgstr "Mostra come Documento HTML" #~ msgid "System Services" #~ msgstr "Servizi di sistema" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "Avvia, interrompe o riavvia servizi di sistema attraverso script init" #~ msgid "Sudo-like Command" #~ msgstr "Comandi della shell" #~ msgid "Start Service" #~ msgstr "Avvia servizio" #~ msgid "Stop Service" #~ msgstr "Interrompe servizio" #~ msgid "%s Service" #~ msgstr "Servizio %s" #, fuzzy #~ msgid "Show QRCode" #~ msgstr "Mostra codice sorgente" #, fuzzy #~ msgid "Display text as QRCode in a window" #~ msgstr "Mostra testo in finestra" #~ msgid "Access to Skype contacts" #~ msgstr "Accedi ai contatti Skype" #~ msgid "Skype Me" #~ msgstr "Skype Me" #~ msgid "Logged Out" #~ msgstr "Scollegato" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Chiama" #~ msgid "Place a call to contact" #~ msgstr "Chiama il contatto" #~ msgid "Skype Contacts" #~ msgstr "Contatti Skype" #~ msgid "Skype Statuses" #~ msgstr "Stati Skype" #~ msgid "Tracker 0.6" #~ msgstr "Tracker 0.6" #~ msgid "Tracker tags" #~ msgstr "Etichette di Tracker" #~ msgid "Tracker Tags" #~ msgstr "Etichette di Tracker" #~ msgid "Browse Tracker's tags" #~ msgstr "Esplora le etichette di Tracker" #~ msgid "Tag %s" #~ msgstr "Etichetta %s" #~ msgid "Objects tagged %s with Tracker" #~ msgstr "Oggetti etichettati «%s» con Tracker" #~ msgid "Add Tag..." #~ msgstr "Aggiungi etichetta..." #~ msgid "Add tracker tag to file" #~ msgstr "Aggiunge l'etichetta di tracker al file" #~ msgid "Remove Tag..." #~ msgstr "Rimuovi etichetta..." #~ msgid "Remove tracker tag from file" #~ msgstr "Rimuove l'etichetta di tracker dal file" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Volumi TrueCrypt recenti" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "Volume TrueCrypt: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Monta questo volume" #~ msgid "Mount in Truecrypt" #~ msgstr "Monta con Truecrypt" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Prova a montare il file come volume Truecrypt" #~ msgid "Dismount All Volumes" #~ msgstr "Smonta tutti i volumi" #~ msgid "TrueCrypt Volumes" #~ msgstr "Volumi TrueCrypt" #~ msgid "Terminal Server Client" #~ msgstr "Client per terminal server" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Sessione salvata nel client per terminal server" #~ msgid "TSClient sessions" #~ msgstr "Sessioni del client per terminal server" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Sessioni salvate nel client per terminal server" #~ msgid "Vinagre" #~ msgstr "Visualizzatore di desktop remoti" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Voci speciali e azioni" #~ msgid "Start Vinagre Session" #~ msgstr "Avvia sessione Vinagre" #~ msgid "Vinagre Bookmarks" #~ msgstr "Segnalibri di Vinagre" #~ msgid "Recently used documents in Vim" #~ msgstr "Documenti utilizzati recentemente in Vim" #~ msgid "Vim Recent Documents" #~ msgstr "Documenti utilizzati recentemente in VIM" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "Controlla macchine virtuali di VirtualBox. Supporta sia VirtualBox di Sun " #~ "che la versione open source." #~ msgid "Power On" #~ msgstr "Accensione" #~ msgid "Power On Headless" #~ msgstr "Accensione headless" #~ msgid "Send Power Off Signal" #~ msgstr "Invia segnale di spegnimento" #~ msgid "Reboot" #~ msgstr "Riavvia" #~ msgid "Resume" #~ msgstr "Riprendi" #~ msgid "Save State" #~ msgstr "Salva stato" #~ msgid "Power Off" #~ msgstr "Spegni" #~ msgid "VirtualBox Machines" #~ msgstr "VirtualBox" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "" #~ "Accede alle pagine memorizzate in Zim - Un wiki per la scrivania e " #~ "organizzatore di testi" #~ msgid "Page names start with :colon" #~ msgstr "Il nome della pagina comincia con i due punti" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Pagina Zim da Blocco note \"%s\"" #~ msgid "Create Zim Page" #~ msgstr "Crea pagina Zim" #~ msgid "Create page in default notebook" #~ msgstr "Crea pagina nel blocco note predefinito" #~ msgid "Create Zim Page In..." #~ msgstr "Crea pagina Zim in..." #~ msgid "Create Subpage..." #~ msgstr "Crea sottopagina..." #~ msgid "Zim Notebooks" #~ msgstr "Blocchi note Zim" #~ msgid "Zim Pages" #~ msgstr "Pagine Zim" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Pagine memorizzate nei blocchi note Zim" #~ msgid "Directories" #~ msgstr "Cartelle" #~ msgid "Interface" #~ msgstr "Interfaccia" #~ msgid "Hide Kupfer when focus is lost" #~ msgstr "Nascondere Kupfer quando perde il focus" #~ msgid "" #~ "Tick the box next to a source to make sure its objects are exported to " #~ "the top level of the catalog. An unticked source's contents are only " #~ "available by locating its subcatalog and entering it.\n" #~ "\n" #~ "Note: Kupfer is an integrator, not an indexer itself. Kupfer is not " #~ "designed to carry a catalog larger than a couple of thousand objects, and " #~ "may become slow if overly large subcatalogs are included in the top level." #~ msgstr "" #~ "Selezionare la casella accanto ad una fonte per assicurarsi che i suoi " #~ "oggetti vengano esportati al livello superiore del catalogo. I contenuti " #~ "di una fonte non selezionata sono disponibili solo individuando il suo " #~ "sotto catalogo ed entrandovi.\n" #~ "\n" #~ "Nota: Kupfer è un integratore, non un indicizzatore. Kupfer non è " #~ "progettato per gestire un catalogo più grande di alcune migliaia di " #~ "oggetti e potrebbe diventare lento se sotto cataloghi troppo grandi sono " #~ "inclusi nel livello principale." #~ msgid "Text Matches" #~ msgstr "Corrispondenze del testo" #~ msgid "noun" #~ msgstr "nome" #~ msgid "verb" #~ msgstr "verbo" #~ msgid "adjective" #~ msgstr "aggettivo" #~ msgid "Twitter" #~ msgstr "Twitter" #~ msgid "Microblogging with Twitter: send updates and show friends' tweets" #~ msgstr "" #~ "Microblogging con Twitter: invia aggiornamenti e mostra tweets da amici" #~ msgid "Load friends' pictures" #~ msgstr "Carica immagini di amici" #~ msgid "Load friends' public tweets" #~ msgstr "Carica tweets pubblici da amici" #~ msgid "Load timeline" #~ msgstr "Carica timeline" #~ msgid "Post Update to Twitter" #~ msgstr "Pubblica aggiornamento su Twitter" #~ msgid "Twitter Timeline" #~ msgstr "Timeline Twitter" #~ msgid "Twitter Friends" #~ msgstr "Amici Twitter" #~ msgid "Timeline for %s" #~ msgstr "Timeline per %s" #~ msgid "OpenOffice" #~ msgstr "OpenOffice" #~ msgid "Preferred terminal" #~ msgstr "Terminale preferito" #~ msgid "" #~ "The preferred terminal emulator. It's used to launch the SSH sessions." #~ msgstr "" #~ "Emulatore di terminale preferito. Utilizzato per lanciare le sessioni SSH." #~ msgid "" #~ "The flag which makes the terminal execute everything following it inside " #~ "the terminal (e.g. '-x' for gnome-terminal and terminal, '-e' for konsole " #~ "and urxvt)." #~ msgstr "" #~ "Flag che permette di eseguire tutto ciò che ne segue all'interno del " #~ "terminale (es. '-x' per gnome-terminal e terminal, '-e' per konsole e " #~ "urxvt)." #~ msgid "Tracker 0.8" #~ msgstr "Tracker 0.8" #~ msgid "Plugins may not be unloaded at runtime" #~ msgstr "Attivazione dei plugin dopo il riavvio" #~ msgid "Include in top level" #~ msgstr "Includere nel livello principale" #~ msgid "" #~ "If enabled, objects from the plugin's source(s) will be available in the " #~ "top level.\n" #~ "Sources are always available as subcatalogs in the top level." #~ msgstr "" #~ "Se abilitata, gli oggetti dal sorgente dei plugin saranno disponibili nel " #~ "livello principale.\n" #~ "I sorgenti sono sempre disponibili come sotto cataloghi nel livello " #~ "principale." #~ msgid "Keybinding" #~ msgstr "Associazione di tasti" #~ msgid "Applied" #~ msgstr "Applicato" #~ msgid "Gnome Session Management" #~ msgstr "Gestore sessioni di Gnome" #~ msgid "Special items and actions for Gnome environment" #~ msgstr "Voci speciali e azioni per l'ambiente Gnome" kupfer-328/po/ko.po000066400000000000000000001607771500175051100142700ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: kupfer\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: \n" "Last-Translator: Kim Boram \n" "Language-Team: Kim Boram \n" "Language: \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-Poedit-Language: Korean\n" "X-Poedit-Country: KOREA, REPUBLIC OF\n" "X-Poedit-SourceCharset: utf-8\n" msgid "User credentials" msgstr "사용자 인증서" msgid "_User:" msgstr "사용자(_U):" msgid "_Password:" msgstr "암호(_P):" msgid "_Change" msgstr "바꾸기(_C)" msgid "Set Keyboard Shortcut" msgstr "키보드 바로 가기 설정" msgid "Please press desired key combination" msgstr "원하시는 키 조합을 눌러주십시오" msgid "Keybinding could not be bound" msgstr "키 조합을 묶을 수 없습니다" msgid "Kupfer Preferences" msgstr "쿠퍼 기본 설정" msgid "Start automatically on login" msgstr "로그인할 때 자동으로 시작" msgid "Start" msgstr "시작" msgid "Show icon in notification area" msgstr "알림 영역에 아이콘 보이기" msgid "Icon set:" msgstr "" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" #, fuzzy msgid "Terminal emulator:" msgstr "여기에서 터미널 열기" #, fuzzy msgid "Desktop Environment" msgstr "데스크톱 환경 응용 프로그램" msgid "General" msgstr "일반" msgid "Global Keyboard Shortcuts" msgstr "전역 키보드 바로 가기" msgid "Reset" msgstr "초기화" msgid "Browser Keyboard Shortcuts" msgstr "브라우저 키보드 바로 가기" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "단독 키 스트로크 명령 사용 (스페이스, /, 마침표, 구 점 등.)" msgid "Keyboard" msgstr "키보드" msgid "Plugins" msgstr "플러그인" #, fuzzy msgid "Inclusion in Top Level Searches" msgstr "최 상위에 노래 포함" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" #, fuzzy msgid "Indexed Folders" msgstr "새 폴더" msgid "Folders whose files are always available in the catalog." msgstr "" msgid "Catalog" msgstr "카탈로그" msgid "Kupfer" msgstr "쿠퍼" msgid "Application Launcher" msgstr "응용 프로그램 실행 아이콘" msgid "Convenient command and access tool for applications and documents" msgstr "편리하게 응용프로그램이나 문서에 접근하고 명령을 내릴 수 있는 도구" msgid "Execute in Kupfer" msgstr "쿠퍼에서 실행" msgid "Saved Kupfer Command" msgstr "저장된 쿠퍼 명령어" #, python-format msgid "Could not to carry out '%s'" msgstr "'%s'을(를) 실행할 수 없습니다" #, python-format msgid "\"%s\" produced a result" msgstr "\"%s\"이(가) 결과를 만들었습니다" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "\"%s\"을(를) 실행할 권한이 없습니다 (실행 권한 없음)" #, python-format msgid "Command in \"%s\" is not available" msgstr "\"%s\" 안의 명령을 실행할 수 없습니다" #, python-format msgid "Keyboard relay is active for display %s" msgstr "" msgid "do not present main interface on launch" msgstr "실행할 때 주 인터페이스를 보이지 않기" msgid "list available plugins" msgstr "사용 가능한 플러그인 목록 보기" msgid "enable debug info" msgstr "디버그 정보 활성화" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "" msgid "show usage help" msgstr "사용법 도움말 보이기" msgid "show version information" msgstr "버전 정보 보이기" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "사용법: kupfer [ 옵션 | 파일 ... ]" msgid "Available plugins:" msgstr "사용 가능 플러그인:" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "찾으려면 입력하세요" #, python-format msgid "%s is empty" msgstr "%s이(가) 비어있음" #, fuzzy msgid "Text" msgstr "텍스트 보이기" msgid "Run after Delay..." msgstr "대기 후 실행..." msgid "Perform command after a specified time interval" msgstr "특정한 시간 동안 대기한 후 명령어를 실행합니다" msgid "Multiple Objects" msgstr "다수의 개체" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s 개체" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "" #, fuzzy msgid "Aim" msgstr "Vim" #, fuzzy msgid "Google Talk" msgstr "구글 번역" msgid "ICQ" msgstr "" msgid "MSN" msgstr "" msgid "QQ" msgstr "" msgid "Yahoo" msgstr "" msgid "Skype" msgstr "스카이프" #, python-format msgid "%s does not support this operation" msgstr "" msgid "Can not be used with multiple objects" msgstr "" msgid "Open" msgstr "열기" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "%(file)s (%(type)s)을(를) 실행할 기본 응용 프로그램 없음" #, fuzzy, python-format msgid "Please use \"%s\"" msgstr "선택한 파일 \"%s\"" msgid "Set Default Application..." msgstr "기본 응용 프로그램 설정..." msgid "Open with default application" msgstr "기본 응용 프로그램으로 열기" msgid "Reveal" msgstr "나타나기" msgid "Open parent folder" msgstr "상위 폴더를 엽니다" msgid "Open Terminal Here" msgstr "여기에서 터미널 열기" msgid "Open this location in a terminal" msgstr "이 위치를 터미널로 엽니다" msgid "Run in Terminal" msgstr "터미널에서 실행" msgid "Run (Execute)" msgstr "실행" msgid "Run this program in a Terminal" msgstr "이 프로그램을 터미널에서 실행합니다" msgid "Run this program" msgstr "이 프로그램 실행" msgid "Go To" msgstr "이동" msgid "Open URL" msgstr "URL 열기" msgid "Open URL with default viewer" msgstr "기본 프로그램으로 이 주소 열기" msgid "Launch" msgstr "실행" msgid "Show application window" msgstr "응용 프로그램 창 열기" msgid "Launch application" msgstr "응용 프로그램 실행" msgid "Launch Again" msgstr "다시 실행" msgid "Launch another instance of this application" msgstr "또 다른 이 응용 프로그램 인스턴스를 실행합니다" msgid "Close" msgstr "닫기" msgid "Attempt to close all application windows" msgstr "모든 응용 프로그램 창을 닫기를 실행합니다" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "실행" msgid "Perform command" msgstr "명령어 실행" #, fuzzy msgid "(Empty Text)" msgstr "빈 파일" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "(%(num)d 줄) \"%(text)s\"" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s 등." #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "귀납적 소스 %(dir)s, (%(levels)d 레벨)" #, python-format msgid "Directory source %s" msgstr "디렉터리 소스 %s" msgid "Home Folder" msgstr "내 폴더" msgid "Catalog Index" msgstr "카탈로그 인덱스" msgid "An index of all available sources" msgstr "사용 가능한 모든 소스의 인덱스" msgid "Root catalog" msgstr "루트 카탈로그" msgid "Please Configure Plugin" msgstr "플러그인을 설정해 주십시오" #, python-format msgid "Plugin %s is not configured" msgstr "플러그인 %s이(가) 설정되지 않았습니다" #, python-format msgid "Invalid user credentials for %s" msgstr "유효하지 않은 사용자 인증서 %s" msgid "Applications" msgstr "응용 프로그램" msgid "All applications and preferences" msgstr "모든 응용 프로그램과 기본 설정" msgid "Applications for Desktop Environment" msgstr "데스크톱 환경 응용 프로그램" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "다른 프로그램으로 열기..." msgid "Open with any application" msgstr "다른 프로그램으로 열기..." msgid "Set default application to open this file type" msgstr "이 파일 형식을 열 기본 응용 프로그램을 설정합니다" #, fuzzy msgid "Reset Associations" msgstr "URL 동작" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "압축 파일 내부 검색" msgid "Allow browsing inside compressed archive files" msgstr "압축 파일 내부를 찾아볼 수 있게 합니다" #, python-format msgid "Content of %s" msgstr "%s 항목" #, fuzzy msgid "Archive Manager" msgstr "압축 파일" #, fuzzy msgid "Use Archive Manager actions" msgstr "파일 관리자 Thunar 동작" msgid "Compressed archive type for 'Create Archive In'" msgstr "'다음에서 압축 파일 만들기'를 위한 압축 파일 형식" msgid "Extract Here" msgstr "여기에 풀기" msgid "Extract compressed archive" msgstr "압축 파일 여기에 풀기" msgid "Create Archive" msgstr "압축 파일 만들기" msgid "Create a compressed archive from folder" msgstr "폴더에서 압축 파일 만들기" msgid "Create Archive In..." msgstr "다음에서 압축 파일 만들기..." #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "압축 파일" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "Audacious 재생 기능과 재생 목록을 조정합니다" msgid "Include songs in top level" msgstr "최 상위에 노래 포함" msgid "Enqueue" msgstr "대기열에 추가" msgid "Add track to the Audacious play queue" msgstr "Audacious 재생 대기열에 트랙을 추가합니다" msgid "Dequeue" msgstr "재생 대기열에서 제거" msgid "Remove track from the Audacious play queue" msgstr "Audacious 재생 대기열에서 트랙을 제거합니다" msgid "Play" msgstr "재생" msgid "Jump to track in Audacious" msgstr "Audacious 안의 트랙으로 이동" msgid "Resume playback in Audacious" msgstr "Audacious 재생 계속" msgid "Pause" msgstr "일시 정지" msgid "Pause playback in Audacious" msgstr "Audacious 재생 일시 정지" msgid "Next" msgstr "다음" msgid "Jump to next track in Audacious" msgstr "Audacious 다음 트랙으로 이동" msgid "Previous" msgstr "이전" msgid "Jump to previous track in Audacious" msgstr "Audacious 이전 트랙으로 이동" msgid "Clear Queue" msgstr "대기열 지우기" msgid "Clear the Audacious play queue" msgstr "Audacious 재생 대기열 지우기" msgid "Shuffle" msgstr "임의 연주" msgid "Toggle shuffle in Audacious" msgstr "Audacious 임의 연주 켜고 끄기" msgid "Repeat" msgstr "반복 연주" msgid "Toggle repeat in Audacious" msgstr "Audacious 반복 연주 켜고 끄기" msgid "Show Playing" msgstr "재생 중인 노래 보이기" msgid "Tell which song is currently playing" msgstr "어떤 노래를 지금 재생하고 있는지 알려줍니다" msgid "Playlist" msgstr "재생 목록" msgid "Calculator" msgstr "계산기" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "계산" msgid "Clipboards" msgstr "클립보드" msgid "Recent clipboards and clipboard proxy objects" msgstr "" #, fuzzy msgid "Number of recent clipboards to remember" msgstr "최근 클립보드의 수" msgid "Include selected text in clipboard history" msgstr "" #, fuzzy msgid "Copy selected text to primary clipboard" msgstr "선택한 것을 주 클립보드로 복사" msgid "Selected Text" msgstr "선택한 텍스트" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "%(num)d 줄 \"%(desc)s\" 클립보드" #, fuzzy msgid "Clipboard Text" msgstr "클립보드" #, fuzzy msgid "Clipboard File" msgstr "클립보드" #, fuzzy msgid "Clipboard Files" msgstr "클립보드" msgid "Clear" msgstr "지우기" msgid "Remove all recent clipboards" msgstr "모든 최근 클립보드 제거" msgid "Shell Commands" msgstr "쉘 명령어" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" msgid "Run (Get Output)" msgstr "실행 (출력 받기)" msgid "Run program and return its output" msgstr "프로그램을 실행하고 출력 결과를 되돌려 받습니다" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command #, fuzzy msgid "Pass to Command..." msgstr "마지막 명령어" msgid "Run program with object as an additional parameter" msgstr "" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin #, fuzzy msgid "Write to Command..." msgstr "다음에 쓰기..." #, fuzzy msgid "Run program and supply text on the standard input" msgstr "프로그램을 실행하고 출력 결과를 되돌려 받습니다" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "" #, fuzzy msgid "Run command-line programs" msgstr "명령줄 프로그램 실행" msgid "GTK+" msgstr "" #, fuzzy msgid "GNOME Terminal" msgstr "그놈 터미널 프로필" #, fuzzy msgid "XFCE Terminal" msgstr "터미널에서 실행" #, fuzzy msgid "LXTerminal" msgstr "터미널에서 실행" #, fuzzy msgid "X Terminal" msgstr "터미널에서 실행" msgid "Urxvt" msgstr "" msgid "Konsole" msgstr "" msgid "Save As..." msgstr "다른 이름으로 저장..." #, fuzzy msgid "Restart Kupfer" msgstr "서비스 다시 시작" msgid "Quit" msgstr "끝내기" msgid "Quit Kupfer" msgstr "쿠퍼 끝내기" msgid "About Kupfer" msgstr "쿠퍼 정보" msgid "Show information about Kupfer authors and license" msgstr "쿠퍼 제작자와 라이선스에 대한 정보를 보여줍니다" msgid "Kupfer Help" msgstr "쿠퍼 도움말" msgid "Get help with Kupfer" msgstr "쿠퍼에 대한 도움을 받습니다" msgid "Show preferences window for Kupfer" msgstr "쿠퍼 기본 설정 창 보이기" msgid "Search Contents" msgstr "내용 검색" msgid "Search inside this catalog" msgstr "이 카탈로그 안을 찾아봅니다" msgid "Copy" msgstr "복사" msgid "Copy to clipboard" msgstr "클립보드로 복사" msgid "Rescan" msgstr "다시 읽기" msgid "Force reindex of this source" msgstr "이 소스를 다시 인덱스 하게 합니다" msgid "Last Command" msgstr "마지막 명령어" msgid "Internal Kupfer Objects" msgstr "내부 쿠퍼 개체" msgid "Last Result" msgstr "마지막 결과" msgid "Command Results" msgstr "명령어 결과" #, fuzzy msgid "Custom Terminal" msgstr "터미널에서 실행" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "명령어" msgid "Execute flag" msgstr "실행 플래그" msgid "Default Email Client" msgstr "기본 전자 메일 클라이언트" msgid "Compose email using the system's default mailto: handler" msgstr "시스템 기본값으로 설정된 전자 메일 클라이언트로 전자 메일을 작성합니다" #, fuzzy msgid "Compose Email To" msgstr "전자 메일 작성" msgid "Dictionary" msgstr "사전" msgid "Look up word in dictionary" msgstr "사전에서 단어를 찾아봅니다" msgid "Look Up" msgstr "찾기" msgid "Documents" msgstr "문서" msgid "Recently used documents and bookmarked folders" msgstr "최근 사용한 문서와 책갈피 폴더" msgid "Max recent document days" msgstr "최근 문서에 표시할 최대 일 수" msgid "Recent Items" msgstr "최근 항목" msgid "Recently used documents" msgstr "최근 사용한 문서" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "문서 %s" #, python-format msgid "Recently used documents for %s" msgstr "최근 사용한 문서 %s" msgid "Places" msgstr "위치" msgid "Bookmarked folders" msgstr "책갈피에 추가된 폴더" #, fuzzy msgid "DuckDuckGo Search" msgstr "구글 검색" msgid "Search the web securely with DuckDuckGo" msgstr "" msgid "Favorites" msgstr "즐겨찾기" msgid "Mark commonly used items and store objects for later use" msgstr "다음에 사용하기 위해 자주 사용하는 항목과 보관된 개체 표시" msgid "Shelf of \"Favorite\" items" msgstr "\"Favorite\" 항목 칸" msgid "Add to Favorites" msgstr "즐겨찾기에 추가" msgid "Add item to favorites shelf" msgstr "즐겨찾기 칸에 항목 추가" msgid "Remove from Favorites" msgstr "즐겨찾기에서 제거" msgid "Remove item from favorites shelf" msgstr "항목을 즐겨찾기 칸에서 제거합니다" msgid "File Actions" msgstr "파일 동작" msgid "More file actions" msgstr "더 많은 파일 동작" msgid "Move To..." msgstr "다음으로 이동..." msgid "Move file to new location" msgstr "파일을 새 위치로 옮깁니다" msgid "Rename To..." msgstr "다음으로 이름 바꾸기..." msgid "Copy To..." msgstr "다음으로 복사..." msgid "Copy file to a chosen location" msgstr "선택한 위치로 파일을 복사합니다" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "고차 동작" msgid "Tools to work with commands as objects" msgstr "명령을 개체로서 작업하기 위한 도구" msgid "Select in Kupfer" msgstr "쿠퍼에서 선택" #, python-format msgid "Result of %s (%s)" msgstr "%s (%s) 결과" msgid "Run (Take Result)" msgstr "실행 (결과 받기)" msgid "Take the command result as a proxy object" msgstr "프록시 개체로 명령 결과를 받습니다" msgid "Run (Discard Result)" msgstr "실행 (결과 버리기)" msgid "Image Tools" msgstr "그림 도구" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "그림 변형 도구" msgid "Scale..." msgstr "크기 조정..." msgid "Scale image to fit inside given pixel measure(s)" msgstr "주어진 픽셀 치수에 맞게 그림의 크기를 조정합니다 " msgid "Rotate Clockwise" msgstr "시계 방향으로 회전" msgid "Rotate Counter-Clockwise" msgstr "시계 반대 방향으로 회전" msgid "Autorotate" msgstr "자동 회전" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "사진의 EXIF 메타 정보에 따라 사진을 회전합니다" msgid "Kupfer Plugins" msgstr "쿠퍼 플러그인" msgid "Access Kupfer's plugin list in Kupfer" msgstr "쿠퍼 플러그인 목록에 접근합니다" msgid "Show Information" msgstr "정보 보이기" msgid "Show Source Code" msgstr "소스 코드 보이기" msgid "enabled" msgstr "활성화" msgid "disabled" msgstr "비 활성화 됨" msgid "Notes" msgstr "쪽지" msgid "Gnote or Tomboy notes" msgstr "G노트 또는 톰보이 쪽지" msgid "Work with application" msgstr "응용 프로그램으로 작업" msgid "Open with notes application" msgstr "쪽지 응용 프로그램으로 열기" msgid "Append to Note..." msgstr "쪽지에 추가..." msgid "Add text to existing note" msgstr "존재하는 쪽지에 텍스트를 추가합니다" msgid "Create Note" msgstr "쪽지 만들기" msgid "Create a new note from this text" msgstr "이 텍스트로 새 쪽지를 만듭니다" msgid "Get Note Search Results..." msgstr "쪽지 검색 결과 가져오기..." msgid "Show search results for this query" msgstr "이 쿼리 검색 결과 보이기" #, python-format msgid "today, %s" msgstr "오늘, %s" #, python-format msgid "yesterday, %s" msgstr "어제, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "마지막 업데이트 %s" msgid "Quicksilver Icons" msgstr "" msgid "Quick Image Viewer" msgstr "" msgid "View Image" msgstr "" msgid "GNU Screen" msgstr "GNU 스크린" msgid "Active GNU Screen sessions" msgstr "GNU 스크린 세션 활성화" msgid "Attached" msgstr "결합됨" msgid "Detached" msgstr "분리됨" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "%(status)s 세션 (%(pid)s) 만들어짐 %(time)s" msgid "Screen Sessions" msgstr "스크린 세션" msgid "Attach" msgstr "결합" msgid "Send Keys" msgstr "" msgid "Send synthetic keyboard events using xautomation" msgstr "" msgid "Paste to Foreground Window" msgstr "" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "" msgid "Send keys to foreground window" msgstr "" msgid "Type Text" msgstr "" msgid "Type the text to foreground window" msgstr "" msgid "GNOME Session Management" msgstr "그놈 세션 관리" msgid "Special items and actions for GNOME environment" msgstr "그놈 환경의 특별한 동작이나 항목" msgid "Log Out..." msgstr "로그아웃..." msgid "Log out or change user" msgstr "로그아웃 또는 사용자 바꾸기" msgid "Shut Down..." msgstr "시스템 종료..." msgid "Shut down, restart or suspend computer" msgstr "시스템을 종료하거나 다시 시작 또는 최대 절전 모드로 만듭니다" msgid "Lock Screen" msgstr "화면 잠그기" msgid "Enable screensaver and lock" msgstr "화면 보호기를 활성화 한 후 잠급니다" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "XFCE 세션 관리" msgid "Special items and actions for XFCE environment" msgstr "XFCE 환경의 특별한 동작이나 항목" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "SSH 호스트" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "~/.ssh/config에서 발견된 SSH 호스트를 추가합니다." msgid "SSH host" msgstr "SSH 호스트" msgid "Connect" msgstr "연결" msgid "Connect to SSH host" msgstr "SSH 호스트에 연결" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "~/.ssh/config에 지정된 SSH 호스트" msgid "No D-Bus connection to desktop session" msgstr "데스크톱 세션에 D-Bus 연결 없음" #, fuzzy msgid "GNOME Keyring" msgstr "그놈 터미널 프로필" msgid "KWallet" msgstr "" #, fuzzy msgid "Unencrypted File" msgstr "선택한 파일" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "\"%s\" 안의 명령을 실행할 수 없습니다" msgid "Document Templates" msgstr "문서 서식" msgid "Create new documents from your templates" msgstr "서식을 이용해 새 문서를 만듭니다" #, python-format msgid "%s template" msgstr "%s 서식" msgid "Empty File" msgstr "빈 파일" msgid "New Folder" msgstr "새 폴더" msgid "Create New Document..." msgstr "새 문서 만들기..." msgid "Create a new document from template" msgstr "서식을 이용해 새 문서 만들기" msgid "Create Document In..." msgstr "다음에 문서 만들기..." msgid "Textfiles" msgstr "텍스트 파일" msgid "Append To..." msgstr "다음에 첨가..." msgid "Append..." msgstr "첨가..." msgid "Write To..." msgstr "다음에 쓰기..." msgid "Get Text Contents" msgstr "텍스트 항목 가져오기" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "파일 관리자 Thunar 동작" msgid "Select in File Manager" msgstr "파일 관리자로 선택" msgid "Show Properties" msgstr "속성 보이기" msgid "Show information about file in file manager" msgstr "파일 관리자로 파일 정보를 봅니다" msgid "Send To..." msgstr "보내기..." msgid "Symlink In..." msgstr "" #, fuzzy msgid "Create a symlink to file in a chosen location" msgstr "선택한 위치로 파일을 복사합니다" msgid "Empty Trash" msgstr "휴지통 비우기" msgid "Thunar Send To Objects" msgstr "Thunar 개체로 보내기" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "썬더버드" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "썬더버드/아이스도브 연락처와 동작" msgid "Compose New Email" msgstr "새 메일 작성" msgid "Compose a new message in Thunderbird" msgstr "썬더버드로 새 메시지 작성" #, fuzzy msgid "Attach in Email To..." msgstr "전자 메일 보내기...." #, fuzzy msgid "Compose Email With" msgstr "전자 메일 작성" #, fuzzy msgid "Compose a new message using the text as body" msgstr "썬더버드로 새 메시지 작성" msgid "Thunderbird Address Book" msgstr "썬더버드 주소록" msgid "Contacts from Thunderbird Address Book" msgstr "썬더버드 주소록 상의 연락처" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Top" msgid "Show running tasks and allow sending signals to them" msgstr "실행 중인 작업을 보고 신호를 보낼 수 있게 합니다" msgid "Sort Order" msgstr "정렬 순서" msgid "Commandline" msgstr "명령줄" msgid "CPU usage (descending)" msgstr "CPU 사용 (내림차순)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "메모리 사용 (내림차순)" msgid "Send Signal..." msgstr "신호 보내기..." msgid "Signals" msgstr "신호" msgid "Running Tasks" msgstr "실행 중인 작업" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgid "Running tasks for current user" msgstr "현재 사용자가 실행 중인 작업" msgid "Trash" msgstr "휴지통" msgid "Access trash contents" msgstr "휴지통 항목에 접근합니다" msgid "Move to Trash" msgstr "휴지통에 버리기" msgid "Move this file to trash" msgstr "이 파일을 휴지통에 버리기" msgid "Restore" msgstr "되살리기" msgid "Move file back to original location" msgstr "파일을 원래 위치로 되돌립니다" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "휴지통이 비어있습니다" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "휴지통에 %(num)s 개의 파일이 있습니다" msgid "Triggers" msgstr "트리거" #, fuzzy msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "'명령 구성(컨트롤+리턴)'으로 만들어진 개체에 전역 키 조합(트리거)을 배정합니" "다." msgid "Add Trigger..." msgstr "트리거 추가..." msgid "Remove Trigger" msgstr "트리거 제거" msgid "URL Actions" msgstr "URL 동작" msgid "Download and Open" msgstr "다운로드한 후 열기" msgid "Download To..." msgstr "다음에 다운로드..." msgid "Download URL to a chosen location" msgstr "선택한 위치에 URL을 다운로드합니다" msgid "Wikipedia" msgstr "위키백과" msgid "Search in Wikipedia" msgstr "위키백과 검색" msgid "Wikipedia language" msgstr "위키백과 언어" #. TRANS: Default wikipedia language code msgid "en" msgstr "영어" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "이 용어를 %s.wikipedia.org에서 검색합니다" msgid "Window List" msgstr "창 목록" msgid "All windows on all workspaces" msgstr "모든 작업 공간의 모든 창" msgid "Activate" msgstr "활성화" msgid "Shade" msgstr "말아올리기" msgid "Unshade" msgstr "말아올리기 해제" msgid "Minimize" msgstr "최소화" msgid "Unminimize" msgstr "최소화 취소" msgid "Maximize" msgstr "최대화" msgid "Unmaximize" msgstr "최대화 취소" msgid "Maximize Vertically" msgstr "세로로 최대화" msgid "Unmaximize Vertically" msgstr "세로 최대화 취소" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "%(wkspc)s 위의 창" msgid "Frontmost Window" msgstr "가장 앞의 창" msgid "Next Window" msgstr "다음 창" msgid "Jump to this window's workspace and focus" msgstr "이 창이 있는 작업 공간으로 이동한 후 포커스 맞추기" #, fuzzy, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "다음 창" #, fuzzy msgid "Active workspace" msgstr "이 작업 공간으로 이동" msgid "Jump to this workspace" msgstr "이 작업 공간으로 이동" msgid "Workspaces" msgstr "작업 공간" msgid "Volumes and Disks" msgstr "볼륨과 디스크" msgid "Mounted volumes and disks" msgstr "마운트 된 볼륨과 디스크" #, python-format msgid "Volume mounted at %s" msgstr "%s에 마운트 된 볼륨" msgid "Unmount" msgstr "마운트 해제" msgid "Unmount this volume" msgstr "이 볼륨 마운트 해제" msgid "Eject" msgstr "꺼내기" msgid "Unmount and eject this media" msgstr "마운트를 해제한 후 이 미디어를 꺼냅니다" msgid "Show Text" msgstr "텍스트 보이기" msgid "Display text in a window" msgstr "창에 텍스트 표시" msgid "Large Type" msgstr "큰 형식" msgid "Show Notification" msgstr "알림 보이기" #, fuzzy msgid "Tracker" msgstr "트래커 0.6" msgid "Tracker desktop search integration" msgstr "트래커 데스크톱 검색 통합" msgid "Search in Tracker" msgstr "트래커로 검색" msgid "Open Tracker Search Tool and search for this term" msgstr "트래커 검색 도구를 연 후 이 용어를 검색합니다" msgid "Get Tracker Results..." msgstr "트래커 결과 가져오기..." msgid "Show Tracker results for query" msgstr "쿼리의 트래커 결과 보이기" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "\"%s\" 결과" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "파일 위치 찾기" msgid "Search filesystem using locate" msgstr "locate를 이용해 파일 시스템을 검색합니다" msgid "Ignore case distinctions when searching files" msgstr "파일을 찾을 때 대소문자를 무시합니다" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "파이어폭스 책갈피" msgid "Index of Firefox bookmarks" msgstr "파이어폭스 책갈피 인덱스" #, fuzzy msgid "Firefox Keywords" msgstr "파이어폭스 책갈피" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "OpenSearch 검색 엔진으로 웹을 검색합니다" msgid "Search With..." msgstr "다음으로 검색..." msgid "Search For..." msgstr "다음 항목 검색..." #, fuzzy msgid "Search Terms" msgstr "검색 엔진" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "선택한 파일 \"%s\"" #, fuzzy msgid "Resume playback" msgstr "Audacious 재생 계속" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "다음" #, fuzzy msgid "Skip to next track" msgstr "Audacious 다음 트랙으로 이동" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "이전" #, fuzzy msgid "Skip to previous track" msgstr "Audacious 이전 트랙으로 이동" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "피진" msgid "Access to Pidgin Contacts" msgstr "피진 연락처에 접근" msgid "Show offline contacts" msgstr "오프라인 연락처 보이기" msgid "Open Chat" msgstr "대화 열기" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d 개의 문자)" msgid "Send Message..." msgstr "메시지 보내기..." msgid "Available" msgstr "사용 가능" msgid "Away" msgstr "자리 비움" msgid "Pidgin Contacts" msgstr "피진 연락처" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "줄여진 링크" msgid "Create short aliases of long URLs" msgstr "긴 주소 대신 사용할 짧은 주소를 만듦" msgid "Error" msgstr "오류" msgid "Shorten With..." msgstr "다음으로 줄임..." msgid "Services" msgstr "서비스" msgid "Rhythmbox" msgstr "리듬박스" msgid "Play and enqueue tracks and browse the music library" msgstr "트랙을 연주하거나 재생 대기열에 추가하고 음악 라이브러리를 검색합니다" msgid "Include artists in top level" msgstr "최 상위에 음악가 포함" msgid "Include albums in top level" msgstr "최 상위에 앨범 포함" msgid "Play tracks in Rhythmbox" msgstr "리듬박스로 트랙을 연주합니다" msgid "Add tracks to the play queue" msgstr "재생 대기열에 트랙을 추가합니다" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "음악가 %(artist)s 앨범 %(album)s" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "음악가 %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "트랙 음악가 %s" msgid "Albums" msgstr "앨범" msgid "Music albums in Rhythmbox Library" msgstr "리듬박스 라이브러리 안의 음악 앨범" msgid "Artists" msgstr "음악가" msgid "Music artists in Rhythmbox Library" msgstr "리듬박스 라이브러리 안의 음악가" msgid "Songs" msgstr "노래" msgid "Songs in Rhythmbox library" msgstr "리듬박스 라이브러리 안의 노래" msgid "Getting Things GNOME" msgstr "Getting Things GNOME" msgid "Browse and create new tasks in GTG" msgstr "GTG를 찾아보고 새 작업을 만듭니다" #, python-format msgid "due: %s" msgstr "기한: %s" #, python-format msgid "start: %s" msgstr "시작: %s" #, python-format msgid "tags: %s" msgstr "태그: %s" msgid "Open task in Getting Things GNOME!" msgstr "Getting Things GNOME!에 작업을 엽니다" msgid "Delete" msgstr "삭제" msgid "Permanently remove this task" msgstr "이 작업을 영구적으로 제거" msgid "Mark Done" msgstr "완료된 것으로 표시" msgid "Mark this task as done" msgstr "이 작업을 완료한 것으로 표시" msgid "Dismiss" msgstr "해제" msgid "Mark this task as not to be done anymore" msgstr "이 작업을 더 이상 완료할 수 없는 것으로 표시" msgid "Create Task" msgstr "작업 만들기" msgid "Create new task in Getting Things GNOME" msgstr "Getting Things GNOME에 새 작업 만들기" msgid "Devhelp" msgstr "개발자 도움말" msgid "Search in Devhelp" msgstr "개발자 도움말 검색" #, fuzzy msgid "Empathy" msgstr "Gajim 연락처" #, fuzzy msgid "Access to Empathy Contacts" msgstr "Gajim 연락처에 접근" msgid "Busy" msgstr "다른 용무 중" msgid "Not Available" msgstr "사용 불가" msgid "Invisible" msgstr "보이지 않음" msgid "Offline" msgstr "연결안됨" msgid "Change Global Status To..." msgstr "전역 상태를 다음으로 바꾸기..." #, fuzzy msgid "Empathy Contacts" msgstr "Gajim 연락처" #, fuzzy msgid "Empathy Account Status" msgstr "Gajim 계정 상태" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "대안 활성화" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "구점 트릭" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "명령어 구성" #, fuzzy msgid "Mark Default Action" msgstr "기본 응용 프로그램 설정..." msgid "Forget Object" msgstr "" msgid "Reset All" msgstr "모두 초기화" msgid "Select Quit" msgstr "선택 끝내기" msgid "Select Selected File" msgstr "선택한 파일 선택" msgid "Select Selected Text" msgstr "선택한 텍스트 선택" msgid "Show Help" msgstr "도움말 보이기" msgid "Show Preferences" msgstr "기본 설정 보이기" msgid "Switch to First Pane" msgstr "첫 패널로 전환" msgid "Toggle Text Mode" msgstr "토글 텍스트 모드" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "%(src)s에서 \"%(query)s\"와 일치하는 항목 없음" msgid "No matches" msgstr "일치하는 항목 없음" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "일치하는 항목 없음" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "주 인터페이스 보이기" msgid "Show with Selection" msgstr "선택 보이기" #. TRANS: Plugin info fields msgid "Description" msgstr "설명" msgid "Author" msgstr "저자" msgid "Version" msgstr "버전" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "파이선 모듈 '%s'이(가) 필요합니다" msgid "Plugin could not be read due to an error:" msgstr "오류로 인해 플러그인을 읽을 수 없습니다:" msgid "Content of" msgstr "내용" #. TRANS: Plugin contents header msgid "Sources" msgstr "소스" #. TRANS: Plugin contents header msgid "Actions" msgstr "동작" #, python-format msgid "Using encrypted password storage: %s" msgstr "" #, python-format msgid "Using password storage: %s" msgstr "" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "설정" msgid "Set username and password" msgstr "사용자 이름과 암호 설정" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "디렉터리 선택" msgid "Reset all shortcuts to default values?" msgstr "모든 바로 가기를 기본 값으로 초기화하시겠습니까?" msgid "Shortcut" msgstr "바로 가기" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "김보람 " msgid "A free software (GPLv3+) launcher" msgstr "자유 소프트웨어 (GPLv3+) 실행 아이콘" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "실행 중인 쿠퍼를 찾을 수 없습니다" #~ msgid "Compose Email" #~ msgstr "전자 메일 작성" #~ msgid "Send in Email To..." #~ msgstr "전자 메일 보내기...." #~ msgid "Type to search %s" #~ msgstr "%s을(를) 검색하려면 입력하세요" #~ msgid "No action" #~ msgstr "동작 없음" #~ msgid "GNOME Terminal Profiles" #~ msgstr "그놈 터미널 프로필" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "그놈 터미널 프로필 실행" #~ msgid "Selected Text \"%s\"" #~ msgstr "선택한 텍스트 \"%s\"" #~ msgid "Calculate expressions starting with '='" #~ msgstr "계산기 표현은 '=' 기호로 시작합니다" #~ msgid "Recent clipboards" #~ msgstr "최근 클립보드" #~ msgid "Include recent selections" #~ msgstr "최근 선택 포함" #~ msgid "Epiphany Bookmarks" #~ msgstr "에피파니 책갈피" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "에피파니 책갈피 인덱스" #~ msgid "Include visited sites" #~ msgstr "방문한 사이트 포함" #~ msgid "" #~ "Provides current nautilus selection, using Kupfer's Nautilus Extension" #~ msgstr "쿠퍼 노틸러스 확장 기능을 이용해 현재 노틸러스 선택을 제공합니다" #~ msgid "Selected File \"%s\"" #~ msgstr "선택한 파일 \"%s\"" #~ msgid "Selected Files" #~ msgstr "선택한 파일" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "리듬박스 재생을 계속합니다" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "리듬박스 재생을 잠시 정지합니다" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "리듬박스를 다음 트랙으로 넘깁니다" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "리듬박스를 이전 트랙으로 넘깁니다" #~ msgid "Search the Web" #~ msgstr "웹 검색" #~ msgid "Abiword" #~ msgstr "AbiWord" #~ msgid "Recently used documents in Abiword" #~ msgstr "Abiword가 최근 사용한 문서" #~ msgid "Abiword Recent Items" #~ msgstr "Abiword 최근 항목" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "패키지 관리자 APT 인터페이스" #~ msgid "Installation method" #~ msgstr "설치 방법" #~ msgid "Show Package Information" #~ msgstr "패키지 정보 보이기" #~ msgid "Install" #~ msgstr "설치" #~ msgid "Install package using the configured method" #~ msgstr "설정된 방법으로 패키지 설치" #~ msgid "Packages matching \"%s\"" #~ msgstr "\"%s\"와(과) 패키지 일치" #~ msgid "Search Package Name..." #~ msgstr "패키지 이름 검색..." #~ msgid "Chromium Bookmarks" #~ msgstr "크로미움 책갈피" #~ msgid "Index of Chromium bookmarks" #~ msgstr "크로미움 책갈피 인덱스" #~ msgid "Claws Mail" #~ msgstr "클러 메일" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "클러 메일 연락처와 동작" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "클러 메일로 새 메시지를 작성합니다" #~ msgid "Receive All Email" #~ msgstr "모든 전자 메일 받기" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "클러 메일에 설정된 모든 계정에서 새 메시지를 받습니다" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "클러 메일로 새 메시지를 적성하고 파일을 첨부합니다" #~ msgid "Claws Mail Address Book" #~ msgstr "클러 메일 주소록" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "클러 메일 주소록 안의 연락처" #~ msgid "Evolution" #~ msgstr "에볼루션" #~ msgid "Evolution contacts" #~ msgstr "에볼루션 연락처" #~ msgid "Compose a new message in Evolution" #~ msgstr "에볼루션으로 새 메시지 작성" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "에볼루션으로 새 메시지를 적성하고 파일을 첨부합니다" #~ msgid "Evolution Address Book" #~ msgstr "에볼루션 주소록" #~ msgid "Filezilla" #~ msgstr "파일질라" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "파일질라로 사이트를 보고 FTP 주소를 다룹니다" #~ msgid "Open Site with Filezilla" #~ msgstr "파일질라로 사이트 열기" #~ msgid "Filezilla Sites" #~ msgstr "파일질라 사이트" #~ msgid "Sites from Filezilla" #~ msgstr "파일질라 사이트" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Gajim 연락처에 접근" #~ msgid "Free for Chat" #~ msgstr "대화 가능" #~ msgid "Gajim Contacts" #~ msgstr "Gajim 연락처" #~ msgid "Gajim Account Status" #~ msgstr "Gajim 계정 상태" #~ msgid "Gmail" #~ msgstr "지메일" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "지메일로 연락처를 불러오고 새 전자 메일을 작성합니다" #~ msgid "Load contacts' pictures" #~ msgstr "연락처 그림 불러오기" #~ msgid "Compose Email in GMail" #~ msgstr "지메일로 전자 메일 작성" #~ msgid "Open web browser and compose new email in GMail" #~ msgstr "웹 브라우저를 연 후 지메일로 새 메시지를 작성합니다" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "구글 서비스(지메일)안의 연락처" #~ msgid "Google Picasa" #~ msgstr "구글 피카사" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "피카사로 앨범을 보고 파일을 업로드합니다" #~ msgid "Users to show: (,-separated)" #~ msgstr "볼 사용자: (,-separated)" #~ msgid "Load user and album icons" #~ msgstr "사용자와 앨범 아이콘을 불러옵니다" #~ msgid "Uploading Pictures" #~ msgstr "그림 업로드 중" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "피카사 웹 엘범으로 사진을 업로드하는 중" #~ msgid "Creating album:" #~ msgstr "앨범 만들기:" #~ msgid "Album created by Kupfer" #~ msgstr "쿠퍼로 만든 앨범" #~ msgid "File:" #~ msgstr "파일:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "%(num)d 개의 앨범" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "%(num)s 개의 사진" #~ msgid "Upload to Picasa Album..." #~ msgstr "피카사 앨범에 업로드..." #~ msgid "Upload files to Picasa album" #~ msgstr "파일을 피카사 앨범에 업로드" #~ msgid "Upload to Picasa as New Album" #~ msgstr "피카사에 새 앨범으로 업로드" #~ msgid "Create album from selected local directory" #~ msgstr "선택한 로컬 디렉터리로 새 앨범 만들기" #~ msgid "Picasa Albums" #~ msgstr "피카사 앨범" #~ msgid "User albums in Picasa" #~ msgstr "피카사 사용자 앨범" #~ msgid "Search Google with results shown directly" #~ msgstr "결과가 직접 표시되는 구글로 검색합니다" #~ msgid "Show More Results For \"%s\"" #~ msgstr "\"%s\" 검색 결과 더 보이기" #~ msgid "%s total found" #~ msgstr "%s 전체 검색" #~ msgid "Translate text with Google Translate" #~ msgstr "텍스트를 구글 번역으로 번역합니다" #~ msgid "Google Translate connection timed out" #~ msgstr "구글 번역 접속 시간 초과" #~ msgid "Error connecting to Google Translate" #~ msgstr "구글 번역에 연결하는 중 오류가 발생했습니다" #~ msgid "Translate To..." #~ msgstr "다음으로 번역..." #~ msgid "Translate into %s" #~ msgstr "%s(으)로 번역" #~ msgid "Languages" #~ msgstr "언어" #~ msgid "Show translated page in browser" #~ msgstr "번역된 페이지 브라우저로 보이기" #~ msgid "Show Translation To..." #~ msgstr "다음으로 번역 보이기..." #~ msgid "Show translation in browser" #~ msgstr "브라우저로 변역 보이기" #, fuzzy #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s %(when)s" #, fuzzy #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s" #, fuzzy #~ msgid "Send Message" #~ msgstr "메시지 보내기..." #, fuzzy #~ msgid "Send Message To..." #~ msgstr "메시지 보내기..." #~ msgid "Reply..." #~ msgstr "회신..." #, fuzzy #~ msgid "Delete Message" #~ msgstr "메시지 보내기..." #, fuzzy #~ msgid "Send Private Message..." #~ msgstr "직통 메시지 보내기..." #, fuzzy #~ msgid "Send direct message to user" #~ msgstr "다음 사람에게 직통 메시지 보내기..." #, fuzzy #~ msgid "Retweet" #~ msgstr "초기화" #, fuzzy #~ msgid "Retweet To..." #~ msgstr "다음으로 이름 바꾸기..." #, fuzzy #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "클러 메일에 설정된 모든 계정에서 새 메시지를 받습니다" #, fuzzy #~ msgid "Open in Browser" #~ msgstr "상위 폴더를 엽니다" #, fuzzy #~ msgid "Open message in default web browser" #~ msgstr "기본 프로그램으로 이 주소 열기" #, fuzzy #~ msgid "Gwibber Accounts" #~ msgstr "Gajim 계정 상태" #, fuzzy #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "오픈오피스가 사용한 최근 문서" #, fuzzy #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "오픈 오피스 최근 항목" #~ msgid "Opera Bookmarks" #~ msgstr "오페라 책갈피" #~ msgid "Index of Opera bookmarks" #~ msgstr "오페라 책갈피 인덱스" #~ msgid "Opera Mail" #~ msgstr "오페라 메일" #~ msgid "Opera Mail contacts and actions" #~ msgstr "오페라 메일 연락처와 동작" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "오페라 메일로 새 메시지를 작성합니다" #~ msgid "Opera Mail Contacts" #~ msgstr "오페라 메일 연락처" #~ msgid "Contacts from Opera Mail" #~ msgstr "오페라 메일 연락처" #~ msgid "PuTTY Sessions" #~ msgstr "PuTTY 세션" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "PuTTY 세션으로 빠르게 접속" #~ msgid "Start Session" #~ msgstr "세션 시작" #~ msgid "reStructuredText" #~ msgstr "reStructuredText" #~ msgid "Render reStructuredText and show the result" #~ msgstr "reStructuredText 그리고 결과 보이기" #~ msgid "View as HTML Document" #~ msgstr "HTML 문서로 보기" #~ msgid "System Services" #~ msgstr "시스템 서비스" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "init 스크립트로 시스템 서비스를 시작, 정지 또는 다시 시작합니다" #~ msgid "Sudo-like Command" #~ msgstr "Sudo와 같은 명령" #~ msgid "Start Service" #~ msgstr "서비스 시작" #~ msgid "Stop Service" #~ msgstr "서비스 정지" #~ msgid "%s Service" #~ msgstr "%s 서비스" #, fuzzy #~ msgid "Show QRCode" #~ msgstr "소스 코드 보이기" #, fuzzy #~ msgid "Display text as QRCode in a window" #~ msgstr "창에 텍스트 표시" #~ msgid "Access to Skype contacts" #~ msgstr "스카이프 연락처에 접근" #~ msgid "Skype Me" #~ msgstr "Skype Me" #~ msgid "Logged Out" #~ msgstr "로그아웃 됨" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "연락" #~ msgid "Place a call to contact" #~ msgstr "연락처에 전화 걸기" #~ msgid "Skype Contacts" #~ msgstr "스카이프 연락처" #~ msgid "Skype Statuses" #~ msgstr "스카이프 상태" #~ msgid "Tracker 0.6" #~ msgstr "트래커 0.6" #~ msgid "Tracker tags" #~ msgstr "트래커 태그" #~ msgid "Tracker Tags" #~ msgstr "트래커 태그" #~ msgid "Browse Tracker's tags" #~ msgstr "트래커 태그 찾아보기" #~ msgid "Tag %s" #~ msgstr "태그 %s" #~ msgid "Objects tagged %s with Tracker" #~ msgstr "트래커로 개체에 %s 태그를 붙였습니다" #~ msgid "Add Tag..." #~ msgstr "태그 추가..." #~ msgid "Add tracker tag to file" #~ msgstr "파일에 트래커 태그 추가" #~ msgid "Remove Tag..." #~ msgstr "태그 제거..." #~ msgid "Remove tracker tag from file" #~ msgstr "파일에서 트래커 태그를 제거합니다" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "TrueCrypt 기록 볼륨" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "TrueCrypt 볼륨: %(file)s" #~ msgid "Mount Volume" #~ msgstr "볼륨 마운트" #~ msgid "Mount in Truecrypt" #~ msgstr "Truecrypt에 마운트" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "파일을 Truecrypt 볼륨으로 마운트 시도" #~ msgid "Dismount All Volumes" #~ msgstr "모든 볼륨 마운트 해제" #~ msgid "TrueCrypt Volumes" #~ msgstr "TrueCrypt 볼륨" #~ msgid "Terminal Server Client" #~ msgstr "터미널 서버 클라이언트" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "터미널 서버 클라이언트에 저장된 세션" #~ msgid "TSClient sessions" #~ msgstr "터미널 서버 클라이언트 세션" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "터미널 서버 클라이언트에 저장된 세션" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Vinagre 책갈피와 동작" #~ msgid "Start Vinagre Session" #~ msgstr "Vinagre 세션 시작" #~ msgid "Vinagre Bookmarks" #~ msgstr "Vinagre 책갈피" #~ msgid "Recently used documents in Vim" #~ msgstr "Vim 최근 사용한 문서" #~ msgid "Vim Recent Documents" #~ msgstr "Vim 최근 문서" #~ msgid "VirtualBox" #~ msgstr "버추얼 박스" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "버추얼 박스 머신을 조작합니다. 오라클 버추얼 박스와 오픈 소스 에디션을 모" #~ "두 지원합니다." #~ msgid "Power On" #~ msgstr "시스템 시작" #~ msgid "Power On Headless" #~ msgstr "헤드레스 시스템 시작" #~ msgid "Send Power Off Signal" #~ msgstr "시스템 종료 신호 보내기" #~ msgid "Reboot" #~ msgstr "다시 시작" #~ msgid "Resume" #~ msgstr "계속" #~ msgid "Save State" #~ msgstr "상태 저장" #~ msgid "Power Off" #~ msgstr "시스템 종료" #~ msgid "VirtualBox Machines" #~ msgstr "버추얼 박스 머신" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "Zim에 보관된 페이지에 접근합니다 - 데스크톱 위키와 아우트라이너" #~ msgid "Page names start with :colon" #~ msgstr "페이지 이름은 콜론으로 시작합니다" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Notebook \"%s\"의 Zim Page" #~ msgid "Create Zim Page" #~ msgstr "Zim Page 만들기" #~ msgid "Create page in default notebook" #~ msgstr "기본 공책에 페이지 만들기" #~ msgid "Create Zim Page In..." #~ msgstr "다음에 Zim Page 만들기..." #~ msgid "Create Subpage..." #~ msgstr "하위 페이지 만들기..." #~ msgid "Zim Notebooks" #~ msgstr "Zim Notebooks" #~ msgid "Zim Pages" #~ msgstr "Zim 페이지" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Zim Notebooks에 보관된 페이지" #~ msgid "Directories" #~ msgstr "디렉터리" #, fuzzy #~| msgid "Directories" #~ msgid "Icons" #~ msgstr "디렉터리" #~ msgid "Interface" #~ msgstr "인터페이스" #, fuzzy #~| msgid "Interface" #~ msgid "Terminal" #~ msgstr "인터페이스" #~ msgid "Text Matches" #~ msgstr "텍스트 일치" #, fuzzy #~| msgid "%s total found" #~ msgid "Command '%s' not found" #~ msgstr "%s 전체 검색" #~ msgid "noun" #~ msgstr "명사" #~ msgid "verb" #~ msgstr "동사" #~ msgid "adjective" #~ msgstr "형용사" #~ msgid "Tracker 0.8" #~ msgstr "트래커 0.8" #~ msgid "" #~ "Tick the box next to a source to make sure its objects are exported to " #~ "the top level of the catalog. An unticked source's contents are only " #~ "available by locating its subcatalog and entering it.\n" #~ "\n" #~ "Note: Kupfer is an integrator, not an indexer itself. Kupfer is not " #~ "designed to carry a catalog larger than a couple of thousand objects, and " #~ "may become slow if overly large subcatalogs are included in the top level." #~ msgstr "" #~ "개체를 최 상위 단계의 카탈로그로 내보내려면 소스 옆의 상자를 표시하십시" #~ "오. 표시되지 않은 소스의 항목은 하위 카탈로그에 이동해서 들어가야만 사용" #~ "할 수 있습니다.\n" #~ "\n" #~ "주의: 쿠퍼는 인테그레이터이지 인덱서가 아닙니다. 쿠퍼는 수 천 개체 이상의 " #~ "카탈로그를 가질 수 없고, 최 상위 단계에 필요 이상의 하위 카탈로그가 포함되" #~ "면 느려질 수 있습니다." #~ msgid "Twitter" #~ msgstr "트위터" #~ msgid "Microblogging with Twitter: send updates and show friends' tweets" #~ msgstr "" #~ "트위터로 마이크로 블로깅을 합니다: 업데이트를 보내고 친구의 트위트를 봅니" #~ "다" #~ msgid "Load friends' pictures" #~ msgstr "친구의 그림 불러오기" #~ msgid "Load friends' public tweets" #~ msgstr "친구의 공개 트위트 불러오기" #~ msgid "Load timeline" #~ msgstr "일정 불러오기" #~ msgid "Post Update to Twitter" #~ msgstr "트위터 계정에 업데이트 글을 올립니다" #~ msgid "Twitter Timeline" #~ msgstr "트위터 일정" #~ msgid "Twitter Friends" #~ msgstr "트위터 친구" #~ msgid "Timeline for %s" #~ msgstr "%s의 일정" #~ msgid "OpenOffice" #~ msgstr "오픈 오피스" #~ msgid "Preferred terminal" #~ msgstr "선호하는 터미널" #~ msgid "" #~ "The preferred terminal emulator. It's used to launch the SSH sessions." #~ msgstr "선호하는 터미널 에뮬레이터. SSH 세션을 실행하는데 사용됩니다." #~ msgid "" #~ "The flag which makes the terminal execute everything following it inside " #~ "the terminal (e.g. '-x' for gnome-terminal and terminal, '-e' for konsole " #~ "and urxvt)." #~ msgstr "" #~ "터미널 안에 따르는 모든 것을 터미널에서 실행할 수 있게 해주는 플래그 (예 " #~ "그놈 터미널과 터미널을 실행하려면 '-x' , konsole과 urxvt를 실행하려면 '-" #~ "e')." kupfer-328/po/nb.po000066400000000000000000001103441500175051100142370ustar00rootroot00000000000000# Norwegian bokmål translation of kupfer # Copyright (C) 2007--2010 Ulrik Sverdrup # This file is distributed under the same license as the Kupfer package. # Kjartan Maraas , 2005-2012. # msgid "" msgstr "" "Project-Id-Version: kupfer\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2012-08-23 09:52+0200\n" "Last-Translator: Kjartan Maraas \n" "Language-Team: Norwegian bokmål \n" "Language: \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" msgid "User credentials" msgstr "Brukerinformasjon" msgid "_User:" msgstr "Br_uker:" msgid "_Password:" msgstr "_Passord:" msgid "_Change" msgstr "_Bruk" msgid "Set Keyboard Shortcut" msgstr "" msgid "Please press desired key combination" msgstr "" msgid "Keybinding could not be bound" msgstr "Tastaturbinding kunne ikke bindes" msgid "Kupfer Preferences" msgstr "Brukervalg for Kupfer" msgid "Start automatically on login" msgstr "Start automatisk ved innlogging" msgid "Start" msgstr "Start" msgid "Show icon in notification area" msgstr "Vis ikon i statusfeltet" msgid "Icon set:" msgstr "" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" msgid "Terminal emulator:" msgstr "Terminalemulator:" msgid "Desktop Environment" msgstr "" msgid "General" msgstr "Generelt" msgid "Global Keyboard Shortcuts" msgstr "" msgid "Reset" msgstr "Nullstill" msgid "Browser Keyboard Shortcuts" msgstr "" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "" msgid "Keyboard" msgstr "Tastatur" msgid "Plugins" msgstr "Tillegg" msgid "Inclusion in Top Level Searches" msgstr "" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" msgid "Indexed Folders" msgstr "Indekserte mapper" msgid "Folders whose files are always available in the catalog." msgstr "" msgid "Catalog" msgstr "Katalog" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Programstarter" msgid "Convenient command and access tool for applications and documents" msgstr "Praktiskt kommandoverktøy for programmer og dokumenter " msgid "Execute in Kupfer" msgstr "Kjør i Kupfer" msgid "Saved Kupfer Command" msgstr "" #, python-format msgid "Could not to carry out '%s'" msgstr "Kunne ikke utføre «%s»" #, python-format msgid "\"%s\" produced a result" msgstr "\"%s\" produserte et resultat" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "" #, python-format msgid "Command in \"%s\" is not available" msgstr "" #, python-format msgid "Keyboard relay is active for display %s" msgstr "" msgid "do not present main interface on launch" msgstr "ikke vis grensesnitt ved start" msgid "list available plugins" msgstr "liste tilgjenelige tillegg" msgid "enable debug info" msgstr "aktiver felsøkingsinformasjon" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "" msgid "show usage help" msgstr "vis brukshjelp" msgid "show version information" msgstr "vis versjonsinformasjon" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Bruk: kupfer [ VALG | FIL ... ]" msgid "Available plugins:" msgstr "Tilgjengelige tillegg:" #, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" msgid "Type to search" msgstr "Skriv for å søke" #, python-format msgid "%s is empty" msgstr "%s er tom" msgid "Text" msgstr "Tekst" msgid "Run after Delay..." msgstr "Kjør etter ventetid …" msgid "Perform command after a specified time interval" msgstr "" msgid "Multiple Objects" msgstr "Flere objekter" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s objekt" msgstr[1] "%s objekter" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "" msgid "unknown" msgstr "" msgid "Aim" msgstr "Aim" msgid "Google Talk" msgstr "Google Talk" msgid "ICQ" msgstr "" msgid "MSN" msgstr "" msgid "QQ" msgstr "" msgid "Yahoo" msgstr "" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "" msgid "Can not be used with multiple objects" msgstr "" msgid "Open" msgstr "Åpne" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Har ikke standardprogram for %(file)s (%(type)s)" #, python-format msgid "Please use \"%s\"" msgstr "Vennligst bruk «%s»" msgid "Set Default Application..." msgstr "Velg standardprogram …" msgid "Open with default application" msgstr "Åpne med standardprogram" msgid "Reveal" msgstr "Vis" msgid "Open parent folder" msgstr "Åpne foreldermappe" msgid "Open Terminal Here" msgstr "Åpne terminal her" msgid "Open this location in a terminal" msgstr "Åpne plassen i en terminal" msgid "Run in Terminal" msgstr "Kjør i terminal" msgid "Run (Execute)" msgstr "Kjør" msgid "Run this program in a Terminal" msgstr "Kjør dette programmet i en terminal" msgid "Run this program" msgstr "Kjør dette programmet" msgid "Go To" msgstr "Gå til" msgid "Open URL" msgstr "Åpne URL" msgid "Open URL with default viewer" msgstr "" msgid "Launch" msgstr "Start" msgid "Show application window" msgstr "Vis programvindu" msgid "Launch application" msgstr "Start program" msgid "Launch Again" msgstr "Start igjen" msgid "Launch another instance of this application" msgstr "" msgid "Close" msgstr "Lukk" msgid "Attempt to close all application windows" msgstr "Lukk programmets vinduer" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Kjør" msgid "Perform command" msgstr "Utfør kommando" msgid "(Empty Text)" msgstr "(Tom tekst)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "«%(text)s»" msgstr[1] "(%(num)d linjer) «%(text)s»" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "" #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "" #, python-format msgid "Directory source %s" msgstr "" msgid "Home Folder" msgstr "Hjemmemappe" msgid "Catalog Index" msgstr "Katalogindeks" msgid "An index of all available sources" msgstr "En indeks med tilgjengelige kilder" msgid "Root catalog" msgstr "Rotkatalog" msgid "Please Configure Plugin" msgstr "Vennligst konfigurer tillegg" #, python-format msgid "Plugin %s is not configured" msgstr "Tillegg %s er ikke konfigurert" #, python-format msgid "Invalid user credentials for %s" msgstr "Ugyldig påloggingsinformasjon for %s" msgid "Applications" msgstr "Programmer" msgid "All applications and preferences" msgstr "Alle programmer og brukervalg" msgid "Applications for Desktop Environment" msgstr "" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "Åpne med …" msgid "Open with any application" msgstr "Åpne med valgfritt program" msgid "Set default application to open this file type" msgstr "" #, fuzzy msgid "Reset Associations" msgstr "URL-handlinger" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "Dype arkiver" msgid "Allow browsing inside compressed archive files" msgstr "" #, python-format msgid "Content of %s" msgstr "Innholdet av %s" msgid "Archive Manager" msgstr "Arkivhåndterer" msgid "Use Archive Manager actions" msgstr "" msgid "Compressed archive type for 'Create Archive In'" msgstr "" msgid "Extract Here" msgstr "Pakk ut her" msgid "Extract compressed archive" msgstr "Pakk ut arkiv" msgid "Create Archive" msgstr "Lag arkiv" msgid "Create a compressed archive from folder" msgstr "" msgid "Create Archive In..." msgstr "Lag arkiv i …" #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Arkiv" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "" msgid "Include songs in top level" msgstr "" msgid "Enqueue" msgstr "Legg i kø" msgid "Add track to the Audacious play queue" msgstr "" msgid "Dequeue" msgstr "" msgid "Remove track from the Audacious play queue" msgstr "" msgid "Play" msgstr "Spill av" msgid "Jump to track in Audacious" msgstr "" msgid "Resume playback in Audacious" msgstr "" msgid "Pause" msgstr "Pause" msgid "Pause playback in Audacious" msgstr "" msgid "Next" msgstr "Neste" msgid "Jump to next track in Audacious" msgstr "" msgid "Previous" msgstr "Forrige" msgid "Jump to previous track in Audacious" msgstr "" msgid "Clear Queue" msgstr "Tøm kø" msgid "Clear the Audacious play queue" msgstr "" msgid "Shuffle" msgstr "" msgid "Toggle shuffle in Audacious" msgstr "" msgid "Repeat" msgstr "Gjenta" msgid "Toggle repeat in Audacious" msgstr "" msgid "Show Playing" msgstr "" msgid "Tell which song is currently playing" msgstr "" msgid "Playlist" msgstr "Spilleliste" msgid "Calculator" msgstr "Kalkulator" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "Beregn" msgid "Clipboards" msgstr "Utklippstavler" msgid "Recent clipboards and clipboard proxy objects" msgstr "" msgid "Number of recent clipboards to remember" msgstr "Antall nylige utklippstavler å huske" msgid "Include selected text in clipboard history" msgstr "Inkluder markert tekst i historikken" msgid "Copy selected text to primary clipboard" msgstr "Kopier markert tekst til utklippstavlen" msgid "Selected Text" msgstr "Markert tekst" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "" msgstr[1] "" msgid "Clipboard Text" msgstr "Tekst i Utklippstavlen" #, fuzzy msgid "Clipboard File" msgstr "Utklippstavler" #, fuzzy msgid "Clipboard Files" msgstr "Utklippstavler" msgid "Clear" msgstr "Tøm" #, fuzzy msgid "Remove all recent clipboards" msgstr "Antall nylige utklippstavler" msgid "Shell Commands" msgstr "Skallkommando" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" msgid "Run (Get Output)" msgstr "Kjør (Ta utdata)" msgid "Run program and return its output" msgstr "" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "Send til kommando …" msgid "Run program with object as an additional parameter" msgstr "" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "Skriv til kommando …" msgid "Run program and supply text on the standard input" msgstr "" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "" msgid "Run command-line programs" msgstr "Kjør skallkommandoer" msgid "GTK+" msgstr "GTK+" msgid "GNOME Terminal" msgstr "GNOME-terminal" msgid "XFCE Terminal" msgstr "XFCE-terminal" msgid "LXTerminal" msgstr "LXTerminal" msgid "X Terminal" msgstr "X-terminal" msgid "Urxvt" msgstr "Urxvt" msgid "Konsole" msgstr "" msgid "Save As..." msgstr "Lagre som …" msgid "Restart Kupfer" msgstr "Start Kupfer på nytt" msgid "Quit" msgstr "Avslutt" msgid "Quit Kupfer" msgstr "Avslutt Kupfer" msgid "About Kupfer" msgstr "Om Kupfer" msgid "Show information about Kupfer authors and license" msgstr "Vis informasjon om Kupfers utviklere og lisens" msgid "Kupfer Help" msgstr "Hjelp med Kupfer" msgid "Get help with Kupfer" msgstr "Få hjelp med Kupfer" msgid "Show preferences window for Kupfer" msgstr "Vis Kupfers brukervalg" msgid "Search Contents" msgstr "Søk i innhold" msgid "Search inside this catalog" msgstr "Søk i denne katalogen" msgid "Copy" msgstr "Kopier" msgid "Copy to clipboard" msgstr "Kopier til utklippstavlen" msgid "Rescan" msgstr "Søk på nytt" msgid "Force reindex of this source" msgstr "" msgid "Last Command" msgstr "Siste kommando" msgid "Internal Kupfer Objects" msgstr "Interne Kupfer-objekter" msgid "Last Result" msgstr "Siste resultat" msgid "Command Results" msgstr "Kommandoutdata" msgid "Custom Terminal" msgstr "Egendefinert terminal" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Kommando" msgid "Execute flag" msgstr "Kjør-flagg" msgid "Default Email Client" msgstr "Forvalgt e-postklient" msgid "Compose email using the system's default mailto: handler" msgstr "" msgid "Compose Email To" msgstr "Skriv e-post til" msgid "Dictionary" msgstr "Ordbok" msgid "Look up word in dictionary" msgstr "Slå opp ord i ordbok" msgid "Look Up" msgstr "Slå opp" msgid "Documents" msgstr "Dokumenter" msgid "Recently used documents and bookmarked folders" msgstr "" msgid "Max recent document days" msgstr "Maksimum alder (dager) for siste dokumenter" msgid "Recent Items" msgstr "Nylig brukte dokumenter" msgid "Recently used documents" msgstr "Nylig brukte dokumenter" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "%s-dokumenter" #, python-format msgid "Recently used documents for %s" msgstr "Nylig brukte dokumenter for %s" msgid "Places" msgstr "Steder" msgid "Bookmarked folders" msgstr "Bokmerkete steder" msgid "DuckDuckGo Search" msgstr "DuckDuckGo søk" msgid "Search the web securely with DuckDuckGo" msgstr "" msgid "Favorites" msgstr "Favoritter" msgid "Mark commonly used items and store objects for later use" msgstr "" msgid "Shelf of \"Favorite\" items" msgstr "" msgid "Add to Favorites" msgstr "Legg til favoritt" msgid "Add item to favorites shelf" msgstr "" msgid "Remove from Favorites" msgstr "Ta bort favoritt" msgid "Remove item from favorites shelf" msgstr "" #, fuzzy msgid "File Actions" msgstr "Handlinger" #, fuzzy msgid "More file actions" msgstr "Vis tidligere brukte handlinger" msgid "Move To..." msgstr "Flytt til …" msgid "Move file to new location" msgstr "" msgid "Rename To..." msgstr "Endre navn til …" msgid "Copy To..." msgstr "Kopier til …" msgid "Copy file to a chosen location" msgstr "" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "" msgid "Select objects using '*' and '?' as wildcards." msgstr "" #, fuzzy msgid "Higher-order Actions" msgstr "Handlinger for datamaskinen" msgid "Tools to work with commands as objects" msgstr "" msgid "Select in Kupfer" msgstr "Velg i Kupfer" #, python-format msgid "Result of %s (%s)" msgstr "Resultat for %s (%s)" msgid "Run (Take Result)" msgstr "" msgid "Take the command result as a proxy object" msgstr "" msgid "Run (Discard Result)" msgstr "" msgid "Image Tools" msgstr "Bildeverktøy" msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "" msgid "Scale..." msgstr "" msgid "Scale image to fit inside given pixel measure(s)" msgstr "" msgid "Rotate Clockwise" msgstr "" msgid "Rotate Counter-Clockwise" msgstr "" msgid "Autorotate" msgstr "" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "" msgid "Kupfer Plugins" msgstr "" msgid "Access Kupfer's plugin list in Kupfer" msgstr "" msgid "Show Information" msgstr "" msgid "Show Source Code" msgstr "Vis kildekode" msgid "enabled" msgstr "aktivert" msgid "disabled" msgstr "deaktivert" msgid "Notes" msgstr "Notater" msgid "Gnote or Tomboy notes" msgstr "Søk i dine Gnote- eller Tomboy-notater" msgid "Work with application" msgstr "" msgid "Open with notes application" msgstr "" msgid "Append to Note..." msgstr "Tilføy til notat …" msgid "Add text to existing note" msgstr "" msgid "Create Note" msgstr "Lag notat" msgid "Create a new note from this text" msgstr "Opprett nytt notat fra teksten" msgid "Get Note Search Results..." msgstr "Hent søketreff i notater …" msgid "Show search results for this query" msgstr "Vis søkeretreff for denne termen" #, python-format msgid "today, %s" msgstr "idag, %s" #, python-format msgid "yesterday, %s" msgstr "igår, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Sist oppdatert %s" msgid "Quicksilver Icons" msgstr "" msgid "Quick Image Viewer" msgstr "" msgid "View Image" msgstr "Vis vilde" msgid "GNU Screen" msgstr "GNU Screen" msgid "Active GNU Screen sessions" msgstr "" msgid "Attached" msgstr "Tilkoblet" msgid "Detached" msgstr "Frakoblet" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "" msgid "Screen Sessions" msgstr "Skjermøkter" msgid "Attach" msgstr "Fest" msgid "Send Keys" msgstr "Send taster" msgid "Send synthetic keyboard events using xautomation" msgstr "" msgid "Paste to Foreground Window" msgstr "" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "" msgid "Send keys to foreground window" msgstr "" msgid "Type Text" msgstr "Skriv tekst" msgid "Type the text to foreground window" msgstr "" msgid "GNOME Session Management" msgstr "" msgid "Special items and actions for GNOME environment" msgstr "" msgid "Log Out..." msgstr "Logg ut …" msgid "Log out or change user" msgstr "" msgid "Shut Down..." msgstr "Slå av …" msgid "Shut down, restart or suspend computer" msgstr "" msgid "Lock Screen" msgstr "Lås skjermen" msgid "Enable screensaver and lock" msgstr "" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "" msgid "Special items and actions for XFCE environment" msgstr "" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "" msgid "SSH host" msgstr "" msgid "Connect" msgstr "" msgid "Connect to SSH host" msgstr "" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "" msgid "No D-Bus connection to desktop session" msgstr "" msgid "GNOME Keyring" msgstr "GNOME-nøkkelring" msgid "KWallet" msgstr "" msgid "Unencrypted File" msgstr "Ukryptert fil" #, python-format msgid "Dependency '%s' is not available" msgstr "" msgid "Document Templates" msgstr "Dokumentmaler" msgid "Create new documents from your templates" msgstr "Lag nye dokumenter fra dine maler" #, python-format msgid "%s template" msgstr "%s mal" msgid "Empty File" msgstr "Tom fil" msgid "New Folder" msgstr "Ny mappe" msgid "Create New Document..." msgstr "Lag nytt dokument …" msgid "Create a new document from template" msgstr "Lag ett nytt dokument fra mal" msgid "Create Document In..." msgstr "Lag dokument i …" msgid "Textfiles" msgstr "Tekstfiler" msgid "Append To..." msgstr "Legg til i …" msgid "Append..." msgstr "Legg til …" msgid "Write To..." msgstr "Skriv til …" msgid "Get Text Contents" msgstr "Hent tekstinnhold" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "" msgid "Select in File Manager" msgstr "" msgid "Show Properties" msgstr "Vis egenskaper" msgid "Show information about file in file manager" msgstr "" msgid "Send To..." msgstr "Send til …" msgid "Symlink In..." msgstr "" msgid "Create a symlink to file in a chosen location" msgstr "" msgid "Empty Trash" msgstr "Tøm papirkurven" msgid "Thunar Send To Objects" msgstr "" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "" msgid "Compose New Email" msgstr "" msgid "Compose a new message in Thunderbird" msgstr "" msgid "Attach in Email To..." msgstr "Legg ved i e-post til..." msgid "Compose Email With" msgstr "Skriv e-post med" msgid "Compose a new message using the text as body" msgstr "Skriv ny e-post med teksten" msgid "Thunderbird Address Book" msgstr "Thunderbird adressebok" msgid "Contacts from Thunderbird Address Book" msgstr "" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "" msgid "Show running tasks and allow sending signals to them" msgstr "" msgid "Sort Order" msgstr "Sorteringsrekkefølge" msgid "Commandline" msgstr "Kommandolinje" msgid "CPU usage (descending)" msgstr "" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "" msgid "Send Signal..." msgstr "Send signal …" msgid "Signals" msgstr "Signaler" msgid "Running Tasks" msgstr "Kjørende oppgaver" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "" msgid "Running tasks for current user" msgstr "" msgid "Trash" msgstr "Papirkurv" msgid "Access trash contents" msgstr "Tilgang til papirkurvens innhold" msgid "Move to Trash" msgstr "Flytt til papirkurven" msgid "Move this file to trash" msgstr "Flytt fil til papirkurven" msgid "Restore" msgstr "Gjenopprett" msgid "Move file back to original location" msgstr "Flytt fil tilbake til opprinnelig sted" msgid "" "Could not delete files:\n" " " msgstr "" "Kunne ikke slette filer:\n" " " msgid "Trash is empty" msgstr "Papirkurven er tom" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "Papirkurven inneholder én fil" msgstr[1] "Papirkurven inneholder %(num)s filer" msgid "Triggers" msgstr "Utløsere" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" msgid "Add Trigger..." msgstr "" msgid "Remove Trigger" msgstr "" msgid "URL Actions" msgstr "URL-handlinger" msgid "Download and Open" msgstr "Last ned og åpne" msgid "Download To..." msgstr "Last ned til …" msgid "Download URL to a chosen location" msgstr "" msgid "Wikipedia" msgstr "Wikipedia" msgid "Search in Wikipedia" msgstr "Søk i Wikipedia" msgid "Wikipedia language" msgstr "Wikipedia-språk" #. TRANS: Default wikipedia language code msgid "en" msgstr "no" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Søk etter dette begrepet i %s.wikipedia.org" msgid "Window List" msgstr "Vinduliste" msgid "All windows on all workspaces" msgstr "Alle vinduer på alle arbeidsområder" msgid "Activate" msgstr "Slå på" msgid "Shade" msgstr "Skyggelegg" msgid "Unshade" msgstr "" msgid "Minimize" msgstr "Minimer" msgid "Unminimize" msgstr "Gjenopprett" msgid "Maximize" msgstr "Maksimer" msgid "Unmaximize" msgstr "" msgid "Maximize Vertically" msgstr "" msgid "Unmaximize Vertically" msgstr "" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "" msgid "Frontmost Window" msgstr "" msgid "Next Window" msgstr "Neste vindu" msgid "Jump to this window's workspace and focus" msgstr "" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "%d vindu" msgstr[1] "%d vinduer" msgid "Active workspace" msgstr "Aktivt arbeidsområde" msgid "Jump to this workspace" msgstr "Hopp til dette arbeidsområdet" msgid "Workspaces" msgstr "Arbeidsområder" msgid "Volumes and Disks" msgstr "Volum og disker" msgid "Mounted volumes and disks" msgstr "Monterte volum og disker" #, python-format msgid "Volume mounted at %s" msgstr "Volum montert %s" msgid "Unmount" msgstr "Avmonter" msgid "Unmount this volume" msgstr "Avmonter dette volumet" msgid "Eject" msgstr "Løs ut" msgid "Unmount and eject this media" msgstr "Avmonter og løs ut dette mediet" msgid "Show Text" msgstr "Vis tekst" msgid "Display text in a window" msgstr "Vis tekst i et vindu" msgid "Large Type" msgstr "Vis med stor tekst" msgid "Show Notification" msgstr "Vis varsling" msgid "Tracker" msgstr "" msgid "Tracker desktop search integration" msgstr "" msgid "Search in Tracker" msgstr "" msgid "Open Tracker Search Tool and search for this term" msgstr "" msgid "Get Tracker Results..." msgstr "" msgid "Show Tracker results for query" msgstr "" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "Finn filer" #, fuzzy msgid "Search filesystem using locate" msgstr "Søk etter %s med Beagle" msgid "Ignore case distinctions when searching files" msgstr "" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Firefox-bokmerker" #, fuzzy msgid "Index of Firefox bookmarks" msgstr "Åpne bokmerke %s" #, fuzzy msgid "Firefox Keywords" msgstr "Firefox-bokmerker" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "Søk på nettet med nettleserens innstillinger for søk" msgid "Search With..." msgstr "Søk med …" msgid "Search For..." msgstr "Søk etter …" #, fuzzy msgid "Search Terms" msgstr "Søkemotorer" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, python-format msgid "Play/Pause (%s)" msgstr "Spill av/Pause (%s)" msgid "Resume playback" msgstr "" #. TRANS: %s is a media player name #, python-format msgid "Next (%s)" msgstr "Neste (%s)" msgid "Skip to next track" msgstr "" #. TRANS: %s is a media player name #, python-format msgid "Previous (%s)" msgstr "Forrige (%s)" msgid "Skip to previous track" msgstr "" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "Stopp (%s)" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "Pidgin" #, fuzzy msgid "Access to Pidgin Contacts" msgstr "Pidgin-kontakter" msgid "Show offline contacts" msgstr "Vis frakoblede kontakter" msgid "Open Chat" msgstr "Åpne prat" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d tegn)" msgstr[1] "%s (%d tegn)" msgid "Send Message..." msgstr "Send melding …" msgid "Available" msgstr "Tilgjengelig" msgid "Away" msgstr "Borte" msgid "Pidgin Contacts" msgstr "Pidgin-kontakter" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "" msgid "Create short aliases of long URLs" msgstr "" msgid "Error" msgstr "Feil" #, fuzzy msgid "Shorten With..." msgstr "Åpne med …" msgid "Services" msgstr "Tjenester" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "" msgid "Include artists in top level" msgstr "" msgid "Include albums in top level" msgstr "" msgid "Play tracks in Rhythmbox" msgstr "" msgid "Add tracks to the play queue" msgstr "" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "av %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Spor av %s" msgid "Albums" msgstr "Album" msgid "Music albums in Rhythmbox Library" msgstr "" msgid "Artists" msgstr "Artister" msgid "Music artists in Rhythmbox Library" msgstr "" msgid "Songs" msgstr "Sanger" msgid "Songs in Rhythmbox library" msgstr "" msgid "Getting Things GNOME" msgstr "" msgid "Browse and create new tasks in GTG" msgstr "" #, python-format msgid "due: %s" msgstr "" #, python-format msgid "start: %s" msgstr "" #, python-format msgid "tags: %s" msgstr "" msgid "Open task in Getting Things GNOME!" msgstr "" #, fuzzy msgid "Delete" msgstr "Slett melding" msgid "Permanently remove this task" msgstr "" msgid "Mark Done" msgstr "" msgid "Mark this task as done" msgstr "Merk denne oppgaven som utført" msgid "Dismiss" msgstr "" #, fuzzy msgid "Mark this task as not to be done anymore" msgstr "Merk denne oppgaven som utført" msgid "Create Task" msgstr "Lag oppgave" msgid "Create new task in Getting Things GNOME" msgstr "" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "Søk i Devhelp" msgid "Empathy" msgstr "Empathy" #, fuzzy msgid "Access to Empathy Contacts" msgstr "Empathy-kontakter" msgid "Busy" msgstr "Opptatt" msgid "Not Available" msgstr "Ikke tilgjengelig" msgid "Invisible" msgstr "Usynlig" msgid "Offline" msgstr "Frakoblet" msgid "Change Global Status To..." msgstr "" msgid "Empathy Contacts" msgstr "Empathy-kontakter" #, fuzzy msgid "Empathy Account Status" msgstr "Empathy-kontakter" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Aktiver (alternativ)" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Bygg kommando" msgid "Mark Default Action" msgstr "Velg standardhandling" msgid "Forget Object" msgstr "Glem objekt" msgid "Reset All" msgstr "Nullstill alle" msgid "Select Quit" msgstr "Velg avslutt" msgid "Select Selected File" msgstr "Velg markert fil" msgid "Select Selected Text" msgstr "Velg markert tekst" msgid "Show Help" msgstr "Vis hjelp" msgid "Show Preferences" msgstr "Vis brukervalg" msgid "Switch to First Pane" msgstr "" msgid "Toggle Text Mode" msgstr "" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Ingen treff i %(src)s for «%(query)s»" msgid "No matches" msgstr "Ingen treff" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Ingen treff" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "" msgid "Show with Selection" msgstr "Vis med utvalg" #. TRANS: Plugin info fields msgid "Description" msgstr "Beskrivelse" msgid "Author" msgstr "Utvikler" msgid "Version" msgstr "Versjon" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Python-modulen '%s' trenges" msgid "Plugin could not be read due to an error:" msgstr "Tillegget kunne ikke leses på grunn av en feil:" msgid "Content of" msgstr "Innholdet av" #. TRANS: Plugin contents header msgid "Sources" msgstr "Kilder" #. TRANS: Plugin contents header msgid "Actions" msgstr "Handlinger" #, python-format msgid "Using encrypted password storage: %s" msgstr "" #, python-format msgid "Using password storage: %s" msgstr "" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Konfigurasjon" msgid "Set username and password" msgstr "Sett brukernavn og passord" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Velg en katalog" msgid "Reset all shortcuts to default values?" msgstr "" msgid "Shortcut" msgstr "" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "Kjartan Maraas " msgid "A free software (GPLv3+) launcher" msgstr "En programstarter og fri programvare (GPLv3+)" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "" #~ msgid "Type to search %s" #~ msgstr "Skriv for å søke i %s" #~ msgid "No action" #~ msgstr "Ingen handling" #, fuzzy #~ msgid "GNOME Terminal Profiles" #~ msgstr "Åpne terminal her" #, fuzzy #~ msgid "Epiphany Bookmarks" #~ msgstr "Åpne bokmerke %s" #, fuzzy #~ msgid "Firefox tag" #~ msgstr "Firefox-bokmerker" #~ msgid "Search the Web" #~ msgstr "Søk på nettet" #~ msgid "Abiword" #~ msgstr "Abiword" #, fuzzy #~ msgid "Recently used documents in Abiword" #~ msgstr "Siste dokumenter" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Installation method" #~ msgstr "Installasjonsmetode" #~ msgid "Show Package Information" #~ msgstr "Vis pakkeinformasjon" #~ msgid "Install" #~ msgstr "Installer" #~ msgid "Search Package Name..." #~ msgstr "Søke etter pakkenavn …" #, fuzzy #~ msgid "Chromium Bookmarks" #~ msgstr "del.icio.us bokmerker" #, fuzzy #~ msgid "Claws Mail Address Book" #~ msgstr "E-post (adressebok)" #, fuzzy #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "E-post (adressebok)" #~ msgid "Theme:" #~ msgstr "Tema:" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Evolution kontakter" #~ msgid "Evolution Address Book" #~ msgstr "Evolution adressebok" #~ msgid "Filezilla" #~ msgstr "Filezilla" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Free for Chat" #~ msgstr "Ledig for prat" #~ msgid "Gajim Contacts" #~ msgstr "Gajim-kontakter" #~ msgid "Gmail" #~ msgstr "Gmail" #, fuzzy #~ msgid "Load additional information" #~ msgstr "vis versjonsinformasjon" #~ msgid "Work email" #~ msgstr "E-post på arbeid" #~ msgid "Home email" #~ msgstr "E-post hjemme" #~ msgid "Other email" #~ msgstr "Annen e-post" #~ msgid "Work address" #~ msgstr "Adresse på arbeid" #~ msgid "Home address" #~ msgstr "Hjemmeadresse" #~ msgid "Other address" #~ msgstr "Annen adresse" #~ msgid "Car phone" #~ msgstr "Biltelefon" #~ msgid "Fax" #~ msgstr "Faks" #~ msgid "Home phone" #~ msgstr "Hjemmetelefon" #~ msgid "Home fax" #~ msgstr "Faks hjemme" #~ msgid "Internal phone" #~ msgstr "Intern telefon" #~ msgid "Mobile" #~ msgstr "Mobil" #~ msgid "Other" #~ msgstr "Annet" #, fuzzy #~ msgid "Work phone" #~ msgstr "Arbeidsområder" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "File:" #~ msgstr "Fil:" #~ msgid "Google Search" #~ msgstr "Google søk" #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s på %(where)s" #~ msgid "Send Message" #~ msgstr "Send melding" #~ msgid "Send message to all Gwibber accounts" #~ msgstr "Send melding til alle Gwibber-kontoer" #~ msgid "Send Message To..." #~ msgstr "Send melding til …" #~ msgid "Send message to a Gwibber account" #~ msgstr "Send melding til en Gwibber-konto" #~ msgid "Send message to selected Gwibber account" #~ msgstr "Send melding til valgt Gwibber-konto" #~ msgid "Reply..." #~ msgstr "Svar …" #~ msgid "Send Private Message..." #~ msgstr "Send privat melding …" #~ msgid "Send direct message to user" #~ msgstr "Send direktemelding til bruker" #, fuzzy #~ msgid "Retweet To..." #~ msgstr "Endre navn til …" #~ msgid "Open in Browser" #~ msgstr "Åpne i nettleser" #~ msgid "Open message in default web browser" #~ msgstr "Åpne melding i forvalgt nettleser" #~ msgid "Gwibber Accounts" #~ msgstr "Gwibber-kontoer" #~ msgid "Send Update" #~ msgstr "Send oppdatering" #, fuzzy #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Siste dokumenter" #~ msgid "Opera Mail" #~ msgstr "Opera e-post" #, fuzzy #~ msgid "Opera Mail Contacts" #~ msgstr "Rediger kontakt %s" #, fuzzy #~ msgid "Contacts from Opera Mail" #~ msgstr "E-post (adressebok)" #~ msgid "Opera Bookmarks" #~ msgstr "Opera-bokmerker" #~ msgid "PuTTY Sessions" #~ msgstr "PuTTY-økter" #~ msgid "Start Session" #~ msgstr "Start økt" #~ msgid "View as HTML Document" #~ msgstr "Vis som HTML-dokument" #~ msgid "System Services" #~ msgstr "Systemtjenester" #~ msgid "Start Service" #~ msgstr "Start tjeneste" #~ msgid "Stop Service" #~ msgstr "Stopp tjeneste" #, fuzzy #~ msgid "Show QRCode" #~ msgstr "Vis QRCode" #, fuzzy #~ msgid "Display text as QRCode in a window" #~ msgstr "Vis tekst i et vindu" #~ msgid "Logged Out" #~ msgstr "Logget ut" #~ msgid "Vim" #~ msgstr "Vim" #, fuzzy #~ msgid "Recently used documents in Vim" #~ msgstr "Siste dokumenter" #, fuzzy #~ msgid "Vim Recent Documents" #~ msgstr "Nylig brukte dokumenter" #~ msgid "Close (Save All)" #~ msgstr "Lukk (lagre alle)" #~ msgid "Send..." #~ msgstr "Send …" #, fuzzy #~ msgid "Send ex command" #~ msgstr "Skallkommando" #, fuzzy #~ msgid "Active Vim Sessions" #~ msgstr "Skjermøkter" #~ msgid "Vim Session %s" #~ msgstr "Vim-økt %s" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Start Vinagre Session" #~ msgstr "Start Vinagre-økt" #~ msgid "Vinagre Bookmarks" #~ msgstr "Vinagre-bokmerker" #~ msgid "Reboot" #~ msgstr "Start på nytt" #, fuzzy #~ msgid "Create Zim Page" #~ msgstr "Opprett dokument" #~ msgid "Zim Pages" #~ msgstr "Zim-sider" kupfer-328/po/nl.po000066400000000000000000001421151500175051100142520ustar00rootroot00000000000000# Dutch translations for the kupfer package # Nederlandse vertaling voor kupfer. # Copyright (C) 2009 Ulrik Sverdrup # This file is distributed under the same license as the kupfer package. # Martin Koelewijn , 2009. # msgid "" msgstr "" "Project-Id-Version: kupfer beta\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2009-10-12 01:54+0200\n" "Last-Translator: Martin Koelewijn \n" "Language-Team: Dutch\n" "Language: \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" msgid "User credentials" msgstr "" msgid "_User:" msgstr "" msgid "_Password:" msgstr "" msgid "_Change" msgstr "" msgid "Set Keyboard Shortcut" msgstr "" msgid "Please press desired key combination" msgstr "" msgid "Keybinding could not be bound" msgstr "Sneltoets kon niet worden toegepast" msgid "Kupfer Preferences" msgstr "Kupfer Voorkeuren" msgid "Start automatically on login" msgstr "Automatisch starten bij aanmelden" msgid "Start" msgstr "Start" msgid "Show icon in notification area" msgstr "Pictogram tonen in systeemvak" msgid "Icon set:" msgstr "" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" #, fuzzy msgid "Terminal emulator:" msgstr "Hier Terminal openen" #, fuzzy msgid "Desktop Environment" msgstr "Programma's voor Desktopomgeving" msgid "General" msgstr "Algemeen" msgid "Global Keyboard Shortcuts" msgstr "" msgid "Reset" msgstr "" msgid "Browser Keyboard Shortcuts" msgstr "" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "" msgid "Keyboard" msgstr "" msgid "Plugins" msgstr "Plug-ins" #, fuzzy msgid "Inclusion in Top Level Searches" msgstr "Liederen opnemen in eerste level" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" #, fuzzy msgid "Indexed Folders" msgstr "Persoonlijke map" msgid "Folders whose files are always available in the catalog." msgstr "" msgid "Catalog" msgstr "Catalogus" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Programmastarter" msgid "Convenient command and access tool for applications and documents" msgstr "Handige opdracht- en toegangshulp voor programma's en documenten" #, fuzzy msgid "Execute in Kupfer" msgstr "Selecteren in Kupfer" msgid "Saved Kupfer Command" msgstr "" #, python-format msgid "Could not to carry out '%s'" msgstr "" #, python-format msgid "\"%s\" produced a result" msgstr "" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "" #, python-format msgid "Command in \"%s\" is not available" msgstr "" #, python-format msgid "Keyboard relay is active for display %s" msgstr "" msgid "do not present main interface on launch" msgstr "hoofdscherm niet tonen bij opstarten" msgid "list available plugins" msgstr "Maak lijst beschikbare plug-ins" msgid "enable debug info" msgstr "debug info activeren" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "" msgid "show usage help" msgstr "gebruikshulp tonen" msgid "show version information" msgstr "versie-informatie tonen" #, fuzzy msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Gebruik: kupfer [OPTIES | ZOEKTERM]" msgid "Available plugins:" msgstr "Beschikbare plug-ins:" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "Typ om te zoeken" #, python-format msgid "%s is empty" msgstr "%s is leeg" #, fuzzy msgid "Text" msgstr "Tekst tonen" msgid "Run after Delay..." msgstr "Uitvoeren na..." msgid "Perform command after a specified time interval" msgstr "Opdracht uitvoeren na bepaalde interval" msgid "Multiple Objects" msgstr "Meerdere objecten" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s object" msgstr[1] "%s object" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "" #, fuzzy msgid "Aim" msgstr "Zim" #, fuzzy msgid "Google Talk" msgstr "Google Translate" msgid "ICQ" msgstr "" msgid "MSN" msgstr "" msgid "QQ" msgstr "" msgid "Yahoo" msgstr "" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "" msgid "Can not be used with multiple objects" msgstr "" msgid "Open" msgstr "Openen" #, fuzzy, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Stel standaardprogramma in om dit bestandstype te openen" #, fuzzy, python-format msgid "Please use \"%s\"" msgstr "Geselecteerd bestand \"%s\"" msgid "Set Default Application..." msgstr "Standaardprogramma instellen..." #, fuzzy msgid "Open with default application" msgstr "Open met een programma" msgid "Reveal" msgstr "Tonen" msgid "Open parent folder" msgstr "Bovenliggende map openen" msgid "Open Terminal Here" msgstr "Hier Terminal openen" msgid "Open this location in a terminal" msgstr "Deze locatie in een terminal openen" msgid "Run in Terminal" msgstr "Uitvoeren in Terminal" msgid "Run (Execute)" msgstr "Uitvoeren" msgid "Run this program in a Terminal" msgstr "Dit programma uitvoeren in een Terminal" msgid "Run this program" msgstr "Dit programma uitvoeren" msgid "Go To" msgstr "Ga naar" msgid "Open URL" msgstr "URL openen" msgid "Open URL with default viewer" msgstr "Open URL met standaardprogramma" msgid "Launch" msgstr "Starten" msgid "Show application window" msgstr "Programmavenster tonen" msgid "Launch application" msgstr "Programma starten" msgid "Launch Again" msgstr "Nogmaals starten" msgid "Launch another instance of this application" msgstr "Start nog een versie van dit programma" msgid "Close" msgstr "Sluiten" #, fuzzy msgid "Attempt to close all application windows" msgstr "Probeer alle programmavensters te sluiten" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Uitvoeren" msgid "Perform command" msgstr "Opdracht uitvoeren" #, fuzzy msgid "(Empty Text)" msgstr "Leeg bestand" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "\"%(text)s\"" msgstr[1] "(%(num)d lines) \"%(text)s\"" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s e.a." #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Recursieve bron van %(dir)s, (%(levels)d levels)" #, python-format msgid "Directory source %s" msgstr "" msgid "Home Folder" msgstr "Persoonlijke map" msgid "Catalog Index" msgstr "Catalogusindex" msgid "An index of all available sources" msgstr "Een index van alle beschikbare bronnen" msgid "Root catalog" msgstr "Systeemcatalogus" msgid "Please Configure Plugin" msgstr "" #, python-format msgid "Plugin %s is not configured" msgstr "" #, fuzzy, python-format msgid "Invalid user credentials for %s" msgstr "Pas gebruikte documenten voor %s" msgid "Applications" msgstr "Programma's" msgid "All applications and preferences" msgstr "Alle programma's en voorkeuren" msgid "Applications for Desktop Environment" msgstr "Programma's voor Desktopomgeving" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "Openen met..." msgid "Open with any application" msgstr "Open met een programma" msgid "Set default application to open this file type" msgstr "Stel standaardprogramma in om dit bestandstype te openen" #, fuzzy msgid "Reset Associations" msgstr "URL Acties" msgid "Reset program associations for files of this type." msgstr "" #, fuzzy msgid "Deep Archives" msgstr "Archiveren" msgid "Allow browsing inside compressed archive files" msgstr "" #, fuzzy, python-format msgid "Content of %s" msgstr "Inhoud van" msgid "Archive Manager" msgstr "" msgid "Use Archive Manager actions" msgstr "" msgid "Compressed archive type for 'Create Archive In'" msgstr "Type gecomprimeerd archief voor 'Archiveren in'" msgid "Extract Here" msgstr "Hier uitpakken" msgid "Extract compressed archive" msgstr "Gecomprimeerd archief uitpakken" msgid "Create Archive" msgstr "Archiveren" msgid "Create a compressed archive from folder" msgstr "Een map comprimeren tot archief" msgid "Create Archive In..." msgstr "Archiveren in..." #. TRANS: Default filename (no extension) for 'Create Archive In...' #, fuzzy msgid "Archive" msgstr "Archiveren" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "Beheer Audacious' gedrag en afspeellijst" msgid "Include songs in top level" msgstr "Liederen opnemen in eerste level" msgid "Enqueue" msgstr "Toevoegen" msgid "Add track to the Audacious play queue" msgstr "Voeg nummer toe aan afspeellijst" msgid "Dequeue" msgstr "Verwijderen" msgid "Remove track from the Audacious play queue" msgstr "Verwijder nummer uit Audacious'afspeellijst" msgid "Play" msgstr "Afspelen" msgid "Jump to track in Audacious" msgstr "Spring naar nummer in Rhythmbox" msgid "Resume playback in Audacious" msgstr "Afspelen hervatten in Audacious" msgid "Pause" msgstr "Pauze" msgid "Pause playback in Audacious" msgstr "Pauzeer afspelen in Audacious" msgid "Next" msgstr "Volgende" msgid "Jump to next track in Audacious" msgstr "Spring naar volgende nummer in Audacious" msgid "Previous" msgstr "Vorige" msgid "Jump to previous track in Audacious" msgstr "Spring naar vorige nummer in Audacious" msgid "Clear Queue" msgstr "Lijst legen" msgid "Clear the Audacious play queue" msgstr "Audacious afspeellijst legen" msgid "Shuffle" msgstr "Shuffle" msgid "Toggle shuffle in Audacious" msgstr "Shuffle in Audacious aan-uit" msgid "Repeat" msgstr "Herhalen" msgid "Toggle repeat in Audacious" msgstr "Herhalen in Audacious aan-uit" msgid "Show Playing" msgstr "Toon huidige" msgid "Tell which song is currently playing" msgstr "Laat zien welk nummer wordt gespeeld" msgid "Playlist" msgstr "Afspeellijst" msgid "Calculator" msgstr "Rekenmachine" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "Berekenen" msgid "Clipboards" msgstr "Klemborden" msgid "Recent clipboards and clipboard proxy objects" msgstr "" #, fuzzy msgid "Number of recent clipboards to remember" msgstr "Aantal recente klemborden" msgid "Include selected text in clipboard history" msgstr "" #, fuzzy msgid "Copy selected text to primary clipboard" msgstr "Kopieer naar klembord" msgid "Selected Text" msgstr "Geselecteerde tekst" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Klembord \"%(desc)s\"" msgstr[1] "Klembord met %(num)d regels \"%(desc)s\"" #, fuzzy msgid "Clipboard Text" msgstr "Klemborden" #, fuzzy msgid "Clipboard File" msgstr "Klemborden" #, fuzzy msgid "Clipboard Files" msgstr "Klemborden" #, fuzzy msgid "Clear" msgstr "Lijst legen" #, fuzzy msgid "Remove all recent clipboards" msgstr "Aantal recente klemborden" msgid "Shell Commands" msgstr "Shell opdrachten" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" #, fuzzy msgid "Run (Get Output)" msgstr "Uitvoeren" msgid "Run program and return its output" msgstr "" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command #, fuzzy msgid "Pass to Command..." msgstr "Laatste opdracht" msgid "Run program with object as an additional parameter" msgstr "" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "" msgid "Run program and supply text on the standard input" msgstr "" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "" #, fuzzy msgid "Run command-line programs" msgstr "Start opdrachtregelprogramma" msgid "GTK+" msgstr "" #, fuzzy msgid "GNOME Terminal" msgstr "Hier Terminal openen" #, fuzzy msgid "XFCE Terminal" msgstr "Uitvoeren in Terminal" #, fuzzy msgid "LXTerminal" msgstr "Uitvoeren in Terminal" #, fuzzy msgid "X Terminal" msgstr "Uitvoeren in Terminal" msgid "Urxvt" msgstr "" msgid "Konsole" msgstr "" msgid "Save As..." msgstr "" #, fuzzy msgid "Restart Kupfer" msgstr "Kupfer sluiten" msgid "Quit" msgstr "Stoppen" msgid "Quit Kupfer" msgstr "Kupfer sluiten" msgid "About Kupfer" msgstr "Over Kupfer" msgid "Show information about Kupfer authors and license" msgstr "Toon informatie over Kupfers auteurs en licensie" msgid "Kupfer Help" msgstr "Kupfer Help" msgid "Get help with Kupfer" msgstr "Zoek hulp met Kupfer" msgid "Show preferences window for Kupfer" msgstr "Voorkeurenscherm voor Kupfer tonen" msgid "Search Contents" msgstr "Inhoud doorzoeken" msgid "Search inside this catalog" msgstr "In deze catalogus zoeken" msgid "Copy" msgstr "Kopiëren" msgid "Copy to clipboard" msgstr "Kopieer naar klembord" msgid "Rescan" msgstr "Opnieuw scannen" msgid "Force reindex of this source" msgstr "Herindexering van deze bron forceren" msgid "Last Command" msgstr "Laatste opdracht" msgid "Internal Kupfer Objects" msgstr "Interne kupfer-objecten" msgid "Last Result" msgstr "" msgid "Command Results" msgstr "" #, fuzzy msgid "Custom Terminal" msgstr "Uitvoeren in Terminal" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" #, fuzzy msgid "Command" msgstr "Algemeen" msgid "Execute flag" msgstr "" msgid "Default Email Client" msgstr "Standaard E-mailprogramma" msgid "Compose email using the system's default mailto: handler" msgstr "E-mail opstellen met standaard mailto: programma" #, fuzzy msgid "Compose Email To" msgstr "Opstellen e-mail" msgid "Dictionary" msgstr "Woordenboek" msgid "Look up word in dictionary" msgstr "Woord opzoeken in woordenboek" msgid "Look Up" msgstr "Opzoeken" msgid "Documents" msgstr "Documenten" #, fuzzy msgid "Recently used documents and bookmarked folders" msgstr "Pas gebruikte documenten in Abiword" msgid "Max recent document days" msgstr "Max dagen recente documenten" msgid "Recent Items" msgstr "Recente items" msgid "Recently used documents" msgstr "Pas gebruikte documenten" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "%s Documenten" #, python-format msgid "Recently used documents for %s" msgstr "Pas gebruikte documenten voor %s" msgid "Places" msgstr "Locaties" #, fuzzy msgid "Bookmarked folders" msgstr "Persoonlijke map" msgid "DuckDuckGo Search" msgstr "" msgid "Search the web securely with DuckDuckGo" msgstr "" msgid "Favorites" msgstr "Favorieten" msgid "Mark commonly used items and store objects for later use" msgstr "Veelgebruikte items markeren en objecten opslaan" msgid "Shelf of \"Favorite\" items" msgstr "Plank met \"favoriete\" items" msgid "Add to Favorites" msgstr "Toevoegen aan Favorieten" msgid "Add item to favorites shelf" msgstr "Item toevoegen aan plank met favorieten" msgid "Remove from Favorites" msgstr "Verwijderen uit Favorieten" msgid "Remove item from favorites shelf" msgstr "Item verwijderen van plank met favorieten" msgid "File Actions" msgstr "Bestandsacties" msgid "More file actions" msgstr "Meer bestandsacties" msgid "Move To..." msgstr "Verplaatsen naar..." msgid "Move file to new location" msgstr "Bestand verplaatsen naar nieuwe locatie" msgid "Rename To..." msgstr "Hernoemen als..." msgid "Copy To..." msgstr "Kopiëren naar..." msgid "Copy file to a chosen location" msgstr "Bestand kopiëren naar opgegeven locatie" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "Belangrijkere acties" msgid "Tools to work with commands as objects" msgstr "Middelen om met opdrachten als objecten te werken" msgid "Select in Kupfer" msgstr "Selecteren in Kupfer" #, python-format msgid "Result of %s (%s)" msgstr "Resultaat van %s (%s)" msgid "Run (Take Result)" msgstr "Uitvoeren (Neem resultaat)" msgid "Take the command result as a proxy object" msgstr "Neem uitkomst opdracht als proxyobject" msgid "Run (Discard Result)" msgstr "Uitvoeren (Negeer uitkomst)" msgid "Image Tools" msgstr "Tools voor afbeeldingen" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Bewerkingstools voor Afbeeldingen" msgid "Scale..." msgstr "Schalen..." msgid "Scale image to fit inside given pixel measure(s)" msgstr "Afbeelding schalen om in opgegeven pixelgrootte te passen" msgid "Rotate Clockwise" msgstr "Draaien met klok mee" msgid "Rotate Counter-Clockwise" msgstr "Draaien tegen klok in" msgid "Autorotate" msgstr "Automatisch draaien" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "Draai JPEG (in-place) volgens zijn EXIF metadata" msgid "Kupfer Plugins" msgstr "Kupfer Plug-ins" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Toegang tot Kupfer plug-in lijst in Kupfer" msgid "Show Information" msgstr "versie-informatie tonen" msgid "Show Source Code" msgstr "Broncode tonen" msgid "enabled" msgstr "ingeschakeld" msgid "disabled" msgstr "uitgeschakeld" msgid "Notes" msgstr "Notities" msgid "Gnote or Tomboy notes" msgstr "Gnote of Tomboy notities" msgid "Work with application" msgstr "Werken met programma" msgid "Open with notes application" msgstr "Openen met notitieprogramma" msgid "Append to Note..." msgstr "Toevoegen aan Notitie" msgid "Add text to existing note" msgstr "Tekst toevoegen aan bestaande notitie" msgid "Create Note" msgstr "Notitie maken" msgid "Create a new note from this text" msgstr "Nieuwe notitie maken van deze tekst" #, fuzzy msgid "Get Note Search Results..." msgstr "Haal Tracker Resultaten" #, fuzzy msgid "Show search results for this query" msgstr "Toon Tracker resultaten voor zoekopdracht" #, python-format msgid "today, %s" msgstr "vandaag, %s" #, python-format msgid "yesterday, %s" msgstr "gisteren, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Laatst geupdated %s" msgid "Quicksilver Icons" msgstr "" msgid "Quick Image Viewer" msgstr "" msgid "View Image" msgstr "" msgid "GNU Screen" msgstr "GNU Scherm" msgid "Active GNU Screen sessions" msgstr "Actieve GNU Schermsessies" msgid "Attached" msgstr "Vastgemaakt" msgid "Detached" msgstr "Losgekoppeld" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "%(status)s sessie (%(pid)s) begonnen %(time)s" msgid "Screen Sessions" msgstr "Schermsessies" msgid "Attach" msgstr "Vastkoppelen" msgid "Send Keys" msgstr "" msgid "Send synthetic keyboard events using xautomation" msgstr "" msgid "Paste to Foreground Window" msgstr "" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "" msgid "Send keys to foreground window" msgstr "" msgid "Type Text" msgstr "" msgid "Type the text to foreground window" msgstr "" #, fuzzy msgid "GNOME Session Management" msgstr "XFCE Sessiebeheer" #, fuzzy msgid "Special items and actions for GNOME environment" msgstr "Speciale items en acties voor XFCE-omgeving" msgid "Log Out..." msgstr "Afmelden..." msgid "Log out or change user" msgstr "Afmelden of gebruiker wisselen" msgid "Shut Down..." msgstr "Afsluiten..." msgid "Shut down, restart or suspend computer" msgstr "Afsluiten, herstarten of suspenderen" msgid "Lock Screen" msgstr "Scherm vergrendelen" msgid "Enable screensaver and lock" msgstr "Schermbeveiliging activeren en vergrendelen" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "XFCE Sessiebeheer" msgid "Special items and actions for XFCE environment" msgstr "Speciale items en acties voor XFCE-omgeving" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "" msgid "SSH host" msgstr "" msgid "Connect" msgstr "" msgid "Connect to SSH host" msgstr "" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "" msgid "No D-Bus connection to desktop session" msgstr "Geen D-Bus verbinding met desktopsessie" #, fuzzy msgid "GNOME Keyring" msgstr "Hier Terminal openen" msgid "KWallet" msgstr "" #, fuzzy msgid "Unencrypted File" msgstr "Geselecteerd bestand" #, python-format msgid "Dependency '%s' is not available" msgstr "" msgid "Document Templates" msgstr "Documentsjablonen" msgid "Create new documents from your templates" msgstr "Nieuwe documenten maken vanuit sjablonen" #, python-format msgid "%s template" msgstr "%s sjabloon" msgid "Empty File" msgstr "Leeg bestand" #, fuzzy msgid "New Folder" msgstr "Persoonlijke map" msgid "Create New Document..." msgstr "Maak nieuw document..." msgid "Create a new document from template" msgstr "Maak nieuw document vanuit sjabloon" #, fuzzy msgid "Create Document In..." msgstr "Maak nieuw document..." msgid "Textfiles" msgstr "" #, fuzzy msgid "Append To..." msgstr "Toevoegen aan Notitie" #, fuzzy msgid "Append..." msgstr "Toevoegen aan Notitie" #, fuzzy msgid "Write To..." msgstr "Vertalen naar..." #, fuzzy msgid "Get Text Contents" msgstr "Inhoud doorzoeken" msgid "Thunar" msgstr "" msgid "File manager Thunar actions" msgstr "" #, fuzzy msgid "Select in File Manager" msgstr "Selecteren in Kupfer" msgid "Show Properties" msgstr "" #, fuzzy msgid "Show information about file in file manager" msgstr "Toon informatie over Kupfers auteurs en licensie" #, fuzzy msgid "Send To..." msgstr "Hernoemen als..." msgid "Symlink In..." msgstr "" #, fuzzy msgid "Create a symlink to file in a chosen location" msgstr "Bestand kopiëren naar opgegeven locatie" #, fuzzy msgid "Empty Trash" msgstr "Prullenbak" msgid "Thunar Send To Objects" msgstr "" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Thunderbird/Icedove Adressen en Acties" msgid "Compose New Email" msgstr "Nieuwe e-mail opstellen" msgid "Compose a new message in Thunderbird" msgstr "Opstellen nieuw bericht in Thunderbird" #, fuzzy msgid "Attach in Email To..." msgstr "In e-mail sturen naar..." #, fuzzy msgid "Compose Email With" msgstr "Opstellen e-mail" #, fuzzy msgid "Compose a new message using the text as body" msgstr "Opstellen nieuw bericht in Thunderbird" msgid "Thunderbird Address Book" msgstr "Thunderbird adresboek" msgid "Contacts from Thunderbird Address Book" msgstr "Adressen uit Thunderbird Adresboek" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Top" msgid "Show running tasks and allow sending signals to them" msgstr "Toon actieve taken en toestaan signalen " msgid "Sort Order" msgstr "" msgid "Commandline" msgstr "" msgid "CPU usage (descending)" msgstr "CPU-gebruik (aflopend)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Geheugengebruik (aflopend)" msgid "Send Signal..." msgstr "Zend signaal..." msgid "Signals" msgstr "Signalen" msgid "Running Tasks" msgstr "Actieve taken" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgid "Running tasks for current user" msgstr "Actieve taken voor huidige gebruiker" msgid "Trash" msgstr "Prullenbak" msgid "Access trash contents" msgstr "Toegang tot prullenbak" msgid "Move to Trash" msgstr "Verplaatsen naar Prullenbak" msgid "Move this file to trash" msgstr "Gooi dit bestand in Prullenbak" msgid "Restore" msgstr "Herstellen" msgid "Move file back to original location" msgstr "Zet bestand terug op oorspronkelijke locatie" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "Prullenbak is leeg" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "Prullenbak bevat één bestand" msgstr[1] "Prullenbak bevat %(num)s bestanden" msgid "Triggers" msgstr "" #, fuzzy msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Sneltoetsen (triggers) toewijzen aan objecten gemaakt met " "'Samenstellen'Opdracht' (Ctrl+Return)." msgid "Add Trigger..." msgstr "Trigger Toevoegen..." msgid "Remove Trigger" msgstr "Trigger verwijderen..." msgid "URL Actions" msgstr "URL Acties" msgid "Download and Open" msgstr "Downloaden en openen" msgid "Download To..." msgstr "Downloaden naar..." msgid "Download URL to a chosen location" msgstr "URL downloaden naar een gegeven locatie" msgid "Wikipedia" msgstr "Wikipedia" msgid "Search in Wikipedia" msgstr "Zoeken in Wikipedia" msgid "Wikipedia language" msgstr "Wikipedia taal" #. TRANS: Default wikipedia language code msgid "en" msgstr "en" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Zoeken naar deze term in %s.wikipedia.org" msgid "Window List" msgstr "Schermlijst" msgid "All windows on all workspaces" msgstr "Alle schermen op alle werkplaatsen" msgid "Activate" msgstr "Activeren" msgid "Shade" msgstr "Oprollen" msgid "Unshade" msgstr "Uitrollen" msgid "Minimize" msgstr "Minimaliseren" msgid "Unminimize" msgstr "Ontminimaliseren" msgid "Maximize" msgstr "Maximaliseren" msgid "Unmaximize" msgstr "Ontmaximaliseren" msgid "Maximize Vertically" msgstr "Verticaal maximaliseren" msgid "Unmaximize Vertically" msgstr "Verticaal ontmaximaliseren" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Scherm op %(wkspc)s" msgid "Frontmost Window" msgstr "Voorste venster" msgid "Next Window" msgstr "" msgid "Jump to this window's workspace and focus" msgstr "Naar werkplaats springen van dit scherm en focus geven" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "" msgstr[1] "" #, fuzzy msgid "Active workspace" msgstr "Naar werkplaats springen" msgid "Jump to this workspace" msgstr "Naar werkplaats springen" msgid "Workspaces" msgstr "Werkplaatsen" msgid "Volumes and Disks" msgstr "Volumes en schijven" msgid "Mounted volumes and disks" msgstr "Aangekoppelde volumes en schijven" #, python-format msgid "Volume mounted at %s" msgstr "Volume aankoppelen naar %s" msgid "Unmount" msgstr "Ontkoppelen" msgid "Unmount this volume" msgstr "Dit volume ontkoppelen" msgid "Eject" msgstr "Uitspugen" msgid "Unmount and eject this media" msgstr "Ontkoppelen en medium uitspugen" msgid "Show Text" msgstr "Tekst tonen" msgid "Display text in a window" msgstr "Tekst tonen in venster" msgid "Large Type" msgstr "Groot type" msgid "Show Notification" msgstr "Toon melding" msgid "Tracker" msgstr "Tracker" msgid "Tracker desktop search integration" msgstr "Tracker's \"doorzoek desktop\" integratie " msgid "Search in Tracker" msgstr "Zoek in Tracker" msgid "Open Tracker Search Tool and search for this term" msgstr "Tracker Search Tool openen en naar deze term zoeken" msgid "Get Tracker Results..." msgstr "Haal Tracker Resultaten" msgid "Show Tracker results for query" msgstr "Toon Tracker resultaten voor zoekopdracht" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "Resultaten voor \"%s\"" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "Bestanden opsporen" msgid "Search filesystem using locate" msgstr "Bestandssysteem doorzoeken met \"locate\"" msgid "Ignore case distinctions when searching files" msgstr "Hoofdletters negeren bij zoeken bestanden" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Firefox Favorieten" msgid "Index of Firefox bookmarks" msgstr "Index van Firefox favorieten" #, fuzzy msgid "Firefox Keywords" msgstr "Firefox Favorieten" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "Het web doorzoeken met OpenSearch zoekmotoren" msgid "Search With..." msgstr "Zoeken met..." msgid "Search For..." msgstr "Zoeken naar..." #, fuzzy msgid "Search Terms" msgstr "Zoekmotoren" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Geselecteerd bestand \"%s\"" #, fuzzy msgid "Resume playback" msgstr "Afspelen hervatten in Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Volgende" #, fuzzy msgid "Skip to next track" msgstr "Spring naar volgende nummer in Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Vorige" #, fuzzy msgid "Skip to previous track" msgstr "Spring naar vorige nummer in Audacious" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "Toegang tot Pidgin Contacten" msgid "Show offline contacts" msgstr "Toon offline kennissen" msgid "Open Chat" msgstr "Chat openen" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "" msgstr[1] "" msgid "Send Message..." msgstr "Stuur bericht..." msgid "Available" msgstr "Beschikbaar" msgid "Away" msgstr "Afwezig" msgid "Pidgin Contacts" msgstr "Pidgin Contacten" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Verkort links" msgid "Create short aliases of long URLs" msgstr "Maak korte aliases van lange URLs" msgid "Error" msgstr "Fout" msgid "Shorten With..." msgstr "Verkorten met..." msgid "Services" msgstr "" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "" "Nummers spelen en toevoegen aan speellijst en muziekbibliotheek doorzoeken" msgid "Include artists in top level" msgstr "Artiesten opnemen in eerste level" msgid "Include albums in top level" msgstr "Albums opnemen in eerste level" msgid "Play tracks in Rhythmbox" msgstr "Speel nummers in Rhythmbox" msgid "Add tracks to the play queue" msgstr "Voeg nummers toe aan speellijst" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "door %(artist)s uit %(album)s" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "door %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Nummers van %s" msgid "Albums" msgstr "Albums" msgid "Music albums in Rhythmbox Library" msgstr "Muziekalbums in Rhythmboxbibliotheek" msgid "Artists" msgstr "Artiesten" msgid "Music artists in Rhythmbox Library" msgstr "Muzikanten in Rhythmboxbibliotheek" msgid "Songs" msgstr "Liedjes" msgid "Songs in Rhythmbox library" msgstr "Liedjes in Rhythmboxbibliotheek" msgid "Getting Things GNOME" msgstr "" msgid "Browse and create new tasks in GTG" msgstr "" #, python-format msgid "due: %s" msgstr "" #, python-format msgid "start: %s" msgstr "" #, python-format msgid "tags: %s" msgstr "" msgid "Open task in Getting Things GNOME!" msgstr "" #, fuzzy msgid "Delete" msgstr "Stuur bericht..." msgid "Permanently remove this task" msgstr "" msgid "Mark Done" msgstr "" msgid "Mark this task as done" msgstr "" msgid "Dismiss" msgstr "" msgid "Mark this task as not to be done anymore" msgstr "" #, fuzzy msgid "Create Task" msgstr "Notitie maken" msgid "Create new task in Getting Things GNOME" msgstr "" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "Devhelp doorzoeken" #, fuzzy msgid "Empathy" msgstr "Gajim Contacten" #, fuzzy msgid "Access to Empathy Contacts" msgstr "Toegang tot Gajim Contacten" msgid "Busy" msgstr "Bezig" msgid "Not Available" msgstr "Niet beschikbaar" msgid "Invisible" msgstr "Onzichtbaar" msgid "Offline" msgstr "Offline" msgid "Change Global Status To..." msgstr "Algemene status veranderen naar..." #, fuzzy msgid "Empathy Contacts" msgstr "Gajim Contacten" #, fuzzy msgid "Empathy Account Status" msgstr "Gajim Account status" #. TRANS: Names of accelerators in the interface #, fuzzy msgid "Alternate Activate" msgstr "Archiveren" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) #, fuzzy msgid "Compose Command" msgstr "Opstellen e-mail" #, fuzzy msgid "Mark Default Action" msgstr "Standaardprogramma instellen..." msgid "Forget Object" msgstr "" msgid "Reset All" msgstr "" #, fuzzy msgid "Select Quit" msgstr "Geselecteerde tekst" #, fuzzy msgid "Select Selected File" msgstr "Geselecteerd bestand" #, fuzzy msgid "Select Selected Text" msgstr "Geselecteerde tekst" #, fuzzy msgid "Show Help" msgstr "Tekst tonen" #, fuzzy msgid "Show Preferences" msgstr "Kupfer Voorkeuren" msgid "Switch to First Pane" msgstr "" msgid "Toggle Text Mode" msgstr "" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Geen treffers in %(src)s voor \"%(query)s\"" msgid "No matches" msgstr "Geen treffers" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Geen treffers" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "" #. TRANS: Names of global keyboard shortcuts #, fuzzy msgid "Show Main Interface" msgstr "Toon offline kennissen" #, fuzzy msgid "Show with Selection" msgstr "Werken met programma" #. TRANS: Plugin info fields msgid "Description" msgstr "Omschrijving" msgid "Author" msgstr "Auteur" msgid "Version" msgstr "Versie" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Python module '%s' is vereist" msgid "Plugin could not be read due to an error:" msgstr "Plugin kon niet worden gelezen vanwege een fout:" msgid "Content of" msgstr "Inhoud van" #. TRANS: Plugin contents header msgid "Sources" msgstr "Bronnen" #. TRANS: Plugin contents header msgid "Actions" msgstr "Acties" #, python-format msgid "Using encrypted password storage: %s" msgstr "" #, python-format msgid "Using password storage: %s" msgstr "" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Configuratie" msgid "Set username and password" msgstr "" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Kies een map" msgid "Reset all shortcuts to default values?" msgstr "" msgid "Shortcut" msgstr "" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "vertaal-erkenning" msgid "A free software (GPLv3+) launcher" msgstr "Een gratis (GPLv3+) programmastarter" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Dit programma is gratis software; je mag het verspreiden en / of\n" "wijzigen onder voorwaarden van de GNU General Public License zoals\n" "gepubliceerd bij de Free Software Foundation, versie 3 van de License\n" "of (als je wilt) een latere versie.\n" "\n" "Dit programma is verspreid in de hoop dat het nuttig zal zijn, maar\n" "ZONDER ENIGE GARANTIE; zelfs zonder impliciete garanties van, zoals\n" "de Engelsen zeggen, MERCHANTABILITY of FITNESS FOR A PARTICULAR PURPOSE.\n" "Lees de GNU General Public License voor meer details.\n" "\n" "Je zou een kopie van de GNU General Public License samen met dit pro-\n" "gramma moeten hebben gehad. Zo niet, lees .\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "" #~ msgid "Compose Email" #~ msgstr "Opstellen e-mail" #~ msgid "Send in Email To..." #~ msgstr "In e-mail sturen naar..." #~ msgid "Type to search %s" #~ msgstr "Typ om %s te doorzoeken" #~ msgid "No action" #~ msgstr "Geen actie" #, fuzzy #~ msgid "GNOME Terminal Profiles" #~ msgstr "Gnome Terminal profielen" #, fuzzy #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Start Gnome Terminal profielen" #~ msgid "Selected Text \"%s\"" #~ msgstr "Geselecteerde tekst \"%s\"" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Bereken expressies die beginnen met '='" #~ msgid "Recent clipboards" #~ msgstr "Recente klemborden" #, fuzzy #~ msgid "Include recent selections" #~ msgstr "Levert huidige selectie" #~ msgid "Epiphany Bookmarks" #~ msgstr "Epiphany Favorieten" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Index van Epiphany favorieten" #, fuzzy #~ msgid "Include visited sites" #~ msgstr "Artiesten opnemen in eerste level" #~ msgid "" #~ "Provides current nautilus selection, using Kupfer's Nautilus Extension" #~ msgstr "Levert huidige selectie in nautilus met Kupfer's Nautilus Extension" #~ msgid "Selected File \"%s\"" #~ msgstr "Geselecteerd bestand \"%s\"" #~ msgid "Selected Files" #~ msgstr "Geselecteerd bestanden" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Afspelen hervatten in Rhythmbox" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Pauzeer afspelen in Rhythmbox" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Spring naar volgende nummer in Rhythmbox" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Spring naar vorige nummer in Rhythmbox" #~ msgid "Search the Web" #~ msgstr "Het Web doorzoeken" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Pas gebruikte documenten in Abiword" #~ msgid "Abiword Recent Items" #~ msgstr "Abiword recente items" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "Interface met pakkettenbeheerder APT" #~ msgid "Installation method" #~ msgstr "Installatiemethode" #~ msgid "Show Package Information" #~ msgstr "Pakket-informatie tonen" #~ msgid "Install" #~ msgstr "Installeren" #~ msgid "Install package using the configured method" #~ msgstr "Pakket installeren met ingestelde methode" #~ msgid "Packages matching \"%s\"" #~ msgstr "Pakketten met \"%s\"" #~ msgid "Search Package Name..." #~ msgstr "Zoek pakketnaam..." #~ msgid "Chromium Bookmarks" #~ msgstr "Chromium Favorieten" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Index van Chromium favorieten" #~ msgid "Claws Mail" #~ msgstr "Claws Mail" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Claws Mail Adressen en Acties" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Nieuwe e-mail opstellen met Claws Mail" #~ msgid "Receive All Email" #~ msgstr "Alle e-mail ophalen" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "Alle nieuwe e-mail van alle accounts ophalen met Claws Mail" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Nieuwe e-mail opstellen met Claws Mail en bestand bijvoegen" #~ msgid "Claws Mail Address Book" #~ msgstr "Claws Mail Adresboek" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Adressen uit Claws Mail Adresboek" #, fuzzy #~ msgid "Evolution contacts" #~ msgstr "Toon offline kennissen" #, fuzzy #~ msgid "Compose a new message in Evolution" #~ msgstr "Nieuwe e-mail opstellen met Claws Mail" #, fuzzy #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Nieuwe e-mail opstellen met Claws Mail en bestand bijvoegen" #, fuzzy #~ msgid "Evolution Address Book" #~ msgstr "Claws Mail Adresboek" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Toegang tot Gajim Contacten" #~ msgid "Free for Chat" #~ msgstr "Vrij om the chatten" #~ msgid "Gajim Contacts" #~ msgstr "Gajim Contacten" #~ msgid "Gajim Account Status" #~ msgstr "Gajim Account status" #, fuzzy #~ msgid "Compose Email in GMail" #~ msgstr "Opstellen e-mail" #, fuzzy #~ msgid "Google Picasa" #~ msgstr "Google Translate" #, fuzzy #~ msgid "Album created by Kupfer" #~ msgstr "Over Kupfer" #, fuzzy #~ msgid "Picasa Albums" #~ msgstr "Albums" #, fuzzy #~ msgid "Show More Results For \"%s\"" #~ msgstr "Resultaten voor \"%s\"" #~ msgid "Translate text with Google Translate" #~ msgstr "Tekst vertalen met Google Translate" #~ msgid "Error connecting to Google Translate" #~ msgstr "Fout bij verbinden met Google Translate" #~ msgid "Translate To..." #~ msgstr "Vertalen naar..." #~ msgid "Translate into %s" #~ msgstr "Vertalen naar %s" #~ msgid "Languages" #~ msgstr "Talen" #~ msgid "Show translated page in browser" #~ msgstr "Vertaalde pagina tonen in browser" #~ msgid "Show Translation To..." #~ msgstr "Vertaling tonen aan..." #~ msgid "Show translation in browser" #~ msgstr "Vertaling tonen in browser" #, fuzzy #~ msgid "%(user)s on %(service)s" #~ msgstr "[%(status)s] %(userid)s/%(service)s" #, fuzzy #~ msgid "Send Message" #~ msgstr "Stuur bericht..." #, fuzzy #~ msgid "Send Message To..." #~ msgstr "Stuur bericht..." #, fuzzy #~ msgid "Send Private Message..." #~ msgstr "Stuur bericht..." #, fuzzy #~ msgid "Retweet To..." #~ msgstr "Hernoemen als..." #, fuzzy #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Alle nieuwe e-mail van alle accounts ophalen met Claws Mail" #, fuzzy #~ msgid "Open in Browser" #~ msgstr "Map openen" #, fuzzy #~ msgid "Open message in default web browser" #~ msgstr "Openen met standaardprogramma" #, fuzzy #~ msgid "Gwibber Accounts" #~ msgstr "Gajim Account status" #, fuzzy #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Pas gebruikte documenten in OpenOffice" #, fuzzy #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "OpenOfficeRecente items" #~ msgid "Opera Bookmarks" #~ msgstr "Opera Favorieten" #~ msgid "Index of Opera bookmarks" #~ msgstr "Index van Opera favorieten" #, fuzzy #~ msgid "Opera Mail" #~ msgstr "Claws Mail" #, fuzzy #~ msgid "Opera Mail contacts and actions" #~ msgstr "Claws Mail Adressen en Acties" #, fuzzy #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Nieuwe e-mail opstellen met Claws Mail" #, fuzzy #~ msgid "Opera Mail Contacts" #~ msgstr "Gajim Contacten" #, fuzzy #~ msgid "Contacts from Opera Mail" #~ msgstr "Adressen uit Claws Mail Adresboek" #~ msgid "PuTTY Sessions" #~ msgstr "PuTTY sessies" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Snelle toegang tot PuTTY sessies" #~ msgid "Start Session" #~ msgstr "Sessie starten" #~ msgid "View as HTML Document" #~ msgstr "Bekijken als HTML-document" #~ msgid "Sudo-like Command" #~ msgstr "Sudo-achtige opdracht" #, fuzzy #~ msgid "Show QRCode" #~ msgstr "Broncode tonen" #, fuzzy #~ msgid "Display text as QRCode in a window" #~ msgstr "Tekst tonen in venster" #~ msgid "Access to Skype contacts" #~ msgstr "Toegang tot Skype Contacten" #~ msgid "Skype Me" #~ msgstr "Skype me" #~ msgid "Logged Out" #~ msgstr "Afgemeld" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Bellen" #~ msgid "Skype Contacts" #~ msgstr "Skype Contacten" #~ msgid "Skype Statuses" #~ msgstr "Skype statussen" #, fuzzy #~ msgid "Tracker 0.6" #~ msgstr "Tracker" #~ msgid "Tracker tags" #~ msgstr "Tracker tags" #~ msgid "Tracker Tags" #~ msgstr "Tracker tags" #~ msgid "Browse Tracker's tags" #~ msgstr "Tracker's tags doorzoeken" #~ msgid "Tag %s" #~ msgstr "Tag %s" #~ msgid "Objects tagged %s with Tracker" #~ msgstr "Objecten getagged %s met Tracker" #~ msgid "Add Tag..." #~ msgstr "Tag Toevoegen..." #~ msgid "Add tracker tag to file" #~ msgstr "Voeg tracker tag toe aan bestand" #~ msgid "Remove Tag..." #~ msgstr "Tag verwijderen..." #~ msgid "Remove tracker tag from file" #~ msgstr "Tracker tag van bestand verwijderen" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Volumes uit TrueCrypt geschiedenis" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "TrueCrypt volume: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Volume aankoppelen" #~ msgid "Mount in Truecrypt" #~ msgstr "Aankoppelen in TrueCrypt" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Probeer bestand als Truecrypt volume aan te koppelen" #~ msgid "Dismount All Volumes" #~ msgstr "Alle volumes ontkoppelen" #~ msgid "TrueCrypt Volumes" #~ msgstr "TrueCrypt Volumes" #~ msgid "Terminal Server Client" #~ msgstr "Terminal Server Client" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Sessie opgeslagen in Terminal Server Client" #~ msgid "TSClient sessions" #~ msgstr "TSClient sessies" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Opgeslagen sessies in Terminal Server Client" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Vinagre favorieten en acties" #~ msgid "Start Vinagre Session" #~ msgstr "Vinagre-sessie starten" #~ msgid "Vinagre Bookmarks" #~ msgstr "Vinagre Favorieten" #, fuzzy #~ msgid "Recently used documents in Vim" #~ msgstr "Pas gebruikte documenten in Abiword" #, fuzzy #~ msgid "Vim Recent Documents" #~ msgstr "Pas gebruikte documenten" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "VirtualBox Virtual Machines beheren. Ondersteunt zowel Sun Virtualboxals " #~ "de Open Source Edition." #~ msgid "Power On" #~ msgstr "Aanzetten" #~ msgid "Send Power Off Signal" #~ msgstr "Zend \"uitzetten\" signaal" #~ msgid "Reboot" #~ msgstr "Herstarten" #~ msgid "Resume" #~ msgstr "Doorgaan" #~ msgid "Save State" #~ msgstr "Status opslaan" #~ msgid "Power Off" #~ msgstr "Uitzetten" #~ msgid "VirtualBox Machines" #~ msgstr "VirtualBox Machines" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "Toegang to pagina's opgeslagen in Zim - Een Desktop-Wiki" #~ msgid "Page names start with :colon" #~ msgstr "Paginanamen beginnen met :dubbelepunt" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Zim pagina uit Notitieboek \"%s\"" #~ msgid "Create Zim Page" #~ msgstr "Zim-pagina aanmaken" #~ msgid "Create page in default notebook" #~ msgstr "Pagina in standaard notitieboek aanmaken" #~ msgid "Create Zim Page In..." #~ msgstr "Zim-pagina aanmaken in..." #~ msgid "Create Subpage..." #~ msgstr "Subpagina aanmaken..." #~ msgid "Zim Notebooks" #~ msgstr "Zim Notitieboeken" #~ msgid "Zim Pages" #~ msgstr "Zim-pagina's" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Pagina's opgeslagen in Zim Notitieboeken" #~ msgid "Directories" #~ msgstr "Mappen" #~ msgid "Interface" #~ msgstr "Uiterlijk" #~ msgid "Keybinding" #~ msgstr "Sneltoets" #~ msgid "Plugins activate after restart" #~ msgstr "Plug-ins laden na herstart" #~ msgid "To configure kupfer, edit:" #~ msgstr "Om kupfer te configureren, bewerk:" #~ msgid "The default config for reference is at:" #~ msgstr "De standaard-configuratie bevindt zich in:" #~ msgid "Applied" #~ msgstr "Toegepast" #~ msgid "Text Matches" #~ msgstr "Tekst treffers" #~ msgid "Open with %s" #~ msgstr "Openen met %s" #~ msgid "Recently used documents and nautilus places" #~ msgstr "Pas gebruikte documenten en nautilus locaties" #~ msgid "Bookmarked locations in Nautilus" #~ msgstr "Favoriete locaties in Nautilus" #~ msgid "Special items and actions for Gnome environment" #~ msgstr "Speciale items en acties voor Gnome-omgeving" #~ msgid "noun" #~ msgstr "zelfst. nw." #~ msgid "verb" #~ msgstr "werkwoord" #~ msgid "adjective" #~ msgstr "bijv. nw." #~ msgid "OpenOffice" #~ msgstr "OpenOffice" #~ msgid "Include in top level" #~ msgstr "Opnemen in eerste level" #~ msgid "" #~ "If enabled, objects from the plugin's source(s) will be available in the " #~ "top level.\n" #~ "Sources are always available as subcatalogs in the top level." #~ msgstr "" #~ "Indien geactiveerd, zullen objecten van de plug-inbronnen beschikbaar " #~ "zijn in het toplevel.\n" #~ "Bronnen zijn altijd beschikbaar als subcatalogi in het toplevel." #~ msgid "Do" #~ msgstr "Doen" #~ msgid "Compose New Mail To" #~ msgstr "Nieuwe e-mail opstallen aan" #~ msgid "Special Items" #~ msgstr "Speciale items" #~ msgid "Items and special actions" #~ msgstr "Items en speciale acties" #~ msgid "Kupfer items and actions" #~ msgstr "Kupfer items en acties" #~ msgid "(Simple) favorites plugin" #~ msgstr "(Eenvoudige) favorietenplug-in" #~ msgid "(no description)" #~ msgstr "(geen omschrijving)" #~ msgid " %(name)-20s %(version)-4s %(description)s" #~ msgstr " %(name)-20s %(version)-4s %(description)s" #~ msgid "Free-text Queries" #~ msgstr "Vrije-tekst zoekopdrachten" #~ msgid "Basic support for free-text queries" #~ msgstr "Basale ondersteuning van vrije-tekst zoekopdrachten" #~ msgid "Filesystem Text Matches" #~ msgstr "Bestandssysteem Tekst Treffers" #~ msgid "URL Text Matches" #~ msgstr "URL Tekst Treffers" #~ msgid "Searching..." #~ msgstr "Zoeken..." #~ msgid "Searching %(source)s..." #~ msgstr "Zoeken in %(source)s ..." kupfer-328/po/pl.po000066400000000000000000003466051500175051100142660ustar00rootroot00000000000000# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # Aviary.pl # Jeśli masz jakiekolwiek uwagi odnoszące się do tłumaczenia lub chcesz # pomóc w jego rozwijaniu i pielęgnowaniu, napisz do nas: # gnomepl@aviary.pl # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # Maciej Kwiatkowski , 2009. # Aviary.pl , 2011-2015. # Piotr Drąg , 2011-2023. # Karol Będkowski , 2009-2024. # msgid "" msgstr "" "Project-Id-Version: kupfer\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-04-07 19:51+0200\n" "PO-Revision-Date: 2025-04-07 19:53+0200\n" "Last-Translator: Karol Będkowski \n" "Language-Team: Polish <->\n" "Language: 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-Poedit-Language: Polish\n" "X-Poedit-Country: Poland\n" "X-Generator: Gtranslator 46.1\n" #: ../data/credentials_dialog.ui.h:1 msgid "User credentials" msgstr "Dane użytkownika" #: ../data/credentials_dialog.ui.h:2 ../data/getkey_dialog.ui.h:3 #: ../data/progress_dialog.ui.h:1 msgid "Cancel" msgstr "Anuluj" #: ../data/credentials_dialog.ui.h:3 msgid "_Change" msgstr "_Zmień" #: ../data/credentials_dialog.ui.h:4 msgid "_User:" msgstr "_Użytkownik:" #: ../data/credentials_dialog.ui.h:5 msgid "_Password:" msgstr "_Hasło:" #: ../data/getkey_dialog.ui.h:1 msgid "Set Keyboard Shortcut" msgstr "Wybór klawisza skrótu" #: ../data/getkey_dialog.ui.h:2 ../kupfer/ui/_widgets.py:211 #: ../kupfer/plugin/clipboard.py:198 msgid "Clear" msgstr "Wyczyść" #: ../data/getkey_dialog.ui.h:4 msgid "Please press desired key combination" msgstr "Proszę nacisnąć żądaną kombinację klawiszy" #: ../data/getkey_dialog.ui.h:5 msgid "Keybinding could not be bound" msgstr "Przypisanie klawisza się nie powiodło" #: ../data/getdata_dialog.ui.h:1 ../auxdata/kupfer.desktop.in.h:1 #: ../kupfer/version.py:19 ../kupfer/ui/uiutils.py:289 #: ../kupfer/plugin/core/contents.py:125 msgid "Kupfer" msgstr "Kupfer" #: ../data/preferences.ui.h:1 ../kupfer/plugin/core/contents.py:105 msgid "Kupfer Preferences" msgstr "Preferencje programu Kupfer" #: ../data/preferences.ui.h:2 msgid "Desktop Environment" msgstr "Środowisko graficzne" #: ../data/preferences.ui.h:3 msgid "Start automatically on login" msgstr "Automatycznie uruchamianie po zalogowaniu" #: ../data/preferences.ui.h:4 msgid "Show icon in notification area" msgstr "Ikona w obszarze powiadamiania" #: ../data/preferences.ui.h:5 msgid "Terminal emulator:" msgstr "Emulator terminala:" #: ../data/preferences.ui.h:6 msgid "Text editor:" msgstr "Edytor tekstu:" #: ../data/preferences.ui.h:7 msgid "Appearance" msgstr "Wygląd" #: ../data/preferences.ui.h:8 msgid "Small Icon Size:" msgstr "Rozmiar małych ikon:" #: ../data/preferences.ui.h:9 msgid "Large Icon Size:" msgstr "Rozmiar dużych ikon:" #: ../data/preferences.ui.h:10 msgid "Icon set:" msgstr "Zestaw ikon:" #: ../data/preferences.ui.h:11 msgid "" "What sort of ellipsization should be applied to text.\n" "Restart may be required." msgstr "" "Jaki sposób skracania tekstu powinien być zastosowany.\n" "Może wymagać restartu." #: ../data/preferences.ui.h:13 msgid "Text ellipsization:" msgstr "Skracanie tekstu:" #: ../data/preferences.ui.h:14 msgid "in the middle " msgstr "w środku" #: ../data/preferences.ui.h:15 msgid "at the end" msgstr "na końcu" #: ../data/preferences.ui.h:16 msgid "General" msgstr "Ogólne" #: ../data/preferences.ui.h:17 msgid "Global Keyboard Shortcuts" msgstr "Globalne skróty klawiszowe" #: ../data/preferences.ui.h:18 ../kupfer/ui/preferences.py:1241 msgid "Reset" msgstr "Przywróć" #: ../data/preferences.ui.h:19 msgid "Browser Keyboard Shortcuts" msgstr "Skróty klawiszowe przeglądarki" #: ../data/preferences.ui.h:20 msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "" "Włączenie jednoklawiszowych poleceń (spacja, /, kropka, przecinek itp.)" #: ../data/preferences.ui.h:21 msgid "Action accelerators use Alt" msgstr "Aktywacja akcji z użyciem Alt-a" #: ../data/preferences.ui.h:22 msgid "Action accelerators use Ctrl" msgstr "Aktywacja akcji z użyciem Ctrl" #: ../data/preferences.ui.h:23 msgid "Keyboard" msgstr "Klawiatura" #: ../data/preferences.ui.h:24 msgid "Plugins" msgstr "Wtyczki" #: ../data/preferences.ui.h:25 msgid "Inclusion in Top Level Searches" msgstr "Zawartość najwyższego poziomu katalogu" #: ../data/preferences.ui.h:26 msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "Obiekty zaznaczonych źródeł zostaną umieszczone na najwyższym poziomie listy " "wyszukiwania.\n" "Zawartość odznaczonych źródeł jest dostępna jedynie przez podkatalogi listy." #: ../data/preferences.ui.h:28 ../kupfer/ui/_widgets.py:54 msgid "Add" msgstr "Dodaj" #: ../data/preferences.ui.h:29 ../kupfer/ui/_widgets.py:60 msgid "Remove" msgstr "Usuń" #: ../data/preferences.ui.h:30 msgid "Indexed Folders" msgstr "Indeksowane katalogi" #: ../data/preferences.ui.h:31 msgid "Folders whose files are always available in the catalog." msgstr "" "Katalogi, których pliki będą zawsze dostępne w katalogu programu Kupfer." #: ../data/preferences.ui.h:32 ../kupfer/obj/sources.py:65 msgid "Catalog" msgstr "Katalog" #: ../data/preferences.ui.h:33 msgid "Help" msgstr "Pomoc" #: ../data/preferences.ui.h:34 ../data/result.ui.h:2 ../kupfer/obj/apps.py:357 #: ../kupfer/plugin/windows.py:89 msgid "Close" msgstr "Zamknij" #: ../data/result.ui.h:1 ../kupfer/plugin/core/__init__.py:107 msgid "Copy" msgstr "Skopiuj" #: ../auxdata/kupfer.desktop.in.h:2 msgid "Application Launcher" msgstr "Aktywator programów" #: ../auxdata/kupfer.desktop.in.h:3 msgid "Convenient command and access tool for applications and documents" msgstr "Wygodne narzędzie do uruchamiania programów i otwierania dokumentów" #: ../auxdata/kupfer-exec.desktop.in.h:1 msgid "Execute in Kupfer" msgstr "Wykonaj w programie Kupfer" #: ../auxdata/kupfer-mimetypes.xml.in.h:1 msgid "Saved Kupfer Command" msgstr "Zapisane polecenie programu Kupfer" #: ../kupfer/keyrelay.py:73 #, python-format msgid "Keyboard relay is active for display %s" msgstr "Przekazywanie klawiszy jest aktywne dla ekranu %s" #: ../kupfer/obj/sources.py:35 msgid "Catalog Index" msgstr "Indeks katalogu" #: ../kupfer/obj/sources.py:53 msgid "An index of all available sources" msgstr "Indeks wszystkich dostępnych źródeł" #: ../kupfer/obj/sources.py:80 msgid "Root catalog" msgstr "Katalog główny" #: ../kupfer/obj/special.py:32 msgid "Please Configure Plugin" msgstr "Proszę skonfigurować wtyczkę" #: ../kupfer/obj/special.py:33 #, python-format msgid "Plugin %s is not configured" msgstr "Wtyczka %s nie jest skonfigurowana" #: ../kupfer/obj/special.py:55 #, python-format msgid "Invalid user credentials for %s" msgstr "Nieprawidłowe dane użytkownika dla %s" #: ../kupfer/obj/special.py:75 #, python-format msgid "Command '%s' not available" msgstr "Polecenie „%s” jest niedostępne" #: ../kupfer/obj/grouping.py:257 #, python-format msgid "Copy %s" msgstr "Skopiuj %s" #: ../kupfer/obj/grouping.py:277 #, python-format msgid "Copy '%s' to clipboard" msgstr "Kopiuje '%s' do schowka" #: ../kupfer/obj/exceptions.py:45 #, python-format msgid "%s does not support this operation" msgstr "%s nie obsługuje tego działania" #: ../kupfer/obj/exceptions.py:52 msgid "Can not be used with multiple objects" msgstr "Nie może być użyte z wieloma obiektami" #: ../kupfer/obj/objects.py:135 msgid "(Empty Text)" msgstr "(brak tekstu)" #: ../kupfer/obj/objects.py:158 #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "(%(num)d wiersz) „%(text)s”" msgstr[1] "(%(num)d wiersze) „%(text)s”" msgstr[2] "(%(num)d wierszy) „%(text)s”" #: ../kupfer/obj/objects.py:176 msgid "Run On..." msgstr "Uruchom dla..." #: ../kupfer/obj/actions.py:29 msgid "Open Terminal Here" msgstr "Uruchom terminal w tym miejscu" #: ../kupfer/obj/actions.py:49 msgid "Open this location in a terminal" msgstr "Otwiera to położenie w terminalu" #: ../kupfer/obj/actions.py:61 msgid "Run in Terminal" msgstr "Uruchom w terminalu" #: ../kupfer/obj/actions.py:61 msgid "Run (Execute)" msgstr "Uruchom (wykonaj)" #: ../kupfer/obj/actions.py:88 msgid "Run this program in a Terminal" msgstr "Uruchamia ten program w terminalu" #: ../kupfer/obj/actions.py:90 msgid "Run this program" msgstr "Uruchamia ten program" #: ../kupfer/obj/actions.py:97 msgid "Open URL" msgstr "Otwórz adres URL" #: ../kupfer/obj/actions.py:114 msgid "Open URL with default viewer" msgstr "Otwiera adres URL za pomocą domyślnej przeglądarki" #: ../kupfer/obj/actions.py:132 msgid "Run" msgstr "Uruchom" #: ../kupfer/obj/actions.py:160 msgid "Perform command" msgstr "Wykonuje polecenie" #: ../kupfer/obj/base.py:514 ../kupfer/ui/search.py:1013 msgid "Type to search" msgstr "Pisz aby szukać" #: ../kupfer/obj/base.py:518 #, python-format msgid "%s is empty" msgstr "%s jest puste" #: ../kupfer/obj/base.py:534 ../kupfer/obj/base.py:573 #: ../kupfer/obj/base.py:576 ../kupfer/plugin/core/text.py:32 msgid "Text" msgstr "Tekst" #: ../kupfer/obj/compose.py:36 msgid "Run after Delay..." msgstr "Uruchom z opóźnieniem…" #: ../kupfer/obj/compose.py:68 msgid "Perform command after a specified time interval" msgstr "Wykonuje polecenie po podanym czasie" #: ../kupfer/obj/compose.py:140 msgid "Multiple Objects" msgstr "Wiele obiektów" #: ../kupfer/obj/compose.py:174 #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s obiekt" msgstr[1] "%s obiekty" msgstr[2] "%s obiektów" #: ../kupfer/obj/filesrc.py:120 #, python-format msgid "Directory source %s" msgstr "Źródło katalogu %s" #: ../kupfer/obj/filesrc.py:132 msgid "Home Folder" msgstr "Katalog domowy" #. TRANS: Multiple artist description "Artist1 et. al. " #: ../kupfer/obj/filesrc.py:150 ../kupfer/plugin/rhythmbox.py:359 #, python-format msgid "%s et. al." msgstr "%s i inni" #: ../kupfer/obj/filesrc.py:176 #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Rekurencyjne źródło %(dir)s, (%(levels)d poziomów)" #: ../kupfer/obj/fileactions.py:39 ../kupfer/plugin/gtg.py:155 #: ../kupfer/plugin/notes.py:177 msgid "Open" msgstr "Otwórz" #: ../kupfer/obj/fileactions.py:61 #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Brak domyślnego programu dla %(file)s (%(type)s)" #: ../kupfer/obj/fileactions.py:65 #, python-format msgid "Please use \"%s\"" msgstr "Proszę użyć „%s”" #: ../kupfer/obj/fileactions.py:65 ../kupfer/plugin/applications.py:285 msgid "Set Default Application..." msgstr "Ustaw domyślny program…" #: ../kupfer/obj/fileactions.py:106 msgid "Open with default application" msgstr "Otwiera za pomocą domyślnego programu" #: ../kupfer/obj/fileactions.py:113 msgid "Get Parent Folder" msgstr "Wybierz katalog nadrzędny" #: ../kupfer/obj/contacts.py:177 ../kupfer/plugin/pidgin.py:183 #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" #. TRANS: unknown user status #. TRANS: network device status #: ../kupfer/obj/contacts.py:179 ../kupfer/plugin/nm.py:65 msgid "unknown" msgstr "nieznany" #: ../kupfer/obj/contacts.py:198 msgid "Aim" msgstr "AIM" #: ../kupfer/obj/contacts.py:208 msgid "Google Talk" msgstr "Google Talk" #: ../kupfer/obj/contacts.py:218 msgid "ICQ" msgstr "ICQ" #: ../kupfer/obj/contacts.py:227 msgid "MSN" msgstr "MSN" #: ../kupfer/obj/contacts.py:236 msgid "QQ" msgstr "QQ" #: ../kupfer/obj/contacts.py:246 msgid "Yahoo" msgstr "Yahoo!" #: ../kupfer/obj/contacts.py:257 msgid "Skype" msgstr "Skype" #: ../kupfer/obj/apps.py:263 ../kupfer/plugin/windows.py:187 #: ../kupfer/plugin/windows.py:416 msgid "Go To" msgstr "Przejdź do" #: ../kupfer/obj/apps.py:296 msgid "Launch" msgstr "Uruchom" #: ../kupfer/obj/apps.py:323 msgid "Show application window" msgstr "Wyświetla okno programu" #: ../kupfer/obj/apps.py:325 msgid "Launch application" msgstr "Uruchamia program" #: ../kupfer/obj/apps.py:338 msgid "Launch Again" msgstr "Uruchom jeszcze raz" #: ../kupfer/obj/apps.py:349 msgid "Launch another instance of this application" msgstr "Uruchamia kolejną kopię tego programu" #: ../kupfer/obj/apps.py:378 msgid "Attempt to close all application windows" msgstr "Próbuje zamknąć wszystkie okna programu" #: ../kupfer/plugin_support.py:192 msgid "No D-Bus connection to desktop session" msgstr "Brak połączenia usługi D-Bus do sesji pulpitu" #: ../kupfer/plugin_support.py:210 #, python-format msgid "Dependency '%s' is not available" msgstr "Wymagana biblioteka „%s” jest niedostępna" #: ../kupfer/plugin_support.py:353 #, python-format msgid "Command %(msg)s is not available." msgid_plural "Commands %(msg)s are not available." msgstr[0] "Polecenie %(msg)s jest niedostępne" msgstr[1] "Polecenia %(msg)s są niedostępne" msgstr[2] "Polecenia %(msg)s są niedostępne" #: ../kupfer/plugin_support.py:368 #, python-format msgid "None of commands %(msg)s is available." msgstr "Żadne z poleceń %(msg)s nie jest niedostępne" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language #: ../kupfer/version.py:81 msgid "translator-credits" msgstr "" "Maciej Kwiatkowski , 2009\n" "Karol Będkowski , 2009-2011\n" "Piotr Drąg , 2011-2015\n" "Aviary.pl , 2011-2015" #: ../kupfer/version.py:86 msgid "A free software (GPLv3+) launcher" msgstr "Aktywator programów na wolnej licencji (GPLv3+)" #: ../kupfer/version.py:90 msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Niniejszy program jest wolnym oprogramowaniem; można go rozprowadzać dalej\n" "i/lub modyfikować na warunkach Powszechnej Licencji Publicznej GNU, wydanej\n" "przez Fundację Wolnego Oprogramowania (Free Software Foundation) — według\n" "wersji trzeciej tej Licencji lub którejś z późniejszych wersji.\n" "\n" "Niniejszy program rozpowszechniany jest z nadzieją, iż będzie on użyteczny\n" "— jednak BEZ JAKIEJKOLWIEK GWARANCJI, nawet domyślnej gwarancji\n" "PRZYDATNOŚCI HANDLOWEJ albo PRZYDATNOŚCI DO OKREŚLONYCH ZASTOSOWAŃ. W celu\n" "uzyskania bliższych informacji należy zapoznać się z Powszechną Licencją\n" "Publiczną GNU.\n" "\n" "Z pewnością wraz z niniejszym programem dostarczono także egzemplarz\n" "Powszechnej Licencji Publicznej GNU (GNU General Public License); jeśli nie\n" "— proszę odwiedzić stronę internetową .\n" #. follows strings used elsewhere #: ../kupfer/version.py:108 msgid "Could not find running Kupfer" msgstr "Nie można odnaleźć uruchomionego programu Kupfer" #: ../kupfer/main.py:59 msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Użycie: kupfer [ OPCJE | PLIK… ]" #. require setup path and locales #. pylint: disable=import-outside-toplevel #: ../kupfer/main.py:73 msgid "Available plugins:" msgstr "Dostępne wtyczki:" #: ../kupfer/main.py:82 msgid "do not present main interface on launch" msgstr "bez wyświetlania głównego okna po uruchomieniu" #: ../kupfer/main.py:83 msgid "list available plugins" msgstr "wyświetla listę dostępnych wtyczek" #: ../kupfer/main.py:84 msgid "enable debug info" msgstr "włącza informacje debugowania" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer #: ../kupfer/main.py:87 msgid "run plugin helper" msgstr "uruchamia program pomocniczy wtyczek" #: ../kupfer/main.py:88 msgid "do not use colored text in terminal" msgstr "nie używa kolorowego tekstu na terminalu" #: ../kupfer/main.py:91 msgid "show usage help" msgstr "wyświetla ekran pomocy" #: ../kupfer/main.py:92 msgid "show version information" msgstr "wyświetla informację o wersji" #: ../kupfer/main.py:151 #, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" #: ../kupfer/ui/preferences.py:111 #, python-format msgid "Using encrypted password storage: %s" msgstr "Używanie zaszyfrowanego przechowywania haseł: %s" #: ../kupfer/ui/preferences.py:114 #, python-format msgid "Using password storage: %s" msgstr "Używanie przechowywania haseł: %s" #: ../kupfer/ui/preferences.py:337 ../kupfer/plugin/custom_terminal.py:21 msgid "Command" msgstr "Polecenie" #: ../kupfer/ui/preferences.py:337 msgid "Shortcut" msgstr "Skrót klawiszowy" #. TRANS: Names of global keyboard shortcuts #: ../kupfer/ui/preferences.py:566 ../kupfer/ui/browser.py:286 msgid "Show Main Interface" msgstr "Wyświetlanie głównego interfejsu" #: ../kupfer/ui/preferences.py:567 msgid "Show with Selection" msgstr "Wyświetlanie zaznaczenia" #. TRANS: Plugin contents header #: ../kupfer/ui/preferences.py:860 msgid "Sources" msgstr "Źródła" #. TRANS: Plugin contents header #: ../kupfer/ui/preferences.py:866 msgid "Actions" msgstr "Działania" #: ../kupfer/ui/preferences.py:886 msgid "Configuration" msgstr "Konfiguracja" #: ../kupfer/ui/preferences.py:895 msgid "Set username and password" msgstr "Proszę ustawić nazwę użytkownika i hasło" #: ../kupfer/ui/preferences.py:954 ../kupfer/ui/_widgets.py:138 #: ../kupfer/ui/_widgets.py:249 msgid "Choose a Directory" msgstr "Wybór katalog" #: ../kupfer/ui/preferences.py:1237 msgid "Reset all shortcuts to default values?" msgstr "Przywrócić wszystkie skróty klawiszowe do ich domyślnych wartości?" #: ../kupfer/ui/interface.py:787 #, python-format msgid "Assign Accelerator to \"%(action)s\"" msgstr "Przypis wywołanie dla \"%(action)s\"" #: ../kupfer/ui/interface.py:793 #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Zaznaczenie „%(action)s” jako domyśle dla „%(object)s”" #: ../kupfer/ui/interface.py:804 #, python-format msgid "Forget About \"%s\"" msgstr "Zapomnij o „%s”" #. TRANS: Names of accelerators in the interface #: ../kupfer/ui/accelerators.py:9 msgid "Alternate Activate" msgstr "Alternatywna aktywacja" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action #: ../kupfer/ui/accelerators.py:12 msgid "Comma Trick" msgstr "Sztuczka z przecinkiem" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) #: ../kupfer/ui/accelerators.py:15 msgid "Compose Command" msgstr "Polecenie komponowania" #: ../kupfer/ui/accelerators.py:16 msgid "Mark Default Action" msgstr "Oznaczenie domyślnego działania" #: ../kupfer/ui/accelerators.py:17 msgid "Forget Object" msgstr "Zapomnienie o obiekcie" #: ../kupfer/ui/accelerators.py:18 msgid "Reset All" msgstr "Przywrócenie wszystkiego" #: ../kupfer/ui/accelerators.py:19 msgid "Select Quit" msgstr "Przejście do „Zakończ”" #: ../kupfer/ui/accelerators.py:20 msgid "Select Selected File" msgstr "Przejście do zaznaczonego pliku" #: ../kupfer/ui/accelerators.py:21 msgid "Select Selected Text" msgstr "Przejście do zaznaczonego tekstu" #: ../kupfer/ui/accelerators.py:22 msgid "Select Clipboard File" msgstr "Wybierz plik w schowku" #: ../kupfer/ui/accelerators.py:23 msgid "Select Clipboard Text" msgstr "Wybierz tekst w schowku" #: ../kupfer/ui/accelerators.py:24 msgid "Show Help" msgstr "Wyświetlenie pomocy" #: ../kupfer/ui/accelerators.py:25 msgid "Show Preferences" msgstr "Wyświetlenie preferencji" #: ../kupfer/ui/accelerators.py:26 msgid "Switch to 1st Pane" msgstr "Przejście do pierwszego panelu" #: ../kupfer/ui/accelerators.py:27 msgid "Switch to 2nd Pane" msgstr "Przejście do drugiego panelu" #: ../kupfer/ui/accelerators.py:28 msgid "Switch to 3rd Pane" msgstr "Przejście do trzeciego panelu" #: ../kupfer/ui/accelerators.py:29 msgid "Toggle Text Mode" msgstr "Przełączenie trybu tekstowego" #: ../kupfer/ui/search.py:995 #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Brak wyników w %(src)s dla „%(query)s”" #: ../kupfer/ui/search.py:1003 msgid "No matches" msgstr "Brak wyników" #: ../kupfer/ui/search.py:1096 #, python-format msgid "No action matches \"%s\"" msgstr "Brak wyników dla \"%s\"" #: ../kupfer/ui/_widgets.py:206 msgid "Select" msgstr "Wybierz" #: ../kupfer/ui/_widgets.py:252 msgid "Choose a File" msgstr "Wybór pliku" #: ../kupfer/ui/_widgets.py:346 msgid "Content of" msgstr "Zawartość" #: ../kupfer/ui/_widgets.py:373 msgid "Description" msgstr "Opis" #: ../kupfer/ui/_widgets.py:374 msgid "Author" msgstr "Autor" #: ../kupfer/ui/_widgets.py:375 msgid "Version" msgstr "Wersja" #: ../kupfer/ui/_widgets.py:389 msgid "Plugin could not be read due to an error:" msgstr "Wtyczka nie może zostać odczytana z powodu błędu:" #: ../kupfer/ui/_widgets.py:397 msgid "Plugin is disabled" msgstr "Wtyczka jest wyłączona" #. TRANS: Error message when Plugin needs a Python module to load #: ../kupfer/ui/_widgets.py:437 #, python-format msgid "Python module '%s' is needed" msgstr "Wymagany jest moduł języka Python „%s”" #: ../kupfer/core/execfile.py:43 #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Brak uprawień do uruchomienia „%s” (plik nie jest wykonywalny)" #: ../kupfer/core/execfile.py:65 #, python-format msgid "Command in \"%s\" is not available" msgstr "Polecenie w „%s” jest niedostępne" #: ../kupfer/core/commandexec.py:269 #, python-format msgid "Could not to carry out '%s'" msgstr "Nie można wykonać „%s”" #: ../kupfer/core/commandexec.py:330 #, python-format msgid "\"%s\" produced a result" msgstr "„%s” zwróciło wynik" #: ../kupfer/plugin/show_qrcode.py:5 ../kupfer/plugin/show_qrcode.py:48 #: ../kupfer/plugin/show_qrcode.py:62 ../kupfer/plugin/show_qrcode.py:120 #: ../kupfer/plugin/show_qrcode.py:170 msgid "Show QRCode" msgstr "Wyświetl QRCode" #: ../kupfer/plugin/show_qrcode.py:7 ../kupfer/plugin/show_qrcode.py:93 msgid "Display text as QRCode in a window" msgstr "Wyświetla tekst jako QRCode w oknie" #: ../kupfer/plugin/show_qrcode.py:34 msgid "Max QRCode size (pixels)" msgstr "Maks. rozmiar QRCode (piksele)" #: ../kupfer/plugin/show_qrcode.py:62 ../kupfer/plugin/show_qrcode.py:120 #: ../kupfer/plugin/show_qrcode.py:170 #, python-format msgid "Cannot create QRCode: %s" msgstr "Nie można utworzyć QRCode: %s" #: ../kupfer/plugin/show_qrcode.py:105 msgid "Create QRCode image" msgstr "Utwórz obraz z QRCode" #: ../kupfer/plugin/show_qrcode.py:138 msgid "Create PNG file with QRCode" msgstr "Utwórz plik PNG z QRCode" #: ../kupfer/plugin/show_qrcode.py:152 msgid "Create QRCode text" msgstr "Utwórz QRCode jako tekst" #: ../kupfer/plugin/show_qrcode.py:187 msgid "Create QRCode as text with unicode characters" msgstr "Utwórz QRCode jako tekst ze znakami unicode" #: ../kupfer/plugin/shorten_links.py:1 msgid "Shorten Links" msgstr "Skróć linki" #: ../kupfer/plugin/shorten_links.py:3 msgid "Create short aliases of long URLs" msgstr "Tworzenie skrótów do długich adresów URL" #: ../kupfer/plugin/shorten_links.py:52 msgid "Error" msgstr "Błąd" #: ../kupfer/plugin/shorten_links.py:88 msgid "Shorten With..." msgstr "Skróć za pomocą…" #: ../kupfer/plugin/shorten_links.py:121 msgid "Services" msgstr "Usługi" #: ../kupfer/plugin/applications.py:3 ../kupfer/plugin/applications.py:123 #: ../kupfer/plugin/applications.py:316 msgid "Applications" msgstr "Programy" #: ../kupfer/plugin/applications.py:13 ../kupfer/plugin/applications.py:161 msgid "All applications and preferences" msgstr "Wszystkie programy i preferencje" #: ../kupfer/plugin/applications.py:51 msgid "Applications for Desktop Environment" msgstr "Programy środowiska graficznego" #: ../kupfer/plugin/applications.py:58 msgid "Use Desktop Filter" msgstr "Filtruj aplikacje typu Desktop" #: ../kupfer/plugin/applications.py:64 msgid "Load extra aliases" msgstr "Wczytaj dodatkowe aliasy" #: ../kupfer/plugin/applications.py:68 msgid "" "Load additional aliases like keywords or other names. This may slowdown " "searching. Change this setting may require reload." msgstr "" "Wczytywanie dodatkowych aliasów jak słowa kluczowe i inne nazwy. Może to " "spowolnić wyszukiwanie. Zmiana tego ustawienia może wymagać przeładowania." #: ../kupfer/plugin/applications.py:174 msgid "Open With Any Application..." msgstr "Otwiera za pomocą dowolnego programu..." #: ../kupfer/plugin/applications.py:215 msgid "Open with any application" msgstr "Otwiera za pomocą innego programu" #: ../kupfer/plugin/applications.py:223 msgid "Open With..." msgstr "Otwórz za pomocą…" #: ../kupfer/plugin/applications.py:280 msgid "Open with application supporting this file type" msgstr "Otwórz w programie wspierający ten typu plików" #: ../kupfer/plugin/applications.py:311 msgid "Set default application to open this file type" msgstr "Ustawia domyślny program dla tego typu plików" #: ../kupfer/plugin/applications.py:360 #, python-format msgid "Applications supporting %s" msgstr "Programy wspierające %s" #: ../kupfer/plugin/applications.py:381 msgid "Reset Associations" msgstr "Resetuj przypisanie" #: ../kupfer/plugin/applications.py:391 msgid "Reset program associations for files of this type." msgstr "Resetuj przypisany program dla plików tego typu" #: ../kupfer/plugin/applications.py:395 msgid "Start Application Here..." msgstr "Uruchom program tutaj…" #: ../kupfer/plugin/applications.py:412 msgid "Launch application in this location" msgstr "Uruchamia program w tej lokalizacji" #: ../kupfer/plugin/applications.py:462 msgid "Application actions..." msgstr "Akcje programu..." #: ../kupfer/plugin/applications.py:490 msgid "Extra actions for application" msgstr "Dodatkowe akcje dla programu" #: ../kupfer/plugin/urlactions.py:3 ../kupfer/plugin/urlactions.py:7 msgid "URL Actions" msgstr "Działania adresów URL" #: ../kupfer/plugin/urlactions.py:102 msgid "Download and Open" msgstr "Pobierz i otwórz" #: ../kupfer/plugin/urlactions.py:129 msgid "Download To..." msgstr "Pobierz do…" #: ../kupfer/plugin/urlactions.py:160 msgid "Download URL to a chosen location" msgstr "Pobiera adres URL do wybranego położenia" #: ../kupfer/plugin/screenshot.py:3 msgid "Screenshot" msgstr "Zrzut ekranu" #: ../kupfer/plugin/screenshot.py:7 msgid "Take screenshot of screen using Scrot or Flameshot." msgstr "Wykonuje zrzut ekranu z użyciem Scrot lub Flameshot." #: ../kupfer/plugin/screenshot.py:29 msgid "Tool:" msgstr "Narzędzie:" #: ../kupfer/plugin/screenshot.py:39 msgid "Format:" msgstr "Format:" #: ../kupfer/plugin/screenshot.py:61 msgid "Take Screenshot To File" msgstr "Wykonaj zrzut ekranu do pliku" #: ../kupfer/plugin/screenshot.py:117 ../kupfer/plugin/screenshot.py:144 msgid "Take Screenshot to the Clipboard" msgstr "Wykonaj zrzut ekranu do schowka" #: ../kupfer/plugin/screenshot.py:180 msgid "Screenshot tools" msgstr "Narzędzia do zrzutu ekranu" #: ../kupfer/plugin/clawsmail.py:1 msgid "Claws Mail" msgstr "Claws Mail" #: ../kupfer/plugin/clawsmail.py:4 msgid "Claws Mail Contacts and Actions" msgstr "Kontakty i działania programu Claws Mail" #: ../kupfer/plugin/clawsmail.py:31 ../kupfer/plugin/thunderbird.py:40 msgid "Compose New Email" msgstr "Napisz nową wiadomość e-mail" #: ../kupfer/plugin/clawsmail.py:37 msgid "Compose a new message in Claws Mail" msgstr "Tworzy nową wiadomość w programie Claws Mail" #: ../kupfer/plugin/clawsmail.py:47 msgid "Receive All Email" msgstr "Pobierz wszystkie wiadomości" #: ../kupfer/plugin/clawsmail.py:53 msgid "Receive new messages from all accounts in ClawsMail" msgstr "Pobiera wiadomości ze wszystkich kont programu Claws Mail" #: ../kupfer/plugin/clawsmail.py:63 msgid "Compose Email" msgstr "Utwórz wiadomość e-mail" #: ../kupfer/plugin/clawsmail.py:89 msgid "Send in Email To..." msgstr "Wyślij w wiadomości e-mail do…" #: ../kupfer/plugin/clawsmail.py:121 msgid "Compose new message in Claws Mail and attach file" msgstr "Tworzy nową wiadomość w programie Claws Mail i załącza plik" #: ../kupfer/plugin/clawsmail.py:133 msgid "Claws Mail Address Book" msgstr "Książka adresowa programu Claws Mail" #: ../kupfer/plugin/clawsmail.py:193 msgid "Contacts from Claws Mail Address Book" msgstr "Kontakty z książki adresowej programu Claws Mail" #: ../kupfer/plugin/session_gnome.py:7 ../kupfer/plugin/session_gnome.py:40 msgid "GNOME Session Management" msgstr "Menedżer sesji GNOME" #: ../kupfer/plugin/session_gnome.py:9 msgid "Special items and actions for GNOME environment" msgstr "Specjalne elementy i działania dla środowiska GNOME" #: ../kupfer/plugin/vim.py:7 msgid "Vim" msgstr "Vim" #: ../kupfer/plugin/vim.py:9 msgid "Load recent files edited in VIM/GVIM" msgstr "Załaduj ostatnie pliki edytowane w VIM/GVIM" #: ../kupfer/plugin/vim.py:35 msgid "VimWiki directories:" msgstr "Katalogi VimWiki:" #: ../kupfer/plugin/vim.py:42 msgid "Max recent documents:" msgstr "Maksymalna liczba ostatnich dokumentów:" #: ../kupfer/plugin/vim.py:74 msgid "Vim Recent Documents" msgstr "Ostatnie dokumenty Vim" #: ../kupfer/plugin/vim.py:136 #, python-format msgid "VimWiki in %s" msgstr "VimWiki w %s" #: ../kupfer/plugin/vim.py:141 msgid "VimWiki Wikis" msgstr "Wiki VimWiki" #: ../kupfer/plugin/vim.py:235 msgid "Open in Vim" msgstr "Otwórz w Vim" #: ../kupfer/plugin/textfiles.py:10 msgid "Textfiles" msgstr "Pliki tekstowe" #: ../kupfer/plugin/textfiles.py:18 msgid "Action for text files" msgstr "Akcje dla plików tekstowych" #: ../kupfer/plugin/textfiles.py:36 msgid "Append To..." msgstr "Dopisz do…" #: ../kupfer/plugin/textfiles.py:66 ../kupfer/plugin/notes.py:277 msgid "Append..." msgstr "Dopisz…" #: ../kupfer/plugin/textfiles.py:71 msgid "Write To..." msgstr "Zapisz do…" #: ../kupfer/plugin/textfiles.py:83 ../kupfer/plugin/templates.py:44 msgid "Empty File" msgstr "Pusty plik" #: ../kupfer/plugin/textfiles.py:130 msgid "Write the text to a new file in specified directory" msgstr "Zapisz tekst do nowego pliku w wybranym katalogu" #: ../kupfer/plugin/textfiles.py:138 msgid "Get Text Contents" msgstr "Pobiera zawartość pliku tekstowego" #: ../kupfer/plugin/textfiles.py:161 msgid "Copy content" msgstr "Skopiuj zawartość" #: ../kupfer/plugin/textfiles.py:203 msgid "Copy file content to clipboard" msgstr "Kopiuje zawartość pliku do schowka" #: ../kupfer/plugin/aria2.py:3 msgid "Aria2" msgstr "Aria2" #: ../kupfer/plugin/aria2.py:7 msgid "Download files using remote instance of Aria2" msgstr "Pobierz pliki z użyciem zdalnej instancji Aria2" #: ../kupfer/plugin/aria2.py:27 msgid "Aria2 URL" msgstr "URL Aria2" #: ../kupfer/plugin/aria2.py:31 msgid "Base URL for remote Aria2 instance ie. http://localhost:6800/" msgstr "Bazowy URL dla zdalnej instancji Aria (np. http://localhost:6800/)" #: ../kupfer/plugin/aria2.py:36 msgid "Secret token" msgstr "Sekretny token" #: ../kupfer/plugin/aria2.py:40 msgid "" "Enter the Aria2 RPC secret token (leave empty if authentication is not " "enabled) " msgstr "" "Wprowadź sekretny token dla RPC Aria2 (pozostaw pusty, jeżeli " "uwierzytelnianie nie jest włączone)" #: ../kupfer/plugin/aria2.py:51 msgid "Remote Download" msgstr "Zdalne pobieranie" #. noqa:PLR2004 #: ../kupfer/plugin/aria2.py:78 msgid "Download started" msgstr "Pobieranie rozpoczęte" #: ../kupfer/plugin/aria2.py:92 msgid "Download using remote instance of Aria2" msgstr "Pobieranie z użyciem zdalnej instancji Aria2" #: ../kupfer/plugin/websearch.py:3 msgid "Search the Web" msgstr "Wyszukiwanie w sieci WWW" #: ../kupfer/plugin/websearch.py:12 msgid "Search the web with OpenSearch and user defined search engines" msgstr "" "Wyszukiwanie w sieci za pomocą wyszukiwarek OpenSearch oraz zdefiniowanych " "przez użytkownika" #: ../kupfer/plugin/websearch.py:38 msgid "User search engines:" msgstr "Wyszukiwarki użytkownika:" #: ../kupfer/plugin/websearch.py:44 #, python-format msgid "Define URLs for search engines; '%s' is replaced by search term." msgstr "URL-e wyszukiwarek; \"%s\" jest zastępowany przez szukane wyrażenie." #: ../kupfer/plugin/websearch.py:50 msgid "Default search engine:" msgstr "Domyśnla wyszukiwarka:" #: ../kupfer/plugin/websearch.py:54 #, python-format msgid "" "Define URL for default search engine; '%s' is replaced by search term. If " "empty, use first engine from 'User search engines' or DuckDuckGo" msgstr "" "Definicja URL-i wyszukiwarek; \"%s\" jest zastępowany przez szukane " "wyrażenie. Jeżeli puste, używany jest pierwszy wpis z \"Wyszukiwarek " "użytkownika\" lub DuckDuckGo" #: ../kupfer/plugin/websearch.py:107 msgid "Search..." msgstr "Znajdź..." #: ../kupfer/plugin/websearch.py:121 msgid "Search the web with default search engines" msgstr "Wyszukiwanie w sieci za domyslnej wyszukiwarki" #: ../kupfer/plugin/websearch.py:131 ../kupfer/plugin/firefox_keywords.py:139 msgid "Search With..." msgstr "Znajdź za pomocą…" #: ../kupfer/plugin/websearch.py:151 ../kupfer/plugin/websearch.py:184 msgid "Search the web with OpenSearch search engines" msgstr "Wyszukiwanie w sieci za pomocą wyszukiwarek OpenSearch" #: ../kupfer/plugin/websearch.py:166 ../kupfer/plugin/zeal.py:195 #: ../kupfer/plugin/firefox_keywords.py:177 msgid "Search For..." msgstr "Znajdź…" #: ../kupfer/plugin/websearch.py:292 msgid "Search Engines" msgstr "Wyszukiwarki" #: ../kupfer/plugin/screen.py:1 msgid "GNU Screen" msgstr "GNU Screen" #: ../kupfer/plugin/screen.py:3 ../kupfer/plugin/screen.py:113 msgid "Active GNU Screen sessions" msgstr "Aktywuj sesje GNU Screen" #: ../kupfer/plugin/screen.py:65 ../kupfer/plugin/tmux.py:48 msgid "Attached" msgstr "Podłączone" #: ../kupfer/plugin/screen.py:67 ../kupfer/plugin/tmux.py:48 msgid "Detached" msgstr "Odłączone" #: ../kupfer/plugin/screen.py:69 #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "Sesja %(status)s (%(pid)s) utworzona %(time)s" #: ../kupfer/plugin/screen.py:87 msgid "Screen Sessions" msgstr "Sesje programu Screen" #: ../kupfer/plugin/screen.py:124 ../kupfer/plugin/tmux.py:116 msgid "Attach" msgstr "Podłącz" #: ../kupfer/plugin/pidgin.py:3 msgid "Pidgin" msgstr "Pidgin" #: ../kupfer/plugin/pidgin.py:6 msgid "Access to Pidgin Contacts" msgstr "Dostęp do kontaktów programu Pidgin" #: ../kupfer/plugin/pidgin.py:31 msgid "Show offline contacts" msgstr "Wyświetlanie kontaktów offline" #: ../kupfer/plugin/pidgin.py:110 msgid "Open Chat" msgstr "Rozpocznij rozmowę" #: ../kupfer/plugin/pidgin.py:127 #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d znak)" msgstr[1] "%s (%d znaki)" msgstr[2] "%s (%d znaków)" #: ../kupfer/plugin/pidgin.py:139 msgid "Send Message..." msgstr "Wyślij wiadomość…" #: ../kupfer/plugin/pidgin.py:184 msgid "Available" msgstr "Dostępny" #: ../kupfer/plugin/pidgin.py:184 msgid "Away" msgstr "Zaraz wracam" #: ../kupfer/plugin/pidgin.py:221 msgid "Pidgin Contacts" msgstr "Kontakty programu Pidgin" #: ../kupfer/plugin/gtg.py:7 ../kupfer/plugin/gtg.py:75 msgid "Getting Things GNOME" msgstr "Getting Things GNOME" #: ../kupfer/plugin/gtg.py:10 msgid "Browse and create new tasks in GTG" msgstr "Przeglądanie i tworzenie nowych zadań w programie GTG" #: ../kupfer/plugin/gtg.py:124 #, python-format msgid "due: %s" msgstr "do: %s" #: ../kupfer/plugin/gtg.py:127 #, python-format msgid "start: %s" msgstr "początek: %s" #: ../kupfer/plugin/gtg.py:130 #, python-format msgid "tags: %s" msgstr "etykiety: %s" #: ../kupfer/plugin/gtg.py:165 msgid "Open task in Getting Things GNOME!" msgstr "Otwiera zadanie w programie Getting Things GNOME" #: ../kupfer/plugin/gtg.py:172 msgid "Delete" msgstr "Usuń" #: ../kupfer/plugin/gtg.py:182 msgid "Permanently remove this task" msgstr "Trwale usuwa to zadanie" #: ../kupfer/plugin/gtg.py:189 msgid "Mark Done" msgstr "Wykonane" #: ../kupfer/plugin/gtg.py:198 msgid "Mark this task as done" msgstr "Oznacza zadanie jako wykonane" #: ../kupfer/plugin/gtg.py:205 msgid "Dismiss" msgstr "Pomiń" #: ../kupfer/plugin/gtg.py:214 msgid "Mark this task as not to be done anymore" msgstr "Oznacza zadanie jako zadanie do pominięcia" #: ../kupfer/plugin/gtg.py:219 ../kupfer/plugin/gtg.py:238 msgid "Create Task" msgstr "Utwórz zadanie" #: ../kupfer/plugin/gtg.py:233 ../kupfer/plugin/gtg.py:254 msgid "Create new task in Getting Things GNOME" msgstr "Tworzy nowe zadanie w programie Getting Things GNOME" #: ../kupfer/plugin/session_lxqt.py:1 ../kupfer/plugin/session_lxqt.py:24 msgid "LXQT Session Management" msgstr "Menedżer sesji LXQT" #: ../kupfer/plugin/session_lxqt.py:3 msgid "Actions for LXQT desktop" msgstr "Akcje dla środowiska LXQT" #: ../kupfer/plugin/zeal.py:7 ../kupfer/plugin/zeal.py:34 msgid "Zeal Search" msgstr "Wyszukiwanie w Zeal" #: ../kupfer/plugin/zeal.py:11 msgid "Search in Zeal, offline documentation browser for software developers." msgstr "Wyszukiwanie w Zeal, offlinowej dokumentacji dla deweloperów" #: ../kupfer/plugin/zeal.py:40 msgid "Search in Zeal" msgstr "Wyszukiwanie w programie Zeal" #: ../kupfer/plugin/zeal.py:60 msgid "Zeal Docsets" msgstr "Dokumentacje Zeal" #: ../kupfer/plugin/zeal.py:127 #, python-format msgid "Zeal %s Docset" msgstr "Dokumentacja %s w Zeal" #: ../kupfer/plugin/zeal.py:158 msgid "Search In Zeal docset..." msgstr "Wyszukaj w dokumentacjach Zeal..." #: ../kupfer/plugin/zeal.py:179 ../kupfer/plugin/zeal.py:213 msgid "Search in Zeal docsets" msgstr "Znajdź w dokumentacjach Zeal" #: ../kupfer/plugin/archiveinside.py:10 msgid "Deep Archives" msgstr "Przeglądane archiwów" #: ../kupfer/plugin/archiveinside.py:12 msgid "Allow browsing inside compressed archive files" msgstr "Dostęp do zawartości skompresowanych archiwów" #: ../kupfer/plugin/archiveinside.py:65 #, python-format msgid "Content of %s" msgstr "Zawartość %s" #: ../kupfer/plugin/tmux.py:8 msgid "Tmux / Tmuxp" msgstr "Tmux / Tmuxp" #: ../kupfer/plugin/tmux.py:10 msgid "Manage tmux and tmuxp sessions" msgstr "Zarządzaj sesjami tmux i tmuxp" #: ../kupfer/plugin/tmux.py:47 #, python-format msgid "%(status)s tmux session, created %(time)s" msgstr "%(status)s sesja tmux, utworzona %(time)s" #: ../kupfer/plugin/tmux.py:95 msgid "tmux Sessions" msgstr "Sesje tmux" #: ../kupfer/plugin/tmux.py:105 msgid "Active tmux sessions" msgstr "Aktywne sesje tmux" #: ../kupfer/plugin/tmux.py:133 msgid "tmuxp saved session" msgstr "Zapisane sesje tmuxp" #: ../kupfer/plugin/tmux.py:141 msgid "Start session" msgstr "Uruchom sesję" #: ../kupfer/plugin/tmux.py:156 msgid "tmuxp Workspaces" msgstr "Obszary robocze tmuxp" #: ../kupfer/plugin/tmux.py:175 msgid "Configured tmuxp workspaces" msgstr "Skonfigurowane obszary robocze tmuxp" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. #: ../kupfer/plugin/glob.py:2 ../kupfer/plugin/glob.py:21 msgid "Glob" msgstr "Wyrażenie regularne" #: ../kupfer/plugin/glob.py:4 msgid "Select objects using '*' and '?' as wildcards." msgstr "Wybór obiektów z użyciem '*' i '?' jako znaków wieloznacznych" #: ../kupfer/plugin/commands.py:1 ../kupfer/plugin/commands.py:217 msgid "Shell Commands" msgstr "Polecenia powłoki" #: ../kupfer/plugin/commands.py:7 #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Uruchamianie programów wiersza poleceń. Działania oznaczone symbolem %s " "uruchamiane są w podpowłoce." #: ../kupfer/plugin/commands.py:49 msgid "Run (Get Output)" msgstr "Uruchom (pobierz wynik)" #: ../kupfer/plugin/commands.py:69 msgid "Run program and return its output" msgstr "Uruchamia program i zwraca jego wynik" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command #: ../kupfer/plugin/commands.py:76 msgid "Pass to Command..." msgstr "Przekaż do polecenia…" #: ../kupfer/plugin/commands.py:122 msgid "Run program with object as an additional parameter" msgstr "Uruchomia program z obiektem jako dodatkowym parametrem" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin #: ../kupfer/plugin/commands.py:131 msgid "Write to Command..." msgstr "Zapisz do polecenia…" #: ../kupfer/plugin/commands.py:171 ../kupfer/plugin/commands.py:185 msgid "Run program and supply text on the standard input" msgstr "Uruchamia program i przesyła tekst do standardowego wejścia" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. #: ../kupfer/plugin/commands.py:180 msgid "Filter through Command..." msgstr "Filtruj przez polecenie…" #: ../kupfer/plugin/commands.py:249 msgid "Run command-line programs" msgstr "Uruchamia programy wiersza poleceń" #: ../kupfer/plugin/duckduckgo.py:5 ../kupfer/plugin/duckduckgo.py:24 msgid "DuckDuckGo Search" msgstr "Wyszukiwanie w serwisie DuckDuckGo" #: ../kupfer/plugin/duckduckgo.py:8 ../kupfer/plugin/duckduckgo.py:37 msgid "Search the web securely with DuckDuckGo" msgstr "Bezpieczne wyszukiwanie w sieci za pomocą serwisu DuckDuckGo" #: ../kupfer/plugin/audacious.py:3 ../kupfer/plugin/audacious.py:413 msgid "Audacious" msgstr "Audacious" #: ../kupfer/plugin/audacious.py:5 msgid "Control Audacious playback and playlist" msgstr "Kontrolowanie odtwarzania i list odtwarzania Audacious" #: ../kupfer/plugin/audacious.py:38 ../kupfer/plugin/rhythmbox.py:70 msgid "Include songs in top level" msgstr "Wyświetlanie utworów na najwyższym poziomie listy" #: ../kupfer/plugin/audacious.py:115 #, python-format msgid "Position: %(pos)d / %(total)d" msgstr "Pozycja: %(pos)d / %(total)d" #: ../kupfer/plugin/audacious.py:150 ../kupfer/plugin/rhythmbox.py:219 msgid "Enqueue" msgstr "Dodaj do kolejki" #: ../kupfer/plugin/audacious.py:162 msgid "Add track to the Audacious play queue" msgstr "Dodaje utwór do kolejki odtwarzania Audacious" #: ../kupfer/plugin/audacious.py:173 msgid "Dequeue" msgstr "Usuń z kolejki" #: ../kupfer/plugin/audacious.py:184 msgid "Remove track from the Audacious play queue" msgstr "Usuwa utwór z kolejki odtwarzania Audacious" #: ../kupfer/plugin/audacious.py:197 ../kupfer/plugin/audacious.py:219 #: ../kupfer/plugin/rhythmbox.py:192 msgid "Play" msgstr "Odtwarzaj" #: ../kupfer/plugin/audacious.py:211 msgid "Jump to track in Audacious" msgstr "Przechodzi do utworu w Audacious" #: ../kupfer/plugin/audacious.py:229 msgid "Resume playback in Audacious" msgstr "Wznawia odtwarzanie w Audacious" #: ../kupfer/plugin/audacious.py:237 msgid "Stop" msgstr "Zatrzymaj" #: ../kupfer/plugin/audacious.py:247 msgid "Stop playback in Audacious" msgstr "Wstrzymuje odtwarzanie w Audacious" #: ../kupfer/plugin/audacious.py:255 #: ../kupfer/plugin/virtualbox/__init__.py:112 ../kupfer/plugin/libvirt.py:58 msgid "Pause" msgstr "Wstrzymaj" #: ../kupfer/plugin/audacious.py:265 msgid "Pause playback in Audacious" msgstr "Wstrzymuje odtwarzanie w Audacious" #: ../kupfer/plugin/audacious.py:273 msgid "Next" msgstr "Następny" #: ../kupfer/plugin/audacious.py:283 msgid "Jump to next track in Audacious" msgstr "Przechodzi do następnego utworu w Audacious" #: ../kupfer/plugin/audacious.py:291 msgid "Previous" msgstr "Poprzedni" #: ../kupfer/plugin/audacious.py:301 msgid "Jump to previous track in Audacious" msgstr "Przechodzi do poprzedniego utworu w Audacious" #: ../kupfer/plugin/audacious.py:309 ../kupfer/plugin/rhythmbox.py:166 msgid "Clear Queue" msgstr "Wyczyść kolejkę" #: ../kupfer/plugin/audacious.py:319 msgid "Clear the Audacious play queue" msgstr "Czyści kolejkę odtwarzania Audacious" #: ../kupfer/plugin/audacious.py:327 msgid "Shuffle" msgstr "Odtwarzaj losowo" #: ../kupfer/plugin/audacious.py:333 msgid "Toggle shuffle in Audacious" msgstr "Przełącza odtwarzanie w losowej kolejności w Audacious" #: ../kupfer/plugin/audacious.py:341 msgid "Repeat" msgstr "Powtórz" #: ../kupfer/plugin/audacious.py:347 msgid "Toggle repeat in Audacious" msgstr "Przełącza powtarzanie w Audacious" #: ../kupfer/plugin/audacious.py:355 msgid "Show Playing" msgstr "Wyświetl odtwarzany" #: ../kupfer/plugin/audacious.py:363 msgid "Tell which song is currently playing" msgstr "Wyświetla obecnie odtwarzany utwór" #: ../kupfer/plugin/audacious.py:389 msgid "Playlist" msgstr "Lista odtwarzania" #: ../kupfer/plugin/recoll.py:3 msgid "Recoll" msgstr "Recoll" #: ../kupfer/plugin/recoll.py:5 msgid "Search in Recoll full text search system" msgstr "Wyszukiwanie pełno-tekstowe w aplikacji Recoll" #: ../kupfer/plugin/recoll.py:45 msgid "Search in Recoll" msgstr "Wyszukiwanie Recoll" #: ../kupfer/plugin/recoll.py:57 msgid "Search for text in Recoll database" msgstr "Wyszukaj tekst w Recoll" #: ../kupfer/plugin/recoll.py:67 msgid "Open in Recoll" msgstr "Otwórz w Recoll" #: ../kupfer/plugin/recoll.py:79 msgid "Open Recoll and search for text" msgstr "Otwiera Recoll i wyszukuje tekst" #: ../kupfer/plugin/recoll.py:87 ../kupfer/plugin/tracker3.py:108 #: ../kupfer/plugin/locate.py:59 ../kupfer/plugin/tracker1.py:236 #, python-format msgid "Results for \"%s\"" msgstr "Wyniki dla \"%s\"" #: ../kupfer/plugin/quickview.py:1 msgid "Quick Image Viewer" msgstr "Szybki podgląd obrazów" #: ../kupfer/plugin/quickview.py:48 msgid "View Image" msgstr "Wyświetl obraz" #: ../kupfer/plugin/windows.py:1 ../kupfer/plugin/windows.py:337 msgid "Window List" msgstr "Lista okien" #: ../kupfer/plugin/windows.py:3 ../kupfer/plugin/windows.py:369 msgid "All windows on all workspaces" msgstr "Wszystkie okna ze wszystkich obszarów roboczych" #: ../kupfer/plugin/windows.py:46 msgid "Activate" msgstr "Aktywuj" #: ../kupfer/plugin/windows.py:54 msgid "Shade" msgstr "Zwiń" #: ../kupfer/plugin/windows.py:55 msgid "Unshade" msgstr "Rozwiń" #: ../kupfer/plugin/windows.py:62 msgid "Minimize" msgstr "Zminimalizuj" #: ../kupfer/plugin/windows.py:63 msgid "Unminimize" msgstr "Przywróć" #: ../kupfer/plugin/windows.py:72 msgid "Maximize" msgstr "Zmaksymalizuj" #: ../kupfer/plugin/windows.py:73 msgid "Unmaximize" msgstr "Przywróć" #: ../kupfer/plugin/windows.py:81 msgid "Maximize Vertically" msgstr "Zmaksymalizuj w pionie" #: ../kupfer/plugin/windows.py:82 msgid "Unmaximize Vertically" msgstr "Przywróć w pionie" #. TRANS: Window on (Workspace name), window description #: ../kupfer/plugin/windows.py:106 #, python-format msgid "Window on %(wkspc)s" msgstr "Okno na %(wkspc)s" #: ../kupfer/plugin/windows.py:116 msgid "Frontmost Window" msgstr "Okno na wierzchu" #: ../kupfer/plugin/windows.py:160 msgid "Next Window" msgstr "Następne okno" #: ../kupfer/plugin/windows.py:206 msgid "Jump to this window's workspace and focus" msgstr "Przechodzi do obszaru roboczego okna i uaktywnia je" #: ../kupfer/plugin/windows.py:214 ../kupfer/plugin/thunar.py:254 #: ../kupfer/plugin/fileactions.py:45 msgid "Move To..." msgstr "Przenieś do…" #: ../kupfer/plugin/windows.py:399 #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "%d okno" msgstr[1] "%d okna" msgstr[2] "%d okien" #: ../kupfer/plugin/windows.py:403 msgid "Active workspace" msgstr "Aktywny obszar roboczy" #: ../kupfer/plugin/windows.py:429 msgid "Jump to this workspace" msgstr "Przechodzi do obszaru roboczego" #: ../kupfer/plugin/windows.py:440 msgid "Workspaces" msgstr "Obszary robocze" #: ../kupfer/plugin/virtualbox/__init__.py:1 msgid "VirtualBox" msgstr "VirtualBox" #: ../kupfer/plugin/virtualbox/__init__.py:4 msgid "" "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and Open " "Source Edition." msgstr "" "Kontrolowanie maszyn wirtualnych VirtualBox. Obsługuje zarówno program " "VirtualBox firmy Sun, jak i edycję Open Source." #: ../kupfer/plugin/virtualbox/__init__.py:26 msgid "Force use CLI interface" msgstr "Wymuszenie użycia interfejsu tekstowego" #. libvirt.VIR_DOMAIN_SHUTOFF: #: ../kupfer/plugin/virtualbox/__init__.py:97 #: ../kupfer/plugin/virtualbox/__init__.py:118 ../kupfer/plugin/libvirt.py:78 msgid "Power On" msgstr "Uruchom" #: ../kupfer/plugin/virtualbox/__init__.py:100 #: ../kupfer/plugin/virtualbox/__init__.py:121 msgid "Power On Headless" msgstr "Uruchom bez ekranu" #: ../kupfer/plugin/virtualbox/__init__.py:107 ../kupfer/plugin/libvirt.py:61 msgid "Send Power Off Signal" msgstr "Wyślij sygnał wyłączenia" #: ../kupfer/plugin/virtualbox/__init__.py:114 ../kupfer/plugin/libvirt.py:59 msgid "Reboot" msgstr "Uruchom ponownie" #. VM_STATE_PAUSED #: ../kupfer/plugin/virtualbox/__init__.py:127 ../kupfer/plugin/libvirt.py:71 msgid "Resume" msgstr "Wznów" #: ../kupfer/plugin/virtualbox/__init__.py:131 msgid "Save State" msgstr "Zapisz stan" #: ../kupfer/plugin/virtualbox/__init__.py:134 ../kupfer/plugin/libvirt.py:66 msgid "Power Off" msgstr "Wyłącz" #: ../kupfer/plugin/virtualbox/__init__.py:158 msgid "VirtualBox Machines" msgstr "Maszyny wirtualne programu VirtualBox" #: ../kupfer/plugin/tracker3.py:7 msgid "Tracker3" msgstr "Tracker3" #: ../kupfer/plugin/tracker3.py:12 msgid "Tracker3 search integration" msgstr "Integracja z programem Tracker3" #: ../kupfer/plugin/tracker3.py:44 ../kupfer/plugin/tracker3.py:53 msgid "Search in Tracker3" msgstr "Wyszukaj w Tracker3" #: ../kupfer/plugin/tracker3.py:121 msgid "Tracker3 Full Text Search" msgstr "Wyszukiwanie pełno-tekstowe w Tracker3" #: ../kupfer/plugin/tracker3.py:124 ../kupfer/plugin/tracker1.py:296 msgid "Use '?' prefix to get full text results" msgstr "Przedrostek '?' włącza wyszukiwanie pełno-tekstowe" #: ../kupfer/plugin/kupfer_plugins.py:1 ../kupfer/plugin/kupfer_plugins.py:103 msgid "Kupfer Plugins" msgstr "Wtyczki programu Kupfer" #: ../kupfer/plugin/kupfer_plugins.py:3 msgid "Access Kupfer's plugin list in Kupfer" msgstr "Dostęp do listy wtyczek programu Kupfer" #: ../kupfer/plugin/kupfer_plugins.py:24 msgid "Show Information" msgstr "Wyświetl informacje" #: ../kupfer/plugin/kupfer_plugins.py:43 msgid "Show Source Code" msgstr "Wyświetl kod źródłowy" #: ../kupfer/plugin/kupfer_plugins.py:94 msgid "enabled" msgstr "włączona" #: ../kupfer/plugin/kupfer_plugins.py:94 msgid "disabled" msgstr "wyłączone" #: ../kupfer/plugin/volumes.py:1 ../kupfer/plugin/volumes.py:232 msgid "Volumes and Disks" msgstr "Woluminy i dyski" #: ../kupfer/plugin/volumes.py:3 ../kupfer/plugin/volumes.py:268 msgid "Mounted volumes and disks" msgstr "Zamontowane woluminy i dyski" #: ../kupfer/plugin/volumes.py:57 #, python-format msgid "Volume mounted at %s" msgstr "Wolumin zamontowany w %s" #. TRANS: %s is name of device with volume #: ../kupfer/plugin/volumes.py:84 #, python-format msgid "Volume on %s" msgstr "Wolumin na %s" #: ../kupfer/plugin/volumes.py:95 msgid "Mount" msgstr "Montuj" #: ../kupfer/plugin/volumes.py:109 msgid "Mount finished" msgstr "Montowanie zakończone" #. TRANS: %s is name of volume #: ../kupfer/plugin/volumes.py:111 #, python-format msgid "\"%s\" was successfully mounted" msgstr "\"%s\" zamontowano z sukcesem" #: ../kupfer/plugin/volumes.py:132 msgid "Mount this volume" msgstr "Montuje ten wolumin" #: ../kupfer/plugin/volumes.py:140 msgid "Unmount" msgstr "Odmontuj" #: ../kupfer/plugin/volumes.py:159 msgid "Unmount finished" msgstr "Odmontowanie zakończone" #. TRANS: %s is name of volume #: ../kupfer/plugin/volumes.py:161 #, python-format msgid "\"%s\" was successfully unmounted" msgstr "\"%s\" odmontowano z sukcesem" #: ../kupfer/plugin/volumes.py:185 msgid "Unmount this volume" msgstr "Odmontowuje ten wolumin" #: ../kupfer/plugin/volumes.py:193 msgid "Eject" msgstr "Wysuń" #: ../kupfer/plugin/volumes.py:196 msgid "Unmount and eject this media" msgstr "Odmontowuje i wysuwa ten nośnik" #: ../kupfer/plugin/kupfer_actions.py:3 ../kupfer/plugin/kupfer_actions.py:28 msgid "Kupfer Actions" msgstr "Akcje Kupfer" #: ../kupfer/plugin/kupfer_actions.py:6 msgid "" "'Inverse' action executions - look for action and then select object to " "execute on." msgstr "" "\"Odwrócone\" uruchamianie akcji - wyszukanie akcji a następnie wybór " "obiektu na którym będzie ona uchomiona." #: ../kupfer/plugin/nm.py:6 ../kupfer/plugin/nm.py:50 msgid "NetworkManager" msgstr "Menadżer sieci" #: ../kupfer/plugin/nm.py:9 msgid "Manage NetworkManager connections" msgstr "Zarządzaj połączeniami Menadżer sieci" #. TRANS: network device status #: ../kupfer/plugin/nm.py:67 msgid "unmanaged" msgstr "niezarządzalne" #. TRANS: network device status #: ../kupfer/plugin/nm.py:69 msgid "unavailable" msgstr "niedostępne" #. TRANS: network device status #: ../kupfer/plugin/nm.py:71 msgid "disconnected" msgstr "rozłączone" #. TRANS: network device status #: ../kupfer/plugin/nm.py:73 msgid "prepare" msgstr "przygotowanie" #. TRANS: network device status #: ../kupfer/plugin/nm.py:75 msgid "config" msgstr "konfiguracja" #. TRANS: network device status #: ../kupfer/plugin/nm.py:77 msgid "need auth" msgstr "wymaga uwierzytelniania" #. TRANS: network device status #: ../kupfer/plugin/nm.py:79 msgid "ip config" msgstr "konifguracja ip" #. TRANS: network device status #: ../kupfer/plugin/nm.py:81 msgid "ip check" msgstr "sprawdzenie ip" #. TRANS: network device status #: ../kupfer/plugin/nm.py:83 msgid "secondaries" msgstr "podrzędne" #. TRANS: network device status #: ../kupfer/plugin/nm.py:85 msgid "activated" msgstr "aktywne" #. TRANS: network device status #: ../kupfer/plugin/nm.py:87 msgid "deactivating" msgstr "wyłaczane" #. TRANS: network device status #: ../kupfer/plugin/nm.py:89 msgid "failed" msgstr "błąd" #: ../kupfer/plugin/nm.py:143 #, python-format msgid "Network device %(dtype)s; state: %(state)s" msgstr "Urządzenie sieciowe %(dtype)s; status: %(state)s" #: ../kupfer/plugin/nm.py:170 msgid "Disconnect" msgstr "Rozłącz" #: ../kupfer/plugin/nm.py:189 msgid "Disconnect connection" msgstr "Rozłącz połączenie" #. TRANS: activate connection (connect) #: ../kupfer/plugin/nm.py:201 msgid "Connect..." msgstr "Połącz..." #: ../kupfer/plugin/nm.py:218 msgid "Activate connection" msgstr "Aktywuj połączenie" #: ../kupfer/plugin/nm.py:257 msgid "Show information" msgstr "Wyświetl informacje" #: ../kupfer/plugin/nm.py:286 msgid "Connection details" msgstr "Szczegóły połączenia" #: ../kupfer/plugin/nm.py:289 msgid "Show information about device" msgstr "Wyświetla informacje o urządzeniu" #: ../kupfer/plugin/nm.py:311 msgid "Connections" msgstr "Połączenia" #. TRANS: notification text when wireless is disabled by hardware #: ../kupfer/plugin/nm.py:413 msgid "Hardware wireless disabled" msgstr "Nieaktywne urządzenie bezprzewodowe" #. TRANS: notification text after wireless enabled #: ../kupfer/plugin/nm.py:419 msgid "Wireless enabled" msgstr "Sieć bezprzewodowa aktywna" #. TRANS: notification text after wireless disabled #: ../kupfer/plugin/nm.py:422 msgid "Wireless disabled" msgstr "Sieć bezprzewodowa nieaktywna" #: ../kupfer/plugin/calculator.py:1 ../kupfer/plugin/calculator.py:88 msgid "Calculator" msgstr "Kalkulator" #: ../kupfer/plugin/calculator.py:3 msgid "Calculate mathematical expressions" msgstr "Oblicz wyrażenie matematyczne" #: ../kupfer/plugin/calculator.py:129 msgid "Calculate" msgstr "Oblicz" #: ../kupfer/plugin/archivemanager.py:3 msgid "Archive Manager" msgstr "Menedżer archiwów" #: ../kupfer/plugin/archivemanager.py:7 msgid "Use Archive Manager actions" msgstr "Działania menedżera archiwów" #: ../kupfer/plugin/archivemanager.py:33 msgid "Compressed archive type for 'Create Archive In'" msgstr "Typ skompresowanego archiwum dla „Utwórz archiwum w”" #: ../kupfer/plugin/archivemanager.py:47 msgid "Tool used for operations:" msgstr "Narzędzie używane do operacji:" #: ../kupfer/plugin/archivemanager.py:116 msgid "Extract Here" msgstr "Rozpakuj tutaj" #: ../kupfer/plugin/archivemanager.py:162 msgid "Extract compressed archive" msgstr "Rozpakowuje skompresowane archiwum" #: ../kupfer/plugin/archivemanager.py:176 msgid "Create Archive" msgstr "Utwórz archiwum" #: ../kupfer/plugin/archivemanager.py:188 #: ../kupfer/plugin/archivemanager.py:263 msgid "Create a compressed archive from folder" msgstr "Tworzy skompresowane archiwum z katalogu" #: ../kupfer/plugin/archivemanager.py:230 msgid "Create Archive In..." msgstr "Utwórz archiwum w…" #. TRANS: Default filename (no extension) for 'Create Archive In...' #: ../kupfer/plugin/archivemanager.py:244 msgid "Archive" msgstr "Archiwum" #: ../kupfer/plugin/nemo.py:1 ../kupfer/plugin/nemo.py:208 msgid "Nemo" msgstr "Nemo" #: ../kupfer/plugin/nemo.py:4 msgid "File manager actions" msgstr "Działania menedżera plików" #: ../kupfer/plugin/nemo.py:64 ../kupfer/plugin/thunar.py:80 msgid "Select in File Manager" msgstr "Zaznacz w menedżerze plików" #: ../kupfer/plugin/nemo.py:89 ../kupfer/plugin/thunar.py:119 msgid "Show Properties" msgstr "Wyświetl właściwości" #: ../kupfer/plugin/nemo.py:112 ../kupfer/plugin/thunar.py:145 msgid "Show information about file in file manager" msgstr "Wyświetla informacje o pliku w menedżerze plików" #: ../kupfer/plugin/nemo.py:137 ../kupfer/plugin/thunar.py:197 #: ../kupfer/plugin/fileactions.py:172 msgid "Copy To..." msgstr "Skopiuj do…" #: ../kupfer/plugin/nemo.py:181 ../kupfer/plugin/thunar.py:249 #: ../kupfer/plugin/fileactions.py:203 msgid "Copy file to a chosen location" msgstr "Kopiuje plik do wybranego położenia" #: ../kupfer/plugin/nemo.py:186 ../kupfer/plugin/thunar.py:412 #: ../kupfer/plugin/trash.py:134 msgid "Empty Trash" msgstr "Opóźnij kosz" #: ../kupfer/plugin/darktheme.py:1 ../kupfer/plugin/darktheme.py:19 msgid "Prefer Dark Theme" msgstr "Preferuj ciemny motyw" #: ../kupfer/plugin/defaultmail.py:1 msgid "Default Email Client" msgstr "Domyślny klient poczty" #: ../kupfer/plugin/defaultmail.py:3 msgid "Compose email using the system's default mailto: handler" msgstr "Tworzenie wiadomości e-mail używając domyślnego klienta poczty" #: ../kupfer/plugin/defaultmail.py:19 ../kupfer/plugin/thunderbird.py:57 msgid "Compose Email To" msgstr "Utwórz e-mail do" #: ../kupfer/plugin/sendkeys.py:1 ../kupfer/plugin/sendkeys.py:61 msgid "Send Keys" msgstr "Wyślij klawisz" #: ../kupfer/plugin/sendkeys.py:3 msgid "Send synthetic keyboard events using xautomation" msgstr "Wysyła sztuczne naciśnięcie klawiszy używając programu xautomation" #: ../kupfer/plugin/sendkeys.py:28 msgid "Paste to Foreground Window" msgstr "Wyślij do okna na wierzchu" #: ../kupfer/plugin/sendkeys.py:53 msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "Skopiuj do schowka i wyślij Ctrl+V do okna na wierzchu" #: ../kupfer/plugin/sendkeys.py:114 msgid "Send keys to foreground window" msgstr "Wysyła klawisze do okna na wierzchu" #: ../kupfer/plugin/sendkeys.py:121 msgid "Type Text" msgstr "Napisz tekst" #: ../kupfer/plugin/sendkeys.py:148 msgid "Type the text to foreground window" msgstr "„Napisanie” tekstu na wierzchu" #: ../kupfer/plugin/show_text.py:1 ../kupfer/plugin/show_text.py:21 #: ../kupfer/plugin/show_text.py:29 msgid "Show Text" msgstr "Wyświetl tekst" #: ../kupfer/plugin/show_text.py:3 ../kupfer/plugin/show_text.py:36 #: ../kupfer/plugin/show_text.py:66 msgid "Display text in a window" msgstr "Wyświetla tekst w oknie" #: ../kupfer/plugin/show_text.py:46 msgid "Large Type" msgstr "Duży napis" #: ../kupfer/plugin/show_text.py:79 msgid "Show Notification" msgstr "Wyświetl powiadomienie" #: ../kupfer/plugin/locate.py:1 ../kupfer/plugin/locate.py:36 msgid "Locate Files" msgstr "Wyszukaj pliki" #: ../kupfer/plugin/locate.py:3 ../kupfer/plugin/locate.py:48 msgid "Search filesystem using locate" msgstr "Przeszukuje system plików za pomocą programu locate" #: ../kupfer/plugin/locate.py:23 msgid "Ignore case distinctions when searching files" msgstr "Ignorowanie wielkości liter podczas wyszukiwania plików" #: ../kupfer/plugin/documents.py:3 msgid "Documents" msgstr "Dokumenty" #: ../kupfer/plugin/documents.py:7 msgid "Recently used documents and bookmarked folders" msgstr "Ostatnio używane dokumenty i katalogi w zakładkach" #: ../kupfer/plugin/documents.py:30 msgid "Max recent document days" msgstr "Maksymalna liczba dni dla ostatnio używanych dokumentów" #: ../kupfer/plugin/documents.py:36 msgid "Show only existing documents" msgstr "Wyświetl tylko istniejące dokumenty" #: ../kupfer/plugin/documents.py:186 msgid "Recent Items" msgstr "Ostatnie elementy" #: ../kupfer/plugin/documents.py:206 msgid "Recently used documents" msgstr "Ostatnio używane dokumenty" #. TRANS: Recent Documents for application %s #: ../kupfer/plugin/documents.py:219 #, python-format msgid "%s Documents" msgstr "Dokumenty %s" #: ../kupfer/plugin/documents.py:237 #, python-format msgid "Recently used documents for %s" msgstr "Ostatnio używane dokumenty programu %s" #: ../kupfer/plugin/documents.py:261 msgid "Places" msgstr "Miejsca" #: ../kupfer/plugin/documents.py:302 msgid "Bookmarked folders" msgstr "Katalogi w zakładkach" #: ../kupfer/plugin/documents.py:320 ../kupfer/plugin/documents.py:371 msgid "Toggle Recent Documents" msgstr "Przełącz ostatnie dokumenty" #: ../kupfer/plugin/documents.py:398 msgid "Enable/disable listing recent documents in content for this application" msgstr "" "Włącz/wyłącz wyświetlanie ostatnich dokumentów w kontekście tej aplikacji" #: ../kupfer/plugin/notes.py:6 ../kupfer/plugin/notes.py:381 #: ../kupfer/plugin/notes.py:445 msgid "Notes" msgstr "Notatki" #: ../kupfer/plugin/notes.py:14 msgid "Gnote or Tomboy notes" msgstr "Notatki w programie Gnote lub Tomboy" #: ../kupfer/plugin/notes.py:47 msgid "Work with application" msgstr "Współpraca z programem" #: ../kupfer/plugin/notes.py:194 msgid "Open with notes application" msgstr "Otwiera za pomocą programu notatek" #: ../kupfer/plugin/notes.py:203 msgid "Append to Note..." msgstr "Dołącz do notatki…" #: ../kupfer/plugin/notes.py:269 msgid "Add text to existing note" msgstr "Dodaje tekst do istniejącej notatki" #: ../kupfer/plugin/notes.py:312 msgid "Create Note" msgstr "Utwórz notatkę" #: ../kupfer/plugin/notes.py:339 msgid "Create a new note from this text" msgstr "Tworzy nową notatkę zawierającą ten tekst" #: ../kupfer/plugin/notes.py:347 msgid "Get Note Search Results..." msgstr "Wyszukaj wśród notatek…" #: ../kupfer/plugin/notes.py:375 msgid "Show search results for this query" msgstr "Wyświetla wyniki szukania dla zapytania" #: ../kupfer/plugin/notes.py:421 #, python-format msgid "today, %s" msgstr "dziś, %s" #: ../kupfer/plugin/notes.py:423 #, python-format msgid "yesterday, %s" msgstr "wczoraj, %s" #. TRANS: Note description, %s is last changed time in locale format #: ../kupfer/plugin/notes.py:427 #, python-format msgid "Last updated %s" msgstr "Ostatnia aktualizacja: %s" #: ../kupfer/plugin/thunar.py:1 ../kupfer/plugin/thunar.py:216 #: ../kupfer/plugin/thunar.py:268 ../kupfer/plugin/thunar.py:342 #: ../kupfer/plugin/thunar.py:450 msgid "Thunar" msgstr "Thunar" #: ../kupfer/plugin/thunar.py:11 msgid "File manager Thunar actions" msgstr "Działania menedżera plików Thunar" #: ../kupfer/plugin/thunar.py:155 msgid "Send To..." msgstr "Wyślij do…" #: ../kupfer/plugin/thunar.py:312 ../kupfer/plugin/fileactions.py:82 msgid "Move file to new location" msgstr "Przenosi plik do nowego położenia" #: ../kupfer/plugin/thunar.py:320 msgid "Symlink In..." msgstr "Utwórz dowiązanie symboliczne…" #: ../kupfer/plugin/thunar.py:377 msgid "Create a symlink to file in a chosen location" msgstr "Tworzy dowiązanie symboliczne do wybranego położenia" #: ../kupfer/plugin/thunar.py:382 msgid "Open Trash" msgstr "Otwórz kosz" #: ../kupfer/plugin/thunar.py:404 msgid "Open Trash in Thunar" msgstr "Otwiera Kosz w Thunar" #: ../kupfer/plugin/thunar.py:467 msgid "Thunar Send To Objects" msgstr "Obiekty „Wyślij do” programu Thunar" #: ../kupfer/plugin/mediaplayers.py:1 ../kupfer/plugin/mediaplayers.py:30 msgid "Media Player Control" msgstr "Kontrola odtwarzaczy multimedialnych" #: ../kupfer/plugin/mediaplayers.py:3 msgid "Playback control for media players" msgstr "Kontrola odtwarzania dla odtwarzaczy multimedialnych" #. TRANS: %s is a media player name #: ../kupfer/plugin/mediaplayers.py:101 #, python-format msgid "Play/Pause (%s)" msgstr "Odtwarzaj/Wstrzymaj (%s)" #: ../kupfer/plugin/mediaplayers.py:107 msgid "Resume playback" msgstr "Wznów odtwarzanie" #: ../kupfer/plugin/mediaplayers.py:119 msgid "Pause All" msgstr "Wstrzymaj wszystko" #. TRANS: %s is a media player name #: ../kupfer/plugin/mediaplayers.py:135 #, python-format msgid "Next (%s)" msgstr "Następny (%s)" #: ../kupfer/plugin/mediaplayers.py:141 msgid "Skip to next track" msgstr "Przechodzi do następnego utworu" #. TRANS: %s is a media player name #: ../kupfer/plugin/mediaplayers.py:150 #, python-format msgid "Previous (%s)" msgstr "Poprzedni (%s)" #: ../kupfer/plugin/mediaplayers.py:156 msgid "Skip to previous track" msgstr "Przechodzi do poprzedniego utworu" #. TRANS: %s is a media player name #: ../kupfer/plugin/mediaplayers.py:165 #, python-format msgid "Stop (%s)" msgstr "Zatrzymaj (%s)" #: ../kupfer/plugin/mediaplayers.py:171 msgid "Stop playback" msgstr "Zatrzymaj odtwarzanie" #: ../kupfer/plugin/deepdirectories.py:9 ../kupfer/plugin/deepdirectories.py:47 msgid "Deep Directories" msgstr "Zagnieżdżone katalogi" #: ../kupfer/plugin/deepdirectories.py:11 msgid "Recursive index directories" msgstr "Rekursywny indeks katalogów" #: ../kupfer/plugin/deepdirectories.py:27 msgid "Directories:" msgstr "Katalogi:" #: ../kupfer/plugin/deepdirectories.py:34 msgid "Depth (max 10):" msgstr "Głębokość (maks 10):" #: ../kupfer/plugin/libvirt.py:10 msgid "Libvirt" msgstr "Libvirt" #: ../kupfer/plugin/libvirt.py:12 msgid "Control libvirt guest domains." msgstr "Kontrola domen libvirt." #: ../kupfer/plugin/libvirt.py:33 msgid "Connection" msgstr "Połączenie" #: ../kupfer/plugin/libvirt.py:183 msgid "Libvirt domains" msgstr "Domeny libvirt" #: ../kupfer/plugin/libvirt.py:231 msgid "Open console" msgstr "Otwórz konsole" #: ../kupfer/plugin/libvirt.py:253 msgid "Open Virtual Machine Manager console for domain" msgstr "Otwórz kolnsolę Menadżera maszyn wirtualnych dla domeny" #: ../kupfer/plugin/apt_tools.py:3 msgid "APT" msgstr "APT" #: ../kupfer/plugin/apt_tools.py:13 msgid "Interface with the package manager APT" msgstr "Współpraca z menedżerem pakietów APT" #: ../kupfer/plugin/apt_tools.py:35 msgid "Installation method" msgstr "Metoda instalacji" #: ../kupfer/plugin/apt_tools.py:85 ../kupfer/plugin/apt_tools.py:91 msgid "Show Package Information" msgstr "Wyświetl informacje o pakiecie" #: ../kupfer/plugin/apt_tools.py:115 msgid "Browse packages.debian.org" msgstr "Przeglądaj packages.debian.org" #: ../kupfer/plugin/apt_tools.py:123 msgid "Open packages.debian.org page for package" msgstr "Otwórz stronę packages.debian.org dla pakietu" #: ../kupfer/plugin/apt_tools.py:140 msgid "Install" msgstr "Zainstaluj" #: ../kupfer/plugin/apt_tools.py:157 msgid "Install package using the configured method" msgstr "Instaluje pakiet używając skonfigurowanej metody" #: ../kupfer/plugin/apt_tools.py:181 #, python-format msgid "Packages matching \"%s\"" msgstr "Pakiety pasujące do „%s”" #: ../kupfer/plugin/apt_tools.py:216 msgid "Search Package Name..." msgstr "Wyszukaj pakiet o nazwie…" #: ../kupfer/plugin/apt_tools.py:240 msgid "Search for file in packages..." msgstr "Szukaj pliku w pakietach..." #: ../kupfer/plugin/apt_tools.py:250 msgid "Search the contents of Debian distributions for any files (online)" msgstr "Przeszukaj zawartość dystrybucji Debian w poszukiwaniu plików (online)" #: ../kupfer/plugin/top.py:1 msgid "Top" msgstr "Top" #: ../kupfer/plugin/top.py:3 msgid "Show running tasks and allow sending signals to them" msgstr "Wyświetla uruchomione zadania i umożliwia wysłanie sygnałów do nich" #: ../kupfer/plugin/top.py:24 msgid "Sort Order" msgstr "Kolejność sortowania" #: ../kupfer/plugin/top.py:26 ../kupfer/plugin/top.py:28 #: ../kupfer/plugin/top.py:123 msgid "Commandline" msgstr "Wiersz poleceń" #: ../kupfer/plugin/top.py:29 msgid "CPU usage (descending)" msgstr "Użycie procesora (malejąco)" #: ../kupfer/plugin/top.py:30 ../kupfer/plugin/top.py:119 msgid "Memory usage (descending)" msgstr "Użycie pamięci (malejąco)" #: ../kupfer/plugin/top.py:53 msgid "Send Signal..." msgstr "Wyślij sygnał…" #: ../kupfer/plugin/top.py:84 msgid "Signals" msgstr "Sygnały" #: ../kupfer/plugin/top.py:98 msgid "Running Tasks" msgstr "Uruchomione zadania" #: ../kupfer/plugin/top.py:128 #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "PID: %(pid)s procesor: %(cpu)g%% pamięć: %(mem)g%% czas: %(time)s" #: ../kupfer/plugin/top.py:140 msgid "Running tasks for current user" msgstr "Uruchomione zadania bieżącego użytkownika" #: ../kupfer/plugin/session_xfce.py:3 ../kupfer/plugin/session_xfce.py:45 msgid "XFCE Session Management" msgstr "Menedżer sesji Xfce" #: ../kupfer/plugin/session_xfce.py:5 msgid "Special items and actions for XFCE environment" msgstr "Specjalne elementy i działania dla środowiska Xfce" #: ../kupfer/plugin/session_xfce.py:24 msgid "Screen lock command" msgstr "Polecenie blokady ekranu" #: ../kupfer/plugin/session_xfce.py:30 msgid "Load Whisker Menu Favorite applications" msgstr "Ładuj ulubione aplikacje z menu Whisker" #: ../kupfer/plugin/session_xfce.py:104 msgid "Whisker Favorites" msgstr "Ulubione Whisker" #: ../kupfer/plugin/session_xfce.py:126 msgid "Favorite items from Xfce Whisker Menu" msgstr "Ulubione elementy z menu Xfce Wisker" #: ../kupfer/plugin/templates.py:3 ../kupfer/plugin/templates.py:157 msgid "Document Templates" msgstr "Szablony dokumentów" #: ../kupfer/plugin/templates.py:6 msgid "Create new documents from your templates" msgstr "Tworzy nowe dokumenty na podstawie szablonów" #: ../kupfer/plugin/templates.py:31 #, python-format msgid "%s template" msgstr "Szablon %s" #: ../kupfer/plugin/templates.py:58 msgid "New Folder" msgstr "Pusty katalog" #: ../kupfer/plugin/templates.py:72 msgid "Create New Document..." msgstr "Utwórz nowy dokument…" #: ../kupfer/plugin/templates.py:125 msgid "Create a new document from template" msgstr "Tworzy nowy dokument na podstawie szablonu" #: ../kupfer/plugin/templates.py:138 msgid "Create Document In..." msgstr "Utwórz dokument w…" #: ../kupfer/plugin/rhythmbox.py:16 ../kupfer/plugin/rhythmbox.py:550 msgid "Rhythmbox" msgstr "Rhythmbox" #: ../kupfer/plugin/rhythmbox.py:18 ../kupfer/plugin/rhythmbox.py:595 msgid "Play and enqueue tracks and browse the music library" msgstr "" "Odtwarzanie i kolejkowanie utworów oraz przeglądanie kolekcji muzycznej" #: ../kupfer/plugin/rhythmbox.py:58 msgid "Include artists in top level" msgstr "Wyświetlanie wykonawców na najwyższym poziomie listy" #: ../kupfer/plugin/rhythmbox.py:64 msgid "Include albums in top level" msgstr "Wyświetlanie albumów na najwyższym poziomie listy" #: ../kupfer/plugin/rhythmbox.py:209 msgid "Play tracks in Rhythmbox" msgstr "Odtwarza utwory w programie Rhythmbox" #: ../kupfer/plugin/rhythmbox.py:232 msgid "Add tracks to the play queue" msgstr "Dodaje utwory do kolejki odtwarzania" #. TRANS: Song description #: ../kupfer/plugin/rhythmbox.py:265 #, python-format msgid "by %(artist)s from %(album)s" msgstr " %(artist)s z %(album)s" #: ../kupfer/plugin/rhythmbox.py:279 msgid "Get File" msgstr "Wybierz plik" #. TRANS: Album description "by Artist" #: ../kupfer/plugin/rhythmbox.py:362 #, python-format msgid "by %s" msgstr " %s" #. TRANS: Artist songs collection description #: ../kupfer/plugin/rhythmbox.py:436 #, python-format msgid "Tracks by %s" msgstr "Utwory wykonawcy %s" #: ../kupfer/plugin/rhythmbox.py:450 msgid "Albums" msgstr "Albumy" #: ../kupfer/plugin/rhythmbox.py:461 msgid "Music albums in Rhythmbox Library" msgstr "Albumy w kolekcji programu Rhythmbox" #: ../kupfer/plugin/rhythmbox.py:477 msgid "Artists" msgstr "Wykonawcy" #: ../kupfer/plugin/rhythmbox.py:488 msgid "Music artists in Rhythmbox Library" msgstr "Wykonawcy w kolekcji programu Rhythmbox" #: ../kupfer/plugin/rhythmbox.py:523 msgid "Songs" msgstr "Utwory" #: ../kupfer/plugin/rhythmbox.py:534 msgid "Songs in Rhythmbox library" msgstr "Utwory w kolekcji programu Rhythmbox" #: ../kupfer/plugin/wikipedia.py:5 msgid "Wikipedia" msgstr "Wikipedia" #: ../kupfer/plugin/wikipedia.py:8 ../kupfer/plugin/wikipedia.py:53 msgid "Search in Wikipedia" msgstr "Wyszukaj w Wikipedii" #: ../kupfer/plugin/wikipedia.py:24 msgid "Wikipedia languages (;-separated)" msgstr "Języki Wikipedii (rozdzielone przez ';')" #. TRANS: Default wikipedia language code #: ../kupfer/plugin/wikipedia.py:27 ../kupfer/plugin/wikipedia.py:72 msgid "en" msgstr "pl" #: ../kupfer/plugin/wikipedia.py:92 ../kupfer/plugin/wikipedia.py:94 #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Wyszukuje to wyrażenie w serwisie %s.wikipedia.org" #: ../kupfer/plugin/whatsapp.py:5 ../kupfer/plugin/whatsapp.py:40 msgid "WhatsApp Web" msgstr "WhatsApp Web" #: ../kupfer/plugin/whatsapp.py:9 msgid "" "Open a new number in WhatsApp Web\n" "\n" "The number format must respect:\n" "\"Country Code\" + \"Area Code\" + \"Number\"\n" "\n" "Example for a New York number: 12129999999\n" "Country Code: 1\n" "Area Code: 212\n" "Number: 9999999\n" "\n" "WhatsApp Web will open in the browser.\n" "\n" "For help visit https://faq.whatsapp.com/general/chats/how-to-use-click-to-" "chat/\n" "\n" msgstr "" "Otwórz nowy numer w WhatsApp Web\n" "\n" "Format numeru musi uwzględniać:\n" "\"kod kraju\" + \"numer kierunkowy\" + \"numer\"\n" "\n" "Przykładowy numer dla Nowego Yorku: 12129999999\n" "Kod kraju: 1\n" "Numer kierunkowy: 212\n" "Numer: 9999999\n" "\n" "WhatsApp Web zostanie otwarty w przeglądarce.\n" "\n" "Pomoc można uzyskać na stronie https://faq.whatsapp.com/general/chats/how-to-" "use-click-to-chat/\n" "\n" #: ../kupfer/plugin/whatsapp.py:56 msgid "Send a WhatsApp to a new number." msgstr "Wyślij WhatsApp do nowego numeru." #: ../kupfer/plugin/firefox_keywords.py:3 #: ../kupfer/plugin/firefox_keywords.py:93 msgid "Firefox Keywords" msgstr "Słowa kluczowe Firefox" #: ../kupfer/plugin/firefox_keywords.py:7 #: ../kupfer/plugin/firefox_keywords.py:162 #: ../kupfer/plugin/firefox_keywords.py:202 msgid "Search the web with Firefox keywords" msgstr "Wyszukiwanie w sieci za pomocą słów kluczowych Firefox" #: ../kupfer/plugin/firefox_keywords.py:35 msgid "Default for ?" msgstr "Domyślne dla ?" #: ../kupfer/plugin/firefox_keywords.py:41 ../kupfer/plugin/firefox.py:29 #: ../kupfer/plugin/firefox_tags.py:25 msgid "Firefox profile name or path" msgstr "Nazwa lub ścieżka profilu Firefox" #: ../kupfer/plugin/firefox_keywords.py:195 msgid "Search Terms" msgstr "Szukane wyrażenie" #: ../kupfer/plugin/firefox_keywords.py:217 msgid "Firefox Keywords (?-source)" msgstr "Słowa kluczowe Firefox (?-źródło)" #: ../kupfer/plugin/firefox_keywords.py:258 #, python-format msgid "Search for \"%s\"" msgstr "Wyszukaj \"%s\"" #: ../kupfer/plugin/firefox_keywords.py:276 #, python-format msgid "Search using %s" msgstr "Wyszukaj z użyciem %s" #: ../kupfer/plugin/thunderbird.py:8 msgid "Thunderbird" msgstr "Thunderbird" #: ../kupfer/plugin/thunderbird.py:15 msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Kontakty i działania programu Thunderbird/Icedove" #: ../kupfer/plugin/thunderbird.py:47 msgid "Compose a new message in Thunderbird" msgstr "Tworzy nową wiadomość w programie Thunderbird" #: ../kupfer/plugin/thunderbird.py:87 msgid "Attach in Email To..." msgstr "Załącz w wiadomości e-mail do…" #: ../kupfer/plugin/thunderbird.py:129 msgid "Compose Email With" msgstr "Utwórz wiadomość e-mail z" #: ../kupfer/plugin/thunderbird.py:143 msgid "Compose a new message using the text as body" msgstr "Tworzy nową wiadomość z użyciem tekstu jako treści" #: ../kupfer/plugin/thunderbird.py:152 msgid "Thunderbird Address Book" msgstr "Książka adresowa programu Thunderbird" #: ../kupfer/plugin/thunderbird.py:181 msgid "Contacts from Thunderbird Address Book" msgstr "Kontakty z książki adresowej programu Thunderbird" #: ../kupfer/plugin/fileactions.py:1 msgid "File Actions" msgstr "Działania na plikach" #: ../kupfer/plugin/fileactions.py:5 msgid "More file actions" msgstr "Dodatkowe działania na plikach" #: ../kupfer/plugin/fileactions.py:98 ../kupfer/plugin/fileactions.py:122 msgid "Rename To..." msgstr "Zmień nazwę na…" #: ../kupfer/plugin/fileactions.py:237 msgid "Edit file content" msgstr "Edytuj zawartość pliku" #: ../kupfer/plugin/fileactions.py:288 msgid "Open file in configured editor" msgstr "Otwórz plik w skonfigurowanym edytorz" #: ../kupfer/plugin/session_support.py:44 msgid "Log Out..." msgstr "Wyloguj…" #: ../kupfer/plugin/session_support.py:47 msgid "Log out or change user" msgstr "Wylogowuje lub zmienia użytkownika" #: ../kupfer/plugin/session_support.py:53 msgid "Please confirm log out" msgstr "Proszę potwierdzić wylogowanie" #: ../kupfer/plugin/session_support.py:53 msgid "Log Out" msgstr "Wyloguj" #: ../kupfer/plugin/session_support.py:61 msgid "Shut Down..." msgstr "Wyłącz…" #: ../kupfer/plugin/session_support.py:64 msgid "Shut down, restart or suspend computer" msgstr "Wyłącza, uruchamia ponownie lub usypia komputer" #: ../kupfer/plugin/session_support.py:71 msgid "Please confirm system shut down." msgstr "Proszę potwierdzić wyłączenie systemu." #: ../kupfer/plugin/session_support.py:71 msgid "Shut down" msgstr "Wyłącz" #: ../kupfer/plugin/session_support.py:80 msgid "Lock Screen" msgstr "Zablokuj ekran" #: ../kupfer/plugin/session_support.py:83 msgid "Enable screensaver and lock" msgstr "Wygasza i blokuje ekran" #: ../kupfer/plugin/image.py:1 msgid "Image Tools" msgstr "Narzędzia do obrazów" #: ../kupfer/plugin/image.py:6 msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Przekształcania plików graficznych z użyciem 'convert' z ImageMagick" #: ../kupfer/plugin/image.py:40 msgid "Scale..." msgstr "Skaluj…" #: ../kupfer/plugin/image.py:93 msgid "Scale image to fit inside given pixel measure(s)" msgstr "Dopasowuje obraz do wybranego rozmiaru w pikselach" #: ../kupfer/plugin/image.py:138 msgid "Rotate Clockwise" msgstr "Obróć zgodnie z ruchem wskazówek zegara" #: ../kupfer/plugin/image.py:146 msgid "Rotate Counter-Clockwise" msgstr "Obróć odwrotnie do ruchu wskazówek zegara" #: ../kupfer/plugin/image.py:154 msgid "Autorotate" msgstr "Obróć automatycznie" #: ../kupfer/plugin/image.py:188 msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "Obróć plik JPEG zgodnie z jego danymi EXIF" #: ../kupfer/plugin/core/alternatives.py:17 msgid "GTK+" msgstr "GTK+" #: ../kupfer/plugin/core/alternatives.py:25 msgid "GNOME Terminal" msgstr "Terminal GNOME" #: ../kupfer/plugin/core/alternatives.py:36 msgid "XFCE Terminal" msgstr "Terminal XFCE" #: ../kupfer/plugin/core/alternatives.py:58 msgid "LXTerminal" msgstr "LXTerminal" #: ../kupfer/plugin/core/alternatives.py:69 msgid "X Terminal" msgstr "X Terminal" #: ../kupfer/plugin/core/alternatives.py:91 msgid "Urxvt" msgstr "Urxvt" #: ../kupfer/plugin/core/alternatives.py:102 msgid "Konsole" msgstr "Konsole" #: ../kupfer/plugin/core/alternatives.py:119 msgid "System `editor`" msgstr "Systemowy `editor`" #: ../kupfer/plugin/core/internal.py:19 msgid "Last Command" msgstr "Ostatnie polecenie" #: ../kupfer/plugin/core/internal.py:32 msgid "Internal Kupfer Objects" msgstr "Obiekty wewnętrzne programu Kupfer" #: ../kupfer/plugin/core/internal.py:50 ../kupfer/plugin/core/internal.py:62 msgid "Last Result" msgstr "Ostatni wynik" #: ../kupfer/plugin/core/internal.py:83 msgid "Command Results" msgstr "Wynik polecenia" #: ../kupfer/plugin/core/__init__.py:74 msgid "Search Contents" msgstr "Przeszukaj zawartość" #: ../kupfer/plugin/core/__init__.py:95 msgid "Search inside this catalog" msgstr "Wyszukuje wewnątrz tego katalogu" #: ../kupfer/plugin/core/__init__.py:127 msgid "Copy to clipboard" msgstr "Kopiuje do schowka" #: ../kupfer/plugin/core/__init__.py:158 msgid "Rescan" msgstr "Odśwież" #: ../kupfer/plugin/core/__init__.py:175 msgid "Force reindex of this source" msgstr "Wymusza ponowne indeksowanie tego źródła" #: ../kupfer/plugin/core/commands.py:16 ../kupfer/plugin/core/commands.py:38 msgid "Save As..." msgstr "Zapisz jako…" #: ../kupfer/plugin/core/contents.py:32 msgid "Restart Kupfer" msgstr "Uruchom ponownie Kupfer" #: ../kupfer/plugin/core/contents.py:53 msgid "Quit" msgstr "Zakończ" #: ../kupfer/plugin/core/contents.py:59 msgid "Quit Kupfer" msgstr "Kończy działanie programu Kupfer" #: ../kupfer/plugin/core/contents.py:68 msgid "About Kupfer" msgstr "O programie Kupfer" #: ../kupfer/plugin/core/contents.py:79 msgid "Show information about Kupfer authors and license" msgstr "Wyświetla informacje o autorach i licencji programu Kupfer" #: ../kupfer/plugin/core/contents.py:87 msgid "Kupfer Help" msgstr "Pomoc programu Kupfer" #: ../kupfer/plugin/core/contents.py:97 msgid "Get help with Kupfer" msgstr "Wyświetla pomocy programu Kupfer" #: ../kupfer/plugin/core/contents.py:115 msgid "Show preferences window for Kupfer" msgstr "Wyświetla okno preferencji programu Kupfer" #: ../kupfer/plugin/clipboard.py:3 ../kupfer/plugin/clipboard.py:224 msgid "Clipboards" msgstr "Schowki" #: ../kupfer/plugin/clipboard.py:6 msgid "Recent clipboards and clipboard proxy objects" msgstr "Ostatnie schowki i ich obiekty pośredniczące" #: ../kupfer/plugin/clipboard.py:37 msgid "Number of recent clipboards to remember" msgstr "Liczba ostatnich schowków do pamiętania" #: ../kupfer/plugin/clipboard.py:43 msgid "Include selected text in clipboard history" msgstr "Dołączenie zaznaczonego tekstu w historii schowka" #: ../kupfer/plugin/clipboard.py:49 msgid "Copy selected text to primary clipboard" msgstr "Kopiowanie zaznaczonego tekstu do podstawowego schowka" #: ../kupfer/plugin/clipboard.py:60 msgid "Selected Text" msgstr "Zaznaczony tekst" #: ../kupfer/plugin/clipboard.py:70 msgid "Selected File" msgstr "Wybrane pliki" #: ../kupfer/plugin/clipboard.py:80 msgid "Selected URL" msgstr "Zaznaczony URL" #: ../kupfer/plugin/clipboard.py:107 ../kupfer/plugin/clipboard.py:125 #: ../kupfer/plugin/clipboard.py:130 #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Schowek z %(num)d wierszem „%(desc)s”" msgstr[1] "Schowek z %(num)d wierszami „%(desc)s”" msgstr[2] "Schowek z %(num)d wierszami „%(desc)s”" #: ../kupfer/plugin/clipboard.py:117 msgid "Clipboard Text" msgstr "Tekst w schowku" #: ../kupfer/plugin/clipboard.py:137 msgid "Clipboard URL" msgstr "URL-e w schowku" #: ../kupfer/plugin/clipboard.py:149 msgid "Clipboard File" msgstr "Plik w schowku" #: ../kupfer/plugin/clipboard.py:161 msgid "Clipboard Files" msgstr "Pliki w schowku" #: ../kupfer/plugin/clipboard.py:210 msgid "Remove all recent clipboards" msgstr "Usuwa wszystkie ostatnie schowki" #: ../kupfer/plugin/librewolf.py:1 ../kupfer/plugin/librewolf.py:43 msgid "Librewolf Bookmarks" msgstr "Zakładki programu Librewolf" #: ../kupfer/plugin/librewolf.py:5 msgid "" "Index of Librewolf bookmarks. Bookmark is always opened in default browser." msgstr "" "Indeks zakładek Librewolf. Zakładki są zawsze otwierane w domyślnej " "przeglądarce." #: ../kupfer/plugin/librewolf.py:29 msgid "Librewolf profile name or path" msgstr "Nazwa lub ścieżka profilu Librewolf" #: ../kupfer/plugin/librewolf.py:68 msgid "Index of Librewolf bookmarks" msgstr "Indeks zakładek programu Librewolf" #: ../kupfer/plugin/zoxide.py:9 ../kupfer/plugin/zoxide.py:175 msgid "Zoxide Directories" msgstr "Katalogi Zoxide" #: ../kupfer/plugin/zoxide.py:11 msgid "Load top directories from zoxide database" msgstr "Załaduj najpopularniejsze katalogi z bazy zoxide" #: ../kupfer/plugin/zoxide.py:32 msgid "Exclude directories:" msgstr "Pomijane katalogi:" #: ../kupfer/plugin/zoxide.py:39 msgid "Minimal score:" msgstr "Minimalna punktacja:" #: ../kupfer/plugin/zoxide.py:44 msgid "" "Load only directories that score is equal or higher than configured minimum" msgstr "" "Wczytaj tylko katalogi których punktacja jest równa lub większa niż " "skonfigurowane minimum" #: ../kupfer/plugin/zoxide.py:50 msgid "Load limit:" msgstr "Limit wczytywania:" #: ../kupfer/plugin/zoxide.py:54 msgid "Maximal number of directories to load" msgstr "Maksymalna liczba katalogów do wczytania" #: ../kupfer/plugin/zoxide.py:58 msgid "Show only existing directories" msgstr "Wyświetl tylko istniejące katalogi" #: ../kupfer/plugin/zoxide.py:64 msgid "Update database after activate" msgstr "Aktualizacja katalogu po aktywacji" #: ../kupfer/plugin/zoxide.py:68 msgid "When enabled open files and directories will update zoxide database" msgstr "Po włączeniu otwarcie plików lub katalogów zaktualizuje bazę zoxide" #: ../kupfer/plugin/pinboard.py:1 msgid "Pinboard" msgstr "Pinboard" #: ../kupfer/plugin/pinboard.py:4 msgid "Manage and use bookmarks from Pinboard" msgstr "Zarządzaj i używaj zakładek Pinboard" #: ../kupfer/plugin/pinboard.py:21 msgid "Pinboard API Token" msgstr "Token API Pinboard" #: ../kupfer/plugin/pinboard.py:30 msgid "Pinboard Bookmarks" msgstr "Zakładki Pinboard" #: ../kupfer/plugin/pinboard.py:42 msgid "Index of Pinboard bookmarks" msgstr "Indeks zakładek Pinboard" #: ../kupfer/plugin/higherorder.py:1 msgid "Higher-order Actions" msgstr "Wysokopoziomowe działania" #: ../kupfer/plugin/higherorder.py:3 msgid "Tools to work with commands as objects" msgstr "Narzędzia do pracy z poleceniami jako obiektami" #: ../kupfer/plugin/higherorder.py:22 msgid "Select in Kupfer" msgstr "Wybierz w programie Kupfer" #: ../kupfer/plugin/higherorder.py:73 #, python-format msgid "Result of %s (%s)" msgstr "Wyniki dla %s (%s)" #: ../kupfer/plugin/higherorder.py:91 msgid "Run (Take Result)" msgstr "Uruchom (pobierz rezultat)" #: ../kupfer/plugin/higherorder.py:109 msgid "Take the command result as a proxy object" msgstr "Użyje wynik polecenia jako obiekt pośredniczący" #: ../kupfer/plugin/higherorder.py:116 msgid "Run (Discard Result)" msgstr "Uruchom (porzuć rezultat)" #: ../kupfer/plugin/ssh_hosts.py:3 ../kupfer/plugin/ssh_hosts.py:191 msgid "SSH Hosts" msgstr "Host SSH" #: ../kupfer/plugin/ssh_hosts.py:4 msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "Dodaje hosty SSH odnalezione w ~/.ssh/config." #: ../kupfer/plugin/ssh_hosts.py:55 #, python-format msgid "SSH host: %s" msgstr "Host SSH: %s" #: ../kupfer/plugin/ssh_hosts.py:78 msgid "Connect" msgstr "Połącz" #: ../kupfer/plugin/ssh_hosts.py:90 msgid "Connect to SSH host" msgstr "Łączy z hostem przez SSH" #: ../kupfer/plugin/ssh_hosts.py:109 msgid "Send file to..." msgstr "Wyślij plik do…" #: ../kupfer/plugin/ssh_hosts.py:140 msgid "Copy file or directory to remote host using scp" msgstr "Skopiuj plik lub katalogo do zdalnego hosta używając scp" #: ../kupfer/plugin/ssh_hosts.py:253 msgid "SSH hosts as specified in ~/.ssh/config" msgstr "Hosty SSH określone w ~/.ssh/config" #: ../kupfer/plugin/trash.py:1 ../kupfer/plugin/trash.py:300 msgid "Trash" msgstr "Kosz" #: ../kupfer/plugin/trash.py:4 msgid "Access trash contents" msgstr "Dostęp do zawartości kosza" #: ../kupfer/plugin/trash.py:38 msgid "Move to Trash" msgstr "Przenieś do kosza" #: ../kupfer/plugin/trash.py:42 #, python-format msgid "Move file %s to trash?" msgstr "Przenieść plik do kosza?" #: ../kupfer/plugin/trash.py:42 ../kupfer/plugin/trash.py:61 msgid "Move" msgstr "Przenieś" #: ../kupfer/plugin/trash.py:58 #, python-format msgid "Move one file to trash?" msgid_plural "Move %(num)s files to trash?" msgstr[0] "Przenieść jedn plik do kosza?" msgstr[1] "Przenieść %(num)s pliki do kosza?" msgstr[2] "Przenieść %(num)s plików do kosza?" #: ../kupfer/plugin/trash.py:88 msgid "Move this file to trash" msgstr "Przenosi plik do kosza" #: ../kupfer/plugin/trash.py:99 msgid "Restore" msgstr "Przywróć" #: ../kupfer/plugin/trash.py:124 msgid "Move file back to original location" msgstr "Przenosi plik z powrotem do pierwotnego położenia" #: ../kupfer/plugin/trash.py:147 msgid "" "Could not delete files:\n" " " msgstr "" "Nie można usunąć plików:\n" " " #: ../kupfer/plugin/trash.py:281 msgid "Trash is empty" msgstr "Kosz jest pusty" #: ../kupfer/plugin/trash.py:285 #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "Koszu zawiera %(num)s plik" msgstr[1] "Kosz zawiera %(num)s pliki" msgstr[2] "Kosz zawiera %(num)s plików" #: ../kupfer/plugin/custom_terminal.py:1 ../kupfer/plugin/custom_terminal.py:54 msgid "Custom Terminal" msgstr "Terminal użytkownika" #: ../kupfer/plugin/custom_terminal.py:3 msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" "Konfiguruj własny emulator terminala.\n" "\n" "Wtyczka dodaje kolejny, alternatywny terminal (do wyboru na stronie głównej) " #: ../kupfer/plugin/custom_terminal.py:27 msgid "Execute flag" msgstr "Parametr wykonania" #: ../kupfer/plugin/triggers.py:3 ../kupfer/plugin/triggers.py:53 msgid "Triggers" msgstr "Wyzwalacze" #: ../kupfer/plugin/triggers.py:7 msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Przypisanie skrótów klawiszowych (wyzwalaczy) do obiektów utworzonych przez " "„Polecenie komponowania”." #: ../kupfer/plugin/triggers.py:185 msgid "Add Trigger..." msgstr "Dodaj wyzwalacz…" #: ../kupfer/plugin/triggers.py:206 msgid "Remove Trigger" msgstr "Usuń wyzwalacz" #: ../kupfer/plugin/brotab.py:1 msgid "Brotab" msgstr "Brotab" #: ../kupfer/plugin/brotab.py:4 ../kupfer/plugin/brotab.py:67 msgid "Firefox Tabs" msgstr "Zakładki Firefox" #: ../kupfer/plugin/brotab.py:81 msgid "Firefox browser tabs" msgstr "Zakładki przeglądarki Firefox" #: ../kupfer/plugin/brotab.py:92 msgid "Activate Tab" msgstr "Aktywuj zakładkę" #: ../kupfer/plugin/brotab.py:106 msgid "Close Tab" msgstr "Zamknij zakładkę" #: ../kupfer/plugin/brotab.py:120 msgid "Get URL" msgstr "Weź URL" #: ../kupfer/plugin/dictionary.py:1 ../kupfer/plugin/dictionary.py:38 msgid "Dictionary" msgstr "Słownik" #: ../kupfer/plugin/dictionary.py:3 msgid "Look up word in dictionary" msgstr "Wyszukuje słowa w słowniku" #: ../kupfer/plugin/dictionary.py:25 msgid "Gnome Dictionary" msgstr "Słownik Gnome" #: ../kupfer/plugin/dictionary.py:28 msgid "Mate Dictionary" msgstr "Słownik Mate" #: ../kupfer/plugin/dictionary.py:30 msgid "Purple" msgstr "Purple" #: ../kupfer/plugin/dictionary.py:31 msgid "Xfce4 Dict" msgstr "Słownik Xfce4" #: ../kupfer/plugin/dictionary.py:32 msgid "GoldenDict" msgstr "GoldenDict" #: ../kupfer/plugin/dictionary.py:48 msgid "Look Up" msgstr "Wyszukaj" #: ../kupfer/plugin/dictionary.py:73 #, python-format msgid "Look up word in %s" msgstr "Wyszukuje słowa w %s" #: ../kupfer/plugin/firefox.py:1 ../kupfer/plugin/firefox.py:43 msgid "Firefox Bookmarks" msgstr "Zakładki programu Firefox" #: ../kupfer/plugin/firefox.py:5 msgid "" "Index of Firefox bookmarks. Bookmark is always opened in default browser." msgstr "" "Indeks zakładek Firefox. Zakładki są zawsze otwierane w domyślnej " "przeglądarce." #: ../kupfer/plugin/firefox.py:67 msgid "Index of Firefox bookmarks" msgstr "Indeks zakładek programu Firefox" #: ../kupfer/plugin/devhelp.py:1 msgid "Devhelp" msgstr "Devhelp" #: ../kupfer/plugin/devhelp.py:3 ../kupfer/plugin/devhelp.py:21 msgid "Search in Devhelp" msgstr "Wyszikaj w programie Devhelp" #: ../kupfer/plugin/chromium.py:3 ../kupfer/plugin/chromium.py:42 msgid "Chromium Bookmarks" msgstr "Zakładki programu Chromium" #: ../kupfer/plugin/chromium.py:5 ../kupfer/plugin/chromium.py:72 msgid "Index of Chromium bookmarks" msgstr "Zakładki programu Chromium" #: ../kupfer/plugin/instapaper.py:1 msgid "Instapaper" msgstr "Instapaper" #: ../kupfer/plugin/instapaper.py:4 ../kupfer/plugin/instapaper.py:28 msgid "Save url to Instapaper" msgstr "Zapisz url do Instapaper" #: ../kupfer/plugin/instapaper.py:18 msgid "Save to Instapaper" msgstr "Zapisz do Instapaper" #: ../kupfer/plugin/tracker1.py:5 msgid "Tracker" msgstr "Tracker" #: ../kupfer/plugin/tracker1.py:10 msgid "Tracker desktop search integration" msgstr "Integracja z programem Tracker" #: ../kupfer/plugin/tracker1.py:51 msgid "Search in Tracker" msgstr "Wyszukaj w programie Tracker" #: ../kupfer/plugin/tracker1.py:60 msgid "Open Tracker Search Tool and search for this term" msgstr "Otwiera narzędzie Tracker i wyszukuje to wyrażenie" #: ../kupfer/plugin/tracker1.py:73 msgid "Get Tracker Results..." msgstr "Pobierz wyniki programu Tracker…" #: ../kupfer/plugin/tracker1.py:108 msgid "Show Tracker results for query" msgstr "Wyświetla wyniki wyszukiwania programu Tracker dla zapytania" #: ../kupfer/plugin/tracker1.py:218 #, python-format msgid "Tracker Search for \"%s\"" msgstr "Wyszukaj \"%s\" w Tracker" #: ../kupfer/plugin/tracker1.py:293 msgid "Tracker Full Text Search" msgstr "Wyszukiwanie pełno-tekstowe w Tracker" #: ../kupfer/plugin/favorites.py:3 ../kupfer/plugin/favorites.py:30 msgid "Favorites" msgstr "Ulubione" #: ../kupfer/plugin/favorites.py:6 msgid "Mark commonly used items and store objects for later use" msgstr "" "Oznaczenie często używanych elementów i zachowanie ich do późniejszego użycia" #: ../kupfer/plugin/favorites.py:144 msgid "Shelf of \"Favorite\" items" msgstr "Zbiór „ulubionych” elementów" #: ../kupfer/plugin/favorites.py:159 msgid "Add to Favorites" msgstr "Dodaj do ulubionych" #: ../kupfer/plugin/favorites.py:173 msgid "Add item to favorites shelf" msgstr "Dodaje element do ulubionych" #: ../kupfer/plugin/favorites.py:183 msgid "Remove from Favorites" msgstr "Usuń z ulubionych" #: ../kupfer/plugin/favorites.py:195 msgid "Remove item from favorites shelf" msgstr "Usuwa element ze zbiouru ulubionych" #: ../kupfer/plugin/firefox_tags.py:1 ../kupfer/plugin/firefox_tags.py:57 msgid "Firefox Tags" msgstr "Tagi Firefox" #: ../kupfer/plugin/firefox_tags.py:3 msgid "Browse Firefox bookmarks by tags" msgstr "Przeglądanie zakładek Firefox" #: ../kupfer/plugin/firefox_tags.py:84 msgid "Index of Firefox bookmarks by tags" msgstr "Indeks zakładek Firefox wg tagów" #: ../kupfer/plugin/firefox_tags.py:111 msgid "Firefox Bookmarks by tag" msgstr "Zakładki programu Firefox wg tagu" #: ../kupfer/plugin/qsicons/__init__.py:24 msgid "Quicksilver Icons" msgstr "Ikony Quicksilver" #: ../kupfer/plugin/textutils.py:3 msgid "Textutils" msgstr "Narzędzia tekstowe" #: ../kupfer/plugin/textutils.py:10 msgid "Action for text, useful text generators and converters." msgstr "Akcje dla tekstu, przydatne generatory i konwertery." #: ../kupfer/plugin/textutils.py:190 msgid "Convert…" msgstr "Konwertuj…" #: ../kupfer/plugin/textutils.py:194 msgid "Convert text with selected tool" msgstr "Konwertuj tekst z użyciem wybranego narzędzia" #: ../kupfer/plugin/textutils.py:199 msgid "Encode text with Base64" msgstr "Koduj tekst jako Base64" #: ../kupfer/plugin/textutils.py:203 msgid "Decode text with Base64" msgstr "Dekoduj tekst w Base64" #: ../kupfer/plugin/textutils.py:207 msgid "Quote URL" msgstr "Quote URL" #: ../kupfer/plugin/textutils.py:208 #, python-format msgid "Replace special characters in string using the %%xx escape." msgstr "Zastępuje specjalne znaki w tekście używając znaczników %%xx." #: ../kupfer/plugin/textutils.py:212 msgid "Unquote URL" msgstr "Unquote URL" #: ../kupfer/plugin/textutils.py:213 #, python-format msgid "Replace %%xx escapes with their single-character equivalent." msgstr "Zastępuje znaczniki %%xx odpowiadającymi im pojedynczymi znakami." #: ../kupfer/plugin/textutils.py:218 msgid "Unix timestamp to date" msgstr "Znacznik czasu Unix do daty" #: ../kupfer/plugin/textutils.py:220 msgid "to lower case" msgstr "do małych liter" #: ../kupfer/plugin/textutils.py:221 msgid "to upper case" msgstr "do dużych liter" #: ../kupfer/plugin/textutils.py:222 msgid "to sentence case" msgstr "jak zdanie" #: ../kupfer/plugin/textutils.py:225 msgid "Capitalize words" msgstr "Każde słowo z dużej litery" #: ../kupfer/plugin/textutils.py:226 msgid "Convert 'some string' to 'Some String'" msgstr "Zmienia 'dany napis' na 'Dany Napis'" #: ../kupfer/plugin/textutils.py:230 msgid "To camel case" msgstr "Do camel case" #: ../kupfer/plugin/textutils.py:231 msgid "Convert 'Some string' to 'comeString'" msgstr "Zmienia 'Dany napis' na 'danyNapis'" #: ../kupfer/plugin/textutils.py:235 msgid "To pascal case" msgstr "Do pascal case" #: ../kupfer/plugin/textutils.py:236 msgid "Convert 'Some string' to 'SomeString'" msgstr "Zmienia 'Dany napis' na 'DanyNapis'" #: ../kupfer/plugin/textutils.py:240 msgid "To constant case" msgstr "Do constant case" #: ../kupfer/plugin/textutils.py:241 msgid "Convert 'some string' to 'SOME_STRING'" msgstr "Zmienia 'dany napis' na 'DANY_NAPIS'" #: ../kupfer/plugin/textutils.py:245 msgid "Camel case to lowercase" msgstr "Camel case do małych liter" #: ../kupfer/plugin/textutils.py:246 msgid "Convert 'SomeString' do 'some string'" msgstr "Zmienia 'DanyNapis' na 'dany napis'" #: ../kupfer/plugin/textutils.py:250 msgid "Constant case to lowercase" msgstr "Constant case do małych liter" #: ../kupfer/plugin/textutils.py:251 msgid "Convert 'SOME_STRING' do 'some string'" msgstr "Zmienia 'DANY_NAPIS' na 'dany napis'" #: ../kupfer/plugin/textutils.py:255 msgid "To valid filename" msgstr "Do poprawnej nazwy pliku" #: ../kupfer/plugin/textutils.py:256 msgid "Convert string to usable file name" msgstr "Zmienia napis na używalną nazwę pliku" #: ../kupfer/plugin/textutils.py:262 msgid "Join lines options" msgstr "Opcje łączenia linii" #: ../kupfer/plugin/textutils.py:263 msgid "Please enter characters to join with" msgstr "Proszę wprowadzić znak użyty do łączenia" #: ../kupfer/plugin/textutils.py:264 msgid "Separator" msgstr "Separator" #: ../kupfer/plugin/textutils.py:275 msgid "Quote and join lines options" msgstr "Opcje cytowania i łączenia linii" #: ../kupfer/plugin/textutils.py:277 msgid "Separator:" msgstr "Separator:" #: ../kupfer/plugin/textutils.py:278 msgid "Quotation character:" msgstr "Znak cytowania:" #: ../kupfer/plugin/textutils.py:289 msgid "Convert lines…" msgstr "Konwertuj linie…" #: ../kupfer/plugin/textutils.py:293 msgid "Convert multiline text with selected tool" msgstr "Konwertuje wieloliniowy tekst z użyciem wybranego narzędzia" #: ../kupfer/plugin/textutils.py:298 msgid "Join lines with..." msgstr "Połącz linie z użyciem..." #: ../kupfer/plugin/textutils.py:299 msgid "Join lines with user selected separator" msgstr "Połącz linie z wybranym separatorem" #: ../kupfer/plugin/textutils.py:303 msgid "Quote and join lines..." msgstr "Cytuj i połącz linie..." #: ../kupfer/plugin/textutils.py:304 msgid "Wrap with quote characters and join lines." msgstr "Cytuj i połącz linie." #: ../kupfer/plugin/textutils.py:309 msgid "Format…" msgstr "Formatuj…" #: ../kupfer/plugin/textutils.py:313 msgid "Format text using selected formatter" msgstr "Formatuje tekst z użyciem wybranego formatera" #: ../kupfer/plugin/textutils.py:318 msgid "strip whitespaces" msgstr "obetnij białe znaki" #: ../kupfer/plugin/textutils.py:322 msgid "format json" msgstr "formatuj json" #: ../kupfer/plugin/textutils.py:326 msgid "compress json" msgstr "kompresuj json" #: ../kupfer/plugin/textutils.py:330 msgid "format xml" msgstr "formatuj xml" #: ../kupfer/plugin/textutils.py:372 msgid "Generators" msgstr "Generatory" #: ../kupfer/plugin/textutils.py:381 #, python-format msgid "Random %(size)d-bytes hex token" msgstr "Losowy, %(size)d-bajtowy token w hex-ie" #: ../kupfer/plugin/textutils.py:387 #, python-format msgid "Random %(size)d-bytes alpha-numeric token" msgstr "Losowy, %(size)d-bajtowy token alfa-numeryczny" #: ../kupfer/plugin/textutils.py:393 msgid "UUID based on host and time" msgstr "UUID oparty o hoście i czasie" #: ../kupfer/plugin/textutils.py:396 msgid "Random UUID" msgstr "Losowy UUID" #: ../kupfer/plugin/textutils.py:399 msgid "Current time in ISO8601 format" msgstr "Bieżący czas w formacie ISO8601" #: ../kupfer/plugin/textutils.py:403 msgid "Current time as Unix timestamp" msgstr "Bieżący czas jako znacznik czasu Unix" #: ../kupfer/plugin/textutils.py:407 msgid "Current time as timestamp" msgstr "Bieżący czas jako znacznik czasu" #: ../kupfer/plugin/textutils.py:421 msgid "Generate text content with selected tool" msgstr "Generuje tekst z użyciem wybranego narzędzia" #~ msgid "Title" #~ msgstr "Tytuł" #~ msgid "message" #~ msgstr "wiadomość" #~ msgid "Convert case…" #~ msgstr "Konwertuj wielkość liter…" #~ msgid "Convert text case" #~ msgstr "Zmienia wielkość liter" #~ msgid "capitalize" #~ msgstr "z dużej litery" #~ msgid "tmuxp Sessions" #~ msgstr "Sesje tmuxp" #, python-format #~ msgid "User search engines (;-separated URLs. Use '%s' for search term" #~ msgstr "" #~ "Wyszukiwarki użytkownika (adresy URL odzielone prz ';'. '%s' zastępuje " #~ "wyszukiwany ciąg" #~ msgid "Directories (;-separated):" #~ msgstr "Katalogi (oddzieleni średnikiem):" #~ msgid "Lock screen command" #~ msgstr "Polecenie blokady ekranu" #~ msgid "Start" #~ msgstr "Początek" #~ msgid "Reveal" #~ msgstr "Wyświetl" #~ msgid "GNOME Keyring" #~ msgstr "Baza kluczy GNOME" #~ msgid "KWallet" #~ msgstr "KWallet" #~ msgid "Unencrypted File" #~ msgstr "Niezaszyfrowany plik" #~ msgid "Empathy" #~ msgstr "Empathy" #~ msgid "Access to Empathy Contacts" #~ msgstr "Dostęp do kontaktów programu Empathy" #~ msgid "Busy" #~ msgstr "Zajęty" #~ msgid "Not Available" #~ msgstr "Nieobecny" #~ msgid "Invisible" #~ msgstr "Niewidoczny" #~ msgid "Offline" #~ msgstr "Rozłączony" #~ msgid "Change Global Status To..." #~ msgstr "Zmień globalny stan na…" #~ msgid "Empathy Contacts" #~ msgstr "Kontakty programu Empathy" #~ msgid "Empathy Account Status" #~ msgstr "Stan konta programu Empathy" #~ msgid "Type to search %s" #~ msgstr "Wprowadzenie tekstu wyszuka %s" #~ msgid "No action" #~ msgstr "Brak działania" #~ msgid "GNOME Terminal Profiles" #~ msgstr "Profile Terminala GNOME" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Uruchomianie profili Terminala GNOME" #~ msgid "Multihead Support" #~ msgstr "Obsługa wielu ekranów" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Oblicza wyrażenia zaczynające się od znaku „=”" #~ msgid "Epiphany Bookmarks" #~ msgstr "Zakładki programu Epiphany" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Indeks zakładek programu Epiphany" #~ msgid "Include visited sites" #~ msgstr "Dołączenie odwiedzonych miejsc" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Wznawia odtwarzanie w programie Rhythmbox" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Wstrzymuje odtwarzanie w programie Rhythmbox" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Przechodzi do następnego utworu w programie Rhythmbox" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Przechodzi do poprzedniego utworu w programie Rhythmbox" #~ msgid "Abiword" #~ msgstr "AbiWord" #~ msgid "Recently used documents in Abiword" #~ msgstr "Ostatnio używane dokumenty programu AbiWord" #~ msgid "Abiword Recent Items" #~ msgstr "Ostatnie dokumenty programu AbiWord" #~ msgid "Ascii & Unicode Icon Set" #~ msgstr "Ikony ASCII i unikodu" #~ msgid "" #~ "Provides the Ascii and Unicode icon sets that use letters and symbols to " #~ "produce icons for the objects found in Kupfer." #~ msgstr "" #~ "Dostarcza zestaw ikon ASCII i unikodu, które używają liter i symboli do " #~ "utworzenia ikon dla obiektów zgromadzonych w programie Kupfer." #~ msgid "Ascii" #~ msgstr "ASCII" #~ msgid "Unicode" #~ msgstr "Unikod" #~ msgid "Configure a custom terminal emulator" #~ msgstr "Konfiguracja własnego emulatora terminala" #~ msgid "Custom Theme" #~ msgstr "Motyw użytkownika" #~ msgid "Use a custom color theme" #~ msgstr "Użycie własnego motywu kolorów" #~ msgid "Theme:" #~ msgstr "Motyw:" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Kontakty programu Evolution" #~ msgid "Compose a new message in Evolution" #~ msgstr "Tworzy nową wiadomość w programie Evolution" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Tworzy nową wiadomość w programie Evolution i załącza plik" #~ msgid "Evolution Address Book" #~ msgstr "Książka adresowa programu Evolution" #~ msgid "Filezilla" #~ msgstr "FileZilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Wyświetla witryny i obsługuje adresy FTP przez program FileZilla" #~ msgid "Open Site with Filezilla" #~ msgstr "Otwórz witrynę za pomocą programu FileZilla" #~ msgid "Filezilla Sites" #~ msgstr "Witryny programu FileZilla" #~ msgid "Sites from Filezilla" #~ msgstr "Witryny z programu FileZilla" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Dostęp do kontaktów programu Gajim" #~ msgid "Free for Chat" #~ msgstr "Chętny do rozmowy" #~ msgid "Gajim Contacts" #~ msgstr "Kontakty programu Gajim" #~ msgid "Gajim Account Status" #~ msgstr "Stan konta programu Gajim" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "" #~ "Wczytuje kontakty i umożliwia tworzenie nowych wiadomości e-mail w " #~ "serwisie Gmail" #~ msgid "Load contacts' pictures" #~ msgstr "Pobieranie obrazów kontaktów" #~ msgid "Load additional information" #~ msgstr "Wczytuje dodatkowe informacje" #~ msgid "Work email" #~ msgstr "Służbowy adres e-mail" #~ msgid "Home email" #~ msgstr "Domowy adres e-mail" #~ msgid "Other email" #~ msgstr "Inny adres e-mail" #~ msgid "Work address" #~ msgstr "Adres służbowy" #~ msgid "Home address" #~ msgstr "Adres domowy" #~ msgid "Other address" #~ msgstr "Inny adres" #~ msgid "Car phone" #~ msgstr "Telefon samochodowy" #~ msgid "Fax" #~ msgstr "Faks" #~ msgid "Home phone" #~ msgstr "Telefon domowy" #~ msgid "Home fax" #~ msgstr "Faks domowy" #~ msgid "Internal phone" #~ msgstr "Telefon wewnętrzny" #~ msgid "Mobile" #~ msgstr "Komórka" #~ msgid "Other" #~ msgstr "Inne" #~ msgid "VOIP" #~ msgstr "VoIP" #~ msgid "Work phone" #~ msgstr "Telefon służbowy" #~ msgid "Work fax" #~ msgstr "Faks służbowy" #~ msgid "Compose Email in Gmail" #~ msgstr "Utwórz wiadomość e-mail w serwisie Gmail" #~ msgid "Open web browser and compose new email in Gmail" #~ msgstr "" #~ "Otwiera przeglądarkę WWW i tworzy nową wiadomość e-mail w serwisie Gmail" #~ msgid "Edit Contact in Gmail" #~ msgstr "Modyfikuj kontakt w serwisie Gmail" #~ msgid "Open web browser and edit contact in Gmail" #~ msgstr "Otwiera przeglądarkę WWW i modyfikuje kontakt w serwisie Gmail" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Kontakty z usług firmy Google (Gmail)" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Wyświetla albumy i umożliwia wysyłanie plików do serwisu Picasa" #~ msgid "Uploading Pictures" #~ msgstr "Wysyłanie obrazów" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Wysyłanie obrazów do serwisu Picasa Web Album" #~ msgid "Creating album:" #~ msgstr "Tworzenie albumu:" #~ msgid "Album created by Kupfer" #~ msgstr "Album utworzony przez program Kupfer" #~ msgid "File:" #~ msgstr "Plik:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "%(num)d album" #~ msgstr[1] "%(num)d albumy" #~ msgstr[2] "%(num)d albumów" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "%(num)s zdjęcie" #~ msgstr[1] "%(num)s zdjęcia" #~ msgstr[2] "%(num)s zdjęć" #~ msgid "Upload to Picasa Album..." #~ msgstr "Prześlij do albumu serwisu Picasa…" #~ msgid "Upload files to Picasa album" #~ msgstr "Przesyła pliki do albumu serwisu Picasa" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Prześlij do serwisu Picasa jako nowy album" #~ msgid "Create album from selected local directory" #~ msgstr "Tworzy album na podstawie zaznaczonego lokalnego katalogu" #~ msgid "Picasa Albums" #~ msgstr "Albumy serwisu Picasa" #~ msgid "User albums in Picasa" #~ msgstr "Albumy użytkownika w serwisie Picasa" #~ msgid "Search Google with results shown directly" #~ msgstr "Wyszukuje w serwisie Google i bezpośrednio wyświetla wyniki" #~ msgid "Show More Results For \"%s\"" #~ msgstr "Wyświetl więcej wyników dla „%s”" #~ msgid "%s total found" #~ msgstr "Odnaleziono razem: %s" #~ msgid "Gwibber" #~ msgstr "Gwibber" #~ msgid "" #~ "Microblogging with Gwibber. Allows sending and receiving messages from " #~ "social networks like Twitter, Identi.ca etc. Requires the package " #~ "'gwibber-service'." #~ msgstr "" #~ "Mikroblogowanie za pomocą programu Gwibber. Umożliwia wysyłanie i " #~ "odbieranie wiadomości z sieci społecznych, takich jak Twitter, Identi.ca " #~ "itd. Wymaga pakietu „gwibber-service”." #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s w serwisie %(service)s" #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s w serwisie %(where)s" #~ msgid "Send message to all Gwibber accounts" #~ msgstr "Wysyła wiadomość do wszystkich kont programu Gwibber" #~ msgid "Send Message To..." #~ msgstr "Wyślij wiadomość do…" #~ msgid "Send message to a Gwibber account" #~ msgstr "Wysyła wiadomość do kont programu Gwibber" #~ msgid "Send message to selected Gwibber account" #~ msgstr "Wysyła wiadomość do zaznaczonego konta programu Gwibber" #~ msgid "Reply..." #~ msgstr "Odpowiedz…" #~ msgid "Delete Message" #~ msgstr "Usuń wiadomość" #~ msgid "Send Private Message..." #~ msgstr "Wyślij prywatną wiadomość…" #~ msgid "Send direct message to user" #~ msgstr "Wysyła bezpośrednią wiadomość do użytkownika" #~ msgid "Retweet" #~ msgstr "Prześlij dalej" #~ msgid "Retweet To..." #~ msgstr "Prześlij dalej do…" #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Przesyła wiadomość do wszystkich kont programu Gwibber" #~ msgid "Retweet message to a Gwibber account" #~ msgstr "Przesyła wiadomość do konta programu Gwibber" #~ msgid "Open in Browser" #~ msgstr "Otwórz w przeglądarce" #~ msgid "Open message in default web browser" #~ msgstr "Otwiera wiadomość w domyślnej przeglądarce" #~ msgid "Gwibber Accounts" #~ msgstr "Konta programu Gwibber" #~ msgid "Accounts configured in Gwibber" #~ msgstr "Konta skonfigurowane w programie Gwibber" #~ msgid "Gwibber Messages" #~ msgstr "Wiadomości programu Gwibber" #~ msgid "Recent messages received by Gwibber" #~ msgstr "Ostatnie wiadomości odebrane przez program Gwibber" #~ msgid "Gwibber Messages for %s" #~ msgstr "Wiadomości programu Gwibber dla serwisu %s" #~ msgid "Gwibber Streams" #~ msgstr "Strumienie programu Gwibber" #~ msgid "Streams configured in Gwibber" #~ msgstr "Strumienie skonfigurowane w programie Gwibber" #~ msgid "Gwibber Messages in %s" #~ msgstr "Wiadomości programu Gwibber w strumieniu %s" #~ msgid "Gwibber (Simple)" #~ msgstr "Gwibber (prosty)" #~ msgid "Send updates via the microblogging client Gwibber" #~ msgstr "Wysyła aktualizacje przez klienta mikroblogowania Gwibber" #~ msgid "Send Update" #~ msgstr "Wyślij aktualizację" #~ msgid "Unable to activate Gwibber service" #~ msgstr "Nie można aktywować serwisu Gwibber" #~ msgid "OpenOffice / LibreOffice" #~ msgstr "OpenOffice.org/LibreOffice" #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Ostatnio używane dokumenty programu OpenOffice.org/LibreOffice" #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "Ostatnie dokumenty programu OpenOffice.org/LibreOffice" #~ msgid "Opera Mail" #~ msgstr "Opera Mail" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Kontakty i działania programu Opera Mail" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Tworzy nową wiadomość w programie Opera Mail" #~ msgid "Opera Mail Contacts" #~ msgstr "Kontakty programu Opera Mail" #~ msgid "Contacts from Opera Mail" #~ msgstr "Kontakty z książki adresowej Opera Mail" #~ msgid "Opera Bookmarks" #~ msgstr "Zakładki programu Opera" #~ msgid "Index of Opera bookmarks" #~ msgstr "Indeks zakładek programu Opera" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Szybki dostęp do sesji programu PuTTY" #~ msgid "reStructuredText" #~ msgstr "reStructuredText" #~ msgid "Render reStructuredText and show the result" #~ msgstr "Renderuje pliki w formacie reStructuredText i wyświetla wynik" #~ msgid "View as HTML Document" #~ msgstr "Wyświetl jako dokument HTML" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "" #~ "Uruchamia, zatrzymuje lub ponownie uruchamia usługi systemowe przez " #~ "skrypty startowe" #~ msgid "Sudo-like Command" #~ msgstr "Polecenie podobne do sudo" #~ msgid "Start Service" #~ msgstr "Uruchom usługę" #~ msgid "Stop Service" #~ msgstr "Zatrzymaj usługę" #~ msgid "%s Service" #~ msgstr "Usługa %s" #~ msgid "Access to Skype contacts" #~ msgstr "Dostęp do kontaktów programu Skype" #~ msgid "Skype Me" #~ msgstr "Skype Me" #~ msgid "Logged Out" #~ msgstr "Wylogowano" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Zadzwoń" #~ msgid "Place a call to contact" #~ msgstr "Nawiązuje połączenie z kontaktem" #~ msgid "Skype Contacts" #~ msgstr "Kontakty programu Skype" #~ msgid "Skype Statuses" #~ msgstr "Stany programu Skype" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Woluminy z historii programu TrueCrypt" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "Wolumin programu TrueCrypt: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Zamontuj wolumin" #~ msgid "Mount in Truecrypt" #~ msgstr "Zamontuj w programie TrueCrypt" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Próbuje zamontować plik jako wolumin programu TrueCrypt" #~ msgid "Dismount All Volumes" #~ msgstr "Odmontuj wszystkie woluminy" #~ msgid "TrueCrypt Volumes" #~ msgstr "Woluminy programu TrueCrypt" #~ msgid "Terminal Server Client" #~ msgstr "Klient usług terminala" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Sesje zapisane w Kliencie Usług Terminala" #~ msgid "TSClient sessions" #~ msgstr "Sesje Klienta Usług Terminala" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Sesje zapisane w Kliencie Usług Terminala" #~ msgid "Recently used documents in Vim" #~ msgstr "Ostatnio używane dokumenty w programie Vim" #~ msgid "Close (Save All)" #~ msgstr "Zamknij (zapisz wszystkie)" #~ msgid "Send..." #~ msgstr "Wyślij…" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Zakładki i działania programu Vinagre" #~ msgid "Start Vinagre Session" #~ msgstr "Rozpocznij sesję programu Vinagre" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "Dostęp do stron zapisanych w programie Zim" #~ msgid "Page names start with :colon" #~ msgstr "Nazwy stron rozpoczynają się od dwukropka" #~ msgid "Default page name for quick notes" #~ msgstr "Domyślna nazwa strony dla szybkich notatek" #~ msgid "Note %x %X" #~ msgstr "Notatka %x %X" #~ msgid "" #~ "Strftime tags can be used: %H - hour, %M - minutes, etc\n" #~ "Please check python documentation for details.\n" #~ "NOTE: comma will be replaced by _" #~ msgstr "" #~ "Można używać znaczników strftime: %H — godzina, %M — minuta itp.\n" #~ "Więcej informacji można znaleźć w dokumentacji języka Python.\n" #~ "Uwaga: przecinki zostaną zastąpione znakiem _" #~ msgid "Default namespace for quick notes" #~ msgstr "Domyślna przestrzeń nazw dla szybkich notatek" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Strona programu Zim w notatniku „%s”" #~ msgid "Create page in default notebook" #~ msgstr "Tworzy stronę w domyślnym notatniku" #~ msgid "Create Zim Page In..." #~ msgstr "Utwórz stronę programu Zim w…" #~ msgid "Insert QuickNote into Zim" #~ msgstr "Wstaw szybką notatkę do programu Zim" #~ msgid "Quick note selected text into Zim notebook" #~ msgstr "Tworzy notatkę z zaznaczonego tekstu w notatniku programu Zim" #~ msgid "Create Subpage..." #~ msgstr "Utwórz podstronę…" #~ msgid "Zim Notebooks" #~ msgstr "Notatniki programu Zim" #~ msgid "Zim Pages" #~ msgstr "Strony programu Zim" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Strony w notatnikach programu Zim" kupfer-328/po/pt.po000066400000000000000000001731331500175051100142700ustar00rootroot00000000000000# Portuguese translation for the kupfer package # Traducção para Português de Kupfer # Copyright (C) 2009 Ulrik Sverdrup # This file is distributed under the same license as the kupfer package. (GPLv3) # Ulrik Sverdrup , 2009. # Pedro Albuquerque , 2015. # msgid "" msgstr "" "Project-Id-Version: kupfer beta\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2015-10-31 09:41+0000\n" "Last-Translator: Pedro Albuquerque \n" "Language-Team: Português \n" "Language: pt\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\n" "X-Generator: Gtranslator 2.91.6\n" "X-Language: pt_PT\n" "X-Source-Language: C\n" msgid "User credentials" msgstr "Credenciais do utilizador" msgid "_User:" msgstr "_Utilizador:" msgid "_Password:" msgstr "_Senha:" msgid "_Change" msgstr "_Alterar" msgid "Set Keyboard Shortcut" msgstr "Definir atalho de teclado" msgid "Please press desired key combination" msgstr "Por favor, prima as teclas desejadas" msgid "Keybinding could not be bound" msgstr "Atalho de teclado não encontrado" msgid "Kupfer Preferences" msgstr "Preferências do Kupfer" msgid "Start automatically on login" msgstr "Iniciar automaticamente no início da sessão" msgid "Start" msgstr "Início" msgid "Show icon in notification area" msgstr "Mostrar ícone na área de notificação" msgid "Icon set:" msgstr "Conjunto de ícones:" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" msgid "Terminal emulator:" msgstr "Emulador de terminal:" msgid "Desktop Environment" msgstr "Ambiente da área de trabalho" msgid "General" msgstr "Geral" msgid "Global Keyboard Shortcuts" msgstr "Atalhos de teclado globais" msgid "Reset" msgstr "Repor" msgid "Browser Keyboard Shortcuts" msgstr "Atalhos de teclado do navegador" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "Usar comandos de tecla única (espaço, /, ponto, vírgula, etc.)" msgid "Keyboard" msgstr "Teclado" msgid "Plugins" msgstr "Extensões" msgid "Inclusion in Top Level Searches" msgstr "Inclusão em procuras de nível superior" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "Origens marcadas têm os seus objetos incluídos em procuras de nível " "superior.\n" "Os conteúdos de uma origem não marcada só estão disponíveis localizando o " "seu subcatálogo." msgid "Indexed Folders" msgstr "Pastas indexadas" msgid "Folders whose files are always available in the catalog." msgstr "Pastas cujos ficheiros estão sempre disponíveis no catálogo." msgid "Catalog" msgstr "Catálogo" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Lançador de aplicações" msgid "Convenient command and access tool for applications and documents" msgstr "Ferramenta conveniente para acesso e gestão de aplicações e documentos" msgid "Execute in Kupfer" msgstr "Executar no Kupfer" msgid "Saved Kupfer Command" msgstr "Comando Kupfer gravado" #, python-format msgid "Could not to carry out '%s'" msgstr "Impossível completar \"%s\"" #, python-format msgid "\"%s\" produced a result" msgstr "\"%s\" produziu um resultado" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Sem permissão para executar \"%s\" (não executável)" #, python-format msgid "Command in \"%s\" is not available" msgstr "O comando em \"%s\" não está disponível" #, python-format msgid "Keyboard relay is active for display %s" msgstr "Desvio de teclado ativo para o ecrã %s" msgid "do not present main interface on launch" msgstr "não apresentar ambiente principal ao iniciar" msgid "list available plugins" msgstr "listar extensões disponíveis:" msgid "enable debug info" msgstr "ativar mensagens de depuração" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "executar extensão ajudante" msgid "show usage help" msgstr "Mostrar ajuda" msgid "show version information" msgstr "Mostrar versão da aplicação" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Uso: kupfer [OPÇÕES | FICHEIRO ... ]" msgid "Available plugins:" msgstr "Extensões disponíveis:" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "Escrever p/ buscar" #, python-format msgid "%s is empty" msgstr "%s está vazio" msgid "Text" msgstr "Texto" msgid "Run after Delay..." msgstr "Executar após..." msgid "Perform command after a specified time interval" msgstr "Executar comando depois de um intervalo de tempo especificado" msgid "Multiple Objects" msgstr "Múltiplos objetos" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s objeto" msgstr[1] "%s objetos" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "desconhecido" msgid "Aim" msgstr "Objetivo" msgid "Google Talk" msgstr "Google Talk" msgid "ICQ" msgstr "ICQ" msgid "MSN" msgstr "MSN" msgid "QQ" msgstr "QQ" msgid "Yahoo" msgstr "Yahoo" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "%s não suporta esta operação" msgid "Can not be used with multiple objects" msgstr "Não pode ser usado com múltiplos objetos" msgid "Open" msgstr "Abrir" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Sem aplicação predefinida para%(file)s (%(type)s) " #, python-format msgid "Please use \"%s\"" msgstr "Por favor, use \"%s\"" msgid "Set Default Application..." msgstr "Escolher aplicação predefinida..." msgid "Open with default application" msgstr "Abrir com a aplicação predefinida" msgid "Reveal" msgstr "Revelar" msgid "Open parent folder" msgstr "Abrir pasta-mãe" msgid "Open Terminal Here" msgstr "Abrir terminal aqui" msgid "Open this location in a terminal" msgstr "Abrir esta localização num terminal" msgid "Run in Terminal" msgstr "Executar no terminal" msgid "Run (Execute)" msgstr "Executar" msgid "Run this program in a Terminal" msgstr "Executar esta aplicação num terminal" msgid "Run this program" msgstr "Executar esta aplicação" msgid "Go To" msgstr "Ir para" msgid "Open URL" msgstr "Abrir URL" msgid "Open URL with default viewer" msgstr "Abrir URL com navegador predefinido" msgid "Launch" msgstr "Iniciar" msgid "Show application window" msgstr "Mostrar janela da aplicação" msgid "Launch application" msgstr "Iniciar aplicação" msgid "Launch Again" msgstr "Iniciar de novo" msgid "Launch another instance of this application" msgstr "Iniciar outra instância desta aplicação" msgid "Close" msgstr "Fechar" msgid "Attempt to close all application windows" msgstr "Tentar fechar todas as janelas de aplicações" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Executar" msgid "Perform command" msgstr "Realizar ação" msgid "(Empty Text)" msgstr "(texto vazio)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "\"%(text)s\"" msgstr[1] "(%(num)d linhas) \"%(text)s\"" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s et. al." #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Fonte recursiva de %(dir)s, (%(levels)d níveis)" #, python-format msgid "Directory source %s" msgstr "Pasta fonte %s" msgid "Home Folder" msgstr "Pasta pessoal" msgid "Catalog Index" msgstr "Índice de catálogo" msgid "An index of all available sources" msgstr "Um índice de todas as fontes disponíveis" msgid "Root catalog" msgstr "Catálogo raiz" msgid "Please Configure Plugin" msgstr "Por favor, configure a extensão" #, python-format msgid "Plugin %s is not configured" msgstr "A extensão %s não está configurada" #, python-format msgid "Invalid user credentials for %s" msgstr "Credenciais de utilizador inválidas para %s" msgid "Applications" msgstr "Aplicações" msgid "All applications and preferences" msgstr "Todas as aplicações e preferências" msgid "Applications for Desktop Environment" msgstr "Aplicações para ambiente gráfico" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "Abrir com..." msgid "Open with any application" msgstr "Abrir com qualquer aplicação" msgid "Set default application to open this file type" msgstr "Escolher aplicação predefinida para abrir este tipo de ficheiro" #, fuzzy msgid "Reset Associations" msgstr "Ações de URL" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "Arquivos profundos" msgid "Allow browsing inside compressed archive files" msgstr "Permitir navegação dentro de arquivos comprimidos" #, python-format msgid "Content of %s" msgstr "Conteúdo de %s" msgid "Archive Manager" msgstr "Gestor de arquivos" msgid "Use Archive Manager actions" msgstr "Usar ações do Gestor de arquivos" msgid "Compressed archive type for 'Create Archive In'" msgstr "Tipo de formato de compressão para \"Criar arquivo em\"" msgid "Extract Here" msgstr "Extrair aqui" msgid "Extract compressed archive" msgstr "Extrair arquivo comprimido" msgid "Create Archive" msgstr "Criar arquivo" msgid "Create a compressed archive from folder" msgstr "Criar arquivo comprimido da pasta" msgid "Create Archive In..." msgstr "Criar arquivo em..." #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Arquivo" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "Controlar a fila de espera do Audacious " msgid "Include songs in top level" msgstr "Incluir músicas no nível superior" msgid "Enqueue" msgstr "Colocar em fila de espera" msgid "Add track to the Audacious play queue" msgstr "Adicionar faixas à fila de espera do Audacious" msgid "Dequeue" msgstr "Tirar da fila de espera" msgid "Remove track from the Audacious play queue" msgstr "Remover faixa da fila de espera de Audacious" msgid "Play" msgstr "Reproduzir" msgid "Jump to track in Audacious" msgstr "Saltar para faixa no Audacious" msgid "Resume playback in Audacious" msgstr "Continuar reprodução no Audacious" msgid "Pause" msgstr "Pausar" msgid "Pause playback in Audacious" msgstr "Pausar reprodução no Audacious" msgid "Next" msgstr "Seguinte" msgid "Jump to next track in Audacious" msgstr "Saltar para a faixa seguinte no Audacious" msgid "Previous" msgstr "Anterior" msgid "Jump to previous track in Audacious" msgstr "Saltar para a faixa anterior no Audacious" msgid "Clear Queue" msgstr "Limpar fila" msgid "Clear the Audacious play queue" msgstr "Limpar a fila de espera de Audacious" msgid "Shuffle" msgstr "Baralhar" msgid "Toggle shuffle in Audacious" msgstr "Alternar baralhar no Audacious" msgid "Repeat" msgstr "Repetir" msgid "Toggle repeat in Audacious" msgstr "Alternar repetição no Audacious" msgid "Show Playing" msgstr "Mostrar em reprodução" msgid "Tell which song is currently playing" msgstr "Mostrar que música se está reproduzir atualmente" msgid "Playlist" msgstr "Lista de reprodução" msgid "Calculator" msgstr "Calculadora" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "Calcular" msgid "Clipboards" msgstr "Áreas de transferência" msgid "Recent clipboards and clipboard proxy objects" msgstr "Objetos recentes de área de transferência e proxy" msgid "Number of recent clipboards to remember" msgstr "Número de elementos recentes na área de transferência a lembrar" msgid "Include selected text in clipboard history" msgstr "Incluir texto selecionado no histórico da área de transferência" msgid "Copy selected text to primary clipboard" msgstr "Copiar texto selecionado para a área de transferência primária" msgid "Selected Text" msgstr "Texto selecionado" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Área de transferência \"%(desc)s\"" msgstr[1] "Área de transferência com %(num)d linhas \"%(desc)s\"" msgid "Clipboard Text" msgstr "Texto da área de transferência" msgid "Clipboard File" msgstr "Ficheiro da área de transferência" msgid "Clipboard Files" msgstr "Ficheiros da área de transferência" msgid "Clear" msgstr "Limpar" msgid "Remove all recent clipboards" msgstr "Remover todos os elementos recentes na área de transferência" msgid "Shell Commands" msgstr "Comandos de consola" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Executar programas na linha de comando. Ações marcadas com o símbolo %s são " "executadas num subterminal." msgid "Run (Get Output)" msgstr "Executar (obter saída)" msgid "Run program and return its output" msgstr "Executar o programa e devolver a sua saída" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "Passar a comando..." msgid "Run program with object as an additional parameter" msgstr "Executar o programa com o objeto como parâmetro adicional" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "Escrever para comando..." msgid "Run program and supply text on the standard input" msgstr "Executar o programa e fornecer texto na entrada padrão" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "Filtrar através do comando..." msgid "Run command-line programs" msgstr "Executar aplicações de linha de comando" msgid "GTK+" msgstr "GTK+" msgid "GNOME Terminal" msgstr "Terminal GNOME" msgid "XFCE Terminal" msgstr "Terminal XFCE" msgid "LXTerminal" msgstr "LXTerminal" msgid "X Terminal" msgstr "Terminal X" msgid "Urxvt" msgstr "Urxvt" msgid "Konsole" msgstr "Konsole" msgid "Save As..." msgstr "Gravar como..." #, fuzzy msgid "Restart Kupfer" msgstr "Reinciar serviço" msgid "Quit" msgstr "Sair" msgid "Quit Kupfer" msgstr "Fechar o Kupfer" msgid "About Kupfer" msgstr "Sobre o Kupfer" msgid "Show information about Kupfer authors and license" msgstr "Mostrar informação sobre os autores do Kupfer e licença" msgid "Kupfer Help" msgstr "Ajuda do Kupfer" msgid "Get help with Kupfer" msgstr "Obter ajuda para o Kupfer" msgid "Show preferences window for Kupfer" msgstr "Mostrar janela de preferências do Kupfer" msgid "Search Contents" msgstr "Procurar conteúdo" msgid "Search inside this catalog" msgstr "Procurar dentro do catálogo" msgid "Copy" msgstr "Copiar" msgid "Copy to clipboard" msgstr "Copiar para a área de transferência" msgid "Rescan" msgstr "Redigitalizar" msgid "Force reindex of this source" msgstr "Forçar reindexação desta fonte" msgid "Last Command" msgstr "Último comando" msgid "Internal Kupfer Objects" msgstr "Objetos internos do Kupfer" msgid "Last Result" msgstr "Último resultado" msgid "Command Results" msgstr "Resultados do comando" msgid "Custom Terminal" msgstr "Terminal personalizado" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Comando" msgid "Execute flag" msgstr "Executar bandeira" msgid "Default Email Client" msgstr "Cliente de email predefinido" msgid "Compose email using the system's default mailto: handler" msgstr "Compor email usando o gestor de mailto: predefinido do sistema" #, fuzzy msgid "Compose Email To" msgstr "Compor email" msgid "Dictionary" msgstr "Dicionário" msgid "Look up word in dictionary" msgstr "Procurar palavra em dicionário" msgid "Look Up" msgstr "Procurar" msgid "Documents" msgstr "Documentos" msgid "Recently used documents and bookmarked folders" msgstr "Documentos recentemente usados e pastas marcadas" msgid "Max recent document days" msgstr "Nº. máximo de dias para documentos recentes" msgid "Recent Items" msgstr "Itens recentes" msgid "Recently used documents" msgstr "Documentos usados recentemente" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "%s documentos" #, python-format msgid "Recently used documents for %s" msgstr "Documentos recentes para %s" msgid "Places" msgstr "Locais" msgid "Bookmarked folders" msgstr "Pastas marcadas" msgid "DuckDuckGo Search" msgstr "Procura DuckDuckGo" msgid "Search the web securely with DuckDuckGo" msgstr "Procurar na web com segurança com o DuckDuckGo" msgid "Favorites" msgstr "Favoritos" msgid "Mark commonly used items and store objects for later use" msgstr "Marcar itens normalmente usados e armazenar objetos para uso posterior" msgid "Shelf of \"Favorite\" items" msgstr "Prateleira de itens favoritos" msgid "Add to Favorites" msgstr "Adicionar aos favoritos" msgid "Add item to favorites shelf" msgstr "Adicionar item à prateleira dos favoritos" msgid "Remove from Favorites" msgstr "Remover dos favoritos" msgid "Remove item from favorites shelf" msgstr "Remover item da prateleira dos favoritos" msgid "File Actions" msgstr "Ações de ficheiros" msgid "More file actions" msgstr "Mais ações de ficheiros" msgid "Move To..." msgstr "Mover para..." msgid "Move file to new location" msgstr "Mover ficheiro para nova localização" msgid "Rename To..." msgstr "Renomear para..." msgid "Copy To..." msgstr "Copiar para..." msgid "Copy file to a chosen location" msgstr "Copiar ficheiro para uma localização escolhida" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "Glob" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "Ações de alto nível" msgid "Tools to work with commands as objects" msgstr "Ferramentas para trabalhar com comandos como objetos" msgid "Select in Kupfer" msgstr "Selecionar no Kupfer" #, python-format msgid "Result of %s (%s)" msgstr "Resultados de %s (%s)" msgid "Run (Take Result)" msgstr "Executar (obter resultado)" msgid "Take the command result as a proxy object" msgstr "Receber o resultado do comando como um objeto proxy" msgid "Run (Discard Result)" msgstr "Executar (descartar resultado)" msgid "Image Tools" msgstr "Ferramentas de imagem" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Ferramentas de transformação de imagem" msgid "Scale..." msgstr "Escalar..." msgid "Scale image to fit inside given pixel measure(s)" msgstr "Redimensionar imagem para caber num espaço dado (em pixels)" msgid "Rotate Clockwise" msgstr "Rodar à direita" msgid "Rotate Counter-Clockwise" msgstr "Rodar à esquerda" msgid "Autorotate" msgstr "Rodar automaticamente" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "Rodar JPEG (no sítio) segundo os metadados EXIF" msgid "Kupfer Plugins" msgstr "Extensões do Kupfer" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Aceder à lista de extensões a partir do Kupfer" msgid "Show Information" msgstr "Mostrar informação" msgid "Show Source Code" msgstr "Mostrar código fonte" msgid "enabled" msgstr "ativado" msgid "disabled" msgstr "desativado" msgid "Notes" msgstr "Notas" msgid "Gnote or Tomboy notes" msgstr "Notas do gNote ou Tomboy" msgid "Work with application" msgstr "Trabalhar com a aplicação" msgid "Open with notes application" msgstr "Abrir com aplicação de notas" msgid "Append to Note..." msgstr "Acrescentar à nota..." msgid "Add text to existing note" msgstr "Adicionar texto a nota existente" msgid "Create Note" msgstr "Criar nota" msgid "Create a new note from this text" msgstr "Criar uma nova nota a partir deste texto" msgid "Get Note Search Results..." msgstr "Obter resultados de procura de nota..." msgid "Show search results for this query" msgstr "Mostrar resultados de procura para esta consulta" #, python-format msgid "today, %s" msgstr "hoje, %s" #, python-format msgid "yesterday, %s" msgstr "ontem, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Última atualização %s" msgid "Quicksilver Icons" msgstr "Ícones Quicksilver" msgid "Quick Image Viewer" msgstr "Visualizador Quick Image" msgid "View Image" msgstr "Ver imagem" msgid "GNU Screen" msgstr "GNU Screen" msgid "Active GNU Screen sessions" msgstr "Sessões ativas do GNU Screen" msgid "Attached" msgstr "Anexado" msgid "Detached" msgstr "Não anexado" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "%(status)s sessão %(pid)s) criada %(time)s" msgid "Screen Sessions" msgstr "Sessões de ecrã" msgid "Attach" msgstr "Anexar" msgid "Send Keys" msgstr "Enviar chaves" msgid "Send synthetic keyboard events using xautomation" msgstr "Enviar eventos sintéticos de teclado com o xautomation" msgid "Paste to Foreground Window" msgstr "Colar na janela de 1º plano" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "" "Copiar para a área de transferência e enviar Ctrl+V para a janela de 1º plano" msgid "Send keys to foreground window" msgstr "Enviar teclas para a janela de 1º plano" msgid "Type Text" msgstr "Digitar texto" msgid "Type the text to foreground window" msgstr "Digitar o texto na janela de 1º plano" msgid "GNOME Session Management" msgstr "Gestão de sessão GNOME" msgid "Special items and actions for GNOME environment" msgstr "Itens e ações especiais para o ambiente GNOME" msgid "Log Out..." msgstr "Terminar sessão..." msgid "Log out or change user" msgstr "Terminar sessão ou alterar utilizador" msgid "Shut Down..." msgstr "Encerrar..." msgid "Shut down, restart or suspend computer" msgstr "Encerrar, reiniciar ou suspender o computador" msgid "Lock Screen" msgstr "Trancar ecrã" msgid "Enable screensaver and lock" msgstr "Iniciar proteção de ecrã e trancar" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "Gestão de sessão XFCE" msgid "Special items and actions for XFCE environment" msgstr "Itens e ações especiais para o ambiente XFCE" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "Máquinas SSH" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "Adiciona as máquinas SSH encontradas em ~/.ssh/config." msgid "SSH host" msgstr "Máquina SSH" msgid "Connect" msgstr "Ligar" msgid "Connect to SSH host" msgstr "Ligar à máquina SSH" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "Máquinas SSH especificadas em ~/.ssh/config" msgid "No D-Bus connection to desktop session" msgstr "Sem ligação D-Bus à sessão da área de trabalho" msgid "GNOME Keyring" msgstr "GNOME Keyring" msgid "KWallet" msgstr "KWallet" msgid "Unencrypted File" msgstr "Ficheiro não encriptado" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "O comando em \"%s\" não está disponível" msgid "Document Templates" msgstr "Modelos de documento" msgid "Create new documents from your templates" msgstr "Criar novos documentos a partir dos seus modelos" #, python-format msgid "%s template" msgstr "Modelo %s" msgid "Empty File" msgstr "Ficheiro vazio" msgid "New Folder" msgstr "Nova pasta" msgid "Create New Document..." msgstr "Criar novo documento..." msgid "Create a new document from template" msgstr "Criar um novo documento a partir de um modelo" msgid "Create Document In..." msgstr "Criar documento em..." msgid "Textfiles" msgstr "Ficheiros de texto" msgid "Append To..." msgstr "Acrescentar a..." msgid "Append..." msgstr "Acrescentar..." msgid "Write To..." msgstr "Escrever em..." msgid "Get Text Contents" msgstr "Obter conteúdo de texto" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "Ações do gestor de ficheiros Thunar" msgid "Select in File Manager" msgstr "Selecionar no gestor de ficheiros" msgid "Show Properties" msgstr "Mostrar propriedades" msgid "Show information about file in file manager" msgstr "Mostrar informação sobre o ficheiro no gestor de ficheiros" msgid "Send To..." msgstr "Enviar para..." msgid "Symlink In..." msgstr "Ligação simbólica em..." msgid "Create a symlink to file in a chosen location" msgstr "Criar ligação simbólica a ficheiro numa localização escolhida" msgid "Empty Trash" msgstr "Esvaziar o lixo" msgid "Thunar Send To Objects" msgstr "Objetos Enviar para do Thunar" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Contactos e ações do Thunderbird/Icedove" msgid "Compose New Email" msgstr "Compor novo email" msgid "Compose a new message in Thunderbird" msgstr "Compor uma nova mensagem no Thunderbird" #, fuzzy msgid "Attach in Email To..." msgstr "Enviar email para..." #, fuzzy msgid "Compose Email With" msgstr "Compor email" #, fuzzy msgid "Compose a new message using the text as body" msgstr "Compor uma nova mensagem no Thunderbird" msgid "Thunderbird Address Book" msgstr "Livro de endereços de Thunderbird" msgid "Contacts from Thunderbird Address Book" msgstr "Contactos do livro de endereços do Thunderbird" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Topo" msgid "Show running tasks and allow sending signals to them" msgstr "Mostrar tarefas a correr e permitir enviar-lhes sinais" msgid "Sort Order" msgstr "Ordem" msgid "Commandline" msgstr "Linha de comando" msgid "CPU usage (descending)" msgstr "Uso da CPU (decrescente)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Uso da memória (decrescente)" msgid "Send Signal..." msgstr "Enviar sinal..." msgid "Signals" msgstr "Sinais" msgid "Running Tasks" msgstr "Tarefas em curso" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% tempo: %(time)s" msgid "Running tasks for current user" msgstr "Tarefas em curso para o utilizador atual" msgid "Trash" msgstr "Lixo" msgid "Access trash contents" msgstr "Aceder ao conteúdo do lixo" msgid "Move to Trash" msgstr "Mover para o lixo" msgid "Move this file to trash" msgstr "Mover este ficheiro para o lixo" msgid "Restore" msgstr "Restaurar" msgid "Move file back to original location" msgstr "Mover ficheiro para localização original" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "O lixo está vazio" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "O lixo contém um ficheiro" msgstr[1] "O lixo contém %(num)s ficheiros" msgid "Triggers" msgstr "Acionadores" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Designar atalhos globais (triggers) a objetos criados com \"Comando composto" "\"." msgid "Add Trigger..." msgstr "Adicionar acionador..." msgid "Remove Trigger" msgstr "Remover acionador..." msgid "URL Actions" msgstr "Ações de URL" msgid "Download and Open" msgstr "Transferir e abrir" msgid "Download To..." msgstr "Transferir para..." msgid "Download URL to a chosen location" msgstr "Transferir URL para uma localização escolhida" msgid "Wikipedia" msgstr "Wikipedia" msgid "Search in Wikipedia" msgstr "Procurar na Wikipedia" msgid "Wikipedia language" msgstr "Linguagem da Wikipedia" #. TRANS: Default wikipedia language code msgid "en" msgstr "pt" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Procurar por este termo em %s.wikipedia.org" msgid "Window List" msgstr "Lista de janelas" msgid "All windows on all workspaces" msgstr "Todas as janelas em todas as áreas de trabalho" msgid "Activate" msgstr "Ativar" msgid "Shade" msgstr "Com sombra" msgid "Unshade" msgstr "Sem sombra" msgid "Minimize" msgstr "Minimizar" msgid "Unminimize" msgstr "Restaurar" msgid "Maximize" msgstr "Maximizar" msgid "Unmaximize" msgstr "Restaurar" msgid "Maximize Vertically" msgstr "Maximizar verticalmente" msgid "Unmaximize Vertically" msgstr "Restaurar verticalmente" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Janelas em %(wkspc)s" msgid "Frontmost Window" msgstr "Janela mais à frente" msgid "Next Window" msgstr "Janela seguinte" msgid "Jump to this window's workspace and focus" msgstr "Saltar para a área de trabalho desta janela e focar" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "%d janela" msgstr[1] "%d janelas" msgid "Active workspace" msgstr "Área de trabalho ativa" msgid "Jump to this workspace" msgstr "Saltar para esta área de trabalho" msgid "Workspaces" msgstr "Áreas de trabalho" msgid "Volumes and Disks" msgstr "Volumes e discos" msgid "Mounted volumes and disks" msgstr "Volumes montados e discos" #, python-format msgid "Volume mounted at %s" msgstr "Volume montado em %s" msgid "Unmount" msgstr "Desmontar" msgid "Unmount this volume" msgstr "Desmontar este volume" msgid "Eject" msgstr "Ejetar" msgid "Unmount and eject this media" msgstr "Desmontar e ejetar este suporte" msgid "Show Text" msgstr "Mostrar texto" msgid "Display text in a window" msgstr "Mostrar texto numa janela" msgid "Large Type" msgstr "Tipo grande" msgid "Show Notification" msgstr "Mostrar notificação" msgid "Tracker" msgstr "Tracker" msgid "Tracker desktop search integration" msgstr "Integração com o Tracker" msgid "Search in Tracker" msgstr "Procurar no Tracker" msgid "Open Tracker Search Tool and search for this term" msgstr "Abrir ferramenta de procura do Tracker e procurar por este termo" msgid "Get Tracker Results..." msgstr "Obter resultados do Tracker..." msgid "Show Tracker results for query" msgstr "Mostrar resultados do Tracker para a consulta" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "Resultados para \"%s\"" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "Procurar ficheiros" msgid "Search filesystem using locate" msgstr "Procurar no sistema de ficheiros usando locate" msgid "Ignore case distinctions when searching files" msgstr "Não diferenciar maiúsculas de minúsculas ao procurar por ficheiros" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Marcadores do Firefox" msgid "Index of Firefox bookmarks" msgstr "Índice de marcadores do Firefox" #, fuzzy msgid "Firefox Keywords" msgstr "Marcadores do Firefox" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "Procurar na web com os motores de procura OpenSearch" msgid "Search With..." msgstr "Procurar com..." msgid "Search For..." msgstr "Procurar por..." #, fuzzy msgid "Search Terms" msgstr "Motores de procura" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Por favor, use \"%s\"" #, fuzzy msgid "Resume playback" msgstr "Continuar reprodução no Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Seguinte" #, fuzzy msgid "Skip to next track" msgstr "Saltar para a faixa seguinte no Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Anterior" #, fuzzy msgid "Skip to previous track" msgstr "Saltar para a faixa anterior no Audacious" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "Aceder aos contactos do Pidgin" msgid "Show offline contacts" msgstr "Mostrar contactos offline" msgid "Open Chat" msgstr "Abrir chat" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d carácter)" msgstr[1] "%s (%d caracteres)" msgid "Send Message..." msgstr "Enviar mensagem..." msgid "Available" msgstr "Disponível" msgid "Away" msgstr "Ausente" msgid "Pidgin Contacts" msgstr "Contactos do Pidgin" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Encolher ligações" msgid "Create short aliases of long URLs" msgstr "Criar um pequeno URL equivalente para URLs longos" msgid "Error" msgstr "Erro" msgid "Shorten With..." msgstr "Encurtar com..." msgid "Services" msgstr "Serviços" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "" "Reproduzir e pôr em fila de espera músicas e navegar na biblioteca de música" msgid "Include artists in top level" msgstr "Incluir artistas no nível superior" msgid "Include albums in top level" msgstr "Incluir álbuns no nível superior" msgid "Play tracks in Rhythmbox" msgstr "Reproduzir faixas no Rhythmbox" msgid "Add tracks to the play queue" msgstr "Adicionar faixas à lista de espera" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "por %(artist)s de %(album)s" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "por %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Faixas por %s" msgid "Albums" msgstr "Álbuns" msgid "Music albums in Rhythmbox Library" msgstr "Álbuns na biblioteca do Rhythmbox" msgid "Artists" msgstr "Artistas" msgid "Music artists in Rhythmbox Library" msgstr "Artistas na biblioteca do Rhythmbox" msgid "Songs" msgstr "Músicas" msgid "Songs in Rhythmbox library" msgstr "Músicas na biblioteca do Rhythmbox" msgid "Getting Things GNOME" msgstr "Getting Things GNOME" msgid "Browse and create new tasks in GTG" msgstr "Navegar e criar novas tarefas no GTG" #, python-format msgid "due: %s" msgstr "prazo: %s" #, python-format msgid "start: %s" msgstr "início: %s" #, python-format msgid "tags: %s" msgstr "etiquetas: %s" msgid "Open task in Getting Things GNOME!" msgstr "Abrir tarefa no Getting Things GNOME!" msgid "Delete" msgstr "Eliminar" msgid "Permanently remove this task" msgstr "Remover permanentemente esta tarefa" msgid "Mark Done" msgstr "Marcar como Terminada" msgid "Mark this task as done" msgstr "Marcar esta tarefa como terminada" msgid "Dismiss" msgstr "Descartar" msgid "Mark this task as not to be done anymore" msgstr "Marcar esta tarefa como já não precisando de ser feita" msgid "Create Task" msgstr "Criar tarefa" msgid "Create new task in Getting Things GNOME" msgstr "Criar nova tarefa no Getting Things GNOME" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "Procurar no Devhelp" msgid "Empathy" msgstr "Empathy" msgid "Access to Empathy Contacts" msgstr "Aceder aos contactos do Empathy" msgid "Busy" msgstr "Ocupado" msgid "Not Available" msgstr "Não disponível" msgid "Invisible" msgstr "Invisível" msgid "Offline" msgstr "Offline" msgid "Change Global Status To..." msgstr "Mudar estado global para..." msgid "Empathy Contacts" msgstr "Contactos do Empathy" msgid "Empathy Account Status" msgstr "Estado da conta do Empathy" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Alternar Ativar" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Truque da vírgula" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Comando composto" msgid "Mark Default Action" msgstr "Marcar ação predefinida" msgid "Forget Object" msgstr "Esquecer objeto" msgid "Reset All" msgstr "Repor tudo" msgid "Select Quit" msgstr "Selecionar sair" msgid "Select Selected File" msgstr "Selecionar ficheiro selecionado" msgid "Select Selected Text" msgstr "Selecionar texto selecionado" msgid "Show Help" msgstr "Mostrar ajuda" msgid "Show Preferences" msgstr "Mostrar preferências" msgid "Switch to First Pane" msgstr "Trocar para o 1º painel" msgid "Toggle Text Mode" msgstr "Alternar modo Texto" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Sem resultados em %(src)s para \"%(query)s\"" msgid "No matches" msgstr "Sem resultados" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Sem resultados" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Make \"%(action)s\" Default for \"%(object)s\"" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "Esquecer acerca de \"%s\"" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Mostrar ambiente principal" msgid "Show with Selection" msgstr "Mostrar com seleção" #. TRANS: Plugin info fields msgid "Description" msgstr "Descrição" msgid "Author" msgstr "Autor" msgid "Version" msgstr "Versão" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Módulo de Python \"%s\" é necessário" msgid "Plugin could not be read due to an error:" msgstr "A extensão não pode ser lida devido ao erro:" msgid "Content of" msgstr "Conteúdo de" #. TRANS: Plugin contents header msgid "Sources" msgstr "Fontes" #. TRANS: Plugin contents header msgid "Actions" msgstr "Ações" #, python-format msgid "Using encrypted password storage: %s" msgstr "A usar armazenamento de senhas encriptadas: %s" #, python-format msgid "Using password storage: %s" msgstr "A usar armazenamento de senhas: %s" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Configuração" msgid "Set username and password" msgstr "Definir utilizador e senha" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Escolha uma pasta" msgid "Reset all shortcuts to default values?" msgstr "Repor todos os atalhos nos valores predefinidos?" msgid "Shortcut" msgstr "Atalho" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "" "Carlos Pais \n" "Pedro Albuquerque " msgid "A free software (GPLv3+) launcher" msgstr "Um lançador de aplicações livre (GPLv3+)" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Kupfer é uma aplicação livre; pode redistribuí-la e/ou alterá-la sob os " "termos\n" "da Licença Pública Geral GNU tal como publicada pela Free Software\n" "Foundation; ou a versão 3 da Licença ou, (à sua discrição) qualquer versão\n" "posterior.\n" "\n" "Kupfer é distribuído na expetativa de que será útil, mas SEM QUALQUER\n" "GARANTIA; nem mesmo a garantia implícita de COMERCIALIZAÇÃO ou ADEQUAÇÃO A\n" "UM PROPÓSITO ESPECÍFICO. Consulte a Licença Pública Genérica GNU para mais\n" "detalhes.\n" "\n" "Deverá ter recebido uma cópia da Licença Pública Genérica GNU juntamente " "com\n" "o Kupfer; caso contrário, veja .\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Impossível encontrar um Kupfer em execução" #~ msgid "Compose Email" #~ msgstr "Compor email" #~ msgid "Send in Email To..." #~ msgstr "Enviar email para..." #~ msgid "Type to search %s" #~ msgstr "Escrever p/ buscar %s" #~ msgid "No action" #~ msgstr "Sem ação" #~ msgid "GNOME Terminal Profiles" #~ msgstr "Perfis do terminal Gnome" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Lançar o Perfis do terminal Gnome" #~ msgid "Multihead Support" #~ msgstr "Suporte Multihead" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Calcular expressões começadas por \"=\"" #~ msgid "Epiphany Bookmarks" #~ msgstr "Marcadores do Epiphany" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Índice de marcadores do Epiphany" #~ msgid "Include visited sites" #~ msgstr "Incluir páginas visitadas" #~| msgid "Firefox Bookmarks" #~ msgid "Firefox tag" #~ msgstr "Etiqueta do Firefox" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Continuar reprodução no Rhythmbox" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Pausar reprodução no Rhythmbox" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Saltar para a faixa seguinte no Rhythmbox" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Saltar para a faixa anterior no Rhythmbox" #~ msgid "Search the Web" #~ msgstr "Procurar na web" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Documentos recentemente usados em Abiword" #~ msgid "Abiword Recent Items" #~ msgstr "Itens recentes do Abiword" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "Ambiente para o gestor de pacotes APT" #~ msgid "Installation method" #~ msgstr "Método de instalação" #~ msgid "Show Package Information" #~ msgstr "Mostrar informação do pacote" #~ msgid "Install" #~ msgstr "Instalar" #~ msgid "Install package using the configured method" #~ msgstr "Instalar pacote usando o método configurado" #~ msgid "Packages matching \"%s\"" #~ msgstr "Pacotes correspondentes \"%s\"" #~ msgid "Search Package Name..." #~ msgstr "Procurar nome de um pacote..." #~ msgid "Ascii & Unicode Icon Set" #~ msgstr "Conjunto de ícones Ascii & Unicode" #~ msgid "" #~ "Provides the Ascii and Unicode icon sets that use letters and symbols to " #~ "produce icons for the objects found in Kupfer." #~ msgstr "" #~ "Fornece os conjuntos de ícones Ascii e Unicode que usam letras e símbolos " #~ "para produzir ícones para os objetos encontrados no Kupfer." #~ msgid "Ascii" #~ msgstr "Ascii" #~ msgid "Unicode" #~ msgstr "Unicode" #~ msgid "Chromium Bookmarks" #~ msgstr "Marcadores do Chromium" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Índice dos marcadores do Chromium" #~ msgid "Claws Mail" #~ msgstr "Claws Mail" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Contactos e ações do Claws Mail" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Compor novo email com o Claws Mail" #~ msgid "Receive All Email" #~ msgstr "Receber todos os emails" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "Receber novas mensagens de todos as contas do Claws Mail" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Compor nova mensagem no Claws Mail e anexar ficheiro" #~ msgid "Claws Mail Address Book" #~ msgstr "Livro de endereços do Claws Mail" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Contactos da livro de endereços do Claws Mail " #~ msgid "Configure a custom terminal emulator" #~ msgstr "Configurar um emulador de terminal personalizado" #~ msgid "Custom Theme" #~ msgstr "Tema personalizado" #~ msgid "Use a custom color theme" #~ msgstr "Usar um tema de cores personalizado" #~ msgid "Theme:" #~ msgstr "Tema:" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Contactos do Evolution" #~ msgid "Compose a new message in Evolution" #~ msgstr "Compor novo email no Evolution" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Compor nova mensagem no Evolution e anexar ficheiro" #~ msgid "Evolution Address Book" #~ msgstr "Livro de endereços do Evolution" #~ msgid "Filezilla" #~ msgstr "Filezilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Mostrar páginas e gerir endereços ftp com o Filezilla" #~ msgid "Open Site with Filezilla" #~ msgstr "Abrir página com o Filezilla" #~ msgid "Filezilla Sites" #~ msgstr "Páginas do Filezilla" #~ msgid "Sites from Filezilla" #~ msgstr "Páginas a partir do Filezilla" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Aceder aos contactos do Gajim" #~ msgid "Free for Chat" #~ msgstr "Disponível para chat" #~ msgid "Gajim Contacts" #~ msgstr "Contactos do Gajim" #~ msgid "Gajim Account Status" #~ msgstr "Estado da conta do Gajim" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Carregar contactos e compor novo email no Gmail" #~ msgid "Load contacts' pictures" #~ msgstr "Carregar imagens dos contactos" #~| msgid "show version information" #~ msgid "Load additional information" #~ msgstr "Carregar informação adicional" #~ msgid "Work email" #~ msgstr "Email profissional" #~| msgid "Compose Email" #~ msgid "Home email" #~ msgstr "Email pessoal" #~ msgid "Other email" #~ msgstr "Outro email" #~| msgid "Workspaces" #~ msgid "Work address" #~ msgstr "Endereço profissional" #~| msgid "Home Folder" #~ msgid "Home address" #~ msgstr "Endereço pessoal" #~ msgid "Other address" #~ msgstr "Outro endereço" #~ msgid "Car phone" #~ msgstr "Telefone do carro" #~ msgid "Fax" #~ msgstr "Fax" #~| msgid "Home Folder" #~ msgid "Home phone" #~ msgstr "Telefone pessoal" #~ msgid "Home fax" #~ msgstr "Fax pessoal" #~ msgid "Internal phone" #~ msgstr "Telefone interno" #~ msgid "Mobile" #~ msgstr "Telemóvel" #~ msgid "Other" #~ msgstr "Outro" #~ msgid "VOIP" #~ msgstr "VOIP" #~| msgid "Workspaces" #~ msgid "Work phone" #~ msgstr "Telefone profissional" #~ msgid "Work fax" #~ msgstr "Fax profissional" #~ msgid "Compose Email in Gmail" #~ msgstr "Compor email no Gmail" #~ msgid "Open web browser and compose new email in Gmail" #~ msgstr "Abrir navegador web e compor novo email no Gmail" #~ msgid "Edit Contact in Gmail" #~ msgstr "Editar contacto no Gmail" #~ msgid "Open web browser and edit contact in Gmail" #~ msgstr "Abrir navegador web e editar contacto no Gmail" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Contactos de serviços Google (Gmail)" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Mostrar álbuns e enviar ficheiros para o Picasa" #~ msgid "Users to show: (,-separated)" #~ msgstr "Utilizadores a mostrar: (separados por ,)" #~ msgid "Load user and album icons" #~ msgstr "Carregar ícones de utilizador e álbum" #~ msgid "Uploading Pictures" #~ msgstr "A enviar fotografias" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "A enviar fotografias para o Picasa Web Album" #~ msgid "Creating album:" #~ msgstr "A criar álbum:" #~ msgid "Album created by Kupfer" #~ msgstr "Álbum criado pelo Kupfer" #~ msgid "File:" #~ msgstr "Ficheiro:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "Um álbum" #~ msgstr[1] "%(num)d álbuns" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "Uma fotografia" #~ msgstr[1] "%(num)s fotografias" #~ msgid "Upload to Picasa Album..." #~ msgstr "Enviar para o Picasa Album..." #~ msgid "Upload files to Picasa album" #~ msgstr "Enviar ficheiros para o Picasa album" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Enviar para o Picasa como novo álbum" #~ msgid "Create album from selected local directory" #~ msgstr "Criar álbum de pasta local selecionada" #~ msgid "Picasa Albums" #~ msgstr "Álbuns Picasa" #~ msgid "User albums in Picasa" #~ msgstr "Álbuns do utilizador no Picasa" #~ msgid "Google Search" #~ msgstr "Procura Google" #~ msgid "Search Google with results shown directly" #~ msgstr "Procurar no Google com resultados mostrados diretamente" #~ msgid "Show More Results For \"%s\"" #~ msgstr "Mostrar mais resultados para \"%s\"" #~ msgid "%s total found" #~ msgstr "%s encontrados no total" #~ msgid "Gwibber" #~ msgstr "Gwibber" #~ msgid "" #~ "Microblogging with Gwibber. Allows sending and receiving messages from " #~ "social networks like Twitter, Identi.ca etc. Requires the package " #~ "'gwibber-service'." #~ msgstr "" #~ "Microblogue com o Gwibber. Permite enviar e receber mensagens de redes " #~ "sociais, como Twitter, Identi.ca etc. Requer o pacote 'gwibber-service'." #~ msgid "Maximum number of messages to show" #~ msgstr "Número máximo de mensagens a mostrar" #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s no %(service)s" #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s no %(where)s" #~ msgid "Send Message" #~ msgstr "Enviar mensagem" #~ msgid "Send message to all Gwibber accounts" #~ msgstr "Enviar mensagem a todas as contas do Gwibber" #~ msgid "Send Message To..." #~ msgstr "Enviar mensagem a..." #~ msgid "Send message to a Gwibber account" #~ msgstr "Enviar mensagem a uma conta do Gwibber" #~ msgid "Send message to selected Gwibber account" #~ msgstr "Enviar mensagem a uma conta selecionada do Gwibber" #~ msgid "Reply..." #~ msgstr "Responder..." #~ msgid "Delete Message" #~ msgstr "Eliminar mensagem..." #~ msgid "Send Private Message..." #~ msgstr "Enviar mensagem privada..." #~ msgid "Send direct message to user" #~ msgstr "Enviar mensagem direta ao utilizador" #~ msgid "Retweet" #~ msgstr "Retweetar" #~ msgid "Retweet To..." #~ msgstr "Retweetar para..." #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Retweetar mensagem para todas as contas do Gwibber" #~ msgid "Retweet message to a Gwibber account" #~ msgstr "Retweetar mensagem para uma conta do Gwibber" #~ msgid "Open in Browser" #~ msgstr "Abrir no navegador" #~ msgid "Open message in default web browser" #~ msgstr "Abrir mensagem no navegador web predefinido" #~ msgid "Gwibber Accounts" #~ msgstr "Contas do Gwibber" #~ msgid "Accounts configured in Gwibber" #~ msgstr "Contas configuradas no Gwibber" #~ msgid "Gwibber Messages" #~ msgstr "Mensagens Gwibber" #~ msgid "Recent messages received by Gwibber" #~ msgstr "Mensagens recentes recebidas pelo Gwibber" #~ msgid "Gwibber Messages for %s" #~ msgstr "Mensagens Gwibber para %s" #~ msgid "Gwibber Streams" #~ msgstr "Fluxos Gwibber" #~ msgid "Streams configured in Gwibber" #~ msgstr "Fluxos configurados no Gwibber" #~ msgid "Gwibber Messages in %s" #~ msgstr "Mensagens Gwibber em %s" #~ msgid "Gwibber (Simple)" #~ msgstr "Gwibber (simples)" #~ msgid "Send updates via the microblogging client Gwibber" #~ msgstr "Enviar atualizações via microblogue Gwibber" #~ msgid "Send Update" #~ msgstr "Enviar atualização" #~ msgid "Unable to activate Gwibber service" #~ msgstr "Impossível ativar o serviço Gwibber" #~ msgid "OpenOffice / LibreOffice" #~ msgstr "OpenOffice/LibreOffice" #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Documentos recentemente utilizados no OpenOffice/LibreOffice" #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "Itens recentes do OpenOffice/LibreOffice" #~ msgid "Opera Mail" #~ msgstr "Opera Mail" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Contactos e ações do Opera Mail" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Compor nova mensagem com o Opera Mail" #~ msgid "Opera Mail Contacts" #~ msgstr "Contactos do Opera Mail" #~ msgid "Contacts from Opera Mail" #~ msgstr "Contactos do Opera Mail" #~ msgid "Opera Bookmarks" #~ msgstr "Marcadores do Opera" #~ msgid "Index of Opera bookmarks" #~ msgstr "Índice de marcadores do Opera" #~ msgid "PuTTY Sessions" #~ msgstr "Sessões do PuTTy" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Acesso rápido às sessões do PuTTy" #~ msgid "Start Session" #~ msgstr "Iniciar sessão" #~ msgid "reStructuredText" #~ msgstr "reStruturedText" #~ msgid "Render reStructuredText and show the result" #~ msgstr "Desenhar reStruturedText e mostrar resultado" #~ msgid "View as HTML Document" #~ msgstr "Ver como documento HTML" #~ msgid "System Services" #~ msgstr "Serviços de sistema" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "Iniciar, parar or reiniciar serviços de sistema via init scripts" #~ msgid "Sudo-like Command" #~ msgstr "Comando do tipo Sudo" #~ msgid "Start Service" #~ msgstr "Iniciar serviço" #~ msgid "Stop Service" #~ msgstr "Parar serviço" #~ msgid "%s Service" #~ msgstr "%s serviço" #~ msgid "Show QRCode" #~ msgstr "Mostrar QRCode" #~ msgid "Display text as QRCode in a window" #~ msgstr "Mostrar texto como código QR numa janela" #~ msgid "Access to Skype contacts" #~ msgstr "Aceder aos contactos do Skype" #~ msgid "Skype Me" #~ msgstr "Skype Me" #~ msgid "Logged Out" #~ msgstr "Desligado" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Telefonar" #~ msgid "Place a call to contact" #~ msgstr "Coloque uma chamada para contactar" #~ msgid "Skype Contacts" #~ msgstr "Contactos do Skype" #~ msgid "Skype Statuses" #~ msgstr "Estados do Skype" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Volumes do histórico do TrueCrypt" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "Volume do TrueCrypt: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Montar volume" #~ msgid "Mount in Truecrypt" #~ msgstr "Montar no Truecrypt" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Tentar montar ficheiro como volume do Truecrypt" #~ msgid "Dismount All Volumes" #~ msgstr "Desmontar todos os volumes" #~ msgid "TrueCrypt Volumes" #~ msgstr "Volumes do TrueCrypt" #~ msgid "Terminal Server Client" #~ msgstr "Terminal Server Client" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Sessão gravada no Terminal Server Client" #~ msgid "TSClient sessions" #~ msgstr "Sessões de TSClient" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Sessões gravadas no Terminal Server Client" #~ msgid "Vim" #~ msgstr "Vim" #~ msgid "Recently used documents in Vim" #~ msgstr "Documentos recentemente utilizados no Vim" #~ msgid "Vim Recent Documents" #~ msgstr "Documentos recentes do Vim" #~ msgid "Close (Save All)" #~ msgstr "Fechar (gravar tudo)" #~ msgid "Send..." #~ msgstr "Enviar..." #~| msgid "Sudo-like Command" #~ msgid "Send ex command" #~ msgstr "Enviar comando ex" #~ msgid "Insert in Vim..." #~ msgstr "Inserir no Vim..." #~| msgid "Active GNU Screen sessions" #~ msgid "Active Vim Sessions" #~ msgstr "Sessões ativas do Vim" #~| msgid "PuTTY Sessions" #~ msgid "Vim Session %s" #~ msgstr "Sessão %s do Vim" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Marcadores e ações do Vinagre" #~ msgid "Start Vinagre Session" #~ msgstr "Iniciar sessão do Vinagre" #~ msgid "Vinagre Bookmarks" #~ msgstr "Marcadores do Vinagre" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "Controlar máquinas virtuais do VirtualBox. Suporta Sun VirtualBox e Open " #~ "Source Edition." #~ msgid "Force use CLI interface" #~ msgstr "Forçar uso de ambiente CLI" #~ msgid "Power On" #~ msgstr "Ligar" #~ msgid "Power On Headless" #~ msgstr "Ligar (Headless)" #~ msgid "Send Power Off Signal" #~ msgstr "Enviar sinal para desligar" #~ msgid "Reboot" #~ msgstr "Reinciar" #~ msgid "Resume" #~ msgstr "Resumir" #~ msgid "Save State" #~ msgstr "Gravar estado" #~ msgid "Power Off" #~ msgstr "Desligar" #~ msgid "VirtualBox Machines" #~ msgstr "Máquinas do VirtualBox" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "Aceder a páginas gravadas em Zim - Wiki Pessoal" #~ msgid "Page names start with :colon" #~ msgstr "Nomes das páginas começam por \":\"" #~ msgid "Default page name for quick notes" #~ msgstr "Nome de página predefinido para notas rápidas" #~ msgid "Note %x %X" #~ msgstr "Nota %x %X" #~ msgid "" #~ "Strftime tags can be used: %H - hour, %M - minutes, etc\n" #~ "Please check python documentation for details.\n" #~ "NOTE: comma will be replaced by _" #~ msgstr "" #~ "Pode usar etiquetas Strftime: %H - hora, %M - minutos, etc\n" #~ "Por favor, consulte a documentação Python para mais detalhes.\n" #~ "NOTA: ǘirgulas são substituídas por _" #~ msgid "Default namespace for quick notes" #~ msgstr "Espaço de nome predefinido para notas rápidas" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Página Zim do bloco de notas \"%s\"" #~ msgid "Create Zim Page" #~ msgstr "Criar página Zim" #~ msgid "Create page in default notebook" #~ msgstr "Criar página no bloco de notas predefinido" #~ msgid "Create Zim Page In..." #~ msgstr "Criar página Zim em..." #~ msgid "Insert QuickNote into Zim" #~ msgstr "Inserir QuickNote no Zim" #~ msgid "Quick note selected text into Zim notebook" #~ msgstr "Texto selecionado no QuickNote para o bloco de notas Zim" #~ msgid "Create Subpage..." #~ msgstr "Criar sub página..." #~ msgid "Zim Notebooks" #~ msgstr "Blocos de notas Zim" #~ msgid "Zim Pages" #~ msgstr "Páginas Zim" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Páginas armazenadas no bloco de notas Zim" #~ msgid "Selected Text \"%s\"" #~ msgstr "Texto seleccionado \"%s\"" #~ msgid "Recent clipboards" #~ msgstr "Elementos recentes na Área de Transferência" #~ msgid "Include recent selections" #~ msgstr "Fornece a selecção actual" #~ msgid "" #~ "Provides current nautilus selection, using Kupfer's Nautilus Extension" #~ msgstr "" #~ "Fornece a selecção actual do nautilus, ao usar a Extensão Nautilus do " #~ "Kupfer" #~ msgid "Selected File \"%s\"" #~ msgstr "Ficheiro Seleccionado \"%s\"" #~ msgid "Selected Files" #~ msgstr "Ficheiros Seleccionado" #~ msgid "Translate text with Google Translate" #~ msgstr "Traduzir texto com Google Translate" #~ msgid "Google Translate connection timed out" #~ msgstr "A conecção do Google Translate terminou" #~ msgid "Error connecting to Google Translate" #~ msgstr "Erro ao conectar ao Google Translate" #~ msgid "Translate To..." #~ msgstr "Traduzir Para..." #~ msgid "Translate into %s" #~ msgstr "Traduzir para %s" #~ msgid "Languages" #~ msgstr "Idiomas" #~ msgid "Show translated page in browser" #~ msgstr "Apresentar página traduzida no Navegador" #~ msgid "Show Translation To..." #~ msgstr "Apresentar Tradução Para..." #~ msgid "Show translation in browser" #~ msgstr "Apresentar tradução no Navegador" #~ msgid "Tracker 0.6" #~ msgstr "Tracker" #~ msgid "Tracker tags" #~ msgstr "Tags de Tracker" #~ msgid "Tracker Tags" #~ msgstr "Tags de Tracker" #~ msgid "Browse Tracker's tags" #~ msgstr "Navegar Tags de Tracker" #~ msgid "Tag %s" #~ msgstr "Tag %s" #~ msgid "Objects tagged %s with Tracker" #~ msgstr "Objectos com tag %s no Tracker" #~ msgid "Add Tag..." #~ msgstr "Adicionar Tag..." #~ msgid "Add tracker tag to file" #~ msgstr "Adicionar Tag de tracker ao ficheiro" #~ msgid "Remove Tag..." #~ msgstr "Eliminar Tag..." #~ msgid "Remove tracker tag from file" #~ msgstr "Eliminar Tag do tracker do ficheiro" #~ msgid "Directories" #~ msgstr "Directórios" #~ msgid "Interface" #~ msgstr "Interface" #~ msgid "Keybinding" #~ msgstr "Atalhos de Teclado" #~ msgid "Applied" #~ msgstr "Aplicado" #~ msgid "Text Matches" #~ msgstr "Equivalências de Texto" #~ msgid "Special items and actions for Gnome environment" #~ msgstr "Itens e acções especiais para Gnome" #~ msgid "noun" #~ msgstr "nome" #~ msgid "verb" #~ msgstr "verbo" #~ msgid "adjective" #~ msgstr "adjectivo" #~ msgid "Timeline for %s" #~ msgstr "Preferências para \"%s\"" #~ msgid "OpenOffice" #~ msgstr "OpenOffice" #~ msgid "Include in top level" #~ msgstr "Incluir no nível superior" #~ msgid "" #~ "If enabled, objects from the plugin's source(s) will be available in the " #~ "top level.\n" #~ "Sources are always available as subcatalogs in the top level." #~ msgstr "" #~ "Se activo, objectos da(s) fonte(s) das Extensões estarão disponíveis no " #~ "nivel superior.\n" #~ "As fontes estão sempre disponíveis como subcatálogos no nível superior." #~ msgid "To configure kupfer, edit:" #~ msgstr "Para configurar kupfer, editar:" #~ msgid "The default config for reference is at:" #~ msgstr "A configuração por omissão está em:" #~ msgid "Open with %s" #~ msgstr "Abrir com %s" #~ msgid "Recently used documents and nautilus places" #~ msgstr "Documentos recentes e locais de Nautilus" #~ msgid "Bookmarked locations in Nautilus" #~ msgstr "Locais nos marcadores em Nautilus" #~ msgid "Do" #~ msgstr "Fazer" #~ msgid "Compose New Mail To" #~ msgstr "Compor Novo Mail Para" #~ msgid "Common" #~ msgstr "Comum" #~ msgid "Special Items" #~ msgstr "Itens especiais" #~ msgid "Items and special actions" #~ msgstr "Itens e acções especiais" #~ msgid "Kupfer items and actions" #~ msgstr "Itens e acções de Kupfer" #~ msgid "(Simple) favorites plugin" #~ msgstr "(Simple) extensão para favoritos" #~ msgid "(no description)" #~ msgstr "(sem descrição)" #~ msgid " %(name)-20s %(version)-4s %(description)s" #~ msgstr " %(name)-20s %(version)-4s %(description)s" #~ msgid "Free-text Queries" #~ msgstr "Pesquisas de Free-text" #~ msgid "Basic support for free-text queries" #~ msgstr "Suporte básico para pesquisas de free-text" #~ msgid "Filesystem Text Matches" #~ msgstr "Equivalências de texto no Sistema de ficheiros" #~ msgid "URL Text Matches" #~ msgstr "Equivalências de texto nas URLs" #~ msgid "Searching..." #~ msgstr "A procurar..." #~ msgid "Searching %(source)s..." #~ msgstr "A procurar em %(source)s..." #~ msgid "" #~ "%(program)s: %(desc)s\n" #~ "\t%(copyright)s\n" #~ "\t%(website)s\n" #~ msgstr "" #~ "%(program)s: %(desc)s\n" #~ "\t%(copyright)s\n" #~ "\t%(website)s\n" #~ msgid "Core" #~ msgstr "Nucleo" #~ msgid "%d lines" #~ msgstr "%d lineas" kupfer-328/po/pt_BR.po000066400000000000000000001653621500175051100146600ustar00rootroot00000000000000# Brazilian Portuguese translation for kupfer. # Copyright (C) 2011 kupfer's COPYRIGHT HOLDER # This file is distributed under the same license as the kupfer package. # Djavan Fagundes , 2011. # Rafael Ferreira , 2012. # msgid "" msgstr "" "Project-Id-Version: kupfer master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2013-01-15 12:40-0300\n" "Last-Translator: Rafael Ferreira \n" "Language-Team: Brazilian Portuguese \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: Virtaal 0.6.1\n" msgid "User credentials" msgstr "Credenciais do usuário" msgid "_User:" msgstr "_Usuário:" msgid "_Password:" msgstr "Sen_ha:" msgid "_Change" msgstr "_Alterar" msgid "Set Keyboard Shortcut" msgstr "Definir atalho de teclado" msgid "Please press desired key combination" msgstr "Por favor, pressione a combinação de teclas desejada" msgid "Keybinding could not be bound" msgstr "Associação de tecla não pôde ser vinculada" msgid "Kupfer Preferences" msgstr "Preferências do Kupfer" msgid "Start automatically on login" msgstr "Iniciar automaticamente ao iniciar sessão" msgid "Start" msgstr "Iniciar" msgid "Show icon in notification area" msgstr "Mostrar ícone na área de notificação" msgid "Icon set:" msgstr "Conjunto de ícones:" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" msgid "Terminal emulator:" msgstr "Emulador de terminal:" msgid "Desktop Environment" msgstr "Ambiente de trabalho" msgid "General" msgstr "Geral" msgid "Global Keyboard Shortcuts" msgstr "Atalhos de teclado globais" msgid "Reset" msgstr "Redefinir" msgid "Browser Keyboard Shortcuts" msgstr "Navegar nos atalhos de teclado" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "" "Usar comandos de pressionamento de tecla única (espaço, /, período, vírgula, " "etc.)" msgid "Keyboard" msgstr "Teclado" msgid "Plugins" msgstr "Plug-ins" msgid "Inclusion in Top Level Searches" msgstr "Inclusão em pesquisas de nível superior" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "Fontes marcadas têm seus objetos incluídos nas pesquisas de nível superior.\n" "Conteúdo de uma fonte não marcados só está disponível para localizar seu " "subcatálogo." msgid "Indexed Folders" msgstr "Pastas indexadas" msgid "Folders whose files are always available in the catalog." msgstr "Pastas cujos arquivos estão sempre disponíveis no catálogo." msgid "Catalog" msgstr "Catálogo" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Lançador de aplicativos" msgid "Convenient command and access tool for applications and documents" msgstr "" "Uma conveniente ferramenta de comando e acesso para aplicativos e documentos" msgid "Execute in Kupfer" msgstr "Executar no Kupfer" msgid "Saved Kupfer Command" msgstr "Comando Kupfer salvo" #, python-format msgid "Could not to carry out '%s'" msgstr "Não foi possível realizar \"%s\"" #, python-format msgid "\"%s\" produced a result" msgstr "\"%s\" produziu um resultado" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Nenhuma permissão para executar \"%s\" (não executável)" #, python-format msgid "Command in \"%s\" is not available" msgstr "Comando em \"%s\" não está disponível" #, python-format msgid "Keyboard relay is active for display %s" msgstr "Retransmissão de teclado está ativa para exibir %s" msgid "do not present main interface on launch" msgstr "não apresentam a interface principal no lançamento" msgid "list available plugins" msgstr "lista plug-ins disponíveis" msgid "enable debug info" msgstr "ativar informações de depuração" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "executar o plug-in helper" msgid "show usage help" msgstr "mostrar uso da ajuda" msgid "show version information" msgstr "exibir informações da versão" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Uso: kupfer [ OPCOES | ARQUIVO... ]" msgid "Available plugins:" msgstr "Plug-ins disponíveis:" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "Digite para pesquisar" #, python-format msgid "%s is empty" msgstr "%s está vazio" msgid "Text" msgstr "Texto" msgid "Run after Delay..." msgstr "Executar após atraso..." msgid "Perform command after a specified time interval" msgstr "Execute o comando após um intervalo de tempo especificado" msgid "Multiple Objects" msgstr "Vários objetos" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "Objeto %s" msgstr[1] "Objetos %s" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "desconhecido" msgid "Aim" msgstr "Aim" msgid "Google Talk" msgstr "Google Talk" msgid "ICQ" msgstr "ICQ" msgid "MSN" msgstr "MSN" msgid "QQ" msgstr "QQ" msgid "Yahoo" msgstr "Yahoo" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "%s não provê suporte a esta operação" msgid "Can not be used with multiple objects" msgstr "Não pode ser usado com vários objetos" msgid "Open" msgstr "Abrir" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Nenhum aplicativo padrão para %(file)s (%(type)s)" #, python-format msgid "Please use \"%s\"" msgstr "Por favor, use \"%s\"" msgid "Set Default Application..." msgstr "Definir aplicativo padrão..." msgid "Open with default application" msgstr "Abrir com o aplicativo padrão" msgid "Reveal" msgstr "Revelar" msgid "Open parent folder" msgstr "Abrir a pasta pai" msgid "Open Terminal Here" msgstr "Abrir terminal aqui" msgid "Open this location in a terminal" msgstr "Abrir este local em um terminal" msgid "Run in Terminal" msgstr "Executar em terminal" msgid "Run (Execute)" msgstr "Run (executar)" msgid "Run this program in a Terminal" msgstr "Executar este programa em um terminal" msgid "Run this program" msgstr "Executar este programa" msgid "Go To" msgstr "Ir para" msgid "Open URL" msgstr "Abrir URL" msgid "Open URL with default viewer" msgstr "Abrir URL com visualizador padrão" msgid "Launch" msgstr "Lançamento" msgid "Show application window" msgstr "Show janela do aplicativo" msgid "Launch application" msgstr "Inicie o aplicativo" msgid "Launch Again" msgstr "Lançar novamente" msgid "Launch another instance of this application" msgstr "Inicie outra instância deste aplicativo" msgid "Close" msgstr "Fechar" msgid "Attempt to close all application windows" msgstr "Tentando fechar todas as janelas de aplicativos" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Executar" msgid "Perform command" msgstr "Executar comando" msgid "(Empty Text)" msgstr "(Texto vazio)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "\"%(text)s\"" msgstr[1] "(%(num)d linhas) \"%(text)s\"" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s et. al." #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Fonte recursiva de %(dir)s, (%(levels)d níveis)" #, python-format msgid "Directory source %s" msgstr "Diretório fonte %s" msgid "Home Folder" msgstr "Pasta Home" msgid "Catalog Index" msgstr "Índice de catálogo" msgid "An index of all available sources" msgstr "Um índice de todas as fontes disponíveis" msgid "Root catalog" msgstr "Catálogo raiz" msgid "Please Configure Plugin" msgstr "Por favor, configure o plug-in" #, python-format msgid "Plugin %s is not configured" msgstr "Plug-in %s não está configurado." #, python-format msgid "Invalid user credentials for %s" msgstr "Credenciais de usuário inválidas para %s" msgid "Applications" msgstr "Aplicativos" msgid "All applications and preferences" msgstr "Todos os aplicativos e preferências" msgid "Applications for Desktop Environment" msgstr "Aplicativos para ambiente de trabalho" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "Abrir com..." msgid "Open with any application" msgstr "Abrir com qualquer aplicativo" msgid "Set default application to open this file type" msgstr "Definir aplicativo padrão para abrir este tipo de arquivo" #, fuzzy msgid "Reset Associations" msgstr "Ações de URL" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "Arquivos profundos" msgid "Allow browsing inside compressed archive files" msgstr "Permite a navegação dentro de arquivos compactados" #, python-format msgid "Content of %s" msgstr "Conteúdo de %s" msgid "Archive Manager" msgstr "Gerenciador de arquivos" msgid "Use Archive Manager actions" msgstr "Usar ações do gerenciador de arquivo" msgid "Compressed archive type for 'Create Archive In'" msgstr "Tipo de compactação de arquivo para \"Criar arquivo em\"" msgid "Extract Here" msgstr "Extrair aqui" msgid "Extract compressed archive" msgstr "Extrair arquivo compactado" msgid "Create Archive" msgstr "Criar arquivo" msgid "Create a compressed archive from folder" msgstr "Criar um arquivo compactado da pasta" msgid "Create Archive In..." msgstr "Criar arquivo em..." #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Pacote" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "Controlar a reprodução e lista de reprodução do Audacious" msgid "Include songs in top level" msgstr "Incluir músicas no nível superior" msgid "Enqueue" msgstr "Enfileirado" msgid "Add track to the Audacious play queue" msgstr "Adicionar faixas para a fila de reprodução do Audacious" msgid "Dequeue" msgstr "Desfazer fila" msgid "Remove track from the Audacious play queue" msgstr "Remover faixa da fila de reprodução do Audacious" msgid "Play" msgstr "Reproduzir" msgid "Jump to track in Audacious" msgstr "Saltar para a faixa no Audacious" msgid "Resume playback in Audacious" msgstr "Retomar a reprodução no Audacious" msgid "Pause" msgstr "Pausar" msgid "Pause playback in Audacious" msgstr "Pausar a reprodução no Audacious" msgid "Next" msgstr "Próximo" msgid "Jump to next track in Audacious" msgstr "Saltar para a próxima faixa no Audacious" msgid "Previous" msgstr "Anterior" msgid "Jump to previous track in Audacious" msgstr "Saltar para a faixa anterior no Audacious" msgid "Clear Queue" msgstr "Limpar a fila" msgid "Clear the Audacious play queue" msgstr "Limpar a fila de reprodução do Audacious" msgid "Shuffle" msgstr "Aleatória" msgid "Toggle shuffle in Audacious" msgstr "Alternar para modo aleatório no Audacious" msgid "Repeat" msgstr "Repetir" msgid "Toggle repeat in Audacious" msgstr "Alternar para repetição no Audacious" msgid "Show Playing" msgstr "Exibir reprodução" msgid "Tell which song is currently playing" msgstr "Dizer que música é que joga" msgid "Playlist" msgstr "Lista de reprodução" msgid "Calculator" msgstr "Calculadora" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "Calcular" msgid "Clipboards" msgstr "Áreas de transferência" msgid "Recent clipboards and clipboard proxy objects" msgstr "Transferências recentes e objetos proxy da área de transferência" msgid "Number of recent clipboards to remember" msgstr "Número de itens recentes da área de transferência para guardar" msgid "Include selected text in clipboard history" msgstr "Incluir o texto selecionado no histórico de transferência" msgid "Copy selected text to primary clipboard" msgstr "Copiar o texto selecionado para a área de transferência do principal" msgid "Selected Text" msgstr "Texto selecionado" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Área de transferência \"%(desc)s\"" msgstr[1] "Área de transferência com %(num)d linhas \"%(desc)s\"" msgid "Clipboard Text" msgstr "Texto da área de transferência" msgid "Clipboard File" msgstr "Arquivo da área de transferência" msgid "Clipboard Files" msgstr "Arquivos da área de transferência" msgid "Clear" msgstr "Limpar" msgid "Remove all recent clipboards" msgstr "Remover todas as transferências recentes" msgid "Shell Commands" msgstr "Comandos do shell" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Executar programas de linha de comando. Ações marcadas com o símbolo %s " "executam em um subshell." msgid "Run (Get Output)" msgstr "Executar (pegar saída)" msgid "Run program and return its output" msgstr "Executa o programa e retornar sua saída" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "Passar para o comando..." msgid "Run program with object as an additional parameter" msgstr "Executar o programa com o objeto como um parâmetro adicional" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "Escreva para comando..." msgid "Run program and supply text on the standard input" msgstr "Executar o programa e fornecer texto da entrada padrão" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "Filtrar através do comando..." msgid "Run command-line programs" msgstr "Executar programas de linha de comando" msgid "GTK+" msgstr "GTK+" msgid "GNOME Terminal" msgstr "Terminal GNOME" msgid "XFCE Terminal" msgstr "Terminal XFCE" msgid "LXTerminal" msgstr "LXTerminal" msgid "X Terminal" msgstr "Terminal do X" msgid "Urxvt" msgstr "Urxvt" msgid "Konsole" msgstr "Konsole" msgid "Save As..." msgstr "Salvar como..." #, fuzzy msgid "Restart Kupfer" msgstr "Reiniciar o serviço" msgid "Quit" msgstr "Sair" msgid "Quit Kupfer" msgstr "Sair do Kupfer" msgid "About Kupfer" msgstr "Sobre o Kupfer" msgid "Show information about Kupfer authors and license" msgstr "Mostrar informações sobre autores do Kupfer e licença" msgid "Kupfer Help" msgstr "Ajuda do Kupfer" msgid "Get help with Kupfer" msgstr "Obtenha ajuda com Kupfer" msgid "Show preferences window for Kupfer" msgstr "Mostrar a janela de preferências para o Kupfer" msgid "Search Contents" msgstr "Pesquisar conteúdo" msgid "Search inside this catalog" msgstr "Pesquisar dentro deste catálogo" msgid "Copy" msgstr "Cópia" msgid "Copy to clipboard" msgstr "Copiar para área de transferência" msgid "Rescan" msgstr "Escanear novamente" msgid "Force reindex of this source" msgstr "Força a reindexação desta fonte" msgid "Last Command" msgstr "Último comando" msgid "Internal Kupfer Objects" msgstr "Objetos internos do Kupfer" msgid "Last Result" msgstr "Último resultado" msgid "Command Results" msgstr "Resultados do comando" msgid "Custom Terminal" msgstr "Terminal personalizado" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Comando" msgid "Execute flag" msgstr "Executar flag" msgid "Default Email Client" msgstr "Cliente de e-mail padrão" msgid "Compose email using the system's default mailto: handler" msgstr "Compor e-mail usando mailto padrão do sistema: manipulador" #, fuzzy msgid "Compose Email To" msgstr "Compor e-mail" msgid "Dictionary" msgstr "Dicionário" msgid "Look up word in dictionary" msgstr "Procurar palavra no dicionário" msgid "Look Up" msgstr "Procurar" msgid "Documents" msgstr "Documentos" msgid "Recently used documents and bookmarked folders" msgstr "Documentos usados ​​recentemente e pastas favoritas" msgid "Max recent document days" msgstr "Máximo de dias de documentos recentes" msgid "Recent Items" msgstr "Itens recentes" msgid "Recently used documents" msgstr "Documentos usados recentemente" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "%s documentos" #, python-format msgid "Recently used documents for %s" msgstr "Documentos usados recentemente para %s" msgid "Places" msgstr "Locais" msgid "Bookmarked folders" msgstr "Pastas favoritas" msgid "DuckDuckGo Search" msgstr "Pesquisa do DuckDuckGo" msgid "Search the web securely with DuckDuckGo" msgstr "Pesquisar a web de forma segura com DuckDuckGo" msgid "Favorites" msgstr "Favoritos" msgid "Mark commonly used items and store objects for later use" msgstr "" "Marcar os itens usados com freqüência e armazenar objetos para uso posterior" msgid "Shelf of \"Favorite\" items" msgstr "Prateleira de itens \"Favoritos\"" msgid "Add to Favorites" msgstr "Adicionar a Favoritos" msgid "Add item to favorites shelf" msgstr "Adicionar o item à prateleira de favoritos" msgid "Remove from Favorites" msgstr "Remover dos favoritos" msgid "Remove item from favorites shelf" msgstr "Remover item de prateleira de favoritos" msgid "File Actions" msgstr "Ações de arquivo" msgid "More file actions" msgstr "Mais ações de arquivo" msgid "Move To..." msgstr "Mova para..." msgid "Move file to new location" msgstr "Mover arquivos para o novo local" msgid "Rename To..." msgstr "Renomear para..." msgid "Copy To..." msgstr "Copiar para..." msgid "Copy file to a chosen location" msgstr "Copia o arquivo para um local escolhido" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "Glob" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "Ações de ordem superior" msgid "Tools to work with commands as objects" msgstr "Ferramentas para trabalhar com comandos como objetos" msgid "Select in Kupfer" msgstr "Selecione no Kupfer" #, python-format msgid "Result of %s (%s)" msgstr "Resultado de %s (%s)" msgid "Run (Take Result)" msgstr "Executar (obter resultado)" msgid "Take the command result as a proxy object" msgstr "Capturar o resultado de comando como um objeto proxy" msgid "Run (Discard Result)" msgstr "Executar (descartar resultado)" msgid "Image Tools" msgstr "Ferramentas de imagem" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Ferramentas de transformação de imagens" msgid "Scale..." msgstr "Escala..." msgid "Scale image to fit inside given pixel measure(s)" msgstr "" "Redimensionar imagem para caber dentro de determinada medida(s) de pixel" msgid "Rotate Clockwise" msgstr "Girar no sentido horário" msgid "Rotate Counter-Clockwise" msgstr "Girar no sentido anti-horário" msgid "Autorotate" msgstr "Girar automaticamente" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "Girar JPEG (no local) de acordo com seus metadados EXIF" msgid "Kupfer Plugins" msgstr "Plug-ins do Kupfer" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Acessar a lista de plug-ins do Kupfer no Kupfer" msgid "Show Information" msgstr "Mostrar informações" msgid "Show Source Code" msgstr "Mostrar o código-fonte" msgid "enabled" msgstr "habilitado" msgid "disabled" msgstr "desativado" msgid "Notes" msgstr "Notas" msgid "Gnote or Tomboy notes" msgstr "Notas do Gnote ou Tomboy" msgid "Work with application" msgstr "Trabalhar com aplicativos" msgid "Open with notes application" msgstr "Abrir com o aplicativo de notas" msgid "Append to Note..." msgstr "Anexar à nota..." msgid "Add text to existing note" msgstr "Adicionar texto para a nota existente" msgid "Create Note" msgstr "Criar nota" msgid "Create a new note from this text" msgstr "Criar uma nova nota deste texto" msgid "Get Note Search Results..." msgstr "Obter resultados de pesquisa de nota..." msgid "Show search results for this query" msgstr "Mostrar resultados de pesquisa para esta consulta" #, python-format msgid "today, %s" msgstr "hoje, %s" #, python-format msgid "yesterday, %s" msgstr "ontem, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Última atualização %s" msgid "Quicksilver Icons" msgstr "Ícones do Quicksilver" msgid "Quick Image Viewer" msgstr "Visualizador rápido de imagens" msgid "View Image" msgstr "Ver imagem" msgid "GNU Screen" msgstr "GNU Screen" msgid "Active GNU Screen sessions" msgstr "Sessões ativas do GNU Screen" msgid "Attached" msgstr "Anexado" msgid "Detached" msgstr "Desanexado" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "%(status)s sessão (%(pid)s) criada %(time)s" msgid "Screen Sessions" msgstr "Sessões de tela" msgid "Attach" msgstr "Anexar" msgid "Send Keys" msgstr "Enviar chaves" msgid "Send synthetic keyboard events using xautomation" msgstr "Enviar eventos de teclado sintético usando xautomation" msgid "Paste to Foreground Window" msgstr "Colar a janela de primeiro plano" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "" "Copiar para a área de transferência e enviar Ctrl+V para a janela de " "primeiro plano" msgid "Send keys to foreground window" msgstr "Enviar as teclas para a janela de primeiro plano" msgid "Type Text" msgstr "Tipo de Texto" msgid "Type the text to foreground window" msgstr "Digite o texto da janela de primeiro plano" msgid "GNOME Session Management" msgstr "Gerenciamento de sessão do GNOME" msgid "Special items and actions for GNOME environment" msgstr "Itens especiais e ações para o ambiente GNOME" msgid "Log Out..." msgstr "Encerrar sessão..." msgid "Log out or change user" msgstr "Encerra a sessão ou alterar o usuário" msgid "Shut Down..." msgstr "Desligar..." msgid "Shut down, restart or suspend computer" msgstr "Desliga, reinicia ou suspende o computador" msgid "Lock Screen" msgstr "Tela do fechamento" msgid "Enable screensaver and lock" msgstr "Habilitar a proteção de tela e bloquear" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "Gerenciamento de sessão do XFCE" msgid "Special items and actions for XFCE environment" msgstr "Itens especiais e ações para ambiente XFCE" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "Hosts SSH" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "Adiciona as máquinas SSH encontradas em ~/.ssh/config." msgid "SSH host" msgstr "Host SSH" msgid "Connect" msgstr "Conectar" msgid "Connect to SSH host" msgstr "Conectar-se ao host SSH" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "Hosts SSH como especificado em ~/.ssh/config" msgid "No D-Bus connection to desktop session" msgstr "Nenhuma conexão de D-Bus para sessão de desktop" msgid "GNOME Keyring" msgstr "Chaveiro do GNOME" msgid "KWallet" msgstr "KWallet" msgid "Unencrypted File" msgstr "Arquivo não-criptografado" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "Comando em \"%s\" não está disponível" msgid "Document Templates" msgstr "Modelos de documento" msgid "Create new documents from your templates" msgstr "Cria novos documentos a partir de seus modelos" #, python-format msgid "%s template" msgstr "Modelo %s" msgid "Empty File" msgstr "Arquivo vazio" msgid "New Folder" msgstr "Nova pasta" msgid "Create New Document..." msgstr "Criar novo documento..." msgid "Create a new document from template" msgstr "Crie um novo documento a partir do modelo" msgid "Create Document In..." msgstr "Criar documento em..." msgid "Textfiles" msgstr "ArquivosTexto" msgid "Append To..." msgstr "Anexar em..." msgid "Append..." msgstr "Anexar..." msgid "Write To..." msgstr "Gravar em..." msgid "Get Text Contents" msgstr "Obter o conteúdo de texto" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "Ações do gerenciador de arquivos Thunar" msgid "Select in File Manager" msgstr "Selecione no gerenciador de arquivos" msgid "Show Properties" msgstr "Mostrar propriedades" msgid "Show information about file in file manager" msgstr "Mostrar informações sobre o arquivo no gerenciador de arquivos" msgid "Send To..." msgstr "Enviar para..." msgid "Symlink In..." msgstr "Link simbólico em..." msgid "Create a symlink to file in a chosen location" msgstr "Cria um link simbólico para o arquivo em um local escolhido" msgid "Empty Trash" msgstr "Esvaziar lixeira" msgid "Thunar Send To Objects" msgstr "Enviar para objetos do Thunar" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Contatos e ações do Thunderbird/Icedove" msgid "Compose New Email" msgstr "Compor novo e-mail" msgid "Compose a new message in Thunderbird" msgstr "Compor uma nova mensagem no Thunderbird" #, fuzzy msgid "Attach in Email To..." msgstr "Enviar um e-mail para..." #, fuzzy msgid "Compose Email With" msgstr "Compor e-mail" #, fuzzy msgid "Compose a new message using the text as body" msgstr "Compor uma nova mensagem no Thunderbird" msgid "Thunderbird Address Book" msgstr "Catálogo de endereços do Thunderbird" msgid "Contacts from Thunderbird Address Book" msgstr "Contatos do catálogo de endereços do Thunderbird" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Top" msgid "Show running tasks and allow sending signals to them" msgstr "Mostra as tarefas em execução e permite o envio de sinais para eles" msgid "Sort Order" msgstr "Ordem de classificação" msgid "Commandline" msgstr "Linha de comando" msgid "CPU usage (descending)" msgstr "Uso da CPU (descendente)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Uso de memória (descendente)" msgid "Send Signal..." msgstr "Enviar sinal..." msgid "Signals" msgstr "Sinais" msgid "Running Tasks" msgstr "Executando tarefas" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% tempo: %(time)s" msgid "Running tasks for current user" msgstr "Tarefas em execução para o usuário atual" msgid "Trash" msgstr "Lixeira" msgid "Access trash contents" msgstr "Acessar conteúdo da lixeira" msgid "Move to Trash" msgstr "Mover para a lixeira" msgid "Move this file to trash" msgstr "Mova este arquivo para a lixeira" msgid "Restore" msgstr "Restaurar" msgid "Move file back to original location" msgstr "Mover arquivo de volta ao local original" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "A lixeira está vazia" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "A lixeira contém um arquivo" msgstr[1] "A lixeira contém %(num)s arquivos" msgid "Triggers" msgstr "Disparadores" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Atribuir teclas de atalho global (disparadores) aos objetos criados com " "\"Compor comando\"." msgid "Add Trigger..." msgstr "Adicione disparador..." msgid "Remove Trigger" msgstr "Remover disparador" msgid "URL Actions" msgstr "Ações de URL" msgid "Download and Open" msgstr "Baixar e abrir" msgid "Download To..." msgstr "Faça o download para..." msgid "Download URL to a chosen location" msgstr "URL de download para um local escolhido" msgid "Wikipedia" msgstr "Wikipédia" msgid "Search in Wikipedia" msgstr "Pesquisar na Wikipédia" msgid "Wikipedia language" msgstr "Idioma da Wikipédia" #. TRANS: Default wikipedia language code msgid "en" msgstr "pt" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Procurar por este termo em %s.wikipedia.org" msgid "Window List" msgstr "Lista de janelas" msgid "All windows on all workspaces" msgstr "Todas as janelas em todos as áreas de trabalho" msgid "Activate" msgstr "Ativar" msgid "Shade" msgstr "Sombrear" msgid "Unshade" msgstr "Remover sombra" msgid "Minimize" msgstr "Minimizar" msgid "Unminimize" msgstr "Restaurar" msgid "Maximize" msgstr "Maximizar" msgid "Unmaximize" msgstr "Desfazer maximizar" msgid "Maximize Vertically" msgstr "Maximizar verticalmente" msgid "Unmaximize Vertically" msgstr "Desfazer maximizar verticalmente" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Janela em %(wkspc)s" msgid "Frontmost Window" msgstr "Mais à frente da janela" msgid "Next Window" msgstr "Próxima janela" msgid "Jump to this window's workspace and focus" msgstr "Saltar e focar para esta janela da área de trabalho" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "%d janela" msgstr[1] "%d janelas" msgid "Active workspace" msgstr "Áreas de trabalho ativas" msgid "Jump to this workspace" msgstr "Ir para esta área de trabalho" msgid "Workspaces" msgstr "Áreas de trabalho" msgid "Volumes and Disks" msgstr "Discos e volumes" msgid "Mounted volumes and disks" msgstr "Volumes montados e discos" #, python-format msgid "Volume mounted at %s" msgstr "Volume montado em %s" msgid "Unmount" msgstr "Desmontar" msgid "Unmount this volume" msgstr "Desmontar este volume" msgid "Eject" msgstr "Ejetar" msgid "Unmount and eject this media" msgstr "Desmontar e ejetar essa mídia" msgid "Show Text" msgstr "Mostrar texto" msgid "Display text in a window" msgstr "Exibe o texto em uma janela" msgid "Large Type" msgstr "Tipo grande" msgid "Show Notification" msgstr "Mostrar notificação" msgid "Tracker" msgstr "Tracker" msgid "Tracker desktop search integration" msgstr "Integração de busca na área de trabalho do Tracker" msgid "Search in Tracker" msgstr "Procurar no Tracker" msgid "Open Tracker Search Tool and search for this term" msgstr "Abre a ferramenta de pesquisa Tracker e procura por este termo" msgid "Get Tracker Results..." msgstr "Obter resultados do Tracker..." msgid "Show Tracker results for query" msgstr "Mostrar resultados do Tracker para consulta" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "Resultados para \"%s\"" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "Localizar arquivos" msgid "Search filesystem using locate" msgstr "Procurar no sistema de arquivos usando o locate" msgid "Ignore case distinctions when searching files" msgstr "Ignorar distinções ao pesquisar arquivos" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Favoritos do Firefox" msgid "Index of Firefox bookmarks" msgstr "Índice de favoritos do Firefox" #, fuzzy msgid "Firefox Keywords" msgstr "Favoritos do Firefox" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "Pesquisar na web com mecanismo de busca OpenSearch" msgid "Search With..." msgstr "Pesquisa com..." msgid "Search For..." msgstr "Pesquisar por..." #, fuzzy msgid "Search Terms" msgstr "Mecanismos de busca" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Por favor, use \"%s\"" #, fuzzy msgid "Resume playback" msgstr "Retomar a reprodução no Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Próximo" #, fuzzy msgid "Skip to next track" msgstr "Saltar para a próxima faixa no Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Anterior" #, fuzzy msgid "Skip to previous track" msgstr "Saltar para a faixa anterior no Audacious" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "Acessar aos contatos do Pidgin" msgid "Show offline contacts" msgstr "Mostrar contatos desconectados" msgid "Open Chat" msgstr "Abrir conversa" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d caractere)" msgstr[1] "%s (%d caracteres)" msgid "Send Message..." msgstr "Enviar mensagem..." msgid "Available" msgstr "Disponível" msgid "Away" msgstr "Ausente" msgid "Pidgin Contacts" msgstr "Contatos do Pidgin" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Encurtar links" msgid "Create short aliases of long URLs" msgstr "Criar aliases curto de URLs longas" msgid "Error" msgstr "Erro" msgid "Shorten With..." msgstr "Encurtar com..." msgid "Services" msgstr "Serviços" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "Reproduzir e enfileirar faixas e procurar a biblioteca de música" msgid "Include artists in top level" msgstr "Incluir artistas no nível superior" msgid "Include albums in top level" msgstr "Incluir álbuns em nível superior" msgid "Play tracks in Rhythmbox" msgstr "Reproduz as faixas no Rhythmbox" msgid "Add tracks to the play queue" msgstr "Adicionar faixas para a fila de reprodução" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "por %(artist)s de %(album)s" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "por %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Faixas por %s" msgid "Albums" msgstr "Álbuns" msgid "Music albums in Rhythmbox Library" msgstr "Álbuns de música no na biblioteca do Rhythmbox" msgid "Artists" msgstr "Artistas" msgid "Music artists in Rhythmbox Library" msgstr "Artistas da música na biblioteca do Rhythmbox" msgid "Songs" msgstr "Músicas" msgid "Songs in Rhythmbox library" msgstr "Músicas na biblioteca do Rhythmbox" msgid "Getting Things GNOME" msgstr "Getting Things GNOME" msgid "Browse and create new tasks in GTG" msgstr "Procurar e criar novas tarefas no GTG" #, python-format msgid "due: %s" msgstr "vencimento: %s" #, python-format msgid "start: %s" msgstr "Início: %s" #, python-format msgid "tags: %s" msgstr "etiquetas: %s" msgid "Open task in Getting Things GNOME!" msgstr "Tarefa aberta no Getting Things GNOME!" msgid "Delete" msgstr "Remover" msgid "Permanently remove this task" msgstr "Remove permanentemente esta tarefa" msgid "Mark Done" msgstr "Marcar como feito" msgid "Mark this task as done" msgstr "Marca esta tarefa como concluída" msgid "Dismiss" msgstr "Desconsiderar" msgid "Mark this task as not to be done anymore" msgstr "Marca esta tarefa como uma tarefa que não deve ser feita mais" msgid "Create Task" msgstr "Criar tarefa" msgid "Create new task in Getting Things GNOME" msgstr "Criar nova tarefa no Getting Things GNOME" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "Pesquisa no Devhelp" msgid "Empathy" msgstr "Empathy" msgid "Access to Empathy Contacts" msgstr "Acessar aos contatos do Empathy" msgid "Busy" msgstr "Ocupado" msgid "Not Available" msgstr "Não disponível" msgid "Invisible" msgstr "Invisível" msgid "Offline" msgstr "Desconectado" msgid "Change Global Status To..." msgstr "Alterar status global para..." msgid "Empathy Contacts" msgstr "Contatos do Empathy" msgid "Empathy Account Status" msgstr "Status de conta do Empathy" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Ativar o suplente" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Truque da vírgula" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Compor comando" msgid "Mark Default Action" msgstr "Marcar ação padrão" msgid "Forget Object" msgstr "Esquecer objeto" msgid "Reset All" msgstr "Redefinir tudo" msgid "Select Quit" msgstr "Selecionar sair" msgid "Select Selected File" msgstr "Selecione o arquivo selecionado" msgid "Select Selected Text" msgstr "Selecione o texto selecionado" msgid "Show Help" msgstr "Mostrar ajuda" msgid "Show Preferences" msgstr "Mostrar as preferências" msgid "Switch to First Pane" msgstr "Alterne para o primeiro painel" msgid "Toggle Text Mode" msgstr "Alternar para o modo texto" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Nenhuma correspondência em %(src)s para \"%(query)s\"" msgid "No matches" msgstr "Nenhuma correspondência" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Nenhuma correspondência" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Tornar \"%(action)s\" padrão para \"%(object)s\"" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "Esquecer sobre \"%s\"" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Exibir interface principal" msgid "Show with Selection" msgstr "Exibir com seleção" #. TRANS: Plugin info fields msgid "Description" msgstr "Descrição" msgid "Author" msgstr "Autor" msgid "Version" msgstr "Versão" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Módulo Python \"%s\" é necessário" msgid "Plugin could not be read due to an error:" msgstr "Plug-in não pôde ser lido devido a um erro:" msgid "Content of" msgstr "Conteúdo de" #. TRANS: Plugin contents header msgid "Sources" msgstr "Fontes" #. TRANS: Plugin contents header msgid "Actions" msgstr "Ações" #, python-format msgid "Using encrypted password storage: %s" msgstr "Usando armazenamento de senha criptografada: %s" #, python-format msgid "Using password storage: %s" msgstr "Usando armazenamento de senha: %s" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Configuração" msgid "Set username and password" msgstr "Definir o nome de usuário e senha" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Escolha um diretório" msgid "Reset all shortcuts to default values?" msgstr "Redefinir todos os atalhos para os valores padrão?" msgid "Shortcut" msgstr "Atalho" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "" "Djavan Fagundes \n" "Rafael Ferreira " msgid "A free software (GPLv3+) launcher" msgstr "Um iniciador de software livre (GPLv3+)" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Este programa é um software livre; você pode redistribuí-lo e/ou modificá-" "lo\n" "sob os termos da Licença Pública Geral GNU publicada pela Free Software \n" "Foundation; qualquer versão 2 da Licença, ou (a seu critério) outra versão \n" "posterior. \n" "\n" "Este programa é distribuído na expectativa de que seja útil, mas SEM " "NENHUMA\n" "GARANTIA; sem mesmo implicar garantias de COMERCIABILIDADE ou ADAPTAÇÃO A\n" "UM PROPÓSITO PARTICULAR. Veja a Licença Pública Geral GNU (GPL) para mais\n" "detalhes.\n" "\n" "Você deve ter recebido uma cópia da Licença Pública Geral GNU\n" "junto com este programa; caso contrário, veja .\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Não foi possível encontrar a execução do Kupfer" #~ msgid "Compose Email" #~ msgstr "Compor e-mail" #~ msgid "Send in Email To..." #~ msgstr "Enviar um e-mail para..." #~ msgid "Type to search %s" #~ msgstr "Digite para pesquisar %s" #~ msgid "No action" #~ msgstr "Nenhuma ação" #~ msgid "GNOME Terminal Profiles" #~ msgstr "Perfis do GNOME Terminal" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Lançar perfis do GNOME Terminal" #~ msgid "Multihead Support" #~ msgstr "Suporte multihead" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Calcular expressões começando com \"=\"" #~ msgid "Epiphany Bookmarks" #~ msgstr "Favoritos do Epiphany" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Índice de favoritos do Epiphany" #~ msgid "Include visited sites" #~ msgstr "Incluir sites visitados" #~ msgid "Firefox tag" #~ msgstr "Etiqueta do Firefox" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Retomar a reprodução no Rhythmbox" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Pausar a reprodução no Rhythmbox" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Saltar para a próxima faixa no Rhythmbox" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Saltar para a faixa anterior no Rhythmbox" #~ msgid "Search the Web" #~ msgstr "Pesquisar na Web" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Documentos usados recentemente no Abiword" #~ msgid "Abiword Recent Items" #~ msgstr "Itens recentes do Abiword" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "Interface com o gerenciador de pacotes APT" #~ msgid "Installation method" #~ msgstr "Método de instalação" #~ msgid "Show Package Information" #~ msgstr "Mostrar informações de pacote" #~ msgid "Install" #~ msgstr "Instalar" #~ msgid "Install package using the configured method" #~ msgstr "Instalar pacotes usando o método configurado" #~ msgid "Packages matching \"%s\"" #~ msgstr "Pacotes correspondentes \"%s\"" #~ msgid "Search Package Name..." #~ msgstr "Pesquisar nome do pacote..." #~ msgid "Ascii & Unicode Icon Set" #~ msgstr "Definição de ícones ASCII & Unicode" #~ msgid "" #~ "Provides the Ascii and Unicode icon sets that use letters and symbols to " #~ "produce icons for the objects found in Kupfer." #~ msgstr "" #~ "Fornece a definição de ícones Ascii e Unicode que usam letras e símbolos " #~ "para produzir ícones para os objetos encontrados no Kupfer." #~ msgid "Ascii" #~ msgstr "ASCII" #~ msgid "Unicode" #~ msgstr "Unicode" #~ msgid "Chromium Bookmarks" #~ msgstr "Favoritos do Chromium" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Índice de favoritos do Chromium" #~ msgid "Claws Mail" #~ msgstr "Claws Mail" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Ações e contatos do Claws Mail" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Compor uma nova mensagem no Claws Mail" #~ msgid "Receive All Email" #~ msgstr "Receber todos os E-mails" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "Receber novas mensagens de todas as contas no ClawsMail" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Compor nova mensagem no Claws Mail e anexar arquivo" #~ msgid "Claws Mail Address Book" #~ msgstr "Catálogo de endereços do Claws Mail" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Contatos do catálogo de endereços do Claws Mail" #~ msgid "Configure a custom terminal emulator" #~ msgstr "Configurar um emulador de terminal personalizado" #~ msgid "Custom Theme" #~ msgstr "Tema personalizado" #~ msgid "Use a custom color theme" #~ msgstr "Usar um tema de cor personalizada" #~ msgid "Theme:" #~ msgstr "Tema:" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Contatos do Evolution" #~ msgid "Compose a new message in Evolution" #~ msgstr "Compor uma nova mensagem no Evolution" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Compor nova mensagem no Evolução e anexar arquivo" #~ msgid "Evolution Address Book" #~ msgstr "Catálogo de endereços do Evolution" #~ msgid "Filezilla" #~ msgstr "Filezilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Mostrar sites e manipular endereços ftp pelo Filezilla" #~ msgid "Open Site with Filezilla" #~ msgstr "Abrir site com Filezilla" #~ msgid "Filezilla Sites" #~ msgstr "Sites do Filezilla" #~ msgid "Sites from Filezilla" #~ msgstr "Sites do Filezilla" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Acesso aos contatos do Gajim" #~ msgid "Free for Chat" #~ msgstr "Livre para conversa" #~ msgid "Gajim Contacts" #~ msgstr "Contatos do Gajim" #~ msgid "Gajim Account Status" #~ msgstr "Status da conta do Gajim" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Carregar contatos e compor novo e-mail no Gmail" #~ msgid "Load contacts' pictures" #~ msgstr "Carregar imagens dos contatos" #~ msgid "Load additional information" #~ msgstr "Carregar informações adicionais" #~ msgid "Work email" #~ msgstr "E-mail comercial" #~ msgid "Home email" #~ msgstr "E-mail residencial" #~ msgid "Other email" #~ msgstr "Outro e-mail" #~ msgid "Work address" #~ msgstr "Endereço comercial" #~ msgid "Home address" #~ msgstr "Endereço residencial" #~ msgid "Other address" #~ msgstr "Outro endereço" #~ msgid "Car phone" #~ msgstr "Telefone do carro" #~ msgid "Fax" #~ msgstr "Fax" #~ msgid "Home phone" #~ msgstr "Telefone residencial" #~ msgid "Home fax" #~ msgstr "Fax residencial" #~ msgid "Internal phone" #~ msgstr "Telefone interno" #~ msgid "Mobile" #~ msgstr "Celular" #~ msgid "Other" #~ msgstr "Outro" #~ msgid "VOIP" #~ msgstr "VOIP" #~ msgid "Work phone" #~ msgstr "Telefone de trabalho" #~ msgid "Work fax" #~ msgstr "Fax comercial" #~ msgid "Compose Email in Gmail" #~ msgstr "Escrever e-mail no Gmail" #~ msgid "Open web browser and compose new email in Gmail" #~ msgstr "Abre o navegador de internet e compõe novo e-mail no Gmail" #~ msgid "Edit Contact in Gmail" #~ msgstr "Editar contato no Gmail" #~ msgid "Open web browser and edit contact in Gmail" #~ msgstr "Abre o navegador de internet e edita contato no Gmail" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Contatos de serviços do Google (Gmail)" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Mostrar álbuns e fazer upload de arquivos para o Picasa" #~ msgid "Users to show: (,-separated)" #~ msgstr "Usuários para mostrar: (, -separados)" #~ msgid "Load user and album icons" #~ msgstr "Carregar ícones e álbuns do usuário" #~ msgid "Uploading Pictures" #~ msgstr "Enviando imagens" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Enviando fotos para o álbum web do Picasa" #~ msgid "Creating album:" #~ msgstr "Criando o álbum:" #~ msgid "Album created by Kupfer" #~ msgstr "Álbum criado por Kupfer" #~ msgid "File:" #~ msgstr "Arquivo:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "Um álbum" #~ msgstr[1] "%(num)d álbuns" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "uma foto" #~ msgstr[1] "%(num)s fotos" #~ msgid "Upload to Picasa Album..." #~ msgstr "Enviar para álbum do Picasa..." #~ msgid "Upload files to Picasa album" #~ msgstr "Envia arquivos para o álbum do Picasa" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Enviar para o Picasa como novo álbum" #~ msgid "Create album from selected local directory" #~ msgstr "Criar um álbum do diretório local selecionado" #~ msgid "Picasa Albums" #~ msgstr "Álbuns do Picasa" #~ msgid "User albums in Picasa" #~ msgstr "Álbuns de usuário no Picasa" #~ msgid "Google Search" #~ msgstr "Pesquisa do Google" #~ msgid "Search Google with results shown directly" #~ msgstr "Pesquisa do Google com resultados mostrados diretamente" #~ msgid "Show More Results For \"%s\"" #~ msgstr "Mostrar mais resultados para %s\"" #~ msgid "%s total found" #~ msgstr "Total encontrado %s" #~ msgid "Gwibber" #~ msgstr "Gwibber" #~ msgid "" #~ "Microblogging with Gwibber. Allows sending and receiving messages from " #~ "social networks like Twitter, Identi.ca etc. Requires the package " #~ "'gwibber-service'." #~ msgstr "" #~ "Microblogging é com o Gwibber. Permite enviar e receber mensagens de " #~ "redes sociais como o Twitter, identi.ca etc. Requer o pacote \"gwibber-" #~ "service\"." #~ msgid "Maximum number of messages to show" #~ msgstr "Número máximo de mensagens para mostrar" #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s no %(service)s" #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s via %(where)s" #~ msgid "Send Message" #~ msgstr "Enviar mensagem" #~ msgid "Send message to all Gwibber accounts" #~ msgstr "Enviar mensagem para todas as contas do Gwibber" #~ msgid "Send Message To..." #~ msgstr "Enviar mensagem para..." #~ msgid "Send message to a Gwibber account" #~ msgstr "Envia mensagem para uma conta do Gwibber" #~ msgid "Send message to selected Gwibber account" #~ msgstr "Envia mensagem para a conta do Gwibber selecionada" #~ msgid "Reply..." #~ msgstr "Resposta..." #~ msgid "Delete Message" #~ msgstr "Apagar mensagem" #~ msgid "Send Private Message..." #~ msgstr "Enviar mensagem privada..." #~ msgid "Send direct message to user" #~ msgstr "Envia uma mensagem direta para o usuário" #~ msgid "Retweet" #~ msgstr "Retweet" #~ msgid "Retweet To..." #~ msgstr "Reenviar para..." #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Reenvia a mensagem para todas as contas do Gwibber" #~ msgid "Retweet message to a Gwibber account" #~ msgstr "Reenvia mensagem para uma conta do Gwibber" #~ msgid "Open in Browser" #~ msgstr "Abrir no navegador" #~ msgid "Open message in default web browser" #~ msgstr "Abrir uma mensagem no navegador padrão" #~ msgid "Gwibber Accounts" #~ msgstr "Contas de Gwibber" #~ msgid "Accounts configured in Gwibber" #~ msgstr "Contas configuradas no Gwibber" #~ msgid "Gwibber Messages" #~ msgstr "Mensagens do Gwibber" #~ msgid "Recent messages received by Gwibber" #~ msgstr "Mensagens recentes recebidas pelo Gwibber" #~ msgid "Gwibber Messages for %s" #~ msgstr "Mensagens do Gwibber para %s" #~ msgid "Gwibber Streams" #~ msgstr "Fluxos do Gwibber" #~ msgid "Streams configured in Gwibber" #~ msgstr "Fluxos configurados no Gwibber" #~ msgid "Gwibber Messages in %s" #~ msgstr "Mensagens do Gwibber em %s" #~ msgid "Gwibber (Simple)" #~ msgstr "Gwibber (simples)" #~ msgid "Send updates via the microblogging client Gwibber" #~ msgstr "Envia atualizações através do cliente de microblogging Gwibber" #~ msgid "Send Update" #~ msgstr "Enviar atualização" #~ msgid "Unable to activate Gwibber service" #~ msgstr "Não é possível ativar o serviço do Gwibber" #~ msgid "OpenOffice / LibreOffice" #~ msgstr "OpenOffice / LibreOffice" #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Documentos usados recentemente no OpenOffice/LibreOffice" #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "Itens recentes do OpenOffice/LibreOffice" #~ msgid "Opera Mail" #~ msgstr "Opera Mail" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Ações e contatos do Opera Mail" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Compor uma nova mensagem no Opera Mail" #~ msgid "Opera Mail Contacts" #~ msgstr "Contatos do Opera Mail" #~ msgid "Contacts from Opera Mail" #~ msgstr "Contatos do Opera Mail" #~ msgid "Opera Bookmarks" #~ msgstr "Marcadores do Opera" #~ msgid "Index of Opera bookmarks" #~ msgstr "Índice de favoritos do Firefox" #~ msgid "PuTTY Sessions" #~ msgstr "Sessões do PuTTY" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Acesso rápido às sessões do PuTTY" #~ msgid "Start Session" #~ msgstr "Iniciar sessão" #~ msgid "reStructuredText" #~ msgstr "reStructuredText" #~ msgid "Render reStructuredText and show the result" #~ msgstr "Renderizar reStructuredText e mostrar o resultado" #~ msgid "View as HTML Document" #~ msgstr "Ver como documento HTML" #~ msgid "System Services" #~ msgstr "Serviços do sistema" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "" #~ "Iniciar, parar ou reiniciar os serviços do sistema através de scripts de " #~ "inicialização" #~ msgid "Sudo-like Command" #~ msgstr "Comando sudo-like" #~ msgid "Start Service" #~ msgstr "Iniciar o serviço" #~ msgid "Stop Service" #~ msgstr "Parar o serviço" #~ msgid "%s Service" #~ msgstr "%s serviço" #~ msgid "Show QRCode" #~ msgstr "Mostrar QRCode" #~ msgid "Display text as QRCode in a window" #~ msgstr "Exibir texto como QRCode em uma janela." #~ msgid "Access to Skype contacts" #~ msgstr "Acesse os contatos do Skype" #~ msgid "Skype Me" #~ msgstr "Modo SkypeMe!" #~ msgid "Logged Out" #~ msgstr "Encerrar sessão" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Chamada" #~ msgid "Place a call to contact" #~ msgstr "Faz uma chamada para contato" #~ msgid "Skype Contacts" #~ msgstr "Contatos do Skype" #~ msgid "Skype Statuses" #~ msgstr "Status do Skype" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Histórico de volumes do TrueCrypt" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "Volume TrueCrypt: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Montar volume" #~ msgid "Mount in Truecrypt" #~ msgstr "Montar no Truecrypt" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Tente montar arquivos como um volume Truecrypt" #~ msgid "Dismount All Volumes" #~ msgstr "Desmontar todos os volumes" #~ msgid "TrueCrypt Volumes" #~ msgstr "Volumes TrueCrypt" #~ msgid "Terminal Server Client" #~ msgstr "Cliente do terminal server" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Sessão salva no cliente do terminal server" #~ msgid "TSClient sessions" #~ msgstr "Sessões TSClient" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Sessões salvas no cliente do terminal server" #~ msgid "Vim" #~ msgstr "Vim" #~ msgid "Recently used documents in Vim" #~ msgstr "Documentos usados recentemente no Vim" #~ msgid "Vim Recent Documents" #~ msgstr "Documentos recentes do Vim" #~ msgid "Close (Save All)" #~ msgstr "Fechar (salvar tudo)" #~ msgid "Send..." #~ msgstr "Enviar..." #~ msgid "Send ex command" #~ msgstr "Enviar o comando ex" #~ msgid "Insert in Vim..." #~ msgstr "Inserir no Vim..." #~ msgid "Active Vim Sessions" #~ msgstr "Sessões ativas do Vim" #~ msgid "Vim Session %s" #~ msgstr "Vim sessão %s" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Ações e favoritos do Vinagre" #~ msgid "Start Vinagre Session" #~ msgstr "Iniciar sessão do Vinagre" #~ msgid "Vinagre Bookmarks" #~ msgstr "Favoritos do Vinagre" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "Controla as máquinas virtuais do VirtualBox. Oferece suporte ao Sun " #~ "VirtualBox e Open Source Edition." #~ msgid "Force use CLI interface" #~ msgstr "Forçar o uso da interface CLI" #~ msgid "Power On" #~ msgstr "Ligar" #~ msgid "Power On Headless" #~ msgstr "Ligar sem monitor" #~ msgid "Send Power Off Signal" #~ msgstr "Enviar sinal de desligamento" #~ msgid "Reboot" #~ msgstr "Reiniciar" #~ msgid "Resume" #~ msgstr "Retomar" #~ msgid "Save State" #~ msgstr "Salvar estado" #~ msgid "Power Off" #~ msgstr "Desligar" #~ msgid "VirtualBox Machines" #~ msgstr "Máquinas do VirtualBox" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "" #~ "Acessar páginas armazenadas no Zim - Um ambiente Wiki e próprio para " #~ "escrita" #~ msgid "Page names start with :colon" #~ msgstr "Nomes das páginas começam como :colon" #~ msgid "Default page name for quick notes" #~ msgstr "Nome da página padrão para notas rápidas" #~ msgid "Note %x %X" #~ msgstr "Nota %x %X" #~ msgid "" #~ "Strftime tags can be used: %H - hour, %M - minutes, etc\n" #~ "Please check python documentation for details.\n" #~ "NOTE: comma will be replaced by _" #~ msgstr "" #~ "Tags de strftime podem ser usadas: %H - hora, %M - minutos, etc\n" #~ "Por favor, verifique a documentação do python para mais detalhes.\n" #~ "NOTA: vírgula será substituída por _" #~ msgid "Default namespace for quick notes" #~ msgstr "Espaço de nome padrão para notas rápidas" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Página Zim do caderno \"%s\"" #~ msgid "Create Zim Page" #~ msgstr "Criar página no Zim" #~ msgid "Create page in default notebook" #~ msgstr "Criar página no caderno padrão" #~ msgid "Create Zim Page In..." #~ msgstr "Criar página do Zim em..." #~ msgid "Insert QuickNote into Zim" #~ msgstr "Inserir QuickNote no Zim" #~ msgid "Quick note selected text into Zim notebook" #~ msgstr "Texto selecionado do Quick note para Zim" #~ msgid "Create Subpage..." #~ msgstr "Crie subpágina..." #~ msgid "Zim Notebooks" #~ msgstr "Cadernos do Zim" #~ msgid "Zim Pages" #~ msgstr "Páginas do Zim" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Páginas armazenadas em cadernos do Zim" #~ msgid "Selected File" #~ msgstr "Arquivo selecionado" #~ msgid "" #~ "Provides current nautilus selection, using Kupfer's Nautilus Extension" #~ msgstr "" #~ "Fornece a seleção atual do nautilus, usando a extensão Nautilus do Kupfer" #~ msgid "Selected File \"%s\"" #~ msgstr "Arquivo \"%s\" selecionado" #~ msgid "Selected Files" #~ msgstr "Arquivos selecionados" #~ msgid "Translate text with Google Translate" #~ msgstr "Traduzir texto com o Google Translate" #~ msgid "Google Translate connection timed out" #~ msgstr "A conexão com o Google Translate expirou" #~ msgid "Error connecting to Google Translate" #~ msgstr "Erro ao conectar ao Google Translate" #~ msgid "Translate To..." #~ msgstr "Traduzir para ..." #~ msgid "Translate into %s" #~ msgstr "Traduzir em %s" #~ msgid "Languages" #~ msgstr "Idiomas" #~ msgid "Show translated page in browser" #~ msgstr "Visualizar página traduzida no navegador" #~ msgid "Show Translation To..." #~ msgstr "Mostra tradução para..." #~ msgid "Show translation in browser" #~ msgstr "Mostrar tradução no navegador" #~ msgid "Tracker 0.6" #~ msgstr "Tracker 0.6" #~ msgid "Tracker tags" #~ msgstr "Etiquetas do Tracker" #~ msgid "Tracker Tags" #~ msgstr "Etiquetas do Tracker" #~ msgid "Browse Tracker's tags" #~ msgstr "Navegar nas etiquetas do Tracker" #~ msgid "Tag %s" #~ msgstr "Etiqueta %s" #~ msgid "Objects tagged %s with Tracker" #~ msgstr "Objetos %s etiquetados com o Tracker" #~ msgid "Add Tag..." #~ msgstr "Adicionar etiqueta ..." #~ msgid "Add tracker tag to file" #~ msgstr "Adiciona uma etiqueta para o arquivo" #~ msgid "Remove Tag..." #~ msgstr "Remover etiqueta..." #~ msgid "Remove tracker tag from file" #~ msgstr "Remover etiqueta do tracker do arquivo" kupfer-328/po/ro.po000066400000000000000000001763611500175051100142730ustar00rootroot00000000000000# Romanian translation for kupfer. # Copyright (C) 2011 kupfer's COPYRIGHT HOLDER # This file is distributed under the same license as the kupfer package. # Florentina M. , 2011. # Florentina Musat , 2011. # Florentina Mușat , 2011. # Daniel Șerbănescu , 2015. msgid "" msgstr "" "Project-Id-Version: kupfer master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2015-10-25 11:37+0200\n" "Last-Translator: Daniel Șerbănescu \n" "Language-Team: Gnome Romanian Translation Team\n" "Language: 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: Virtaal 0.7.1\n" msgid "User credentials" msgstr "Credențialele utilizatorului" msgid "_User:" msgstr "_Utilizator:" msgid "_Password:" msgstr "_Parolă:" msgid "_Change" msgstr "S_chimbă" msgid "Set Keyboard Shortcut" msgstr "Configurează scurtătura de tastatură" msgid "Please press desired key combination" msgstr "Apăsați combinația de taste dorită" msgid "Keybinding could not be bound" msgstr "Combinația de taste nu a putut fi legată" msgid "Kupfer Preferences" msgstr "Preferințe Kupfer" msgid "Start automatically on login" msgstr "Pornește automat la autentificare" msgid "Start" msgstr "Pornire" msgid "Show icon in notification area" msgstr "Afișează pictograma în zona de notificare" msgid "Icon set:" msgstr "Set de iconițe:" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" msgid "Terminal emulator:" msgstr "Emulator de terminal:" msgid "Desktop Environment" msgstr "Mediu desktop" msgid "General" msgstr "Generale" msgid "Global Keyboard Shortcuts" msgstr "Scurtături de tastatură globale" msgid "Reset" msgstr "Restabilește" msgid "Browser Keyboard Shortcuts" msgstr "Scurtături de tastatură ale navigatorului" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "" "Utilizează comenzi cu o singură combinație de taste (Spațiu, /, punct, " "virgulă, etc.)" msgid "Keyboard" msgstr "Tastatură" msgid "Plugins" msgstr "Module" msgid "Inclusion in Top Level Searches" msgstr "Includerea în căutările de nivel înalt" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "Sursele marcate au obiectele lor incluse în căutările de nivel înalt.\n" "Conținutul unei surse nemarcate este disponibil numai localizându-i " "subcatalogul." msgid "Indexed Folders" msgstr "Dosare indexate" msgid "Folders whose files are always available in the catalog." msgstr "Dosare ale căror fișiere sunt întotdeauna disponibile în catalog." msgid "Catalog" msgstr "Catalog" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Lansator de aplicații" msgid "Convenient command and access tool for applications and documents" msgstr "Unealtă convenabilă de acces și comandă pentru aplicații și documente" msgid "Execute in Kupfer" msgstr "Execută în Kupfer" msgid "Saved Kupfer Command" msgstr "Comandă Kupfer salvată" #, python-format msgid "Could not to carry out '%s'" msgstr "Nu se poate executa „%s”" #, python-format msgid "\"%s\" produced a result" msgstr "„%s” a produs un rezultat" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Nu există permisiune de a rula „%s” (nu este executabil)" #, python-format msgid "Command in \"%s\" is not available" msgstr "Comanda în „%s” nu este disponibilă" #, python-format msgid "Keyboard relay is active for display %s" msgstr "Releul tastaurii este activ pentru afișajul %s" msgid "do not present main interface on launch" msgstr "nu prezenta interfața principală la lansare" msgid "list available plugins" msgstr "enumeră modulele disponibile" msgid "enable debug info" msgstr "activează informațiile de depanare" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "rulează ajutorul pentru module" msgid "show usage help" msgstr "afișează ajutorul de utilizare" msgid "show version information" msgstr "afișează informațiile versiunii" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Utilizare: kupfer [ OPȚIUNI | FIȘIER ... ]" msgid "Available plugins:" msgstr "Module disponibile:" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "Tastați pentru a căuta" #, python-format msgid "%s is empty" msgstr "%s este gol" msgid "Text" msgstr "Text" msgid "Run after Delay..." msgstr "Rulează după întârziere..." msgid "Perform command after a specified time interval" msgstr "Execută comanda după un interval de timp specificat" msgid "Multiple Objects" msgstr "Obiecte multiple" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s obiect" msgstr[1] "%s obiecte" msgstr[2] "%s de obiecte" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "necunoscut" msgid "Aim" msgstr "Aim" msgid "Google Talk" msgstr "Google Talk" msgid "ICQ" msgstr "ICQ" msgid "MSN" msgstr "MSN" msgid "QQ" msgstr "QQ" msgid "Yahoo" msgstr "Yahoo" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "%s nu suportă această operație" msgid "Can not be used with multiple objects" msgstr "Nu poate fi folosit cu obiecte multiple" msgid "Open" msgstr "Deschide" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Nu există o aplicație implicită pentru %(file)s (%(type)s)" #, python-format msgid "Please use \"%s\"" msgstr "Folosiți „%s”" msgid "Set Default Application..." msgstr "Stabilește aplicația implicită..." msgid "Open with default application" msgstr "Deschide cu aplicația implicită" msgid "Reveal" msgstr "Dezvăluie" msgid "Open parent folder" msgstr "Deschide dosarul părinte" msgid "Open Terminal Here" msgstr "Deschide terminalul aici" msgid "Open this location in a terminal" msgstr "Deschide această locație într-un terminal" msgid "Run in Terminal" msgstr "Rulează în terminal" msgid "Run (Execute)" msgstr "Rulează (Execută)" msgid "Run this program in a Terminal" msgstr "Rulează acest program într-un terminal" msgid "Run this program" msgstr "Rulează acest program" msgid "Go To" msgstr "Navighează la" msgid "Open URL" msgstr "Deschide URL" msgid "Open URL with default viewer" msgstr "Deschide URL cu vizualizatorul implicit" msgid "Launch" msgstr "Lansează" msgid "Show application window" msgstr "Afișează fereastra aplicației" msgid "Launch application" msgstr "Lansează aplicație" msgid "Launch Again" msgstr "Lansează din nou" msgid "Launch another instance of this application" msgstr "Lansează altă instanță a acestei aplicații" msgid "Close" msgstr "Închide" msgid "Attempt to close all application windows" msgstr "Încearcă să închidă toate ferestrele aplicației" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Rulează" msgid "Perform command" msgstr "Execută comanda" msgid "(Empty Text)" msgstr "(Text gol)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "„%(text)s”" msgstr[1] "(%(num)d linii) „%(text)s”" msgstr[2] "(%(num)d de linii) „%(text)s”" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s și alții" #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Sursă recursivă a %(dir)s, (%(levels)d nivele)" #, python-format msgid "Directory source %s" msgstr "Sursa %s a dosarului" msgid "Home Folder" msgstr "Dosarul Acasă" msgid "Catalog Index" msgstr "Indexul catalogului" msgid "An index of all available sources" msgstr "Un index cu toate sursele disponibile" msgid "Root catalog" msgstr "Catalog rădăcină" msgid "Please Configure Plugin" msgstr "Configurați modulul" #, python-format msgid "Plugin %s is not configured" msgstr "Modulul %s nu este configurat" #, python-format msgid "Invalid user credentials for %s" msgstr "Credențiale de utilizator nevalide pentru %s" msgid "Applications" msgstr "Aplicații" msgid "All applications and preferences" msgstr "Toate aplicațiile și preferințele" msgid "Applications for Desktop Environment" msgstr "Aplicații pentru mediul desktop" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "Deschide cu..." msgid "Open with any application" msgstr "Deschide cu orice aplicație" msgid "Set default application to open this file type" msgstr "Stabilește aplicația implicită pentru a deschide acest tip de fișier" #, fuzzy msgid "Reset Associations" msgstr "Acțiuni URL" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "Arhive structurate" msgid "Allow browsing inside compressed archive files" msgstr "Permite navigarea în fișierele de arhive comprimate" #, python-format msgid "Content of %s" msgstr "Conținutul lui %s" msgid "Archive Manager" msgstr "Administrator de arhive" msgid "Use Archive Manager actions" msgstr "Utilizați acțiunile administratorului de arhive" msgid "Compressed archive type for 'Create Archive In'" msgstr "Tipul de arhivă comprimată pentru „Creează arhivă în”" msgid "Extract Here" msgstr "Extrage aici" msgid "Extract compressed archive" msgstr "Extrage arhiva comprimată" msgid "Create Archive" msgstr "Creează arhivă" msgid "Create a compressed archive from folder" msgstr "Creează o arhivă comprimată din dosar" msgid "Create Archive In..." msgstr "Creează arhivă în..." #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Arhivă" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "Controlează redarea și lista de redare Audacious" msgid "Include songs in top level" msgstr "Include piesele în prmul nivel" msgid "Enqueue" msgstr "Plasează la coadă" msgid "Add track to the Audacious play queue" msgstr "Adaugă piesa la coada de redare Audacious" msgid "Dequeue" msgstr "Șterge de la coadă" msgid "Remove track from the Audacious play queue" msgstr "Elimină pista din coada de redare Audacious" msgid "Play" msgstr "Redă" msgid "Jump to track in Audacious" msgstr "Sari la piesă în Audacious" msgid "Resume playback in Audacious" msgstr "Reia redarea în Audacious" msgid "Pause" msgstr "Pauză" msgid "Pause playback in Audacious" msgstr "Pune pauză redării în Audacious" msgid "Next" msgstr "Următorul" msgid "Jump to next track in Audacious" msgstr "Sari la pista următoare în Audacious" msgid "Previous" msgstr "Anteriorul" msgid "Jump to previous track in Audacious" msgstr "Sari la pista anterioară în Audacious" msgid "Clear Queue" msgstr "Eliberează coada" msgid "Clear the Audacious play queue" msgstr "Eliberează coada de redare Audacious" msgid "Shuffle" msgstr "Amestecă" msgid "Toggle shuffle in Audacious" msgstr "Comută amestecarea în Audacious" msgid "Repeat" msgstr "Repetă" msgid "Toggle repeat in Audacious" msgstr "Comută repetarea în Audacious" msgid "Show Playing" msgstr "Afișează redarea" msgid "Tell which song is currently playing" msgstr "Spune ce piesă este redată acum" msgid "Playlist" msgstr "Listă de redare" msgid "Calculator" msgstr "Calculator" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "Calculează" msgid "Clipboards" msgstr "Clipboarduri" msgid "Recent clipboards and clipboard proxy objects" msgstr "Clipboarduri recente și obiecte clipboard de tip proxy" msgid "Number of recent clipboards to remember" msgstr "Numărul de clipboarduri recente de ținut minte" msgid "Include selected text in clipboard history" msgstr "Include textul selectat în istoricul clipboardului" msgid "Copy selected text to primary clipboard" msgstr "Copiază textul selectat în clipboardul de bază" msgid "Selected Text" msgstr "Text selectat" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Clipboard „%(desc)s”" msgstr[1] "Clipboard cu %(num)d linii „%(desc)s”" msgstr[2] "Clipboard cu %(num)d de linii „%(desc)s”" msgid "Clipboard Text" msgstr "Text în clipboard" msgid "Clipboard File" msgstr "Fișier în clipboard" msgid "Clipboard Files" msgstr "Fișiere în clipboard" msgid "Clear" msgstr "Eliberează" msgid "Remove all recent clipboards" msgstr "Elimină toate clipboardurile recente" msgid "Shell Commands" msgstr "Comenzi pentru shell" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Rulează programe în linia de comandă. Acțiunile marcate cu simbolul %s " "rulează într-un subshell." msgid "Run (Get Output)" msgstr "Rulează (Obține ieșire)" msgid "Run program and return its output" msgstr "Rulează programul și întoarce ieșirea acestuia" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "Pasează la comanda..." msgid "Run program with object as an additional parameter" msgstr "Rulează programul cu un obiect ca parametru adițional" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "Scrie la comanda..." msgid "Run program and supply text on the standard input" msgstr "Rulează programul și oferă textul în intrarea standard" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "Filtrează prin comanda..." msgid "Run command-line programs" msgstr "Rulează programe în linia de comandă" msgid "GTK+" msgstr "GTK+" msgid "GNOME Terminal" msgstr "Terminal GNOME" msgid "XFCE Terminal" msgstr "Terminal XFCE" msgid "LXTerminal" msgstr "LXTerminal" msgid "X Terminal" msgstr "Terminal X" msgid "Urxvt" msgstr "Urxvt" msgid "Konsole" msgstr "Konsole" msgid "Save As..." msgstr "Salvează ca..." #, fuzzy msgid "Restart Kupfer" msgstr "Repornește serviciu" msgid "Quit" msgstr "Ieșire" msgid "Quit Kupfer" msgstr "Ieși din Kupfer" msgid "About Kupfer" msgstr "Despre Kupfer" msgid "Show information about Kupfer authors and license" msgstr "Afișează informații despre autorii Kupfer și licență" msgid "Kupfer Help" msgstr "Ajutor Kupfer" msgid "Get help with Kupfer" msgstr "Obține ajutor prin intermediul lui Kupfer" msgid "Show preferences window for Kupfer" msgstr "Afișează fereastra de preferințe pentru Kupfer" msgid "Search Contents" msgstr "Caută conținuturi" msgid "Search inside this catalog" msgstr "Caută în interiorul acestui catalog" msgid "Copy" msgstr "Copiază" msgid "Copy to clipboard" msgstr "Copiază la clipboard" msgid "Rescan" msgstr "Rescanează" msgid "Force reindex of this source" msgstr "Forțează reindexarea acestei surse" msgid "Last Command" msgstr "Ultima comandă" msgid "Internal Kupfer Objects" msgstr "Obiecte Kupfer interne" msgid "Last Result" msgstr "Ultimul rezultat" msgid "Command Results" msgstr "Rezultatele comenzii" msgid "Custom Terminal" msgstr "Terminal personalizat" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Comandă" msgid "Execute flag" msgstr "Execută indicator" msgid "Default Email Client" msgstr "Clientul de email implicit" msgid "Compose email using the system's default mailto: handler" msgstr "" "Compune un email utilizând adiministratorul „mailto:” implicit al sistemului" #, fuzzy msgid "Compose Email To" msgstr "Compune email" msgid "Dictionary" msgstr "Dicționar" msgid "Look up word in dictionary" msgstr "Caută cuvântul în dicționar" msgid "Look Up" msgstr "Caută" msgid "Documents" msgstr "Documente" msgid "Recently used documents and bookmarked folders" msgstr "Documentele utilizate recent și dosarele favorite" msgid "Max recent document days" msgstr "Numărul maxim de zile pentru documentele recente" msgid "Recent Items" msgstr "Elemente recente" msgid "Recently used documents" msgstr "Documente utilizate recent" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "%s documente" #, python-format msgid "Recently used documents for %s" msgstr "Documentele utilizate recent pentru %s" msgid "Places" msgstr "Locuri" msgid "Bookmarked folders" msgstr "Dosare favorite" msgid "DuckDuckGo Search" msgstr "Căutare DuckDuckGo" msgid "Search the web securely with DuckDuckGo" msgstr "Caută pe wem în mod sigur cu DuckDuckGo" msgid "Favorites" msgstr "Favorite" msgid "Mark commonly used items and store objects for later use" msgstr "" "Marchează elementele utilizate uzual și stochează obiectele pentru a le " "utiliza mai târziu" msgid "Shelf of \"Favorite\" items" msgstr "Raftul elementelor „favorite”" msgid "Add to Favorites" msgstr "Adaugă la favorite" msgid "Add item to favorites shelf" msgstr "Adaugă elementul la raftul cu favorite" msgid "Remove from Favorites" msgstr "Elimină de la favorite" msgid "Remove item from favorites shelf" msgstr "Elimină elementul de pe raftul cu favorite" msgid "File Actions" msgstr "Acțiuni de fișier" msgid "More file actions" msgstr "Mai multe acțiuni de fișier" msgid "Move To..." msgstr "Mută la..." msgid "Move file to new location" msgstr "Mută fișierul la o locație nouă" msgid "Rename To..." msgstr "Redenumește în..." msgid "Copy To..." msgstr "Copiază la..." msgid "Copy file to a chosen location" msgstr "Copiază fișierul la o locație selectată" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "Glob" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "Acțiuni de ordin superior" msgid "Tools to work with commands as objects" msgstr "Unelte pentru a lucra cu comenzi ca obiecte" msgid "Select in Kupfer" msgstr "Selectează în Kupfer" #, python-format msgid "Result of %s (%s)" msgstr "Rezultatele lui %s (%s)" msgid "Run (Take Result)" msgstr "Rulează (obține rezultatul)" msgid "Take the command result as a proxy object" msgstr "Obține rezultatul comenzii ca un obiect proxy" msgid "Run (Discard Result)" msgstr "Rulează (renunță la rezultat)" msgid "Image Tools" msgstr "Unelte pentru imagine" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Unelte pentru tansformarea imaginilor" msgid "Scale..." msgstr "Scalează..." msgid "Scale image to fit inside given pixel measure(s)" msgstr "Scalează imaginea pentru a se potrivi la măsura(ile) de pixel dată(e)" msgid "Rotate Clockwise" msgstr "Rotește în sens orar" msgid "Rotate Counter-Clockwise" msgstr "Rotește în sens anti-orar" msgid "Autorotate" msgstr "Rotește automat" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "" "Rotește JPEG (într-un singur loc) potrivit datelor meta EXIF ale acesteia" msgid "Kupfer Plugins" msgstr "Module Kupfer" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Accesează lista de module Kupfer în Kupfer" msgid "Show Information" msgstr "Afișează informații" msgid "Show Source Code" msgstr "Afișează codul sursă" msgid "enabled" msgstr "activat" msgid "disabled" msgstr "dezactivat" msgid "Notes" msgstr "Note" msgid "Gnote or Tomboy notes" msgstr "Gnote sau notițe Tomboy" msgid "Work with application" msgstr "Lucrează cu aplicația" msgid "Open with notes application" msgstr "Deschide cu aplicația de notițe" msgid "Append to Note..." msgstr "Adaugă la notiță..." msgid "Add text to existing note" msgstr "Adaugă text la notița existentă" msgid "Create Note" msgstr "Creează notiță" msgid "Create a new note from this text" msgstr "Creează o notiță nouă din acest text" msgid "Get Note Search Results..." msgstr "Obține rezultatele căutării de note..." msgid "Show search results for this query" msgstr "Afișează rezultatele căutării pentru această interogare" #, python-format msgid "today, %s" msgstr "astăzi, %s" #, python-format msgid "yesterday, %s" msgstr "ieri, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Actualizat ultima dată %s" msgid "Quicksilver Icons" msgstr "Iconițe Quicksilver" msgid "Quick Image Viewer" msgstr "Vizualizator de imagini Quick" msgid "View Image" msgstr "Vizualizează imaginea" msgid "GNU Screen" msgstr "Ecran GNU" msgid "Active GNU Screen sessions" msgstr "Sesiunile active ale ecranului GNU" msgid "Attached" msgstr "Atașat" msgid "Detached" msgstr "Detașat" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "%(status)s sesiune (%(pid)s) creată %(time)s" msgid "Screen Sessions" msgstr "Sesiuni de ecran" msgid "Attach" msgstr "Atașează" msgid "Send Keys" msgstr "Trimite taste" msgid "Send synthetic keyboard events using xautomation" msgstr "Trimite evenimente de tastatură sintetice folosind xautomation" msgid "Paste to Foreground Window" msgstr "Lipește în fereastra din prim plan" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "Copiază în clipboard și trimite Ctrl+V ferestrei din prim plan" msgid "Send keys to foreground window" msgstr "Trimite taste ferestrei din prim plan" msgid "Type Text" msgstr "Tastează text" msgid "Type the text to foreground window" msgstr "Tastează text în fereastra din prim plan" msgid "GNOME Session Management" msgstr "Administrarea sesiunii GNOME" msgid "Special items and actions for GNOME environment" msgstr "Elemente și acțiuni speciale pentru mediul GNOME" msgid "Log Out..." msgstr "Închide sesiunea..." msgid "Log out or change user" msgstr "Închide sesiunea sau schimbă utilizatorul" msgid "Shut Down..." msgstr "Oprește..." msgid "Shut down, restart or suspend computer" msgstr "Oprește, repornește sau suspendă calculatorul" msgid "Lock Screen" msgstr "Blochează ecranul" msgid "Enable screensaver and lock" msgstr "Activează protectorul de ecran și blochează ecranul" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "Administrarea sesiunii XFCE" msgid "Special items and actions for XFCE environment" msgstr "Elemente și acțiuni speciale pentru mediul XFCE" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "Gazde SSH" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "Adaugă gazda SSH găsită în ~/.ssh/config." msgid "SSH host" msgstr "Gazdă SSH" msgid "Connect" msgstr "Conectează" msgid "Connect to SSH host" msgstr "Conectează la gazda SSH" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "Gazdele SSH cum sunt specificate în ~/.ssh/config" msgid "No D-Bus connection to desktop session" msgstr "Nu există conexiune D-Bus la sesiunea desktop" msgid "GNOME Keyring" msgstr "Inelul de chei GNOME" msgid "KWallet" msgstr "KWallet" msgid "Unencrypted File" msgstr "Fișier necriptat" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "Comanda în „%s” nu este disponibilă" msgid "Document Templates" msgstr "Șabloane de documente" msgid "Create new documents from your templates" msgstr "Creează documente noi de la șabloane" #, python-format msgid "%s template" msgstr "%s șablon" msgid "Empty File" msgstr "Fișier gol" msgid "New Folder" msgstr "Dosar nou" msgid "Create New Document..." msgstr "Creează document nou..." msgid "Create a new document from template" msgstr "Creează un document nou de la șablon" msgid "Create Document In..." msgstr "Creează document în..." msgid "Textfiles" msgstr "Fișiere text" msgid "Append To..." msgstr "Adaugă la..." msgid "Append..." msgstr "Adaugă..." msgid "Write To..." msgstr "Scrie la..." msgid "Get Text Contents" msgstr "Obține conținuturi text" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "Acțiunile administratorului de fișier Thunar" msgid "Select in File Manager" msgstr "Selectează în administratorul de fișiere" msgid "Show Properties" msgstr "Afișează proprietăți" msgid "Show information about file in file manager" msgstr "Afișează informații despre fișier în administratorul de fișiere" msgid "Send To..." msgstr "Trimite la..." msgid "Symlink In..." msgstr "Legătură simbolică în..." msgid "Create a symlink to file in a chosen location" msgstr "Creează o legătură simbolică la un fișier în locația aleasă" msgid "Empty Trash" msgstr "Golește gunoiul" msgid "Thunar Send To Objects" msgstr "Trimitere la obiecte Thunar" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Contacte și acțiuni Thunderbird/Icedove" msgid "Compose New Email" msgstr "Redactează email nou" msgid "Compose a new message in Thunderbird" msgstr "Redactează un mesaj nou în Thunderbird" #, fuzzy msgid "Attach in Email To..." msgstr "Trimite email la..." #, fuzzy msgid "Compose Email With" msgstr "Compune email" #, fuzzy msgid "Compose a new message using the text as body" msgstr "Redactează un mesaj nou în Thunderbird" msgid "Thunderbird Address Book" msgstr "Agenda Thunderbird" msgid "Contacts from Thunderbird Address Book" msgstr "Contactele din agenda Thunderbird" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Vârf" msgid "Show running tasks and allow sending signals to them" msgstr "" "Afișează sarcinile care rulează și permite trimiterea de semnale la acestea" msgid "Sort Order" msgstr "Ordinea de sortare" msgid "Commandline" msgstr "Linia de comandă" msgid "CPU usage (descending)" msgstr "Utilizare CPU (descrescător)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Utilizare memorie (descrescător)" msgid "Send Signal..." msgstr "Trimite semnal..." msgid "Signals" msgstr "Semnale" msgid "Running Tasks" msgstr "Sarcinile care rulează" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% timp: %(time)s" msgid "Running tasks for current user" msgstr "Sarcinile care rulează pentru utilizatorul curent" msgid "Trash" msgstr "Gunoi" msgid "Access trash contents" msgstr "Accesează conținutul gunoiului" msgid "Move to Trash" msgstr "Mută la gunoi" msgid "Move this file to trash" msgstr "Mută acest fișier la gunoi" msgid "Restore" msgstr "Restaurează" msgid "Move file back to original location" msgstr "Mută fișierul înapoi la locația originală" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "Coșul de gunoi este gol" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "Gunoiul conține un fișier" msgstr[1] "Gunoiul conține %(num)s fișiere" msgstr[2] "Gunoiul conține %(num)s de fișier" msgid "Triggers" msgstr "Declanșatoare" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Atribuie combinații de taste globale (declanșatoare) la obiectele create " "prin intermediul „Compune comandă”." msgid "Add Trigger..." msgstr "Adaugă declanșator..." msgid "Remove Trigger" msgstr "Elimină declanșator" msgid "URL Actions" msgstr "Acțiuni URL" msgid "Download and Open" msgstr "Descarcă și deschide" msgid "Download To..." msgstr "Descarcă la..." msgid "Download URL to a chosen location" msgstr "Descarcă URL la o locație selectată" msgid "Wikipedia" msgstr "Wikipedia" msgid "Search in Wikipedia" msgstr "Caută în Wikipedia" msgid "Wikipedia language" msgstr "Limbaj Wikipedia" #. TRANS: Default wikipedia language code msgid "en" msgstr "ro" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Caută acest element în %s.wikipedia.org" msgid "Window List" msgstr "Listă de ferestre" msgid "All windows on all workspaces" msgstr "Toate ferestrele de pe toate spațiile de lucru" msgid "Activate" msgstr "Activează" msgid "Shade" msgstr "Umbrește" msgid "Unshade" msgstr "Luminează" msgid "Minimize" msgstr "Minimizează" msgid "Unminimize" msgstr "Deminimează" msgid "Maximize" msgstr "Maximizează" msgid "Unmaximize" msgstr "Demaximizează" msgid "Maximize Vertically" msgstr "Maximizează vertical" msgid "Unmaximize Vertically" msgstr "Demaximizează vertical" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Fereastră pe %(wkspc)s" msgid "Frontmost Window" msgstr "Fereastră de prim plan" msgid "Next Window" msgstr "Fereastra următoare" msgid "Jump to this window's workspace and focus" msgstr "Sari la spațiul de lucru al acestei ferestre și focalizează" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "%d fereastră" msgstr[1] "%d ferestre" msgstr[2] "%d de ferestre" msgid "Active workspace" msgstr "Spațiu de lucru activ" msgid "Jump to this workspace" msgstr "Sari la acest spațiu de lucru" msgid "Workspaces" msgstr "Spații de lucru" msgid "Volumes and Disks" msgstr "Volume și discuri" msgid "Mounted volumes and disks" msgstr "Volume și discuri montate" #, python-format msgid "Volume mounted at %s" msgstr "Volumele montate la %s" msgid "Unmount" msgstr "Demontează" msgid "Unmount this volume" msgstr "Demontează acest volum" msgid "Eject" msgstr "Scoate" msgid "Unmount and eject this media" msgstr "Demontează și scoate aceast mediu" msgid "Show Text" msgstr "Afișează textul" msgid "Display text in a window" msgstr "Afișează textul într-o fereastră" msgid "Large Type" msgstr "Tip mare" msgid "Show Notification" msgstr "Afișează notificări" msgid "Tracker" msgstr "Tracker" msgid "Tracker desktop search integration" msgstr "Integrarea căutării de desktop a Trackerului" msgid "Search in Tracker" msgstr "Caută în Tracker" msgid "Open Tracker Search Tool and search for this term" msgstr "Deschide unealta de căutare Tracker și caută acest element" msgid "Get Tracker Results..." msgstr "Obține rezultatele Trackerului..." msgid "Show Tracker results for query" msgstr "Afișează rezultatele Trackerului pentru interogare" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "Rezultate pentru „%s”" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "Localizează fișiere" msgid "Search filesystem using locate" msgstr "Caută sistemul de fișiere utilizând localizarea" msgid "Ignore case distinctions when searching files" msgstr "Ignoră majusculele atunci când se caută fișiere" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Marcaje Firefox" msgid "Index of Firefox bookmarks" msgstr "Indexul marcajelor Firefox" #, fuzzy msgid "Firefox Keywords" msgstr "Marcaje Firefox" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "Caută pe web cu motoarele de căutare OpenSearch" msgid "Search With..." msgstr "Caută cu..." msgid "Search For..." msgstr "Caută pentru..." #, fuzzy msgid "Search Terms" msgstr "Motoare de căutare" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Folosiți „%s”" #, fuzzy msgid "Resume playback" msgstr "Reia redarea în Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Următorul" #, fuzzy msgid "Skip to next track" msgstr "Sari la pista următoare în Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Anteriorul" #, fuzzy msgid "Skip to previous track" msgstr "Sari la pista anterioară în Audacious" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "Acces la contactele Pidgin" msgid "Show offline contacts" msgstr "Afișează contactele deconectate" msgid "Open Chat" msgstr "Deschide discuție" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d caracter)" msgstr[1] "%s (%d caractere)" msgstr[2] "%s (%d de caractere)" msgid "Send Message..." msgstr "Trimite mesaj..." msgid "Available" msgstr "Disponibil" msgid "Away" msgstr "Plecat" msgid "Pidgin Contacts" msgstr "Contacte Pidgin" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Scurtează legăturile" msgid "Create short aliases of long URLs" msgstr "Creează aliasuri scurte ale URL-urilor lungi" msgid "Error" msgstr "Eroare" msgid "Shorten With..." msgstr "Scurtează cu..." msgid "Services" msgstr "Servicii" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "Redă și plasează la rând pistele și navigheză biblioteca de muzică" msgid "Include artists in top level" msgstr "Include artiștii în primul nivel" msgid "Include albums in top level" msgstr "Include albumele în primul nivel" msgid "Play tracks in Rhythmbox" msgstr "Redă piste în Rhythmbox" msgid "Add tracks to the play queue" msgstr "Adaugă piste la coada de redare" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "de %(artist)s din %(album)s" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "de %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Piste de %s" msgid "Albums" msgstr "Albume" msgid "Music albums in Rhythmbox Library" msgstr "Albume de muzică în biblioteca Rhythmbox" msgid "Artists" msgstr "Artiști" msgid "Music artists in Rhythmbox Library" msgstr "Artiști de muzică în biblioteca Rhythmbox" msgid "Songs" msgstr "Cântece" msgid "Songs in Rhythmbox library" msgstr "Cântece în biblioteca Rhythmbox" msgid "Getting Things GNOME" msgstr "Getting Things GNOME" msgid "Browse and create new tasks in GTG" msgstr "Navighează și creează sarcini noi în GTG" #, python-format msgid "due: %s" msgstr "scadent: %s" #, python-format msgid "start: %s" msgstr "pornire: %s" #, python-format msgid "tags: %s" msgstr "etichete: %s" msgid "Open task in Getting Things GNOME!" msgstr "Deschide sarcina în Getting Things GNOME!" msgid "Delete" msgstr "Șterge" msgid "Permanently remove this task" msgstr "Elimină permanent această sarcină" msgid "Mark Done" msgstr "Marchează ca fiind terminată" msgid "Mark this task as done" msgstr "Marchează această sarcină ca fiind terminată" msgid "Dismiss" msgstr "Eliberează" msgid "Mark this task as not to be done anymore" msgstr "Marchează această sarcină pentru a nu mai fi terminată" msgid "Create Task" msgstr "Creează sarcină" msgid "Create new task in Getting Things GNOME" msgstr "Creează o sarcină nouă în Getting Things GNOME" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "Caută în Devhelp" msgid "Empathy" msgstr "Empathy" msgid "Access to Empathy Contacts" msgstr "Acces la contacte Empathy" msgid "Busy" msgstr "Ocupat" msgid "Not Available" msgstr "Indisponibil" msgid "Invisible" msgstr "Invizibil" msgid "Offline" msgstr "Deconectat" msgid "Change Global Status To..." msgstr "Modifică starea globală la..." msgid "Empathy Contacts" msgstr "Contacte Empathy" msgid "Empathy Account Status" msgstr "Stare cont Empathy" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Activare alternativă" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Truc virgulă" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Compune comanda" msgid "Mark Default Action" msgstr "Marchează acțiunea implicită" msgid "Forget Object" msgstr "Uită obiect" msgid "Reset All" msgstr "Restabilește tot" msgid "Select Quit" msgstr "Selectează ieșire" msgid "Select Selected File" msgstr "Selectează fișierul selectat" msgid "Select Selected Text" msgstr "Selectează textul selectat" msgid "Show Help" msgstr "Afișează ajutor" msgid "Show Preferences" msgstr "Afișează preferințe" msgid "Switch to First Pane" msgstr "Comută la primul panou" msgid "Toggle Text Mode" msgstr "Comută la modul text" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Nu sunt potriviri în %(src)s pentru „%(query)s”" msgid "No matches" msgstr "Nu sunt potriviri" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Nu sunt potriviri" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Fă „%(action)s” implicit pentru „%(object)s”" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "Uită de „%s”" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Afișează interfața principală" msgid "Show with Selection" msgstr "Afișează cu selecție" #. TRANS: Plugin info fields msgid "Description" msgstr "Descriere" msgid "Author" msgstr "Autor" msgid "Version" msgstr "Versiune" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Modulul Python „%s” este necesar" msgid "Plugin could not be read due to an error:" msgstr "Modulul nu a putut fi citit din cauza unei erori:" msgid "Content of" msgstr "Conținut al" #. TRANS: Plugin contents header msgid "Sources" msgstr "Surse" #. TRANS: Plugin contents header msgid "Actions" msgstr "Acțiuni" #, python-format msgid "Using encrypted password storage: %s" msgstr "Se folosește depozitare criptată de parole: %s" #, python-format msgid "Using password storage: %s" msgstr "Se folosește depozitarea de parole: %s" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Configurație" msgid "Set username and password" msgstr "Stabilește numele de utilizator și parola" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Alegeți un director" msgid "Reset all shortcuts to default values?" msgstr "Se restabilesc toate scurtăturile la valorile implicite?" msgid "Shortcut" msgstr "Scurtătură" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "Florentina Mușat " msgid "A free software (GPLv3+) launcher" msgstr "Un lansator de programe libere (GPLv3+)" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Această aplicație este program liber: puteți să îl redistribuiți și/sau să " "îl modificați\n" "sub termenii Licenței Publice Generale GNU așa cum este publicată de\n" "Fundația pentru programe libere, ori versiunea 3 a Licenței, sau\n" "(la latitudinea dumneavoastră) orice versiune mai recentă.\n" "\n" "Acest program este distribuit în speranța că va fi folositor,\n" "dar FĂRĂ NICIUN FEL DE GARANȚIE; nici cu garanția presupusă a " "MERCANTILITĂȚII sau POTRIVIRE PENTRU UN ANUMIT SCOP. Consultați Licența " "Publică Generală GNU pentru mai multe detalii.\n" "\n" "Ar fi trebuit să fi primit o copie a Licenței Publice Generale GNU pe lângă " "acest program. Dacă nu, consultați .\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Nu s-a putut găsi Kupfer care rulează" #~ msgid "Compose Email" #~ msgstr "Compune email" #~ msgid "Send in Email To..." #~ msgstr "Trimite email la..." #~ msgid "Type to search %s" #~ msgstr "Tastați pentru a căuta %s" #~ msgid "No action" #~ msgstr "Nicio acțiune" #~ msgid "GNOME Terminal Profiles" #~ msgstr "Profiluri de terminal GNOME" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Lansează profilurile de terminal GNOME" #~ msgid "Multihead Support" #~ msgstr "Suport pentru afișaje multiple" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Calculează expresiile care încep cu „=”" #~ msgid "Epiphany Bookmarks" #~ msgstr "Marcaje Epiphany" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Indexul marcajelor Epiphany" #~ msgid "Include visited sites" #~ msgstr "Include paginile web vizitate" #~| msgid "Firefox Bookmarks" #~ msgid "Firefox tag" #~ msgstr "Etichetă Firefox" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Reia redarea în Rhythmbox" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Pune pauză la redarea în Rhythmbox" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Mergi la următoarea piesă în Rhythmbox" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Mergi la pista anterioară în Rhythmbox" #~ msgid "Search the Web" #~ msgstr "Caută pe web" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Documente utilizate recent în Abiword" #~ msgid "Abiword Recent Items" #~ msgstr "Elemente recente Abiword" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "Interfață cu administratorul de pachete APT" #~ msgid "Installation method" #~ msgstr "Metodă de instalare" #~ msgid "Show Package Information" #~ msgstr "Afișează informațiile pachetului" #~ msgid "Install" #~ msgstr "Instalează" #~ msgid "Install package using the configured method" #~ msgstr "Instalează pachetul utilizând metoda configurată" #~ msgid "Packages matching \"%s\"" #~ msgstr "Pachetele care se potrivesc cu „%s”" #~ msgid "Search Package Name..." #~ msgstr "Caută numele de pachet..." #~ msgid "Ascii & Unicode Icon Set" #~ msgstr "Set de iconițe Ascii și Unicode" #~ msgid "" #~ "Provides the Ascii and Unicode icon sets that use letters and symbols to " #~ "produce icons for the objects found in Kupfer." #~ msgstr "" #~ "Oferă seturi de iconițe Ascii și Unicode ce folosesc litere și simboluri " #~ "pentru a produce iconițe pentru obiectele găsite în Kupfer." #~ msgid "Ascii" #~ msgstr "Ascii" #~ msgid "Unicode" #~ msgstr "Unicode" #~ msgid "Chromium Bookmarks" #~ msgstr "Marcaje Chromium" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Indexul marcajelor Chromium" #~ msgid "Claws Mail" #~ msgstr "Claws Mail" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Contactele și acțiunile Claws Mail" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Redactează un mesaj nou în Claws Mail" #~ msgid "Receive All Email" #~ msgstr "Primește toate emailurile" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "Primește toate mesajele de pe toate conturile în ClawsMail" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Redactează un mesaj nou în Claws Mail și atașează un fișier" #~ msgid "Claws Mail Address Book" #~ msgstr "Agenda Claws Mail" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Contactele din agenda Claws Mail" #~ msgid "Configure a custom terminal emulator" #~ msgstr "Configurează un emulator de terminal personalizat" #~ msgid "Custom Theme" #~ msgstr "Temă personalizată" #~ msgid "Use a custom color theme" #~ msgstr "Utilizează o temă de culori personalizată" #~ msgid "Theme:" #~ msgstr "Temă:" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Contacte Evolution" #~ msgid "Compose a new message in Evolution" #~ msgstr "Compune un mesaj nou în Evolution" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Compune un mesaj nou în Evolution și atașează un fișier" #~ msgid "Evolution Address Book" #~ msgstr "Agenda Evolution" #~ msgid "Filezilla" #~ msgstr "Filezilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Afișează paginile web și gestionează adresele ftp de Filezilla" #~ msgid "Open Site with Filezilla" #~ msgstr "Deschide pagina web cu Filezilla" #~ msgid "Filezilla Sites" #~ msgstr "Pagini web Filezilla" #~ msgid "Sites from Filezilla" #~ msgstr "Pagini web de la Filezilla" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Acces la contacte Gajim" #~ msgid "Free for Chat" #~ msgstr "Disponibil pentru discuție" #~ msgid "Gajim Contacts" #~ msgstr "Contacte Gajim" #~ msgid "Gajim Account Status" #~ msgstr "Stare cont Gajim" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Încarcă agenda și redactează un mail nou în Gmail" #~ msgid "Load contacts' pictures" #~ msgstr "Încarcă imaginile contactelor" #~| msgid "show version information" #~ msgid "Load additional information" #~ msgstr "Încarcă informații adiționale" #~ msgid "Work email" #~ msgstr "Email de serviciu" #~| msgid "Compose Email" #~ msgid "Home email" #~ msgstr "Email personal" #~ msgid "Other email" #~ msgstr "Alt email" #~| msgid "Workspaces" #~ msgid "Work address" #~ msgstr "Adresa de serviciu" #~ msgid "Home address" #~ msgstr "Adresa de acasă" #~ msgid "Other address" #~ msgstr "Altă adresă" #~ msgid "Car phone" #~ msgstr "Telefon de mașină" #~ msgid "Fax" #~ msgstr "Fax" #~| msgid "one photo" #~| msgid_plural "%(num)s photos" #~ msgid "Home phone" #~ msgstr "Telefon de acasă" #~ msgid "Home fax" #~ msgstr "Fax de acasă" #~ msgid "Internal phone" #~ msgstr "Telefon intern" #~ msgid "Mobile" #~ msgstr "Mobil" #~ msgid "Other" #~ msgstr "Altul" #~ msgid "VOIP" #~ msgstr "VOIP" #~| msgid "Workspaces" #~ msgid "Work phone" #~ msgstr "Telefon de servici" #~ msgid "Work fax" #~ msgstr "Fax de servici" #~| msgid "Compose Email in GMail" #~ msgid "Compose Email in Gmail" #~ msgstr "Compune email în Gmail" #~| msgid "Open web browser and compose new email in GMail" #~ msgid "Open web browser and compose new email in Gmail" #~ msgstr "Deschide navigatorul web și redactează un email nou în Gmail" #~ msgid "Edit Contact in Gmail" #~ msgstr "Editează contact în Gmail" #~| msgid "Open web browser and compose new email in GMail" #~ msgid "Open web browser and edit contact in Gmail" #~ msgstr "Deschide navigatorul web și editează contactul în Gmail" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Contacte de la serviciile Google (Gmail)" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Afișează albume și încarcă fișiere la Picasa" #~ msgid "Users to show: (,-separated)" #~ msgstr "Utilizatori de afișat: (separați prin virgulă)" #~ msgid "Load user and album icons" #~ msgstr "Încarcă pictogramele utilizatorului și albumului" #~ msgid "Uploading Pictures" #~ msgstr "Se încarcă imagini" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Se încarcă imagini la albumul web Picasa" #~ msgid "Creating album:" #~ msgstr "Se creează albumul:" #~ msgid "Album created by Kupfer" #~ msgstr "Album creat de Kupfer" #~ msgid "File:" #~ msgstr "Fișier:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "Un album" #~ msgstr[1] "%(num)d albume" #~ msgstr[2] "%(num)d de albume" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "o imagine" #~ msgstr[1] "%(num)s imagini" #~ msgstr[2] "%(num)s de imagini" #~ msgid "Upload to Picasa Album..." #~ msgstr "Încarcă la albumul Picasa..." #~ msgid "Upload files to Picasa album" #~ msgstr "Încarcă fișiere la albumul Picasa" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Încarcă la Picasa ca un album nou" #~ msgid "Create album from selected local directory" #~ msgstr "Creează album din dosarul local selectat" #~ msgid "Picasa Albums" #~ msgstr "Albume Picasa" #~ msgid "User albums in Picasa" #~ msgstr "Albumele utilizatorului în Picasa" #~ msgid "Google Search" #~ msgstr "Căutare Google" #~ msgid "Search Google with results shown directly" #~ msgstr "Caută pe Google cu afișarea rezultatelor în mod direct" #~ msgid "Show More Results For \"%s\"" #~ msgstr "Afișează mai multe rezultate pentru „%s”" #~ msgid "%s total found" #~ msgstr "%s găsite în total" #~ msgid "Gwibber" #~ msgstr "Gwibber" #~ msgid "" #~ "Microblogging with Gwibber. Allows sending and receiving messages from " #~ "social networks like Twitter, Identi.ca etc. Requires the package " #~ "'gwibber-service'." #~ msgstr "" #~ "Microblogging cu Gwibber. Permite trimiterea și primirea mesajelor de la " #~ "rețelele sociale cum ar fi Twitter, Identic.ca etc. Necesită pachetul " #~ "„gwibber-service”." #~ msgid "Maximum number of messages to show" #~ msgstr "Numărul maxim de mesaje de afișat" #~| msgid "%(user)s %(when)s" #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s pe %(service)s" #~| msgid "%(user)s %(when)s" #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s pe %(where)s" #~| msgid "Send Message..." #~ msgid "Send Message" #~ msgstr "Trimite mesaj" #~ msgid "Send message to all Gwibber accounts" #~ msgstr "Trimite mesaj către toate conturile Gwibber" #~| msgid "Send Message..." #~ msgid "Send Message To..." #~ msgstr "Trimite mesaj către..." #~ msgid "Send message to a Gwibber account" #~ msgstr "Trimite mesaj către un cont Gwibber" #~ msgid "Send message to selected Gwibber account" #~ msgstr "Trimite mesaj către contul Gwibber selectat" #~ msgid "Reply..." #~ msgstr "Răspunde..." #~| msgid "Send Message..." #~ msgid "Delete Message" #~ msgstr "Șterge mesajul" #~| msgid "Send Direct Message..." #~ msgid "Send Private Message..." #~ msgstr "Trimite mesaj privat..." #~| msgid "Send Direct Message To..." #~ msgid "Send direct message to user" #~ msgstr "Trimite mesaj direct la utilizator" #~ msgid "Retweet" #~ msgstr "Retweet" #~| msgid "Rename To..." #~ msgid "Retweet To..." #~ msgstr "Retweet la..." #~| msgid "Receive new messages from all accounts in ClawsMail" #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Retweet la mesajul către toate conturile Gwibber" #~ msgid "Retweet message to a Gwibber account" #~ msgstr "Retweet la mesajul către un cont Gwibber" #~| msgid "Open parent folder" #~ msgid "Open in Browser" #~ msgstr "Deschide în navigator" #~| msgid "Open URL with default viewer" #~ msgid "Open message in default web browser" #~ msgstr "Deschide mesajul în navigatorul web implicit" #~| msgid "Gajim Account Status" #~ msgid "Gwibber Accounts" #~ msgstr "Conturi Gwibber" #~ msgid "Accounts configured in Gwibber" #~ msgstr "Conturi configurate în Gwibber" #~ msgid "Gwibber Messages" #~ msgstr "Mesaj Gwibber" #~ msgid "Recent messages received by Gwibber" #~ msgstr "Mesaje recente primite de Gwibber" #~ msgid "Gwibber Messages for %s" #~ msgstr "Mesaje Gwibber pentru %s" #~ msgid "Gwibber Streams" #~ msgstr "Fluxuri Gwibber" #~ msgid "Streams configured in Gwibber" #~ msgstr "Fluxuri configurate în Gwibber" #~ msgid "Gwibber Messages in %s" #~ msgstr "Mesaje Gwibber în %s" #~ msgid "Gwibber (Simple)" #~ msgstr "Gwibber (simplu)" #~ msgid "Send updates via the microblogging client Gwibber" #~ msgstr "Trimite actualizări prin clientul de microblogging Gwibber" #~ msgid "Send Update" #~ msgstr "Trimite actualizarea" #~ msgid "Unable to activate Gwibber service" #~ msgstr "Nu s-a putut activa serviciul Gwibber" #~ msgid "OpenOffice / LibreOffice" #~ msgstr "OpenOffice / LibreOffice" #~| msgid "Recently used documents in OpenOffice" #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Documente utilizate recent în OpenOffice/LibreOffice" #~| msgid "OpenOffice Recent Items" #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "Elemente recente OpenOffice/LibreOffice" #~ msgid "Opera Mail" #~ msgstr "Opera Mail" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Contacte și acțiuni Opera Mail" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Redactează un mesaj nou în Opera Mail" #~ msgid "Opera Mail Contacts" #~ msgstr "Contacte Opera Mail" #~ msgid "Contacts from Opera Mail" #~ msgstr "Contacte de la Opera Mail" #~ msgid "Opera Bookmarks" #~ msgstr "Marcaje Opera" #~ msgid "Index of Opera bookmarks" #~ msgstr "Indexul marcajelor Opera" #~ msgid "PuTTY Sessions" #~ msgstr "Sesiuni PuTTY" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Acces rapid la sesiunile PuTTY" #~ msgid "Start Session" #~ msgstr "Pornește sesiune" #~ msgid "reStructuredText" #~ msgstr "TextReStructurat" #~ msgid "Render reStructuredText and show the result" #~ msgstr "Randează TextReStructurat și afișează rezultatul" #~ msgid "View as HTML Document" #~ msgstr "Vizualizează ca document HTML" #~ msgid "System Services" #~ msgstr "Servicii de sistem" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "" #~ "Pornește, oprește sau repornește serviciile de sistem prin scripturile " #~ "init" #~ msgid "Sudo-like Command" #~ msgstr "Comandă asemănătoare cu sudo" #~ msgid "Start Service" #~ msgstr "Pornește serviciu" #~ msgid "Stop Service" #~ msgstr "Oprește serviciu" #~ msgid "%s Service" #~ msgstr "Serviciu %s" #~| msgid "Show Source Code" #~ msgid "Show QRCode" #~ msgstr "Afișează codul QR" #~| msgid "Display text in a window" #~ msgid "Display text as QRCode in a window" #~ msgstr "Afișează textul ca cod QR într-o fereastră" #~ msgid "Access to Skype contacts" #~ msgstr "Acces la contactele Skype" #~ msgid "Skype Me" #~ msgstr "Skype Me" #~ msgid "Logged Out" #~ msgstr "Deautentificat" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Sună" #~ msgid "Place a call to contact" #~ msgstr "Plasează un apel la contact" #~ msgid "Skype Contacts" #~ msgstr "Contacte Skype" #~ msgid "Skype Statuses" #~ msgstr "Stări Skype" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Volume pentru istoricul TrueCrypt" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "Volum TrueCrypt: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Montează volumul" #~ msgid "Mount in Truecrypt" #~ msgstr "Montează în Truecrypt" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Încearcă să montezi fișierul ca volum Truecrypt" #~ msgid "Dismount All Volumes" #~ msgstr "Demontează toate volumele" #~ msgid "TrueCrypt Volumes" #~ msgstr "Volume TrueCrypt" #~ msgid "Terminal Server Client" #~ msgstr "Clientul de server al terminalului" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Sesiune salvată în clientul de server al terminalului" #~ msgid "TSClient sessions" #~ msgstr "Sesiuni TSClient" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Sesiunile salvate în clientul de server al terminalului" #~ msgid "Vim" #~ msgstr "Vim" #~ msgid "Recently used documents in Vim" #~ msgstr "Documente utilizate recent în Vim" #~ msgid "Vim Recent Documents" #~ msgstr "Documente recente Vim" #~ msgid "Close (Save All)" #~ msgstr "Închide (salvează tot)" #~| msgid "Send To..." #~ msgid "Send..." #~ msgstr "Trimite..." #~| msgid "Saved Kupfer Command" #~ msgid "Send ex command" #~ msgstr "Trimite comanda ex" #~ msgid "Insert in Vim..." #~ msgstr "Introdu în Vim..." #~| msgid "Active GNU Screen sessions" #~ msgid "Active Vim Sessions" #~ msgstr "Sesiuni Vim active" #~| msgid "PuTTY Sessions" #~ msgid "Vim Session %s" #~ msgstr "Sesiunea Vim %s" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Marcaje și acțiuni Vinagre" #~ msgid "Start Vinagre Session" #~ msgstr "Pornește sesiune Vinagre" #~ msgid "Vinagre Bookmarks" #~ msgstr "Marcaje Vinagre" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "Controlează mașinile virtuale VirtualBox. Suportă atât Sun VirtualBox cât " #~ "și Open Source Edition." #~ msgid "Force use CLI interface" #~ msgstr "Utilizează forțat interfața CLI" #~ msgid "Power On" #~ msgstr "Pornește" #~ msgid "Power On Headless" #~ msgstr "Pornește Headless" #~ msgid "Send Power Off Signal" #~ msgstr "Trimite semnal de oprire" #~ msgid "Reboot" #~ msgstr "Repornește" #~ msgid "Resume" #~ msgstr "Revino" #~ msgid "Save State" #~ msgstr "Salvează stare" #~ msgid "Power Off" #~ msgstr "Oprește" #~ msgid "VirtualBox Machines" #~ msgstr "Mașini VirtualBox" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "" #~ "Acces la pagini stocate în Zim - Un wiki de desktop și un instrument de " #~ "subliniat" #~ msgid "Page names start with :colon" #~ msgstr "Numele paginii începe cu :două puncte" #~ msgid "Default page name for quick notes" #~ msgstr "Nume de pagină implicit pentru notițe rapide" #~ msgid "Note %x %X" #~ msgstr "Notiță %x %X" #~ msgid "" #~ "Strftime tags can be used: %H - hour, %M - minutes, etc\n" #~ "Please check python documentation for details.\n" #~ "NOTE: comma will be replaced by _" #~ msgstr "" #~ "Etichete „strftime” pot fi folosite: %H - oră, %M - minute, etc\n" #~ "Consultați documentația python pentru detalii.\n" #~ "NOTĂ: virgulele vor fi înlocuite de _" #~ msgid "Default namespace for quick notes" #~ msgstr "Spațiul de nume implicit pentru notițe rapide" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Pagină Zim din agenda „%s”" #~ msgid "Create Zim Page" #~ msgstr "Creează pagină Zim" #~ msgid "Create page in default notebook" #~ msgstr "Creează pagină în agenda implicită" #~ msgid "Create Zim Page In..." #~ msgstr "Creează pagină Zim în..." #~ msgid "Insert QuickNote into Zim" #~ msgstr "Introdu notiță rapidă în Zim" #~ msgid "Quick note selected text into Zim notebook" #~ msgstr "Text selectat de notiță rapidă în agenda Zim" #~ msgid "Create Subpage..." #~ msgstr "Creează subpagină..." #~ msgid "Zim Notebooks" #~ msgstr "Agende Zim" #~ msgid "Zim Pages" #~ msgstr "Pagini Zim" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Pagini stocate în agendele Zim" #~ msgid "Directories" #~ msgstr "Dosare" #~ msgid "Interface" #~ msgstr "Interfață" #~ msgid "Hide Kupfer when focus is lost" #~ msgstr "Ascunde Kupfer când s-a pierdut focalizarea" #~ msgid "" #~ "Tick the box next to a source to make sure its objects are exported to " #~ "the top level of the catalog. An unticked source's contents are only " #~ "available by locating its subcatalog and entering it.\n" #~ "\n" #~ "Note: Kupfer is an integrator, not an indexer itself. Kupfer is not " #~ "designed to carry a catalog larger than a couple of thousand objects, and " #~ "may become slow if overly large subcatalogs are included in the top level." #~ msgstr "" #~ "Bifați caseta de lângă o sursă pentru a vă asigura că obiectele acesteia " #~ "sunt exportate la primul nivel al catalogului. Conținuturile unei surse " #~ "nebifate sunt disponibile doar prin localizarea subcatalogului acesteia " #~ "și deschiderea lui.\n" #~ "\n" #~ "Notă: Kupfer este un integrator, nu este un indexator. Kupfer nu este " #~ "proiectat pentru a transporta un catalog mai mare decât câteva mii de " #~ "obiecte, și poate să devină lent dacă sunt incluse subcataloage excesiv " #~ "de mari la primul nivel." #~ msgid "Text Matches" #~ msgstr "Potriviri de text" #~ msgid "Selected Text \"%s\"" #~ msgstr "Textul selectat „%s”" #~ msgid "Recent clipboards" #~ msgstr "Clipboarduri recente" #~ msgid "Include recent selections" #~ msgstr "Include selecțiile recente" #~ msgid "" #~ "Provides current nautilus selection, using Kupfer's Nautilus Extension" #~ msgstr "" #~ "Furnizează selecția nautilus curentă, utilizând Extensia Nautilus a lui " #~ "Kupfer" #~ msgid "Selected Files" #~ msgstr "Fișiere selectare" #~ msgid "Translate text with Google Translate" #~ msgstr "Traduce text cu Traduce Google" #~ msgid "noun" #~ msgstr "substantiv" #~ msgid "verb" #~ msgstr "verb" #~ msgid "adjective" #~ msgstr "adjectiv" #~ msgid "Google Translate connection timed out" #~ msgstr "Timp alocat expirat pentru conexiunea la Traducere Google" #~ msgid "Error connecting to Google Translate" #~ msgstr "Eroare la conectarea la Traducere Google" #~ msgid "Translate To..." #~ msgstr "Traduce la..." #~ msgid "Translate into %s" #~ msgstr "Traduce în %s" #~ msgid "Languages" #~ msgstr "Limbi" #~ msgid "Show translated page in browser" #~ msgstr "Afișează pagina tradusă în navigator" #~ msgid "Show Translation To..." #~ msgstr "Afișează traducerea la..." #~ msgid "Show translation in browser" #~ msgstr "Afișează traducerea în navigator" #~ msgid "Twitter" #~ msgstr "Twitter" #~ msgid "Microblogging with Twitter: send updates and show friends' tweets" #~ msgstr "" #~ "Microblogging cu Twitter: trimite actualizări și afișează tweet-urile " #~ "prietenilor" #~ msgid "Load friends' pictures" #~ msgstr "Încarcă imaginile prietenilor" #~ msgid "Load friends' public tweets" #~ msgstr "Încarcă tweet-urile publice ale prietenilor" #~ msgid "Load timeline" #~ msgstr "Încarcă cronologia" #~ msgid "Post Update to Twitter" #~ msgstr "Trimite actualizare pe Twitter" #~ msgid "Twitter Timeline" #~ msgstr "Cronologie Twitter" #~ msgid "Twitter Friends" #~ msgstr "Prieteni Twitter" #~ msgid "Timeline for %s" #~ msgstr "Cronologie pentru %s" #~ msgid "OpenOffice" #~ msgstr "OpenOffice" #~ msgid "Preferred terminal" #~ msgstr "Terminal preferat" #~ msgid "" #~ "The preferred terminal emulator. It's used to launch the SSH sessions." #~ msgstr "" #~ "Emulatorul de terminal preferat. Este utilizat pentru a lansa sesiunile " #~ "SSH." #~ msgid "" #~ "The flag which makes the terminal execute everything following it inside " #~ "the terminal (e.g. '-x' for gnome-terminal and terminal, '-e' for konsole " #~ "and urxvt)." #~ msgstr "" #~ "Indicatorul care face terminalul să execute tot urmărind din interiorul " #~ "terminalului (ex: „-x” pentru gnome-terminal și terminal, „-e” pentru " #~ "konsole și urxvt)." #~ msgid "Tracker tags" #~ msgstr "Etichete tracker" #~ msgid "Tracker Tags" #~ msgstr "Etichete Tracker" #~ msgid "Browse Tracker's tags" #~ msgstr "Navighează prin etichetele Trackerului" #~ msgid "Tag %s" #~ msgstr "Eticheta %s" #~ msgid "Objects tagged %s with Tracker" #~ msgstr "Obiectele etichetste %s cu Trackerul" #~ msgid "Add Tag..." #~ msgstr "Adaugă etichetă..." #~ msgid "Add tracker tag to file" #~ msgstr "Adaugă etichetă de tracker la fișier" #~ msgid "Remove Tag..." #~ msgstr "Elimină eticheta..." #~ msgid "Remove tracker tag from file" #~ msgstr "Elimină eticheta de tracker de la fișier" #~ msgid "Tracker 0.8" #~ msgstr "Tracker 0.8" kupfer-328/po/ru.po000066400000000000000000002170731500175051100142750ustar00rootroot00000000000000# Russian translation for kupfer. # Copyright (C) 2012 kupfer's COPYRIGHT HOLDER # This file is distributed under the same license as the kupfer package. # Nikolay Barbariyskiy , 2012. # msgid "" msgstr "" "Project-Id-Version: kupfer master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2012-05-17 03:49+0100\n" "Last-Translator: Barbariyskiy Nikolay \n" "Language-Team: Russian \n" "Language: 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" msgid "User credentials" msgstr "Учетные данные пользователя" msgid "_User:" msgstr "_Пользователь" msgid "_Password:" msgstr "_Пароль" msgid "_Change" msgstr "_Изменить" msgid "Set Keyboard Shortcut" msgstr "Установить сочетание клавиш" msgid "Please press desired key combination" msgstr "Пожалуйста, нажмите требуемое сочетание клавиш" msgid "Keybinding could not be bound" msgstr "Данное сочетание клавишь не может быть использовано" msgid "Kupfer Preferences" msgstr "Настройки Kupfer" msgid "Start automatically on login" msgstr "Запустить автоматически при входе в систему" msgid "Start" msgstr "Запустить" msgid "Show icon in notification area" msgstr "Показать значок в области уведомления" msgid "Icon set:" msgstr "Тип значка:" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" msgid "Terminal emulator:" msgstr "Эмулятор терминала" msgid "Desktop Environment" msgstr "Рабочая среда" msgid "General" msgstr "Общие" msgid "Global Keyboard Shortcuts" msgstr "Глобальные сочетания клавиш" msgid "Reset" msgstr "Перезапустить" msgid "Browser Keyboard Shortcuts" msgstr "Сочетания клавиш браузера" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "Использовать одноклавишные команды (Пробел, /, точка, запятая)" msgid "Keyboard" msgstr "Клавиатура" msgid "Plugins" msgstr "Плагины" msgid "Inclusion in Top Level Searches" msgstr "Включение в высокоуровневые поиски" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "Отмеченные источники включают свои объекты в высокоуровневый поиск.\n" "Содержание неотмеченных источников может быть доступно только в подкаталоге." msgid "Indexed Folders" msgstr "Индексированные папки" msgid "Folders whose files are always available in the catalog." msgstr "Папки, файлы которых всегда доступны в каталоге." msgid "Catalog" msgstr "Каталог" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Средство запуска приложений" msgid "Convenient command and access tool for applications and documents" msgstr "Удобный инструмент для быстрого доступа к программам и документам" msgid "Execute in Kupfer" msgstr "Выполнить в Kupfer" msgid "Saved Kupfer Command" msgstr "Сохраннёные команды Kupfer" #, python-format msgid "Could not to carry out '%s'" msgstr "Не удалось выполнить '%s'" #, fuzzy, python-format msgid "\"%s\" produced a result" msgstr "\"%s\" привела результат" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Нет разрешения на запуск \"%s\" (не исполняемый файл)" #, python-format msgid "Command in \"%s\" is not available" msgstr "Команда в \"%s\" не доступна" #, python-format msgid "Keyboard relay is active for display %s" msgstr "Клавиатура активна для дисплея %s" msgid "do not present main interface on launch" msgstr "не показывать основной интерфейс при запуске" msgid "list available plugins" msgstr "список доступных плагинов" msgid "enable debug info" msgstr "включить информацию отладки" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "запустить плагин helper" msgid "show usage help" msgstr "показать справку использования" msgid "show version information" msgstr "показать информацию о версии" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Использование: kupfer [Параметры | Файл ... ]" msgid "Available plugins:" msgstr "Доступные плагины:" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "Введите поисковый запрос" #, python-format msgid "%s is empty" msgstr "%s пуст" msgid "Text" msgstr "Текст" msgid "Run after Delay..." msgstr "Запустить после задержки" msgid "Perform command after a specified time interval" msgstr "Выполнить команду через определённый интервал времени" msgid "Multiple Objects" msgstr "Множественные объекты" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s объект" msgstr[1] "%s объекта" msgstr[2] "%s объектов" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "неизвестный" msgid "Aim" msgstr "Aim" msgid "Google Talk" msgstr "Google Talk" msgid "ICQ" msgstr "ICQ" msgid "MSN" msgstr "MSN" msgid "QQ" msgstr "QQ" msgid "Yahoo" msgstr "Yahoo" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "%s не поддерживает данную операцию" msgid "Can not be used with multiple objects" msgstr "Не может быть использовано с несколькими объектами" msgid "Open" msgstr "Открыть" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Не было найдено приложение по умолчанию для %(file)s (%(type)s)" #, python-format msgid "Please use \"%s\"" msgstr "Пожалуйста, используйте \"%s\"" msgid "Set Default Application..." msgstr "Установить приложение по умолчанию" msgid "Open with default application" msgstr "Открыть с помощью приложения по умолчанию" msgid "Reveal" msgstr "Показать" msgid "Open parent folder" msgstr "Открыть родительскую папку" msgid "Open Terminal Here" msgstr "Открыть терминал здесь" msgid "Open this location in a terminal" msgstr "Открыть это расположение в терминале" msgid "Run in Terminal" msgstr "Запустить в терминале" msgid "Run (Execute)" msgstr "Запустить (Выполнить)" msgid "Run this program in a Terminal" msgstr "Запустить программу в терминале" msgid "Run this program" msgstr "Запустить программу" msgid "Go To" msgstr "Перейти" msgid "Open URL" msgstr "Открыть URL" msgid "Open URL with default viewer" msgstr "Открыть URL при помощи средства просмотра по умолчанию" msgid "Launch" msgstr "Запустить" msgid "Show application window" msgstr "Показать окно приложения" msgid "Launch application" msgstr "Запустить приложение" msgid "Launch Again" msgstr "Запустить снова" msgid "Launch another instance of this application" msgstr "Запустить другую инстанцию приложения" msgid "Close" msgstr "Закрыть" msgid "Attempt to close all application windows" msgstr "Попытка закрыть все окна приложений" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Запустить" msgid "Perform command" msgstr "Выполнить команду" msgid "(Empty Text)" msgstr "(пустой текст)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "(%(num)d строка) \"%(text)s\"" msgstr[1] "(%(num)d строки) \"%(text)s\"" msgstr[2] "(%(num)d строк) \"%(text)s\"" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s и другие." #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Рекурсивные источники %(dir)s, (%(levels)d levels)" #, python-format msgid "Directory source %s" msgstr "Источник каталога %s" msgid "Home Folder" msgstr "Домашняя папка" msgid "Catalog Index" msgstr "Индекс каталога" msgid "An index of all available sources" msgstr "Индекс всех доступных источников" msgid "Root catalog" msgstr "Корневой каталок" msgid "Please Configure Plugin" msgstr "Пожалуйста, настройте плагин" #, python-format msgid "Plugin %s is not configured" msgstr "Плагин %s не настроен" #, python-format msgid "Invalid user credentials for %s" msgstr "Неправельные учетные данные пользователя для %s" msgid "Applications" msgstr "Приложения" msgid "All applications and preferences" msgstr "Все приложения и настройки" msgid "Applications for Desktop Environment" msgstr "Приложения для рабочей среды" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "Открыть в ..." msgid "Open with any application" msgstr "Открыть с помощью любого приложения" msgid "Set default application to open this file type" msgstr "Установить приложение по умолчанию для открытия данного типа файлов" #, fuzzy msgid "Reset Associations" msgstr "Действия URL" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "Deep Archives" msgid "Allow browsing inside compressed archive files" msgstr "Позволяет просматривать файлы внутри архива" #, python-format msgid "Content of %s" msgstr "Содержание %s" msgid "Archive Manager" msgstr "Менеджер Архивов" msgid "Use Archive Manager actions" msgstr "Использовать действие Менеджера Архивов" msgid "Compressed archive type for 'Create Archive In'" msgstr "Тип сжатого архива для 'Создать архив в'" msgid "Extract Here" msgstr "Извлечь здесь" msgid "Extract compressed archive" msgstr "Извлечь сжатый архив" msgid "Create Archive" msgstr "Создать Архив" msgid "Create a compressed archive from folder" msgstr "Создать сжатый архив из папки" msgid "Create Archive In..." msgstr "Создать архив в..." #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Архив" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "Управление воспроизведением и плейлистами Audacious " msgid "Include songs in top level" msgstr "Включая популярные песни" msgid "Enqueue" msgstr "Добавить в очередь" msgid "Add track to the Audacious play queue" msgstr "Добавить трек в очередь воспроизведения Audacious" msgid "Dequeue" msgstr "Убрать из очереди" msgid "Remove track from the Audacious play queue" msgstr "Удалить трек из очереди воспроизведения Audacious" msgid "Play" msgstr "Воспроизвести" msgid "Jump to track in Audacious" msgstr "Перейти к треку в Audacious" msgid "Resume playback in Audacious" msgstr "Возобновить воспроизведение в Audacious" msgid "Pause" msgstr "Пауза" msgid "Pause playback in Audacious" msgstr "Приостановить воспроизведение в Audacious" msgid "Next" msgstr "Следующая" msgid "Jump to next track in Audacious" msgstr "Перейти к следующему треку в Audacious" msgid "Previous" msgstr "Предыдущая" msgid "Jump to previous track in Audacious" msgstr "Перейти к предыдущему треку в Audacious" msgid "Clear Queue" msgstr "Очистите очередь" msgid "Clear the Audacious play queue" msgstr "Очистить очередь воспроизведения Audacious" msgid "Shuffle" msgstr "Перемешать" msgid "Toggle shuffle in Audacious" msgstr "Переключить в режим перемешивание в Audacious" msgid "Repeat" msgstr "Повторить" msgid "Toggle repeat in Audacious" msgstr "Переключить в режим повтора в Audacious" msgid "Show Playing" msgstr "Отобразить воспроизведение" msgid "Tell which song is currently playing" msgstr "Сообщить, какая песня сейчас играет" msgid "Playlist" msgstr "Плейлист" msgid "Calculator" msgstr "Калькулятор" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "Вычислить" msgid "Clipboards" msgstr "Буфер обмена" msgid "Recent clipboards and clipboard proxy objects" msgstr "Недавние объекты и прокси объекты буфера обмена" msgid "Number of recent clipboards to remember" msgstr "Количество запоминаемых буферов обмена," msgid "Include selected text in clipboard history" msgstr "Добавить выделенный текст в историю буфера обмена" msgid "Copy selected text to primary clipboard" msgstr "Скопировать выделенный текст в основной буфер обмена" msgid "Selected Text" msgstr "Выделенный текст" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Буфер обмена содержит %(num)d строку \"%(desc)s\"" msgstr[1] "Буфер обмена содержит %(num)d строки \"%(desc)s\"" msgstr[2] "Буфер обмена содержит %(num)d строк \"%(desc)s\"" msgid "Clipboard Text" msgstr "Текс в буфере обмена " msgid "Clipboard File" msgstr "Файл в буфере обмена" msgid "Clipboard Files" msgstr "Файлы в буфере обмена" msgid "Clear" msgstr "Очистить" msgid "Remove all recent clipboards" msgstr "Очистить буфер обмена" msgid "Shell Commands" msgstr "Команды Shell" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Запуск консольных программ. Действия отмеченные символом %s будут запущены в " "дочернем процессе" msgid "Run (Get Output)" msgstr "Запустить (Получить результат)" msgid "Run program and return its output" msgstr "Запустить программу и возвратить результат" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "Передать команде..." msgid "Run program with object as an additional parameter" msgstr "Запустить программу с объектом в качестве дополнительного параметра" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "Записать в команду..." msgid "Run program and supply text on the standard input" msgstr "Запустить програму и передать текс на стандартый ввод" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "" msgid "Run command-line programs" msgstr "Запуск консольных программ" msgid "GTK+" msgstr "GTK+" msgid "GNOME Terminal" msgstr "терминал GNOME" msgid "XFCE Terminal" msgstr "Терминал XFCE" msgid "LXTerminal" msgstr "LXTerminal" msgid "X Terminal" msgstr "X Терминал" msgid "Urxvt" msgstr "Urxvt" msgid "Konsole" msgstr "" msgid "Save As..." msgstr "Сохранить как..." #, fuzzy msgid "Restart Kupfer" msgstr "Перезапустить службу" msgid "Quit" msgstr "Выйти" msgid "Quit Kupfer" msgstr "Завершить Kupfer" msgid "About Kupfer" msgstr "О программе Kupfer" msgid "Show information about Kupfer authors and license" msgstr "Отобразить информацию об авторах и лицензии Kupfer" msgid "Kupfer Help" msgstr "Справка Kupfer" msgid "Get help with Kupfer" msgstr "Получить справку Kupfer" msgid "Show preferences window for Kupfer" msgstr "Показать окно настроек Kupfer" msgid "Search Contents" msgstr "Поиск содержания" msgid "Search inside this catalog" msgstr "Поиск внутри каталога" msgid "Copy" msgstr "Копировать" msgid "Copy to clipboard" msgstr "Копировать в буфер обмена" msgid "Rescan" msgstr "Повторить поиск" msgid "Force reindex of this source" msgstr "Форсировать рейндексацию данного источника" msgid "Last Command" msgstr "Последняя команда" msgid "Internal Kupfer Objects" msgstr "Внутренние объекты Kupfer" msgid "Last Result" msgstr "Последний результат" msgid "Command Results" msgstr "Результаты команды" msgid "Custom Terminal" msgstr "Пользовательский терминал" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Команда" msgid "Execute flag" msgstr "Выполнить флаг" msgid "Default Email Client" msgstr "Почтовый клиент по умолчанию" msgid "Compose email using the system's default mailto: handler" msgstr "Создание нового электронного письма в почтовом клиенте по умолчанию" #, fuzzy msgid "Compose Email To" msgstr "Создать электронное письмо" msgid "Dictionary" msgstr "Словарь" msgid "Look up word in dictionary" msgstr "Искать слово в словаре" msgid "Look Up" msgstr "Искать" msgid "Documents" msgstr "Документы" msgid "Recently used documents and bookmarked folders" msgstr "Недавно используемые документы и избранные папки" msgid "Max recent document days" msgstr "" msgid "Recent Items" msgstr "Последние элементы" msgid "Recently used documents" msgstr "Недавно используемые документы" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "%s Доументы" #, python-format msgid "Recently used documents for %s" msgstr "Недавно используемые документы для %s" msgid "Places" msgstr "Места" msgid "Bookmarked folders" msgstr "Избранные папки" msgid "DuckDuckGo Search" msgstr "Поиск DuckDuckGo" msgid "Search the web securely with DuckDuckGo" msgstr "Безопасный поис в Интернете с DuckDuckGo" msgid "Favorites" msgstr "Избранные" msgid "Mark commonly used items and store objects for later use" msgstr "" "Отметить часто используемые элементы и хранить объекты для последующего " "использования" msgid "Shelf of \"Favorite\" items" msgstr "\"Избранные \" элементы" msgid "Add to Favorites" msgstr "Добавить в Избранное" msgid "Add item to favorites shelf" msgstr "Добавить элемент в избранное" msgid "Remove from Favorites" msgstr "Удалить из Избраного" msgid "Remove item from favorites shelf" msgstr "Удалить элемент из избранного" msgid "File Actions" msgstr "Действия над файлом" msgid "More file actions" msgstr "Другие действия с файлом" msgid "Move To..." msgstr "Переместитесь в..." msgid "Move file to new location" msgstr "Переместите файл на новое место" msgid "Rename To..." msgstr "Переименовать в..." msgid "Copy To..." msgstr "Копировать в..." msgid "Copy file to a chosen location" msgstr "Копировать файл в выбранное место" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "Glob" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "Действия с высоким приоритетом" msgid "Tools to work with commands as objects" msgstr "Инструменты для работы с командами как с объектами" msgid "Select in Kupfer" msgstr "Выбрать в Kupfer" #, python-format msgid "Result of %s (%s)" msgstr "Результат для %s (%s)" msgid "Run (Take Result)" msgstr "Запустить (Получить результат)" msgid "Take the command result as a proxy object" msgstr "Получить результат команды как прокси-объект" msgid "Run (Discard Result)" msgstr "Запустить (Отменить результат)" msgid "Image Tools" msgstr "Инструменты для работы с изображением" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Инструменты трансформирования изображений" msgid "Scale..." msgstr "Масштабировать" msgid "Scale image to fit inside given pixel measure(s)" msgstr "" msgid "Rotate Clockwise" msgstr "Поворот по часовой стрелке" msgid "Rotate Counter-Clockwise" msgstr "Поворот против часовой стрелки" msgid "Autorotate" msgstr "Автоповорот" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "Повернуть JPEG (на месте) в соответствии с метаданными EXIF" msgid "Kupfer Plugins" msgstr "Плагины Kupfer" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Получить доступ к списку плагинов Kupfer" msgid "Show Information" msgstr "Отобразить информацию" msgid "Show Source Code" msgstr "Отобразить исходный код" msgid "enabled" msgstr "включен" msgid "disabled" msgstr "отключен" msgid "Notes" msgstr "Заметки" msgid "Gnote or Tomboy notes" msgstr "Заметки Gnote или Tomboy" msgid "Work with application" msgstr "Работа с приложением" msgid "Open with notes application" msgstr "Открыть с помощью приложения для работы с заметками" msgid "Append to Note..." msgstr "Добавить к заметке..." msgid "Add text to existing note" msgstr "Добавить текст в существующую заметку" msgid "Create Note" msgstr "Создать заметку" msgid "Create a new note from this text" msgstr "Создать новую заметку из данного текста" msgid "Get Note Search Results..." msgstr "Получить результаты поиска заметок" msgid "Show search results for this query" msgstr "Показать результаты поиска по данному запросу" #, python-format msgid "today, %s" msgstr "сегодня, %s" #, python-format msgid "yesterday, %s" msgstr "вчера, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Последнее обновление %s" msgid "Quicksilver Icons" msgstr "Значки Quicksilver" msgid "Quick Image Viewer" msgstr "Quick Image Viewer" msgid "View Image" msgstr "Просмотр изображения" msgid "GNU Screen" msgstr "GNU Screen" msgid "Active GNU Screen sessions" msgstr "Активные сеансы GNU Screen " msgid "Attached" msgstr "Прикрепленн" msgid "Detached" msgstr "Отсоединён" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "%(status)s сеанс (%(pid)s) создан %(time)s" msgid "Screen Sessions" msgstr "Screen Sessions" msgid "Attach" msgstr "Прикрепить" msgid "Send Keys" msgstr "Отправить нажатие клавиш" msgid "Send synthetic keyboard events using xautomation" msgstr "" "Отправление синтетических событий клавиатуры, с использованием xautomation" msgid "Paste to Foreground Window" msgstr "Встасить в активное окно" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "Копировать в буфер обмена и отправить Ctrl+V активному окну" msgid "Send keys to foreground window" msgstr "Отправить не активному окну нажатие клавиш" msgid "Type Text" msgstr "Ввести текс" msgid "Type the text to foreground window" msgstr "Ввести текст в активное окно" msgid "GNOME Session Management" msgstr "Управление сеансами GNOME" msgid "Special items and actions for GNOME environment" msgstr "Специальные элементы и действия для среды GNOME" msgid "Log Out..." msgstr "Завершить сеанс..." msgid "Log out or change user" msgstr "Выйдите из системы или измените пользователя" msgid "Shut Down..." msgstr "Выключить компьютер..." msgid "Shut down, restart or suspend computer" msgstr "Выключить, перезагрузить или приостановить компьютер" msgid "Lock Screen" msgstr "Заблокировать экран" msgid "Enable screensaver and lock" msgstr "Включить заставку экрана и блокировку" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "Управление сеансами XFCE" msgid "Special items and actions for XFCE environment" msgstr "Специальные элементы и действия для среды XFCE" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "SSH хосты" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "Добавить хосты найденные в ~/.ssh/config." msgid "SSH host" msgstr "SSH хост" msgid "Connect" msgstr "Подключить" msgid "Connect to SSH host" msgstr "Подключить к SSH хосту" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "SSH хосты определённые в ~/.ssh/config" msgid "No D-Bus connection to desktop session" msgstr "Не найдено DBus соединение для данного сеанса рабочего стола" msgid "GNOME Keyring" msgstr "GNOME Keyring" msgid "KWallet" msgstr "KWallet" msgid "Unencrypted File" msgstr "Незашифрованный файл" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "Команда в \"%s\" не доступна" msgid "Document Templates" msgstr "Шаблоны документов" msgid "Create new documents from your templates" msgstr "Создать новый документ из шаблона" #, python-format msgid "%s template" msgstr "%s шаблон" msgid "Empty File" msgstr "Пустой файл" msgid "New Folder" msgstr "Новая папка" msgid "Create New Document..." msgstr "Создать новый документ..." msgid "Create a new document from template" msgstr "Создать новый документ из шаблона" msgid "Create Document In..." msgstr "Создать документ из..." msgid "Textfiles" msgstr "Текстовые файлы" msgid "Append To..." msgstr "Добавьте к..." msgid "Append..." msgstr "Добавить..." msgid "Write To..." msgstr "Записать в..." msgid "Get Text Contents" msgstr "Получить содержание текста" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "Действия файлового менеджера Thunar" msgid "Select in File Manager" msgstr "Выбрать в файловом менеджере" msgid "Show Properties" msgstr "Отобразить свойства" msgid "Show information about file in file manager" msgstr "Отобразить информацию о файле в файловом менеджере" msgid "Send To..." msgstr "Отправить ..." msgid "Symlink In..." msgstr "Символьная ссылка в..." msgid "Create a symlink to file in a chosen location" msgstr "Создать символьную ссылку в выбранном месте" msgid "Empty Trash" msgstr "Очистить корзину" msgid "Thunar Send To Objects" msgstr "Thunar отправить объектам" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Контакты и действия Thunderbird/Icedove" msgid "Compose New Email" msgstr "Создать новое электронное письмо" msgid "Compose a new message in Thunderbird" msgstr "Создать новое сообщение в Thunderbird" #, fuzzy msgid "Attach in Email To..." msgstr "Отправить в электронном письме..." #, fuzzy msgid "Compose Email With" msgstr "Создать электронное письмо" #, fuzzy msgid "Compose a new message using the text as body" msgstr "Создать новое сообщение в Thunderbird" msgid "Thunderbird Address Book" msgstr "Адресная книга Thunderbird" msgid "Contacts from Thunderbird Address Book" msgstr "Контакты из адресной книги Thunderbird" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Top" msgid "Show running tasks and allow sending signals to them" msgstr "Отображение запущенныч задач и возможность посылать им сигналы" msgid "Sort Order" msgstr "Порядок сортировки" msgid "Commandline" msgstr "Командная строка " msgid "CPU usage (descending)" msgstr "Использование ЦП (по убыванию)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Использование памяти (по убыванию)" msgid "Send Signal..." msgstr "Отправить сигнал..." msgid "Signals" msgstr "Сигналы" msgid "Running Tasks" msgstr "Запущенные задачи" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid: %(pid)s ЦПУ: %(cpu)g%% ОЗУ: %(mem)g%% время: %(time)s" msgid "Running tasks for current user" msgstr "Запущенные задачи для текущего пользователя" msgid "Trash" msgstr "Мусорная корзина" msgid "Access trash contents" msgstr "Доступ к содержанию мусорной корзины" msgid "Move to Trash" msgstr "Переместить в мусорную корзину" msgid "Move this file to trash" msgstr "Переместите этот файл в мусорную корзину" msgid "Restore" msgstr "Восстановить" msgid "Move file back to original location" msgstr "Переместить файл на прежнее место" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "Мусорная корзина пуста" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "В мусорной корзине находится %(num)s файл" msgstr[1] "В мусорной корзине находится %(num)s файла" msgstr[2] "В мусорной корзине находится %(num)s файлов" msgid "Triggers" msgstr "Триггеры" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Назначить глобальных сочетаний клавиш (триггеров) для объектов, созданных " "при помощи действия 'Составить команду'" msgid "Add Trigger..." msgstr "Добавить триггер" msgid "Remove Trigger" msgstr "Удалить триггер" msgid "URL Actions" msgstr "Действия URL" msgid "Download and Open" msgstr "Загрузить и открыть" msgid "Download To..." msgstr "Скачать в..." msgid "Download URL to a chosen location" msgstr "Скачать URL в выбранное место" msgid "Wikipedia" msgstr "Wikipedia" msgid "Search in Wikipedia" msgstr "Поиск в Википедии" msgid "Wikipedia language" msgstr "Язык Википедии" #. TRANS: Default wikipedia language code msgid "en" msgstr "en" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Поиск этого термина на %s.wikipedia.org" msgid "Window List" msgstr "Список окон" msgid "All windows on all workspaces" msgstr "Все окна на всех рабочих столах" msgid "Activate" msgstr "Активировать" msgid "Shade" msgstr "Скрутить в заголовок" msgid "Unshade" msgstr "Раскрутить из заголовка" msgid "Minimize" msgstr "Свернуть" #, fuzzy msgid "Unminimize" msgstr "Развернуть" msgid "Maximize" msgstr "Развернуть" msgid "Unmaximize" msgstr "" msgid "Maximize Vertically" msgstr "Развернуть вертикально" msgid "Unmaximize Vertically" msgstr "" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Окно находится на %(wkspc)s" msgid "Frontmost Window" msgstr "Переднее окно" msgid "Next Window" msgstr "Следующие окно" msgid "Jump to this window's workspace and focus" msgstr "Перейти к этому рабочему окну " #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "%d окно" msgstr[1] "%d окна" msgstr[2] "%d окон" msgid "Active workspace" msgstr "Активный рабочий стол" msgid "Jump to this workspace" msgstr "Перейти к этому рабочему столу" msgid "Workspaces" msgstr "Рабочие столы" msgid "Volumes and Disks" msgstr "Тома и Диски" msgid "Mounted volumes and disks" msgstr "Монтированые тома и диски" #, python-format msgid "Volume mounted at %s" msgstr "Том монтирован в %s" msgid "Unmount" msgstr "Размонтировать" msgid "Unmount this volume" msgstr "Размонтировать этот том" msgid "Eject" msgstr "Извлечь" msgid "Unmount and eject this media" msgstr "Размонтировать и извлечь этот носитель" msgid "Show Text" msgstr "Отобразить текс" msgid "Display text in a window" msgstr "Отобразить текст в окне" #, fuzzy msgid "Large Type" msgstr "Большой тип" msgid "Show Notification" msgstr "Отобразить уведомление" msgid "Tracker" msgstr "Tracker" msgid "Tracker desktop search integration" msgstr "Интегрированная поисковая система Track" msgid "Search in Tracker" msgstr "Поиск в Tracker" msgid "Open Tracker Search Tool and search for this term" msgstr "Открыть Поиск Tracker и начать поиск этого выражения " msgid "Get Tracker Results..." msgstr "Получить результаты Tracker..." msgid "Show Tracker results for query" msgstr "Отобразить результаты запроса Tracker " #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "Результаты для \"%s\"" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "Определить местоположение файлов" msgid "Search filesystem using locate" msgstr "Поиск по файловой системе с помощью locate" msgid "Ignore case distinctions when searching files" msgstr "Не учитывать регистр при поиске файлов" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Закладки Firefox" msgid "Index of Firefox bookmarks" msgstr "Список закладок Firefox" #, fuzzy msgid "Firefox Keywords" msgstr "Закладки Firefox" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "Поиск в Интернете при помощи поисковой системы OpenSearch" msgid "Search With..." msgstr "Поиск при помощи..." msgid "Search For..." msgstr "Поиск..." #, fuzzy msgid "Search Terms" msgstr "Поисковые системы" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Пожалуйста, используйте \"%s\"" #, fuzzy msgid "Resume playback" msgstr "Возобновить воспроизведение в Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Следующая" #, fuzzy msgid "Skip to next track" msgstr "Перейти к следующему треку в Audacious" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Предыдущая" #, fuzzy msgid "Skip to previous track" msgstr "Перейти к предыдущему треку в Audacious" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "Доступ к контактам Pidgin" msgid "Show offline contacts" msgstr "Показать контакты не в сети" msgid "Open Chat" msgstr "Открыть чат" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d символ)" msgstr[1] "%s (%d символа)" msgstr[2] "%s (%d символов)" msgid "Send Message..." msgstr "Отправить сообщение..." msgid "Available" msgstr "Доступные " msgid "Away" msgstr "Отошёл" msgid "Pidgin Contacts" msgstr "Контакты Pidgin" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Сократить Ссылки" msgid "Create short aliases of long URLs" msgstr "Создание короткие алиасов для длинных URL" msgid "Error" msgstr "Ошибка" msgid "Shorten With..." msgstr "Сократить с помощью..." msgid "Services" msgstr "Службы" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "" "Воспроизведение и добавление треков в очередь , просмотр библиотеки музыки" msgid "Include artists in top level" msgstr "Включая популярных исполнителей" msgid "Include albums in top level" msgstr "Включая популярные альбомы" msgid "Play tracks in Rhythmbox" msgstr "Воспроизвести трек в Rhythmbox" msgid "Add tracks to the play queue" msgstr "Добавить трек в очередь воспроизведения" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "Исполнитель: %(artist)s, альбом: %(album)s" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "Исполнитель: %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Исполнитель треков: %s" msgid "Albums" msgstr "Альбом" msgid "Music albums in Rhythmbox Library" msgstr "Музыкальные альбомы в библиотеки Rhythmbox" msgid "Artists" msgstr "Исполнитель" msgid "Music artists in Rhythmbox Library" msgstr "Исполнители в библиотеки Rhythmbox" msgid "Songs" msgstr "Песни" msgid "Songs in Rhythmbox library" msgstr "Песни в библиотеки Rhythmbox" msgid "Getting Things GNOME" msgstr "Getting Things GNOME" msgid "Browse and create new tasks in GTG" msgstr "Просмотр и создание новых задач в GTG" #, python-format msgid "due: %s" msgstr "до: %s" #, python-format msgid "start: %s" msgstr "от: %s" #, python-format msgid "tags: %s" msgstr "теги: %s" msgid "Open task in Getting Things GNOME!" msgstr "Открыть задачу в Getting Things GNOME!" msgid "Delete" msgstr "Удалить" msgid "Permanently remove this task" msgstr "Безвозвратно удалить эту задачу" msgid "Mark Done" msgstr "Выполнено" msgid "Mark this task as done" msgstr "Отметить эту задачу, как выполненную" msgid "Dismiss" msgstr "Отклонить" msgid "Mark this task as not to be done anymore" msgstr "Отменить данную задачу как не используемую" msgid "Create Task" msgstr "Создать задачу" msgid "Create new task in Getting Things GNOME" msgstr "Создать новую задачу в Getting Things GNOME" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "Поиск в Devhelp" msgid "Empathy" msgstr "Empathy" msgid "Access to Empathy Contacts" msgstr "Доступ к контактам Empathy" msgid "Busy" msgstr "Занят" msgid "Not Available" msgstr "Не доступен" msgid "Invisible" msgstr "Невидимый" msgid "Offline" msgstr "Не в сети" msgid "Change Global Status To..." msgstr "Изменить глобальный статус на..." msgid "Empathy Contacts" msgstr "Контакты Empathy" msgid "Empathy Account Status" msgstr "Статус учётной записи Empathy" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Alternate Activate" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Назначить одно действие для многих объектов" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Составить команду" msgid "Mark Default Action" msgstr "Отметить действие по умолчанию" msgid "Forget Object" msgstr "Забыть обьект" msgid "Reset All" msgstr "Сбросить все" msgid "Select Quit" msgstr "Закончить" msgid "Select Selected File" msgstr "Выбрать выбранный фаил" msgid "Select Selected Text" msgstr "Выбрать выбранный текст" msgid "Show Help" msgstr "Показать справку" msgid "Show Preferences" msgstr "Показать окно настроек" msgid "Switch to First Pane" msgstr "Переключиться на первую область" msgid "Toggle Text Mode" msgstr "Переключить в текстовый режим" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "нет совпадений в %(src)s для \"%(query)s\"" msgid "No matches" msgstr "Нет совпадений" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Нет совпадений" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Сделать \"%(action)s\" действием по умолчанию для \"%(object)s\"" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "Забыть о \"%s\"" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Показать основной интерфейс" msgid "Show with Selection" msgstr "Показать с выбором" #. TRANS: Plugin info fields msgid "Description" msgstr "Описание" msgid "Author" msgstr "Автор" msgid "Version" msgstr "Версия" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Необходим модуль Python '%s'" msgid "Plugin could not be read due to an error:" msgstr "Плагин не может быть прочитан из-за ошибки:" msgid "Content of" msgstr "Содержание" #. TRANS: Plugin contents header msgid "Sources" msgstr "Источники" #. TRANS: Plugin contents header msgid "Actions" msgstr "Действия" #, python-format msgid "Using encrypted password storage: %s" msgstr "При помощи зашифрованного хранилища паролей: %s" #, python-format msgid "Using password storage: %s" msgstr "При помощи хранилища паролей: %s" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Конфигурация" msgid "Set username and password" msgstr "Установить имя пользователя и пароль" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Выберите папку" msgid "Reset all shortcuts to default values?" msgstr "Восстановить значения ярлыков на значение по умолчанию?" msgid "Shortcut" msgstr "Ярлык" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "Список переводчиков" msgid "A free software (GPLv3+) launcher" msgstr "Средство запуска бесплатного (GPLv3+) программного обеспечения" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Эта программа является свободным программным обеспечением вы можете " "распространять и / или изменять \n" "его в соответствии с условиями GNU General Public License, опубликованной \n" "Free Software Foundation, версии 3 лицензии, или \n" "(по вашему выбору) любой более поздней версии. \n" "\n" "Эта программа распространяется в надежде, что она будет полезна, \n" "но БЕЗ ВСЯКИХ ГАРАНТИЙ, даже без подразумеваемой гарантии \n" "Или ПРИГОДНОСТИ ДЛЯ КОНКРЕТНЫХ ЦЕЛЕЙ. См. \n" "GNU General Public License для более подробной информации. \n" " \n" " Вы должны были получить копию GNU General Public License \n" "Вместе с этой программой. Если нет, см. . \n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Не удалось найти запущенный Kupfer" #~ msgid "Compose Email" #~ msgstr "Создать электронное письмо" #~ msgid "Send in Email To..." #~ msgstr "Отправить в электронном письме..." #~ msgid "Type to search %s" #~ msgstr "Введите поисковый запрос %s" #~ msgid "No action" #~ msgstr "Действие не назначено" #~ msgid "GNOME Terminal Profiles" #~ msgstr "Профили терминала GNOME" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Запустить профили терминала GNOME" #~ msgid "Multihead Support" #~ msgstr "Поддержка нескольких мониторов" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Вычисление значения выражения, начинающегося с '='" #~ msgid "Epiphany Bookmarks" #~ msgstr "Закладки Epiphany" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Список закладок Epiphany" #~ msgid "Include visited sites" #~ msgstr "Включая посещенные сайты" #~ msgid "Selected File" #~ msgstr "Выбранный Файл" #~ msgid "Selected File \"%s\"" #~ msgstr "Выбранный файл \"%s\"" #~ msgid "Selected Files" #~ msgstr "Выбранные файлы" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Возобновить воспроизведение в Rhythmbox" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Приостановить воспроизведение в Rhythmbox" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Перейти к следующему треку в Rhythmbox" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Перейти к предыдущему треку в Rhythmbox" #~ msgid "Search the Web" #~ msgstr "Поиск в Интернете" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Документы, недавно используемый в Abiword" #~ msgid "Abiword Recent Items" #~ msgstr "Недавние элементы Abiword" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "Взаимодействие с менеджером пакетов APT" #~ msgid "Installation method" #~ msgstr "Метод установки" #~ msgid "Show Package Information" #~ msgstr "Отобразить Информация о пакете" #~ msgid "Install" #~ msgstr "Установить" #~ msgid "Install package using the configured method" #~ msgstr "Установить пакет с помощью настроенного метода" #~ msgid "Packages matching \"%s\"" #~ msgstr "Пакеты соответствующие \"%s\"" #~ msgid "Search Package Name..." #~ msgstr "Поиск имени пакеты..." #~ msgid "Ascii & Unicode Icon Set" #~ msgstr "Набор значков Ascii и Unicode" #~ msgid "" #~ "Provides the Ascii and Unicode icon sets that use letters and symbols to " #~ "produce icons for the objects found in Kupfer." #~ msgstr "" #~ "Обеспечивает наборы значков Ascii и Unicode , которые используют буквы и " #~ "символы , чтобы создавать значки для объектов, найденных в Kupfer." #~ msgid "Ascii" #~ msgstr "Ascii" #~ msgid "Unicode" #~ msgstr "Unicode" #~ msgid "Chromium Bookmarks" #~ msgstr "Закладки Chromium" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Список закладок Chromium" #~ msgid "Claws Mail" #~ msgstr "Claws Mail" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Контакты и действия Claws Mail" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Создать новое сообщение в Claws Mail" #~ msgid "Receive All Email" #~ msgstr "Получите все электронные письма" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "Получать новые сообщения из всех учетных записей в ClawsMail" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Создать новое сообщение в Claws Mail и прикрепить файл" #~ msgid "Claws Mail Address Book" #~ msgstr "Адресная книга Claws Mail" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Контакты из адресной книги Claws Mail" #~ msgid "Configure a custom terminal emulator" #~ msgstr "Настройка пользовательского эмулятора терминала" #~ msgid "Custom Theme" #~ msgstr "Пользовательская тема" #~ msgid "Use a custom color theme" #~ msgstr "Использовие пользовательской цветовой схемы" #~ msgid "Theme:" #~ msgstr "Тема:" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Контакты Evolution" #~ msgid "Compose a new message in Evolution" #~ msgstr "Создать новое сообщение в Evolution" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Создать новое сообщение в Evolution и прикрепить файл" #~ msgid "Evolution Address Book" #~ msgstr "Адресная книга Evolution" #~ msgid "Filezilla" #~ msgstr "Filezilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Отображение сайтов и обработка ftp адресов с помощью Filezilla" #~ msgid "Open Site with Filezilla" #~ msgstr "Открыть сайт с помощью Filezilla" #~ msgid "Filezilla Sites" #~ msgstr "Сайты Filezilla" #~ msgid "Sites from Filezilla" #~ msgstr "Сайты из Filezilla" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Доступ к контактам Gajim" #~ msgid "Free for Chat" #~ msgstr "Cвободен для общения" #~ msgid "Gajim Contacts" #~ msgstr "Контакты Gajim" #~ msgid "Gajim Account Status" #~ msgstr "Статус учётной записи Gajim" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Загрузка контактов и создие новых сообщений в Gmail" #~ msgid "Load contacts' pictures" #~ msgstr "Загрузить картинки контактов" #~ msgid "Load additional information" #~ msgstr "Загрузить дополнительную информацию " #~ msgid "Work email" #~ msgstr "Рабочий email" #~ msgid "Home email" #~ msgstr "Домашний email" #~ msgid "Other email" #~ msgstr "Другие email" #~ msgid "Work address" #~ msgstr "Рабочий адрес" #~ msgid "Home address" #~ msgstr "Домашний адрес" #~ msgid "Other address" #~ msgstr "Другой адрес" #~ msgid "Car phone" #~ msgstr "Автомобильный телефон" #~ msgid "Fax" #~ msgstr "Факс" #~ msgid "Home phone" #~ msgstr "Домашний телефон" #~ msgid "Home fax" #~ msgstr "Домашний Факс" #~ msgid "Internal phone" #~ msgstr "Внутренний телефон" #~ msgid "Mobile" #~ msgstr "Мобильный телефон" #~ msgid "Other" #~ msgstr "Другой" #~ msgid "VOIP" #~ msgstr "VOIP" #~ msgid "Work phone" #~ msgstr "Рабочий телефон" #~ msgid "Work fax" #~ msgstr "Рабочий Факс" #~ msgid "Compose Email in Gmail" #~ msgstr "Создать электронное письмо в Gmail" #~ msgid "Open web browser and compose new email in Gmail" #~ msgstr "Открыть веб-браузер и создать новое электронное письмо в Gmail" #~ msgid "Edit Contact in Gmail" #~ msgstr "Редактировать контакты в Gmail" #~ msgid "Open web browser and edit contact in Gmail" #~ msgstr "Открыть веб-браузер и редактировать контакты в Gmail" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Контакты из служеб Google (Gmail)" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Отображение альбомов и загрузка файлов на Picasa" #, fuzzy #~ msgid "Users to show: (,-separated)" #~ msgstr "Пользователи для отображения: (разделитель-\",\")" #~ msgid "Load user and album icons" #~ msgstr "Загрузить пользователей и значки альбомов" #~ msgid "Uploading Pictures" #~ msgstr "Загрузка изображений" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Загрузка изображений в веб-альбом Picasa" #~ msgid "Creating album:" #~ msgstr "Создание альбома:" #~ msgid "Album created by Kupfer" #~ msgstr "Альбом созданный Kupfer" #~ msgid "File:" #~ msgstr "Файл:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "%(num)d альбом" #~ msgstr[1] "%(num)d альбома" #~ msgstr[2] "%(num)d альбомов" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "%(num)s фото" #~ msgstr[1] "%(num)s фото" #~ msgstr[2] "%(num)s фото" #~ msgid "Upload to Picasa Album..." #~ msgstr "Загрузить в альбом Picasa ..." #~ msgid "Upload files to Picasa album" #~ msgstr "Загрузить файлы в альбом Picasa" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Загрузить в Picasa как новый альбом" #~ msgid "Create album from selected local directory" #~ msgstr "Создать альбом из выбранной папки" #~ msgid "Picasa Albums" #~ msgstr "Альбомы Picasa" #~ msgid "User albums in Picasa" #~ msgstr "Пользовательские альбомы в Picasa" #~ msgid "Google Search" #~ msgstr "Поиск Google" #~ msgid "Search Google with results shown directly" #~ msgstr "Поиск в Google с прямым отображением результатов" #~ msgid "Show More Results For \"%s\"" #~ msgstr "Отобразить больше результатов для \"%s\"" #~ msgid "%s total found" #~ msgstr "Всего найденно %s " #~ msgid "Gwibber" #~ msgstr "Gwibber" #~ msgid "" #~ "Microblogging with Gwibber. Allows sending and receiving messages from " #~ "social networks like Twitter, Identi.ca etc. Requires the package " #~ "'gwibber-service'." #~ msgstr "" #~ "Микроблогинг с Gwibber. Позволяет отправлять и получать сообщения из " #~ "социальных сетей, таких как Twitter, Identi.ca и т.д. Необходим пакет " #~ "'gwibber-service'." #~ msgid "Maximum number of messages to show" #~ msgstr "Максимальное количество отображаемых сообщений" #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s на %(service)s" #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s написал в %(where)s" #~ msgid "Send Message" #~ msgstr "Отправить сообщение" #~ msgid "Send message to all Gwibber accounts" #~ msgstr "Отправить сообщение для всех учетных записей Gwibber" #~ msgid "Send Message To..." #~ msgstr "Отправить сообщение для..." #~ msgid "Send message to a Gwibber account" #~ msgstr "Отправит сообщение на учетную запись Gwibber" #~ msgid "Send message to selected Gwibber account" #~ msgstr "Отправьте сообщение для выбранной учетной записи Gwibber" #~ msgid "Reply..." #~ msgstr "Ответить..." #~ msgid "Delete Message" #~ msgstr "Удалить сообщение" #~ msgid "Send Private Message..." #~ msgstr "Отправить личное сообщение..." #~ msgid "Send direct message to user" #~ msgstr "Отправить персональное сообщение для пользователя" #~ msgid "Retweet" #~ msgstr "Ретвит" #~ msgid "Retweet To..." #~ msgstr "Ретвит к..." #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Ретвит сообщения для всех учетных записей Gwibber" #~ msgid "Retweet message to a Gwibber account" #~ msgstr "Ретвит сообщения для учётной записи Gwibber" #~ msgid "Open in Browser" #~ msgstr "Открыть в браузере" #~ msgid "Open message in default web browser" #~ msgstr "Открыть сообщение в веб-браузере по умолчанию" #~ msgid "Gwibber Accounts" #~ msgstr "Учетные записи Gwibber" #~ msgid "Accounts configured in Gwibber" #~ msgstr "Учетные записи, настроенные в Gwibber" #~ msgid "Gwibber Messages" #~ msgstr "Сообщения Gwibber" #~ msgid "Recent messages received by Gwibber" #~ msgstr "Последние сообщения, полученные в Gwibber" #~ msgid "Gwibber Messages for %s" #~ msgstr "Gwibber сообщения для %s" #~ msgid "Gwibber Streams" #~ msgstr "Потоки Gwibber" #~ msgid "Streams configured in Gwibber" #~ msgstr "Потоки, настроенные в Gwibber" #~ msgid "Gwibber Messages in %s" #~ msgstr "Сообщения Gwibber в %s" #~ msgid "Gwibber (Simple)" #~ msgstr "Gwibber (Простой)" #~ msgid "Send updates via the microblogging client Gwibber" #~ msgstr "Отправление обновлений через клиент микроблоггинга Gwibber" #~ msgid "Send Update" #~ msgstr "Отправить обновление" #~ msgid "Unable to activate Gwibber service" #~ msgstr "Не удалось активировать службу Gwibber" #~ msgid "OpenOffice / LibreOffice" #~ msgstr "OpenOffice / LibreOffice" #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Документы, недавно используемые в OpenOffice/LibreOffice" #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "Последние элементы OpenOffice/LibreOffice" #~ msgid "Opera Mail" #~ msgstr "Opera Mail" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Контакты и действия Opera Mail" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Создать новое сообщение в Opera Mail" #~ msgid "Opera Mail Contacts" #~ msgstr "Контакты Opera Mail" #~ msgid "Contacts from Opera Mail" #~ msgstr "Контакты из Opera Mail" #~ msgid "Opera Bookmarks" #~ msgstr "Закладки Opera" #~ msgid "Index of Opera bookmarks" #~ msgstr "Список закладок Opera" #~ msgid "PuTTY Sessions" #~ msgstr "Сеансы PuTTY" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Быстрый доступ к сеансам PuTTY" #~ msgid "Start Session" #~ msgstr "Начать сеанс" #~ msgid "reStructuredText" #~ msgstr "reStructuredText" #~ msgid "Render reStructuredText and show the result" #~ msgstr "Обработка и отображение результатов reStructuredText " #~ msgid "View as HTML Document" #~ msgstr "Просмотреть как HTML документ" #~ msgid "System Services" #~ msgstr "Системные службы" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "Запуск, остановка или перезапуск системных служб через init скрипты" #~ msgid "Sudo-like Command" #~ msgstr "Sudo-подобная команда" #~ msgid "Start Service" #~ msgstr "Запустить службу" #~ msgid "Stop Service" #~ msgstr "Остановить службу" #~ msgid "%s Service" #~ msgstr "%s служба" #~ msgid "Show QRCode" #~ msgstr "Отобразить QR-код" #~ msgid "Display text as QRCode in a window" #~ msgstr "Отобразить текст в окне , как QR-код" #~ msgid "Access to Skype contacts" #~ msgstr "Доступ к контактам Skype" #~ msgid "Skype Me" #~ msgstr "Skype Me" #~ msgid "Logged Out" #~ msgstr "Вышел из системы" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Позвонить" #~ msgid "Place a call to contact" #~ msgstr "Позвонить контакту" #~ msgid "Skype Contacts" #~ msgstr "Контакты Skype" #~ msgid "Skype Statuses" #~ msgstr "Skype статусы" #~ msgid "Tracker 0.6" #~ msgstr "Tracker 0.6" #~ msgid "Tracker tags" #~ msgstr "Теги Tracker" #~ msgid "Tracker Tags" #~ msgstr "Теги Tracker" #~ msgid "Browse Tracker's tags" #~ msgstr "Просмотреть теги Tracker" #~ msgid "Tag %s" #~ msgstr "Тег %s" #~ msgid "Objects tagged %s with Tracker" #~ msgstr "Объекты отмеченные тегом %s с помощью Tracker" #~ msgid "Add Tag..." #~ msgstr "Добавить тег..." #~ msgid "Add tracker tag to file" #~ msgstr "Добавить тег tracker в файл" #~ msgid "Remove Tag..." #~ msgstr "Удалить тег..." #~ msgid "Remove tracker tag from file" #~ msgstr "Удалить тег tracker из файла" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Разделы из истории TrueCrypt" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "Раздел TrueCrypt: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Монтировать раздел" #~ msgid "Mount in Truecrypt" #~ msgstr "Монтировать в Truecrypt" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Попробовать смонтировать файл как раздел Truecrypt" #~ msgid "Dismount All Volumes" #~ msgstr "Размонтировать все разделы" #~ msgid "TrueCrypt Volumes" #~ msgstr "Разделы TrueCrypt" #~ msgid "Terminal Server Client" #~ msgstr "Terminal Server Client" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Сеанс сохраный в Terminal Server Client" #~ msgid "TSClient sessions" #~ msgstr " TSClient" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Сеансы сохранённые в Terminal Server Client" #~ msgid "Vim" #~ msgstr "Vim" #~ msgid "Recently used documents in Vim" #~ msgstr "Документы, недавно используемые в Vim" #~ msgid "Vim Recent Documents" #~ msgstr "Недавние документы Vim" #~ msgid "Close (Save All)" #~ msgstr "Закрыть (Сохранить все)" #~ msgid "Send..." #~ msgstr "Отправить..." #~ msgid "Send ex command" #~ msgstr "Отправить ex-команду" #~ msgid "Insert in Vim..." #~ msgstr "Вставить в Vim..." #~ msgid "Active Vim Sessions" #~ msgstr "Активные сеансы Vim" #~ msgid "Vim Session %s" #~ msgstr "Vim cеанс: %s" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Закладки и действия Vinagre" #~ msgid "Start Vinagre Session" #~ msgstr "Запустить сеанс Vinagre" #~ msgid "Vinagre Bookmarks" #~ msgstr "Закладки Vinagre" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "Управление виртуальными машинами VirtualBox. Поддерживаются как Sun " #~ "VirtualBox так и Open Source Edition." #~ msgid "Force use CLI interface" #~ msgstr "Форсировать использование интерфейса CLI " #~ msgid "Power On" #~ msgstr "Включить" #~ msgid "Power On Headless" #~ msgstr "Запустить без X сервера" #~ msgid "Send Power Off Signal" #~ msgstr "Послать сигнал выключения" #~ msgid "Reboot" #~ msgstr "Перезагрузить" #~ msgid "Resume" #~ msgstr "Возобновить" #~ msgid "Save State" #~ msgstr "Сохранить состояние" #~ msgid "Power Off" #~ msgstr "Выключить" #~ msgid "VirtualBox Machines" #~ msgstr "Машины VirtualBox" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "Доступ к страницам, сохранённым в Zim " #~ msgid "Page names start with :colon" #~ msgstr "Название страниц начинаются с \":\" двоеточия" #~ msgid "Default page name for quick notes" #~ msgstr "Названия быстрых заметок по умолчанию" #~ msgid "Note %x %X" #~ msgstr "Заметка %x %X" #~ msgid "" #~ "Strftime tags can be used: %H - hour, %M - minutes, etc\n" #~ "Please check python documentation for details.\n" #~ "NOTE: comma will be replaced by _" #~ msgstr "" #~ "Strftime-теги могут быть использованы как: %H - часы, %M - минуты, и т.д\n" #~ "Для получения дополнительной информации ознакомьтесь с документацией " #~ "python.\n" #~ "ПРИМЕЧАНИЕ: запятые будут заменены на _" #~ msgid "Default namespace for quick notes" #~ msgstr "Пространство имён быстрых заметок по умолчанию" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Zim страница из записной книжки \"%s\"" #~ msgid "Create Zim Page" #~ msgstr "Создать страницу Zim" #~ msgid "Create page in default notebook" #~ msgstr "Создать страицу в записной книжке по умолчанию" #~ msgid "Create Zim Page In..." #~ msgstr "Создать страицу Zim в..." #~ msgid "Insert QuickNote into Zim" #~ msgstr "Вставить быструю заметку в Zim" #~ msgid "Quick note selected text into Zim notebook" #~ msgstr "Создать быструю заметку из выбранного текста в записной книжке Zim" #~ msgid "Create Subpage..." #~ msgstr "Создать подстраницу" #~ msgid "Zim Notebooks" #~ msgstr "Записная книжка Zim" #~ msgid "Zim Pages" #~ msgstr "Zim страницы" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Страницы, сохранённые в записной книжке Zim " kupfer-328/po/sk.po000066400000000000000000001145011500175051100142540ustar00rootroot00000000000000# Slovak translation for kupfer. # Copyright (C) 2011, 2012 kupfer's COPYRIGHT HOLDER # This file is distributed under the same license as the kupfer package. # Pavol Babincak , 2011-2012. # msgid "" msgstr "" "Project-Id-Version: kupfer master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2012-10-31 19:55+0200\n" "Last-Translator: Pavol Babinčák \n" "Language-Team: Slovak \n" "Language: sk\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) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n" "X-Generator: Virtaal 0.7.1-rc1\n" # GtkDialog title msgid "User credentials" msgstr "Prístupové údaje používateľa" # GtkLabel label msgid "_User:" msgstr "_Používateľ:" # GtkLabel label msgid "_Password:" msgstr "_Heslo:" # PM: nie je v rovnakom okne aj tlačidlo Zrušiť? ak hej tak treba dať Z_meniť # GtkButton label #, fuzzy msgid "_Change" msgstr "_Zmeniť" #  PM: dohodli sme sa, že titulky okien budeme prekladať v štýle nastavenie klavesových skratiek # v druhom prípade by tam zasa asi malo byť Nastavte klávesové skratky. # PM: treba nahlásiť bug aby okno pomenovali inak, napríklad Keyborard shortcut settings # GtkDialog title; GtkLabel label #, fuzzy msgid "Set Keyboard Shortcut" msgstr "Nastaviť klávesové skratky" # GtkLabel label msgid "Please press desired key combination" msgstr "Stlačte prosím požadovanú kombináciu klávesov" # GtkLabel label msgid "Keybinding could not be bound" msgstr "Klávesová skratka nemôže byť priradená" # GtkDialog title; msgid "Kupfer Preferences" msgstr "Nastavenia programu Kupfer" # GtkCheckButton label msgid "Start automatically on login" msgstr "Spúšťať automaticky po prihlásení" # GtkLabel label msgid "Start" msgstr "Štart" # GtkCheckButton label msgid "Show icon in notification area" msgstr "Zobraziť ikonu v oblasti upozornení" # GtkLabel label msgid "Icon set:" msgstr "Sada ikon:" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" # GtkLabel label msgid "Terminal emulator:" msgstr "Emulátor terminálu:" # GtkLabel label msgid "Desktop Environment" msgstr "Pracovné prostredie" # tab GtkLabel label msgid "General" msgstr "Všeobecné" # GtkLabel label msgid "Global Keyboard Shortcuts" msgstr "Globálne klávesové skratky" #  PM: vynulovať asi celkom nevystihuje podstatu #  PM: toto by asi trebalo prebrať v ML ako toto slovo budeme prekladať # GtkButton label #, fuzzy msgid "Reset" msgstr "Vynulovať" # GtkLabel label msgid "Browser Keyboard Shortcuts" msgstr "Klávesové skratky prehliadača" # lomítko je nespisovne, spisovne je lomka # GtkCheckButton label #, fuzzy msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "Použiť jednoklávesové príkazy (medzerník, lomítko, bodka, čiarka atď.)" # GtkLabel label msgid "Keyboard" msgstr "Klávesnica" # tab GtkLabel label msgid "Plugins" msgstr "Zásuvné moduly" # GtkTable GtkLabel label msgid "Inclusion in Top Level Searches" msgstr "Zahrnúť do najvyššej úrovne hľadania" #  PM: nie je mi jasné ku čomu sa vsťahuje "jeho" # GtkTable GtkLabel label #, fuzzy msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "Označené zdroje majú svoje objekty zahrnuté v najvyššej úrovni hľadania.\n" "Obsah neoznačených zdrojov je dostupný iba pri hľadaní v jeho podkatalógu." # GtkLabel label msgid "Indexed Folders" msgstr "Indexované priečinky" # GtkLabel label msgid "Folders whose files are always available in the catalog." msgstr "Priečinky, ktorých súbory sú vždy k dispozícii v katalógu." # tab GtkLabel label msgid "Catalog" msgstr "Katalóg" # desktop entry name msgid "Kupfer" msgstr "Kupfer" # desktop entry generic name msgid "Application Launcher" msgstr "Spúšťač aplikácií" # desktop entry comment msgid "Convenient command and access tool for applications and documents" msgstr "" "Nástroj na pohodlné vykonávanie príkazov a prístup k aplikáciám a dokumentom" # desktop entry name msgid "Execute in Kupfer" msgstr "Spustiť v aplikácii Kupfer" # mime type comment msgid "Saved Kupfer Command" msgstr "Uložený príkaz aplikácie Kupfer" # PM: ku tomuto reťazcu vyvojari napísali komentár pre prekladatelov, ale bohužial zle, preto sa tu nezobrazuje, treba im nahlásiť bug # PM: dal by som akcia „%s“ #, fuzzy, python-format msgid "Could not to carry out '%s'" msgstr "Nebolo možné vykonať „%s“" #  PM: akcia „%s“ aby nebol probléme so sklonovaním #, fuzzy, python-format msgid "\"%s\" produced a result" msgstr "„%s“ vytvoril výsledok" #  PM: právo nie je nedostatočné, nie je nastavené #  PM: dal by som chýba právo... alebo niečo v tom štýle #, fuzzy, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Nedostatočné právo na spustenie „%s“ (nie je spustiteľný)" #, python-format msgid "Command in \"%s\" is not available" msgstr "Príkaz v „%s“ nie je dostupný" #, python-format msgid "Keyboard relay is active for display %s" msgstr "Zachytávanie klávesnice je aktívne pre displej %s" # PM: toto sú popisy volieb príkazového riadka, treba to preložiť popisne napr nezobrazí hlavneé rozhranie po spustení # cmd desc #, fuzzy msgid "do not present main interface on launch" msgstr "po spustení nezobraziť hlavné rozhranie" # cmd desc #, fuzzy msgid "list available plugins" msgstr "zoznam dostupných zásuvných modulov" # cmd desc #, fuzzy msgid "enable debug info" msgstr "zapnúť ladiace informácie" #  Podľa popisu sa mi zdá preklad nesprávny - ten zásuvný modul je to čo pomáha nie? # cmd desc #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer #, fuzzy msgid "run plugin helper" msgstr "spustiť pomocníka zásuvného modulu" # cmd desc #, fuzzy msgid "show usage help" msgstr "zobraziť pomocníka k použitiu" # cmd desc #, fuzzy msgid "show version information" msgstr "zobraziť informácie o verzii" #  PM: treba preložiť aj obsah zátvorky so zachovaním veľkosti písmen a treba aj diakritiku použiť #, fuzzy msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Použitie: kupfer [ OPTIONS | FILE ... ]" msgid "Available plugins:" msgstr "Dostupné zásuvné moduly:" # PM: toto si zaslúži komentár od vývojárov, že prečo to vlastne nastavili na preklad - vyžiadaj si ho prosím #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" # PM: znie to neprirodzene  #, fuzzy msgid "Type to search" msgstr "Píšte pre vyhľadávanie" # PM: čo je %s? je tu správny rod? # PM: podľa kódu je %s to isté ako v nasledujúcom riadku %(src)s #, fuzzy, python-format msgid "%s is empty" msgstr "%s je prázdny" msgid "Text" msgstr "Text" #, fuzzy msgid "Run after Delay..." msgstr "Spustiť po chvíli…" #  PM: popis - Vykoná... #, fuzzy msgid "Perform command after a specified time interval" msgstr "Vykonať príkaz po určenom časovom intervale" msgid "Multiple Objects" msgstr "Viac objektov" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s objektov" msgstr[1] "%s objekt" msgstr[2] "%s objekty" #  PM: prosím uveď príklad ako sa to bude zobrazovať #, fuzzy, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" # status msgid "unknown" msgstr "neznámy" msgid "Aim" msgstr "Aim" msgid "Google Talk" msgstr "Google Talk" msgid "ICQ" msgstr "ICQ" msgid "MSN" msgstr "MSN" msgid "QQ" msgstr "QQ" msgid "Yahoo" msgstr "Yahoo" msgid "Skype" msgstr "Skype" # PM: dal by som nástroj %s aby nebol problém s rodom #, fuzzy, python-format msgid "%s does not support this operation" msgstr "%s nepodporuje túto operáciu" msgid "Can not be used with multiple objects" msgstr "Nie je možné použiť s viacerými objektami" msgid "Open" msgstr "Otvoriť" # PB: Chybové hlásenie #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Nie je dostupná predvolená aplikácia pre %(file)s (%(type)s)" # PB: Chybové hlásenie #, python-format msgid "Please use \"%s\"" msgstr "Použite prosím „%s“" # PB: Chybové hlásenie - odkaz na akciu msgid "Set Default Application..." msgstr "Nastaviť predvolenú aplikáciu…" # PB: Popis akcie msgid "Open with default application" msgstr "Otvorí pomocou predvolenej aplikácie" # PB: Názov akcie msgid "Reveal" msgstr "Ukázať" # PB: Popis akcie msgid "Open parent folder" msgstr "Otvorí rodičovský priečinok" # PB: Názov akcie msgid "Open Terminal Here" msgstr "Tu otvoriť terminál" # PB: Popis akcie msgid "Open this location in a terminal" msgstr "Otvorí toto umiestnenie v termináli" # PB: Názov akcie msgid "Run in Terminal" msgstr "Spustiť v termináli" # PB: Názov akcie msgid "Run (Execute)" msgstr "Spustiť (vykonať)" # PB: Popis akcie msgid "Run this program in a Terminal" msgstr "Spustí tento program v termináli" # PB: Popis akcie msgid "Run this program" msgstr "Spustí tento program" msgid "Go To" msgstr "Prejsť na" # PB: Názov akcie msgid "Open URL" msgstr "Otvoriť URL" # PB: Popis akcie msgid "Open URL with default viewer" msgstr "Otvorí URL v predvolenom prehliadači" # PB: Názov akcie msgid "Launch" msgstr "Spustiť" # PB: Popis akcie msgid "Show application window" msgstr "Zobrazí okno aplikácie" # PB: Popis akcie msgid "Launch application" msgstr "Spustí aplikáciu" # PB: Názov akcie msgid "Launch Again" msgstr "Spustiť znova" # PB: Popis akcie msgid "Launch another instance of this application" msgstr "Spustí ďalšiu inštanciu tejto aplikácie" #, fuzzy msgid "Close" msgstr "Zavrieť" # PB: Popis akcie msgid "Attempt to close all application windows" msgstr "Skúsi zatvoriť všetky okná aplikácií" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Vykonať" # PB: Popis akcie msgid "Perform command" msgstr "Vykoná príkaz" # PB: Názov akcie TextLeaf, pozri nasledovné msgid "(Empty Text)" msgstr "(Prázdny text)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "(%(num)d riadkov) „%(text)s“" msgstr[1] "„%(text)s“" msgstr[2] "(%(num)d riadky) „%(text)s“" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s a ďalší" # PB: Popis akcie #, fuzzy, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Rekurzívny zdroj priečinka %(dir)s, (%(levels)d úrovní)" # PM: adresár # PB: Popis akcie #, python-format msgid "Directory source %s" msgstr "Zdrojový priečinok %s" msgid "Home Folder" msgstr "Domovský priečinok" # PB: Názov akcie msgid "Catalog Index" msgstr "" # PB: Popis akcie msgid "An index of all available sources" msgstr "" # PB: Popis akcie msgid "Root catalog" msgstr "Koreňový katalóg" msgid "Please Configure Plugin" msgstr "Nastavte, prosím, zásuvný modul" #, python-format msgid "Plugin %s is not configured" msgstr "Zásuvný modul %s nie je nastavený" #, python-format msgid "Invalid user credentials for %s" msgstr "Neplatné poverenia používateľa pre %s" # PB: Názov zásuvného modulu msgid "Applications" msgstr "Aplikácie" # PB: Popis zásuvného modulu msgid "All applications and preferences" msgstr "Všetky aplikácie a nastavenia" # PB: Popis nastavení zásuvného modulu msgid "Applications for Desktop Environment" msgstr "Aplikácie pre pracovné prostredie" msgid "Use Desktop Filter" msgstr "" # PB: Názov akcie msgid "Open With..." msgstr "Otvoriť pomocou…" # PB: Popis akcie msgid "Open with any application" msgstr "Otvorí pomocou ľubovoľnej aplikácie" # PB: Popis akcie msgid "Set default application to open this file type" msgstr "Nastaví predvolenú aplikáciu pre otvorenie tohto typu súboru" msgid "Reset Associations" msgstr "" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "" msgid "Allow browsing inside compressed archive files" msgstr "" #, python-format msgid "Content of %s" msgstr "" # PB: Názov zásuvného modulu msgid "Archive Manager" msgstr "Správca archívov" # PB: Popis zásuvného modulu msgid "Use Archive Manager actions" msgstr "Použitie akcií Správcu archívov" # PB: Popis nastavení zásuvného modulu msgid "Compressed archive type for 'Create Archive In'" msgstr "Typ komprimovaného archívu pre „Vytvoriť archív v“" # PB: Názov akcie msgid "Extract Here" msgstr "Rozbaliť sem" # PB: Popis akcie msgid "Extract compressed archive" msgstr "Rozbalí komprimovaný archív" # PB: Názov akcie msgid "Create Archive" msgstr "Vytvoriť archív" # PB: Popis akcie msgid "Create a compressed archive from folder" msgstr "Vytvorí komprimovaný archív z priečinka" # PB: Názov akcie msgid "Create Archive In..." msgstr "Vytvoriť archív v…" #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Archív" msgid "Audacious" msgstr "" msgid "Control Audacious playback and playlist" msgstr "" msgid "Include songs in top level" msgstr "" msgid "Enqueue" msgstr "" msgid "Add track to the Audacious play queue" msgstr "" msgid "Dequeue" msgstr "" msgid "Remove track from the Audacious play queue" msgstr "" msgid "Play" msgstr "" msgid "Jump to track in Audacious" msgstr "" msgid "Resume playback in Audacious" msgstr "" msgid "Pause" msgstr "" msgid "Pause playback in Audacious" msgstr "" msgid "Next" msgstr "" msgid "Jump to next track in Audacious" msgstr "" msgid "Previous" msgstr "" msgid "Jump to previous track in Audacious" msgstr "" msgid "Clear Queue" msgstr "" msgid "Clear the Audacious play queue" msgstr "" msgid "Shuffle" msgstr "" msgid "Toggle shuffle in Audacious" msgstr "" msgid "Repeat" msgstr "" msgid "Toggle repeat in Audacious" msgstr "" msgid "Show Playing" msgstr "" msgid "Tell which song is currently playing" msgstr "" msgid "Playlist" msgstr "" # PB: Názov zásuvného modulu msgid "Calculator" msgstr "Kalkulačka" msgid "Calculate mathematical expressions" msgstr "" # PB: Názov akcie msgid "Calculate" msgstr "Vypočítať" # PB: Názov zásuvného modulu msgid "Clipboards" msgstr "Schránky" # PB: Popis zásuvného modulu msgid "Recent clipboards and clipboard proxy objects" msgstr "Nedávne objekty schránok a proxy schránky" # PB: Popis nastavení zásuvného modulu msgid "Number of recent clipboards to remember" msgstr "Koľko si zapamätať nedávnych schránok" # PB: Popis nastavení zásuvného modulu msgid "Include selected text in clipboard history" msgstr "Zahrnúť vybratý text v histórii schránky" # PB: Popis nastavení zásuvného modulu msgid "Copy selected text to primary clipboard" msgstr "Kopírovať vybraný text do hlavnej schránky" # PB: Názov akcie msgid "Selected Text" msgstr "Vybraný text" # PB: Popis akcie #, fuzzy, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Schránka s %(num)d riadkami „%(desc)s“" msgstr[1] "Schránka „%(desc)s“" msgstr[2] "Schránka s %(num)d riadkami „%(desc)s“" # PB: Názov akcie msgid "Clipboard Text" msgstr "Text schránky" # PB: Názov akcie msgid "Clipboard File" msgstr "Súbor schránky" # PB: Názov akcie msgid "Clipboard Files" msgstr "Súbory schránky" # PB: Názov akcie msgid "Clear" msgstr "Vymazať" # PB: Popis akcie msgid "Remove all recent clipboards" msgstr "Odstráni všetky nedávne položky zo schránky" # PB: Názov zásuvného modulu a názov akcie msgid "Shell Commands" msgstr "" # PB: Popis zásuvného modulu #, fuzzy, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Umožňuje spustenie programov na príkazovom riadku. Akcie označené symbolom " "%s sú spustené v podshelli." # PB: Názov akcie msgid "Run (Get Output)" msgstr "Spustiť (získať výstup)" # PB: Popis akcie msgid "Run program and return its output" msgstr "Spustí program a vráti jeho výstup" # PB: Názov akcie #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command #, fuzzy msgid "Pass to Command..." msgstr "Odovzdať príkazu…" # PB: Popis akcie msgid "Run program with object as an additional parameter" msgstr "Spustí program s objektom ako doplňujúcim parametrom" # PB: Názov akcie #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "Zapísať do príkazu…" # PB: Popis akcie msgid "Run program and supply text on the standard input" msgstr "Spustí program a text zadá na štandardný vstup" # PB: Názov akcie #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "Filtrovať cez príkaz…" # PB: Popis akcie msgid "Run command-line programs" msgstr "Spustí program na príkazovom riadku" msgid "GTK+" msgstr "GTK+" msgid "GNOME Terminal" msgstr "GNOME Terminál" msgid "XFCE Terminal" msgstr "Terminál Xfce" msgid "LXTerminal" msgstr "LXTerminal" msgid "X Terminal" msgstr "X Terminál" msgid "Urxvt" msgstr "Urxvt" #  PM: predpokladám že je to názov programu, ale nie je tento názov v tom danom programe lokalizovaný, skús to preveriť #, fuzzy msgid "Konsole" msgstr "Konsole" # PB: Názov akcie msgid "Save As..." msgstr "Uložiť ako…" # PB: Popis akcie #, fuzzy msgid "Restart Kupfer" msgstr "Ukončí aplikáciu Kupfer" # PB: Názov akcie msgid "Quit" msgstr "Ukončiť" # PB: Popis akcie msgid "Quit Kupfer" msgstr "Ukončí aplikáciu Kupfer" # PB: Názov akcie msgid "About Kupfer" msgstr "O aplikácii Kupfer" # PB: Popis akcie msgid "Show information about Kupfer authors and license" msgstr "Zobrazí informácie o autoroch aplikácie Kupfer a licenciu" # PB: Názov akcie msgid "Kupfer Help" msgstr "Pomocník aplikácie Kupfer" # PB: Popis akcie msgid "Get help with Kupfer" msgstr "Zobrazí pomocníka aplikácie Kupfer" # PB: Popis akcie msgid "Show preferences window for Kupfer" msgstr "Zobrazí okno s nastaveniami aplikácie Kupfer" # PB: Názov akcie msgid "Search Contents" msgstr "Prehľadať obsah" # PB: Popis akcie msgid "Search inside this catalog" msgstr "" # PB: Názov akcie msgid "Copy" msgstr "" # PB: Popis akcie msgid "Copy to clipboard" msgstr "" # PB: Názov akcie msgid "Rescan" msgstr "" # PB: Popis akcie msgid "Force reindex of this source" msgstr "" msgid "Last Command" msgstr "" msgid "Internal Kupfer Objects" msgstr "" msgid "Last Result" msgstr "" msgid "Command Results" msgstr "" msgid "Custom Terminal" msgstr "" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Príkaz" msgid "Execute flag" msgstr "" msgid "Default Email Client" msgstr "" msgid "Compose email using the system's default mailto: handler" msgstr "" # pb: Akcelerátor #, fuzzy msgid "Compose Email To" msgstr "Zostaviť príkaz" msgid "Dictionary" msgstr "" # PB: Popis zásuvného modulu a akcie msgid "Look up word in dictionary" msgstr "" # PB: Názov akcie msgid "Look Up" msgstr "" # PB: Názov zásuvného modulu msgid "Documents" msgstr "" # PB: Popis zásuvného modulu msgid "Recently used documents and bookmarked folders" msgstr "" # PB: Popis nastavení zásuvného modulu msgid "Max recent document days" msgstr "" # PB: Názov zdroja msgid "Recent Items" msgstr "" # PB: Popis zdroja msgid "Recently used documents" msgstr "" # PB: Názov zdroja #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "" # PB: Popis zdroja #, python-format msgid "Recently used documents for %s" msgstr "" # PB: Názov zdroja msgid "Places" msgstr "" # PB: Popis zdroja msgid "Bookmarked folders" msgstr "" msgid "DuckDuckGo Search" msgstr "" msgid "Search the web securely with DuckDuckGo" msgstr "" # PB: Názov zásuvného modulu a zdroja msgid "Favorites" msgstr "" # PB: Popis zásuvného modulu msgid "Mark commonly used items and store objects for later use" msgstr "" # PB: Popis zdroja msgid "Shelf of \"Favorite\" items" msgstr "" # PB: Názov akcie msgid "Add to Favorites" msgstr "" # PB: Popis akcie msgid "Add item to favorites shelf" msgstr "" # PB: Názov akcie msgid "Remove from Favorites" msgstr "" # PB: Popis akcie msgid "Remove item from favorites shelf" msgstr "" # PB: Názov zásuvného modulu msgid "File Actions" msgstr "" # PB: Popis zásuvného modulu msgid "More file actions" msgstr "" # PB: Názov akcie msgid "Move To..." msgstr "" # PB: Popis akcie msgid "Move file to new location" msgstr "" # PB: Názov zdroja a akcie msgid "Rename To..." msgstr "" # PB: Názov akcie msgid "Copy To..." msgstr "" # PB: Popis akcie msgid "Copy file to a chosen location" msgstr "" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "" msgid "Tools to work with commands as objects" msgstr "" msgid "Select in Kupfer" msgstr "" #, python-format msgid "Result of %s (%s)" msgstr "" msgid "Run (Take Result)" msgstr "" msgid "Take the command result as a proxy object" msgstr "" msgid "Run (Discard Result)" msgstr "" msgid "Image Tools" msgstr "" msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "" msgid "Scale..." msgstr "" msgid "Scale image to fit inside given pixel measure(s)" msgstr "" msgid "Rotate Clockwise" msgstr "" msgid "Rotate Counter-Clockwise" msgstr "" msgid "Autorotate" msgstr "" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "" msgid "Kupfer Plugins" msgstr "" msgid "Access Kupfer's plugin list in Kupfer" msgstr "" msgid "Show Information" msgstr "" msgid "Show Source Code" msgstr "" msgid "enabled" msgstr "" msgid "disabled" msgstr "vypnutý" msgid "Notes" msgstr "" msgid "Gnote or Tomboy notes" msgstr "" msgid "Work with application" msgstr "" msgid "Open with notes application" msgstr "" msgid "Append to Note..." msgstr "" msgid "Add text to existing note" msgstr "" msgid "Create Note" msgstr "" msgid "Create a new note from this text" msgstr "" msgid "Get Note Search Results..." msgstr "" msgid "Show search results for this query" msgstr "" #, python-format msgid "today, %s" msgstr "" #, python-format msgid "yesterday, %s" msgstr "" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "" msgid "Quicksilver Icons" msgstr "" msgid "Quick Image Viewer" msgstr "" msgid "View Image" msgstr "" msgid "GNU Screen" msgstr "" msgid "Active GNU Screen sessions" msgstr "" msgid "Attached" msgstr "" msgid "Detached" msgstr "" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "" msgid "Screen Sessions" msgstr "" msgid "Attach" msgstr "" msgid "Send Keys" msgstr "" msgid "Send synthetic keyboard events using xautomation" msgstr "" msgid "Paste to Foreground Window" msgstr "" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "" msgid "Send keys to foreground window" msgstr "" msgid "Type Text" msgstr "" msgid "Type the text to foreground window" msgstr "" msgid "GNOME Session Management" msgstr "" msgid "Special items and actions for GNOME environment" msgstr "" msgid "Log Out..." msgstr "" msgid "Log out or change user" msgstr "" msgid "Shut Down..." msgstr "" msgid "Shut down, restart or suspend computer" msgstr "" msgid "Lock Screen" msgstr "" msgid "Enable screensaver and lock" msgstr "" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "" msgid "Special items and actions for XFCE environment" msgstr "" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "" msgid "SSH host" msgstr "" msgid "Connect" msgstr "" msgid "Connect to SSH host" msgstr "" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "" msgid "No D-Bus connection to desktop session" msgstr "" msgid "GNOME Keyring" msgstr "" msgid "KWallet" msgstr "" msgid "Unencrypted File" msgstr "" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "Príkaz v „%s“ nie je dostupný" msgid "Document Templates" msgstr "" msgid "Create new documents from your templates" msgstr "" #, python-format msgid "%s template" msgstr "" msgid "Empty File" msgstr "" msgid "New Folder" msgstr "" msgid "Create New Document..." msgstr "" msgid "Create a new document from template" msgstr "" msgid "Create Document In..." msgstr "" msgid "Textfiles" msgstr "" msgid "Append To..." msgstr "" msgid "Append..." msgstr "" msgid "Write To..." msgstr "" msgid "Get Text Contents" msgstr "" msgid "Thunar" msgstr "" msgid "File manager Thunar actions" msgstr "" msgid "Select in File Manager" msgstr "" msgid "Show Properties" msgstr "" msgid "Show information about file in file manager" msgstr "" msgid "Send To..." msgstr "" msgid "Symlink In..." msgstr "" msgid "Create a symlink to file in a chosen location" msgstr "" msgid "Empty Trash" msgstr "" msgid "Thunar Send To Objects" msgstr "" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "" msgid "Compose New Email" msgstr "" msgid "Compose a new message in Thunderbird" msgstr "" msgid "Attach in Email To..." msgstr "" # pb: Akcelerátor #, fuzzy msgid "Compose Email With" msgstr "Zostaviť príkaz" msgid "Compose a new message using the text as body" msgstr "" msgid "Thunderbird Address Book" msgstr "" msgid "Contacts from Thunderbird Address Book" msgstr "" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "" msgid "Show running tasks and allow sending signals to them" msgstr "" msgid "Sort Order" msgstr "" msgid "Commandline" msgstr "" msgid "CPU usage (descending)" msgstr "" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "" msgid "Send Signal..." msgstr "" msgid "Signals" msgstr "" msgid "Running Tasks" msgstr "" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "" msgid "Running tasks for current user" msgstr "" msgid "Trash" msgstr "" msgid "Access trash contents" msgstr "" msgid "Move to Trash" msgstr "" msgid "Move this file to trash" msgstr "" msgid "Restore" msgstr "" msgid "Move file back to original location" msgstr "" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "" msgstr[1] "" msgid "Triggers" msgstr "" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" msgid "Add Trigger..." msgstr "" msgid "Remove Trigger" msgstr "" msgid "URL Actions" msgstr "" msgid "Download and Open" msgstr "" msgid "Download To..." msgstr "" msgid "Download URL to a chosen location" msgstr "" msgid "Wikipedia" msgstr "" msgid "Search in Wikipedia" msgstr "" msgid "Wikipedia language" msgstr "" #. TRANS: Default wikipedia language code msgid "en" msgstr "" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "" msgid "Window List" msgstr "" msgid "All windows on all workspaces" msgstr "" msgid "Activate" msgstr "" msgid "Shade" msgstr "" msgid "Unshade" msgstr "" msgid "Minimize" msgstr "" msgid "Unminimize" msgstr "" msgid "Maximize" msgstr "" msgid "Unmaximize" msgstr "" msgid "Maximize Vertically" msgstr "" msgid "Unmaximize Vertically" msgstr "" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "" msgid "Frontmost Window" msgstr "" msgid "Next Window" msgstr "" msgid "Jump to this window's workspace and focus" msgstr "" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "" msgstr[1] "" msgid "Active workspace" msgstr "" msgid "Jump to this workspace" msgstr "" msgid "Workspaces" msgstr "" msgid "Volumes and Disks" msgstr "" msgid "Mounted volumes and disks" msgstr "" #, python-format msgid "Volume mounted at %s" msgstr "" msgid "Unmount" msgstr "" msgid "Unmount this volume" msgstr "" msgid "Eject" msgstr "" msgid "Unmount and eject this media" msgstr "" msgid "Show Text" msgstr "" msgid "Display text in a window" msgstr "" msgid "Large Type" msgstr "" msgid "Show Notification" msgstr "" msgid "Tracker" msgstr "" msgid "Tracker desktop search integration" msgstr "" msgid "Search in Tracker" msgstr "" msgid "Open Tracker Search Tool and search for this term" msgstr "" msgid "Get Tracker Results..." msgstr "" msgid "Show Tracker results for query" msgstr "" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "" msgid "Search filesystem using locate" msgstr "" msgid "Ignore case distinctions when searching files" msgstr "" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "" msgid "Index of Firefox bookmarks" msgstr "" msgid "Firefox Keywords" msgstr "" msgid "Search the web with Firefox keywords" msgstr "" # PB: Názov akcie #, fuzzy msgid "Search With..." msgstr "Otvoriť pomocou…" msgid "Search For..." msgstr "" # PB: Názov akcie #, fuzzy msgid "Search Terms" msgstr "Prehľadať obsah" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" # PB: Chybové hlásenie #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Použite prosím „%s“" msgid "Resume playback" msgstr "" #. TRANS: %s is a media player name #, python-format msgid "Next (%s)" msgstr "" msgid "Skip to next track" msgstr "" #. TRANS: %s is a media player name #, python-format msgid "Previous (%s)" msgstr "" msgid "Skip to previous track" msgstr "" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "" msgid "Access to Pidgin Contacts" msgstr "" #, fuzzy msgid "Show offline contacts" msgstr "Zobraziť hlavné rozhranie" #, fuzzy msgid "Open Chat" msgstr "Otvoriť" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Send Message..." msgstr "" #, fuzzy msgid "Available" msgstr "Dostupné zásuvné moduly:" msgid "Away" msgstr "" msgid "Pidgin Contacts" msgstr "" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "" msgid "Create short aliases of long URLs" msgstr "" msgid "Error" msgstr "" # PB: Názov akcie #, fuzzy msgid "Shorten With..." msgstr "Otvoriť pomocou…" msgid "Services" msgstr "" msgid "Rhythmbox" msgstr "" msgid "Play and enqueue tracks and browse the music library" msgstr "" msgid "Include artists in top level" msgstr "" msgid "Include albums in top level" msgstr "" msgid "Play tracks in Rhythmbox" msgstr "" msgid "Add tracks to the play queue" msgstr "" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "" msgid "Albums" msgstr "" msgid "Music albums in Rhythmbox Library" msgstr "" msgid "Artists" msgstr "" msgid "Music artists in Rhythmbox Library" msgstr "" msgid "Songs" msgstr "" msgid "Songs in Rhythmbox library" msgstr "" msgid "Getting Things GNOME" msgstr "" msgid "Browse and create new tasks in GTG" msgstr "" #, python-format msgid "due: %s" msgstr "" #, python-format msgid "start: %s" msgstr "" #, python-format msgid "tags: %s" msgstr "" msgid "Open task in Getting Things GNOME!" msgstr "" msgid "Delete" msgstr "" msgid "Permanently remove this task" msgstr "" msgid "Mark Done" msgstr "" msgid "Mark this task as done" msgstr "" msgid "Dismiss" msgstr "" msgid "Mark this task as not to be done anymore" msgstr "" msgid "Create Task" msgstr "" msgid "Create new task in Getting Things GNOME" msgstr "" msgid "Devhelp" msgstr "" msgid "Search in Devhelp" msgstr "" msgid "Empathy" msgstr "" msgid "Access to Empathy Contacts" msgstr "" msgid "Busy" msgstr "" #, fuzzy msgid "Not Available" msgstr "Dostupné zásuvné moduly:" msgid "Invisible" msgstr "" msgid "Offline" msgstr "" msgid "Change Global Status To..." msgstr "" msgid "Empathy Contacts" msgstr "" msgid "Empathy Account Status" msgstr "" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Alternatívna aktivácia" # pb: Akcelerátor #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "" # pb: Akcelerátor #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Zostaviť príkaz" # pb: Akcelerátor msgid "Mark Default Action" msgstr "Označiť ako predvolenú akciu" # pb: Akcelerátor msgid "Forget Object" msgstr "Zabudnúť objekt" # pb: Akcelerátor msgid "Reset All" msgstr "" # pb: Akcelerátor msgid "Select Quit" msgstr "" # pb: Akcelerátor msgid "Select Selected File" msgstr "Zvoliť vybraný súbor" # pb: Akcelerátor msgid "Select Selected Text" msgstr "Zvoliť vybraný text" # pb: Akcelerátor msgid "Show Help" msgstr "Zobraziť pomocníka" # pb: Akcelerátor msgid "Show Preferences" msgstr "Zobraziť nastavenia" # pb: Akcelerátor msgid "Switch to First Pane" msgstr "Prepnúť na prvý panel" # pb: Akcelerátor msgid "Toggle Text Mode" msgstr "Prepnúť textový režim" # PM: ako to bude vyzerať, uveď sem prosím nejaké príklady #, fuzzy, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Neboli nájdené žiadne výsledky v %(src)s pre dopyt „%(query)s“" #  PM: skôr žiadne zhody, alebo nič sa nenašlo #, fuzzy msgid "No matches" msgstr "Žiadne výsledky" #  PM: skôr žiadne zhody, alebo nič sa nenašlo #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Žiadne výsledky" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Nastaviť akciu „%(action)s“ ako predvolenú pre „%(object)s“" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "Zabudnúť informácie o „%s“" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Zobraziť hlavné rozhranie" msgid "Show with Selection" msgstr "Zobraziť s výberom" #. TRANS: Plugin info fields msgid "Description" msgstr "Popis" msgid "Author" msgstr "Autor" msgid "Version" msgstr "Verzia" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Je potrebný modul Python „%s“" msgid "Plugin could not be read due to an error:" msgstr "Zásuvný modul nemohol byť načítaný kvôli chybe:" msgid "Content of" msgstr "Obsah" #. TRANS: Plugin contents header msgid "Sources" msgstr "Zdroje" #. TRANS: Plugin contents header msgid "Actions" msgstr "Akcie" #, python-format msgid "Using encrypted password storage: %s" msgstr "Použitie úložiska zašifrovaného heslom: %s" #, python-format msgid "Using password storage: %s" msgstr "Použitie úložiska s heslom: %s" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Nastavenie" # button msgid "Set username and password" msgstr "Nastaviť používateľské meno a heslo" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Výber priečinka" msgid "Reset all shortcuts to default values?" msgstr "" msgid "Shortcut" msgstr "Klávesová skratka" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "Pavol Babinčák " msgid "A free software (GPLv3+) launcher" msgstr "Spúšťač vydaný pod slobodnou licenciou (GPLv3+)" #, fuzzy msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Tento program je slobodný softvér. Môžete ho ďalej šíriť a/alebo upravovať " "podľa ustanovení licencie GNU General Public Licence (Všeobecná " "zverejňovacia licencia GNU), vydávanej organizáciou Free Software " "Foundation, a to buď podľa 3. verzie tejto licencie, alebo (podľa vášho " "uváženia) ktorejkoľvek neskoršej verzie.\n" "\n" "Tento program je rozširovaný v nádeji, že bude užitočný, avšak BEZ " "AKEJKOĽVEK ZÁRUKY. Neposkytujú sa ani odvodené záruky OBCHODOVATEĽNOSTI " "alebo VHODNOSTI PRE URČITÝ ÚČEL. Ďalšie podrobnosti hľadajte v licencii GNU " "General Public License.\n" "\n" "Kópiu licencie GNU General Public License ste mali dostať spolu s týmto " "programom. Ak sa tak nestalo, navštívte stránku http://www.gnu.org/" "licenses/\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Nepodarilo sa nájsť spustenú aplikáciu Kupfer" #  čo je miesto %s: #, fuzzy #~ msgid "Type to search %s" #~ msgstr "Píšte pre vyhľadávanie %s" #~ msgid "No action" #~ msgstr "Žiadna akcia" # PB: Popis zásuvného modulu #~ msgid "Calculate expressions starting with '='" #~ msgstr "Vypočíta výrazy začínajúce „=“" kupfer-328/po/sl.po000066400000000000000000001605701500175051100142640ustar00rootroot00000000000000# Slovenian translations for kupfer. # Copyright (C) 2006 Free Software Foundation, Inc. # This file is distributed under the same license as the kupfer package. # # Andrej Žnidaršič , 2009 - 2010. # msgid "" msgstr "" "Project-Id-Version: kupfer master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2012-07-10 09:04+0100\n" "Last-Translator: Matej Urbančič \n" "Language-Team: Slovenian GNOME Translation Team \n" "Language: \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%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n" "%100==4 ? 3 : 0);\n" "X-Poedit-Country: SLOVENIA\n" "X-Poedit-Language: Slovenian\n" "X-Poedit-SourceCharset: utf-8\n" msgid "User credentials" msgstr "Uporabniška poverila" msgid "_User:" msgstr "_Uporabnik:" msgid "_Password:" msgstr "_Geslo:" msgid "_Change" msgstr "_Spremeni" msgid "Set Keyboard Shortcut" msgstr "Nastavi tipkovno bližnjico" msgid "Please press desired key combination" msgstr "Pritisnite želeno kombinacijo tipk" msgid "Keybinding could not be bound" msgstr "Tipkovna bližnjica ne more biti vezana" msgid "Kupfer Preferences" msgstr "Možnosti Kupfer" msgid "Start automatically on login" msgstr "Samodejno zaženi ob prijavi" msgid "Start" msgstr "Zaženi" msgid "Show icon in notification area" msgstr "Pokaži ikono v obvestilnem področju" msgid "Icon set:" msgstr "Zbirka ikon:" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" msgid "Terminal emulator:" msgstr "Posnemovalnik terminala:" msgid "Desktop Environment" msgstr "Namizno okolje" msgid "General" msgstr "Splošno" msgid "Global Keyboard Shortcuts" msgstr "Splošne tipkovne bližnjice" msgid "Reset" msgstr "Ponastavi" msgid "Browser Keyboard Shortcuts" msgstr "Tipkovne bližnjice brskalnika" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "Uporabi ukaze enega udarca tipk (presledek, /, pika, vejica, itn.)" msgid "Keyboard" msgstr "Tipkovnica" msgid "Plugins" msgstr "Vstavki" msgid "Inclusion in Top Level Searches" msgstr "Vključitev v iskanja vrhnje ravni" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "Označeni viri imajo svoje predmete vključene v iskanjih vrhnje ravni.\n" "Neoznačena vsebina vira je na voljo le z iskanjem njenega podkataloga." msgid "Indexed Folders" msgstr "Mape, uporabljene za pripravo kazala" msgid "Folders whose files are always available in the catalog." msgstr "Mape katerih datoteke so vedno vidne v katalogu." msgid "Catalog" msgstr "Katalog" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Zaganjalnik programov" msgid "Convenient command and access tool for applications and documents" msgstr "" "Prikladno orodje za izvajanje ukazov in dostopa do programov in dokumentov" msgid "Execute in Kupfer" msgstr "Izvedi v Kupferju" msgid "Saved Kupfer Command" msgstr "Shranjen ukaz Kupfer" #, python-format msgid "Could not to carry out '%s'" msgstr "Ni mogoče izvesti '%s'" #, python-format msgid "\"%s\" produced a result" msgstr "\"%s\" je proizvedel rezultat" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Ni dovoljenja za zagon \"%s\" (ni izvedljivo)" #, python-format msgid "Command in \"%s\" is not available" msgstr "Ukaz v \"%s\" ni na voljo" #, python-format msgid "Keyboard relay is active for display %s" msgstr "Rele tipkovnice je dejaven za zaslon %s" msgid "do not present main interface on launch" msgstr "ob zagonu ne pokaži glavnega vmesnika" msgid "list available plugins" msgstr "razvrsti dostopne vstavke" msgid "enable debug info" msgstr "omogoči podatke razhroščevanja" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "poženi vstavek pomočnika" msgid "show usage help" msgstr "pokaži uporabo pomoči" msgid "show version information" msgstr "pokaži podrobnosti različice" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Uporaba: kupfer [MOŽNOSTI | DATOTEKA ...]" msgid "Available plugins:" msgstr "Razpoložljivi vstavki:" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "Vtipkajte za iskanje" #, python-format msgid "%s is empty" msgstr "%s je prazen" msgid "Text" msgstr "Besedilo" msgid "Run after Delay..." msgstr "Zaženi po zamiku ..." msgid "Perform command after a specified time interval" msgstr "Izvede ukaz po določenem časovnem zamiku" msgid "Multiple Objects" msgstr "Več predmetov" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s predmetov" msgstr[1] "%s predmet" msgstr[2] "%s predmeta" msgstr[3] "%s predmeti" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "neznano" msgid "Aim" msgstr "AIM" msgid "Google Talk" msgstr "Google Talk" msgid "ICQ" msgstr "ICQ" msgid "MSN" msgstr "MSN" msgid "QQ" msgstr "QQ" msgid "Yahoo" msgstr "Yahoo" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "%s ne podpira tega opravila" msgid "Can not be used with multiple objects" msgstr "Ni mogoče uporabiti z več predmeti" msgid "Open" msgstr "Odpri" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Ni privzetega programa za %(file)s (%(type)s)" #, python-format msgid "Please use \"%s\"" msgstr "Uporabite \"%s\"" msgid "Set Default Application..." msgstr "Nastavi privzeti program ..." msgid "Open with default application" msgstr "Odpri s privzetim programom" msgid "Reveal" msgstr "Razkrij" msgid "Open parent folder" msgstr "Odpri nadrejeno mapo" msgid "Open Terminal Here" msgstr "Odpri terminal tukaj" msgid "Open this location in a terminal" msgstr "Odpri to mesto v terminalu" msgid "Run in Terminal" msgstr "Zaženi v terminalu" msgid "Run (Execute)" msgstr "Zaženi (izvedi)" msgid "Run this program in a Terminal" msgstr "Zaženi ta program v teminalu" msgid "Run this program" msgstr "Zaženi ta program" msgid "Go To" msgstr "Pojdi na" msgid "Open URL" msgstr "Odpri URL" msgid "Open URL with default viewer" msgstr "Odpri URL s privzetim pregledovalnikom" msgid "Launch" msgstr "Zaženi" msgid "Show application window" msgstr "Pokaže okno programa" msgid "Launch application" msgstr "Zaženi program" msgid "Launch Again" msgstr "Zaženi še enkrat" msgid "Launch another instance of this application" msgstr "Zažene še en primerek tega programa" msgid "Close" msgstr "Zapri" msgid "Attempt to close all application windows" msgstr "Poskusi zapreti vsa okna programa" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Zaženi" msgid "Perform command" msgstr "Izvede ukaz" msgid "(Empty Text)" msgstr "(Prazno besedilo)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "(%(num)d vrstic) \"%(text)s\"" msgstr[1] "(%(num)d vrstica) \"%(text)s\"" msgstr[2] "(%(num)d vrstici) \"%(text)s\"" msgstr[3] "(%(num)d vrstice) \"%(text)s\"" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s in ostali" #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Rekurziven vir %(dir)s, (%(levels)d ravni)" #, python-format msgid "Directory source %s" msgstr "Vir slovarja %s" msgid "Home Folder" msgstr "Domača mapa" msgid "Catalog Index" msgstr "Kazalo kataloga" msgid "An index of all available sources" msgstr "Kazalo vseh razpoložljivih virov" msgid "Root catalog" msgstr "Korenski katalog" msgid "Please Configure Plugin" msgstr "Nastavitve vstavek" #, python-format msgid "Plugin %s is not configured" msgstr "Vstavek %s ni nastavljen" #, python-format msgid "Invalid user credentials for %s" msgstr "Neveljavna uporabniška poverila za %s" msgid "Applications" msgstr "Programi" msgid "All applications and preferences" msgstr "Vsi programi in možnosti" msgid "Applications for Desktop Environment" msgstr "Programi za namizno okolje" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "Odpri z ..." msgid "Open with any application" msgstr "Odpri s katerimkoli programom" msgid "Set default application to open this file type" msgstr "Nastavi privzet program za odpiranje te vrste datotek" #, fuzzy msgid "Reset Associations" msgstr "Dejanja URL-ja" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "Globoki arhivi" msgid "Allow browsing inside compressed archive files" msgstr "Dovoli brskanje v stisnjenih arhivskih datotekah" #, python-format msgid "Content of %s" msgstr "Vsebina %s" msgid "Archive Manager" msgstr "Upravljalnik arhivov" msgid "Use Archive Manager actions" msgstr "Uporabi dejanja upravljalnika arhivov" msgid "Compressed archive type for 'Create Archive In'" msgstr "Vrsta stisnjenega arhiva za 'Ustvari arhiv v'" msgid "Extract Here" msgstr "Razširi sem" msgid "Extract compressed archive" msgstr "Razširi stisnjen arhiv" msgid "Create Archive" msgstr "Ustvari arhiv" msgid "Create a compressed archive from folder" msgstr "Ustvari stisnjen arhiv iz mape" msgid "Create Archive In..." msgstr "Ustvari arhiv v ..." #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Arhiv" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "Nadzira predvajanje in seznam predvajanja Audacious" msgid "Include songs in top level" msgstr "Vključi skladbe v zgornji ravni" msgid "Enqueue" msgstr "Uvrsti" msgid "Add track to the Audacious play queue" msgstr "Doda skladbo čakalni vrsti predvajanja Audaciousa" msgid "Dequeue" msgstr "Odstrani iz vrste" msgid "Remove track from the Audacious play queue" msgstr "Odstrani skladbo iz čakalne vrste predvajanja Audaciousa" msgid "Play" msgstr "Predvajaj" msgid "Jump to track in Audacious" msgstr "Skoči na skladbo v Audaciousu" msgid "Resume playback in Audacious" msgstr "Nadaljevanje predvajanja v Audaciousu" msgid "Pause" msgstr "Premor" msgid "Pause playback in Audacious" msgstr "Premor predvajanja v Audaciousu" msgid "Next" msgstr "Naslednja" msgid "Jump to next track in Audacious" msgstr "Skoči na naslednjo skladbo v Audaciousu" msgid "Previous" msgstr "Predhodna" msgid "Jump to previous track in Audacious" msgstr "Skoči na predhodno skladbo v Audaciousu" msgid "Clear Queue" msgstr "Počisti vrsto" msgid "Clear the Audacious play queue" msgstr "Počisti čakalno vrsto Audaciousa" msgid "Shuffle" msgstr "Mešaj" msgid "Toggle shuffle in Audacious" msgstr "Preklopi mešanje v Audaciousu" msgid "Repeat" msgstr "Ponovi" msgid "Toggle repeat in Audacious" msgstr "Preklopi ponavljanje v Audaciousu" msgid "Show Playing" msgstr "Pokaži predvajajočo" msgid "Tell which song is currently playing" msgstr "Pove katera skladba se trenutno predvaja" msgid "Playlist" msgstr "Seznam predvajanja" msgid "Calculator" msgstr "Računalo" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "Izračunaj" msgid "Clipboards" msgstr "Odložišča" msgid "Recent clipboards and clipboard proxy objects" msgstr "Nedavna odložišča in predmeti posredniškega strežnika odložišča" msgid "Number of recent clipboards to remember" msgstr "Število nedavnih odložišč za pomnjenje" msgid "Include selected text in clipboard history" msgstr "V zgodovino odložišča vključi izbrano besedilo" msgid "Copy selected text to primary clipboard" msgstr "Kopira izbrano besedilo v osnovno odložišče" msgid "Selected Text" msgstr "Izbrano besedilo" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Odložišče z %(num)d vrsticami \"%(desc)s\"" msgstr[1] "Odložišče z %(num)d vrstico \"%(desc)s\"" msgstr[2] "Odložišče z %(num)d vrsticama \"%(desc)s\"" msgstr[3] "Odložišče z %(num)d vrsticami \"%(desc)s\"" msgid "Clipboard Text" msgstr "Besedila odložišča" msgid "Clipboard File" msgstr "Datoteka odložišča" msgid "Clipboard Files" msgstr "Datoteke odložišča" msgid "Clear" msgstr "Počisti" msgid "Remove all recent clipboards" msgstr "Odstrani vsa nedavna odložišča" msgid "Shell Commands" msgstr "Ukazi lupine" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Požene programe ukazne vrstice. Dejanja označena s simbolom %s tečejo v " "podlupini." msgid "Run (Get Output)" msgstr "Poženi (Dobi izhod)" msgid "Run program and return its output" msgstr "Zažene program in vrne njegov izhod" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "Podaj ukazu ..." msgid "Run program with object as an additional parameter" msgstr "Zažene program s predmetom kot dodanim parametrom" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "Zapiši v ukaz ..." msgid "Run program and supply text on the standard input" msgstr "Poženi program in dovedi besedilo na standardnem vhodu" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "Filtriraj skozi ukaz ..." msgid "Run command-line programs" msgstr "Poženi programe ukaze vrstice" msgid "GTK+" msgstr "GTK+" msgid "GNOME Terminal" msgstr "GNOME Terminal" msgid "XFCE Terminal" msgstr "XFCE Terminal" msgid "LXTerminal" msgstr "LXTerminal" msgid "X Terminal" msgstr "X Terminal" msgid "Urxvt" msgstr "Urxvt" msgid "Konsole" msgstr "Konzola" msgid "Save As..." msgstr "Shrani kot ..." #, fuzzy msgid "Restart Kupfer" msgstr "Ponovno zaženi storitev" msgid "Quit" msgstr "Končaj" msgid "Quit Kupfer" msgstr "Konča program Kupfer" msgid "About Kupfer" msgstr "O programu" msgid "Show information about Kupfer authors and license" msgstr "Pokaže podrobnosti o avtorjih in dovoljenju programa Kupfer" msgid "Kupfer Help" msgstr "Pomoč Kupfer" msgid "Get help with Kupfer" msgstr "Dobi pomoč s Kupferjem" msgid "Show preferences window for Kupfer" msgstr "Prikaz okna možnosti za Kupfer" msgid "Search Contents" msgstr "Vsebina iskanja" msgid "Search inside this catalog" msgstr "Poišči znotraj kataloga" msgid "Copy" msgstr "Kopiraj" msgid "Copy to clipboard" msgstr "Kopiraj v odložišče" msgid "Rescan" msgstr "Ponovno preišči" msgid "Force reindex of this source" msgstr "Vsili ponovno preiskovanje tega vira" msgid "Last Command" msgstr "Zadnji ukaz" msgid "Internal Kupfer Objects" msgstr "Notranji predmeti Kupfer" msgid "Last Result" msgstr "Zadnji rezultat" msgid "Command Results" msgstr "Rezultati ukaza" msgid "Custom Terminal" msgstr "Terminal po meri" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Ukaz" msgid "Execute flag" msgstr "Izvedi zastavico" msgid "Default Email Client" msgstr "Privzeti odjemalec elektronske pošte" msgid "Compose email using the system's default mailto: handler" msgstr "Sestavi elektronsko pošto s privzetim sistemskim mailto: ročnik" #, fuzzy msgid "Compose Email To" msgstr "Sestavi e-pošto" msgid "Dictionary" msgstr "Slovar" msgid "Look up word in dictionary" msgstr "Poišči besedo v slovarju" msgid "Look Up" msgstr "Poišči" msgid "Documents" msgstr "Dokumenti" msgid "Recently used documents and bookmarked folders" msgstr "Nedavno uporabljeni dokumenti in zaznamovane mape" # Sem kar malo podaljšal, ker se mi zdi da drugače ni smiselno... msgid "Max recent document days" msgstr "Največja starost nedavnih dokumentov v dnevih" msgid "Recent Items" msgstr "Nedavni predmeti" msgid "Recently used documents" msgstr "Nedavno uporabljeni dokumenti" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "%s dokumentov" #, python-format msgid "Recently used documents for %s" msgstr "Nedavno uporabljeni dokumenti za %s" msgid "Places" msgstr "Mesta" msgid "Bookmarked folders" msgstr "Zaznamovane mape" msgid "DuckDuckGo Search" msgstr "Iskanje DuckDuckGo" msgid "Search the web securely with DuckDuckGo" msgstr "Varno Iskanje po spletu z iskalnikom DuckDuckGo" msgid "Favorites" msgstr "Priljubljene" msgid "Mark commonly used items and store objects for later use" msgstr "" "Označi pogosto uporabljene predmete in shrani predmete za kasnejšo uporabo" msgid "Shelf of \"Favorite\" items" msgstr "Polica \"Priljubljenih\" predmetov" msgid "Add to Favorites" msgstr "Dodaj med priljubljene" msgid "Add item to favorites shelf" msgstr "Doda predmet na polico priljubljenih" msgid "Remove from Favorites" msgstr "Odstrani iz priljubljenih" msgid "Remove item from favorites shelf" msgstr "Odstrani predmete iz police priljubljenih" msgid "File Actions" msgstr "Dejanja datotek" msgid "More file actions" msgstr "Več dejanj datotek" msgid "Move To..." msgstr "Premakni v ..." msgid "Move file to new location" msgstr "Premakne datoteko na novo mesto" msgid "Rename To..." msgstr "Preimenuj v ..." msgid "Copy To..." msgstr "Kopiraj v ..." msgid "Copy file to a chosen location" msgstr "Kopiraj datoteko na izbrano mesto" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "Glob" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "Dejanja višjega reda" msgid "Tools to work with commands as objects" msgstr "Orodja za delo z ukazi kot s predmeti" msgid "Select in Kupfer" msgstr "Izberi v Kupferju" #, python-format msgid "Result of %s (%s)" msgstr "Rezultat %s (%s)" msgid "Run (Take Result)" msgstr "Poženi (vzemi rezultat)" msgid "Take the command result as a proxy object" msgstr "Prevzemi rezultat ukaza kot posredniški predmet" msgid "Run (Discard Result)" msgstr "Poženi (zavrzi rezultat)" msgid "Image Tools" msgstr "Orodja slike" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Orodja preoblikovanja slike" msgid "Scale..." msgstr "Prilagodi velikost ..." msgid "Scale image to fit inside given pixel measure(s)" msgstr "Prilagodi velikost znotraj danih meritev točk " msgid "Rotate Clockwise" msgstr "Zavrti desno" msgid "Rotate Counter-Clockwise" msgstr "Zavrti levo" msgid "Autorotate" msgstr "Samodejno vrtenje" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "Vrtenje JPEG (na mestu) glede na metapodatke EXIF" msgid "Kupfer Plugins" msgstr "Vstavki Kupfer" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Dostop do Kupferjevega seznama vstavkov v Kupferju" msgid "Show Information" msgstr "Pokaži podrobnosti" msgid "Show Source Code" msgstr "Prikaži izvorno kodo" msgid "enabled" msgstr "omogočeno" msgid "disabled" msgstr "onemogočeno" msgid "Notes" msgstr "Sporočilca" msgid "Gnote or Tomboy notes" msgstr "Gnote ali Tomboy sporočilca" msgid "Work with application" msgstr "Delo s programom" msgid "Open with notes application" msgstr "Odpri s programom sporočilc" msgid "Append to Note..." msgstr "Pripni sporočilcu ..." msgid "Add text to existing note" msgstr "Doda besedilo obstoječemu sporočilcu" msgid "Create Note" msgstr "Ustvari sporočilce" msgid "Create a new note from this text" msgstr "Ustvari novo sporočilce iz tega besedila" msgid "Get Note Search Results..." msgstr "Dobi rezultate iskanja sporočilc ..." msgid "Show search results for this query" msgstr "Pokaži rezultate iskanja za to poizvedbo" #, python-format msgid "today, %s" msgstr "danes, %s" #, python-format msgid "yesterday, %s" msgstr "včeraj, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Zadnjič posodobljeno %s" msgid "Quicksilver Icons" msgstr "Ikone Quicksilver" msgid "Quick Image Viewer" msgstr "Pregledovalnik slik Qucik" msgid "View Image" msgstr "Ogled slike" msgid "GNU Screen" msgstr "GNU zaslon" msgid "Active GNU Screen sessions" msgstr "Dejavne seje zaslona GNU" msgid "Attached" msgstr "Priloženo" msgid "Detached" msgstr "Odstranjeno" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "%(status)s seja (%(pid)s) ustvarjena ob %(time)s" msgid "Screen Sessions" msgstr "Zaslonske seje" msgid "Attach" msgstr "Priloži" msgid "Send Keys" msgstr "Pošlji ključe" msgid "Send synthetic keyboard events using xautomation" msgstr "Pošlji sintetične dogodke tipkovne z xautomation" msgid "Paste to Foreground Window" msgstr "Prilepi v okno v ospredju" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "Kopiraj na odložišče in pošlji Ctrl+V na okno v ospredju" msgid "Send keys to foreground window" msgstr "Pošljite tipke na okno v ospredju" msgid "Type Text" msgstr "Vpišite besedilo" msgid "Type the text to foreground window" msgstr "Vpišite besedilo v okno v ospredju" msgid "GNOME Session Management" msgstr "Upravljanje seje Gnome" msgid "Special items and actions for GNOME environment" msgstr "Posebni predmeti in dejanja za okolje Gnome" msgid "Log Out..." msgstr "Odjava ..." msgid "Log out or change user" msgstr "Odjava ali sprememba uporabnika" msgid "Shut Down..." msgstr "Izklop ..." msgid "Shut down, restart or suspend computer" msgstr "Izklop, ponoven zagon ali dajanje računalnika v mirovanje" msgid "Lock Screen" msgstr "Zakleni zaslon" msgid "Enable screensaver and lock" msgstr "Omogoči ohranjevalnik zaslona in zaklepanje" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "Upravljanje seje XFCE" msgid "Special items and actions for XFCE environment" msgstr "Posebni predmeti in dejanja za okolje XFCE" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "Gostitelji SSH" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "Doda gostitelje SSH najdene v ~/.ssh/config." msgid "SSH host" msgstr "Gostitelj SSH" msgid "Connect" msgstr "Poveži se" msgid "Connect to SSH host" msgstr "Poveži se z gostiteljem SSH" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "Gostitelji SSH kot so navedeni v ~/.ssh/config" msgid "No D-Bus connection to desktop session" msgstr "Ni povezave D-Bus s sejo namizja" msgid "GNOME Keyring" msgstr "Zbirka ključev GNOME" msgid "KWallet" msgstr "KWallet" msgid "Unencrypted File" msgstr "Nešifrirana datoteka" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "Ukaz v \"%s\" ni na voljo" msgid "Document Templates" msgstr "Predloge dokumenta" msgid "Create new documents from your templates" msgstr "Ustvari nove dokumente iz vaših predlog" #, python-format msgid "%s template" msgstr "predloga %s" msgid "Empty File" msgstr "Prazna datoteka" msgid "New Folder" msgstr "Nova mapa" msgid "Create New Document..." msgstr "Ustvari nov dokument ..." msgid "Create a new document from template" msgstr "Ustvari nov dokument iz predloge" msgid "Create Document In..." msgstr "Ustvari dokument v ..." msgid "Textfiles" msgstr "Besedilne datoteke" msgid "Append To..." msgstr "Pripni k ..." msgid "Append..." msgstr "Pripni ..." msgid "Write To..." msgstr "Zapiši na ..." msgid "Get Text Contents" msgstr "Dobi vsebino besedila" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "Dejanja upravljalnika datotek Thunar" msgid "Select in File Manager" msgstr "Izberi v upravljalniku datotek" msgid "Show Properties" msgstr "Pokaži lastnosti" msgid "Show information about file in file manager" msgstr "Pokaže podrobnosti o datoteki v upravljalniku datotek" msgid "Send To..." msgstr "Pošlji ..." msgid "Symlink In..." msgstr "Simbolna povezava do ..." msgid "Create a symlink to file in a chosen location" msgstr "Ustvari simbolno povezavo do datoteke na izbranem mestu" msgid "Empty Trash" msgstr "Izprazni smeti" msgid "Thunar Send To Objects" msgstr "Thunar pošlji predmetom" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Stiki in dejanja Thunderbird/Icedove" msgid "Compose New Email" msgstr "Sestavi novo pošto" msgid "Compose a new message in Thunderbird" msgstr "Sestavi novo sporočilo v Thunderbird" #, fuzzy msgid "Attach in Email To..." msgstr "Pošlji v e-pošti ..." #, fuzzy msgid "Compose Email With" msgstr "Sestavi e-pošto" #, fuzzy msgid "Compose a new message using the text as body" msgstr "Sestavi novo sporočilo v Thunderbird" msgid "Thunderbird Address Book" msgstr "Imenik Thunderbird" msgid "Contacts from Thunderbird Address Book" msgstr "Stiki iz imenika Thunderbird" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Top" msgid "Show running tasks and allow sending signals to them" msgstr "Prikaže opravila v teku in dovoli pošiljanje signalov k njim" msgid "Sort Order" msgstr "Vrstni red" msgid "Commandline" msgstr "Ukazna vrstica" msgid "CPU usage (descending)" msgstr "Uporaba CPE (naraščajoče)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Uporaba pomnilnika (padajoče)" msgid "Send Signal..." msgstr "Pošlji signal ..." msgid "Signals" msgstr "Signali" msgid "Running Tasks" msgstr "Opravila v teku" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid: %(pid)s cpe: %(cpu)g%% spomin: %(mem)g%% čas: %(time)s" msgid "Running tasks for current user" msgstr "Opravila v teku za trenutnega uporabnika" msgid "Trash" msgstr "Smeti" msgid "Access trash contents" msgstr "Dostop do vsebine smeti" msgid "Move to Trash" msgstr "Premakni v smeti" msgid "Move this file to trash" msgstr "Premakne datoteko v smeti" msgid "Restore" msgstr "Obnovi" msgid "Move file back to original location" msgstr "Premakne datoteke nazaj na izvirno mesto" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "Smeti so prazne" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "Smeti vsebujejo %(num)s datotek" msgstr[1] "Smeti vsebujejo %(num)s datoteko" msgstr[2] "Smeti vsebujejo %(num)s datoteki" msgstr[3] "Smeti vsebujejo %(num)s datoteke" msgid "Triggers" msgstr "Sprožilci" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Določanje splošnih tipkovnih bližnjic (sprožilcev) do predmetov ustvarjenih " "z 'Ukazom Ustvari'" msgid "Add Trigger..." msgstr "Dodaj sprožilec ..." msgid "Remove Trigger" msgstr "Odstrani sprožilec" msgid "URL Actions" msgstr "Dejanja URL-ja" msgid "Download and Open" msgstr "Prejmi in odpri" msgid "Download To..." msgstr "Prejmi v ..." msgid "Download URL to a chosen location" msgstr "Prejmi URL na izbrano mesto" msgid "Wikipedia" msgstr "Wikipedija" msgid "Search in Wikipedia" msgstr "Išči v wikipediji" msgid "Wikipedia language" msgstr "Jezik Wikipedije" #. TRANS: Default wikipedia language code msgid "en" msgstr "en" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Išče ta izraz v %s.wikipedia.org" msgid "Window List" msgstr "Seznam oken" msgid "All windows on all workspaces" msgstr "Vsa okna na vseh delovnih površinah" msgid "Activate" msgstr "Zaženi" msgid "Shade" msgstr "Zasenči" msgid "Unshade" msgstr "Brez senčenja" msgid "Minimize" msgstr "Skrči" msgid "Unminimize" msgstr "Povečaj" msgid "Maximize" msgstr "Razpni" msgid "Unmaximize" msgstr "Pomanjšaj razpeto" msgid "Maximize Vertically" msgstr "Razpni navpično" msgid "Unmaximize Vertically" msgstr "Pomanjšaj razpeto navpično" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Okno na %(wkspc)s" msgid "Frontmost Window" msgstr "Sprednje okno" msgid "Next Window" msgstr "Naslednje okno" msgid "Jump to this window's workspace and focus" msgstr "Skoči na delovno površino tega okna in izbere okno" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "%d oken" msgstr[1] "%d okno" msgstr[2] "%d okni" msgstr[3] "%d okna" msgid "Active workspace" msgstr "Dejavna delovna površina" msgid "Jump to this workspace" msgstr "Skoči na to delovno površino" msgid "Workspaces" msgstr "Delovne površine" msgid "Volumes and Disks" msgstr "Nosilci in diski" msgid "Mounted volumes and disks" msgstr "Priklopljeni nosilci in diski" #, python-format msgid "Volume mounted at %s" msgstr "Nosilec je priklopljen na %s" msgid "Unmount" msgstr "Odklopi" msgid "Unmount this volume" msgstr "Odklopi nosilec" msgid "Eject" msgstr "Izvrzi" msgid "Unmount and eject this media" msgstr "Odklopi in izvrže nosilec" msgid "Show Text" msgstr "Pokaži besedilo" msgid "Display text in a window" msgstr "Pokaže besedilo v oknu" msgid "Large Type" msgstr "Velika vrsta" msgid "Show Notification" msgstr "Pokaži obvestilo" # Tukaj je tracker ime programa msgid "Tracker" msgstr "Tracker" msgid "Tracker desktop search integration" msgstr "Povezava s Tracker namiznim iskanjem" msgid "Search in Tracker" msgstr "Išči v Trackerju" msgid "Open Tracker Search Tool and search for this term" msgstr "Odpre iskalno orodje Tracker in išče ta izraz" msgid "Get Tracker Results..." msgstr "Dobi rezultate Trackerja ..." msgid "Show Tracker results for query" msgstr "Pokaži rezultate Trackerja za poizvedbo" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "Rezultati za \"%s\"" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "Najdi datoteke" msgid "Search filesystem using locate" msgstr "Iskanje po datotečnemu sistemu z locate" msgid "Ignore case distinctions when searching files" msgstr "Prezri različne velikosti črk pri iskanju datotek" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Zaznamki Firefox" msgid "Index of Firefox bookmarks" msgstr "Kazalo zaznamkov Firefox" #, fuzzy msgid "Firefox Keywords" msgstr "Zaznamki Firefox" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "Iskanje po spletu z iskalniki OpenSearch" msgid "Search With..." msgstr "Išči z ..." msgid "Search For..." msgstr "Išči za ..." #, fuzzy msgid "Search Terms" msgstr "Iskalniki" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Uporabite \"%s\"" #, fuzzy msgid "Resume playback" msgstr "Nadaljevanje predvajanja v Audaciousu" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Naslednja" #, fuzzy msgid "Skip to next track" msgstr "Skoči na naslednjo skladbo v Audaciousu" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Predhodna" #, fuzzy msgid "Skip to previous track" msgstr "Skoči na predhodno skladbo v Audaciousu" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "Dostop do stikov Pidgin" msgid "Show offline contacts" msgstr "Pokaži nepovezane stike" msgid "Open Chat" msgstr "Odpri klepet" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d znakov)" msgstr[1] "%s (%d znak)" msgstr[2] "%s (%d znaka)" msgstr[3] "%s (%d znaki)" msgid "Send Message..." msgstr "Pošlji sporočilo ..." msgid "Available" msgstr "Na voljo" msgid "Away" msgstr "Odsoten" msgid "Pidgin Contacts" msgstr "Stiki Pidgin" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Skrajšaj povezave" msgid "Create short aliases of long URLs" msgstr "Ustvari kratke vzdevke dolgih URL-jev" msgid "Error" msgstr "Napaka" msgid "Shorten With..." msgstr "Skrajšaj z ..." msgid "Services" msgstr "Storitve" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "Predvaja in uvršča skladbe in brska po glasbeni knjižnici" msgid "Include artists in top level" msgstr "Vključi izvajalce v zgornji ravni" msgid "Include albums in top level" msgstr "Vključi albume v zgornji ravni" msgid "Play tracks in Rhythmbox" msgstr "Predvajanje skladb v Rhythmboxu" msgid "Add tracks to the play queue" msgstr "Doda skladbe v predvajalno vrsto" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "od %(artist)s iz %(album)s" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "od %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Skladbe od %s" msgid "Albums" msgstr "Albumi" msgid "Music albums in Rhythmbox Library" msgstr "Glasbeni albumi v knjižnici Rhyhtmbox" msgid "Artists" msgstr "Izvajalci" msgid "Music artists in Rhythmbox Library" msgstr "Izvajalci glasbe v knjižnici Rhythmbox" msgid "Songs" msgstr "Pesmi" msgid "Songs in Rhythmbox library" msgstr "Pesmi v knjižnici Rhythmbox" msgid "Getting Things GNOME" msgstr "Getting Things GNOME" msgid "Browse and create new tasks in GTG" msgstr "Brskanje in ustvarjanje novih opravil v GTG" #, python-format msgid "due: %s" msgstr "rok: %s" #, python-format msgid "start: %s" msgstr "začni: %s" #, python-format msgid "tags: %s" msgstr "oznake: %s" msgid "Open task in Getting Things GNOME!" msgstr "Odpri opravilo v Getting Things GNOME!" msgid "Delete" msgstr "Izbriši" msgid "Permanently remove this task" msgstr "Trajno odstrani to nalogo" msgid "Mark Done" msgstr "Označi končano" msgid "Mark this task as done" msgstr "Označi to nalogo kot končano" msgid "Dismiss" msgstr "Zavrzi" msgid "Mark this task as not to be done anymore" msgstr "Označi to nalogo kot takšno, ki je ni treba več opraviti " msgid "Create Task" msgstr "Ustvari novo nalogo" msgid "Create new task in Getting Things GNOME" msgstr "Ustvari novo opravilo v Getting Things GNOME" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "Iskanje v Devhelp" msgid "Empathy" msgstr "Empathy" msgid "Access to Empathy Contacts" msgstr "Dostop do stikov Empathy" msgid "Busy" msgstr "Zaposlen" msgid "Not Available" msgstr "Ni na voljo" msgid "Invisible" msgstr "Neviden" msgid "Offline" msgstr "Nepovezan" msgid "Change Global Status To..." msgstr "Spremeni splošno stanje v ..." msgid "Empathy Contacts" msgstr "Stiki Empathy" msgid "Empathy Account Status" msgstr "Stanje računa Empathy" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Dodatno omogoči" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Trik vejice" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Sestavi ukaz" msgid "Mark Default Action" msgstr "Označi privzeto dejanje" msgid "Forget Object" msgstr "Pozabi predmet" msgid "Reset All" msgstr "Ponastavi vse" msgid "Select Quit" msgstr "Izberi končaj" msgid "Select Selected File" msgstr "Izberi izbrano datoteko" msgid "Select Selected Text" msgstr "Izberi izbrano besedilo" msgid "Show Help" msgstr "Pokaži pomoč" msgid "Show Preferences" msgstr "Pokaži možnost" msgid "Switch to First Pane" msgstr "Preklopi na prvi pladenj" msgid "Toggle Text Mode" msgstr "Preklopi besedilni način" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "V %(src)s ni zadetkov za \"%(query)s\"" msgid "No matches" msgstr "Ni zadetkov" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Ni zadetkov" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Naredi \"%(action)s\" privzeto za \"%(object)s\"" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "Pozabi \"%s\"" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Pokaži glavni vmesnik" msgid "Show with Selection" msgstr "Pokaži z izbiro" #. TRANS: Plugin info fields msgid "Description" msgstr "Opis" msgid "Author" msgstr "Avtor" msgid "Version" msgstr "Različica" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Zahtevan je Python modul '%s'" msgid "Plugin could not be read due to an error:" msgstr "Vstavka ni mogoče prebrati zaradi napake:" msgid "Content of" msgstr "Vsebina" #. TRANS: Plugin contents header msgid "Sources" msgstr "Viri" #. TRANS: Plugin contents header msgid "Actions" msgstr "Dejanja" #, python-format msgid "Using encrypted password storage: %s" msgstr "Uporabi šifrirane shrambe gesel: %s" #, python-format msgid "Using password storage: %s" msgstr "Uporaba shrambe gesla: %s" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Nastavitev" msgid "Set username and password" msgstr "Nastavi uporabniško ime in geslo" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Izbor mape" msgid "Reset all shortcuts to default values?" msgstr "Ali naj bodo vse bližnjice ponastavljene na privzete vrednosti?" msgid "Shortcut" msgstr "Bližnjica" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "Andrej Žnidaršič, " msgid "A free software (GPLv3+) launcher" msgstr "Zaganjalnik proste programske opreme (GPLv3+)" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Ta program je prosta programska oprema; lahko ga razširjate\n" "in/ali spreminjate pod pogoji GNU Splošnega javnega dovoljenja kot\n" "je objavljeno pri Free Software Foundation; ali različico 2 Licence\n" "ali (na vašo željo) katerakoli kasnejša različica.\n" "\n" "Ta program je distribuiran v upanju da bo uporaben, toda BREZ\n" "KAKRŠNIHKOLI ZAGOTOVIL; tudi brez impliciranih zagotovila za PRODAJO\n" "ali PRIMERNOST ZA DOLOČEN NAMEN. Oglejte si\n" "GNU General Public Licence za več podrobnosti.\n" "\n" "Skupaj s programom bi morali prejeti tudi kopijo splošnega javnega " "potrdila;\n" "v primeru, da kopije niste prejeli, si oglejte .\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Ni mogoče najti Kupferja v teku" #~ msgid "Compose Email" #~ msgstr "Sestavi e-pošto" #~ msgid "Send in Email To..." #~ msgstr "Pošlji v e-pošti ..." #~ msgid "Type to search %s" #~ msgstr "Vtipkajte za iskanje %s" #~ msgid "No action" #~ msgstr "Ni dejanja" #~ msgid "GNOME Terminal Profiles" #~ msgstr "Profili Gnome Terminala" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Zažene profile Gnome Terminala" #~ msgid "Multihead Support" #~ msgstr "Podpora večnitenja" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Izračuna izraze, ki se začnejo z '='" #~ msgid "Epiphany Bookmarks" #~ msgstr "Zaznamki Epihphany" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Kazalo zaznamkov Epiphany" #~ msgid "Include visited sites" #~ msgstr "Vključi obiskane strani" #~ msgid "Firefox tag" #~ msgstr "Oznaka Firefox" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Nadaljevanje predvajanja v Rhythmboxu" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Premor predvajanja v Rhyhtmboxu" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Skoči na naslednjo skladbo v Rhyhtmboxu" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Skoči na predhodno skladbo v Rhythmboxu" #~ msgid "Search the Web" #~ msgstr "Išči po spletu" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Nedavno uporabljeni dokumenti v Abiwordu" #~ msgid "Abiword Recent Items" #~ msgstr "Nedavni predmeti Abiword" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "Vmesnik z upravljalnikom paketov APT" #~ msgid "Installation method" #~ msgstr "Način namestitve" #~ msgid "Show Package Information" #~ msgstr "Prikaz podatkov o paketu" #~ msgid "Install" #~ msgstr "Namesti" #~ msgid "Install package using the configured method" #~ msgstr "Namesti paket z nastavljeno metodo" #~ msgid "Packages matching \"%s\"" #~ msgstr "Paketi skladni z \"%s\"" #~ msgid "Search Package Name..." #~ msgstr "Poišči ime paketa ..." #~ msgid "Ascii & Unicode Icon Set" #~ msgstr "Ascii in Unicode zbirka ikon" #~ msgid "" #~ "Provides the Ascii and Unicode icon sets that use letters and symbols to " #~ "produce icons for the objects found in Kupfer." #~ msgstr "" #~ "Zagotavlja znakovna niza Ascii in Unicode, ki uporabljata črke in simbole " #~ "za proizvajanje ikon za predmete, ki jih je mogoče najti v Kupfer." #~ msgid "Ascii" #~ msgstr "Ascii" #~ msgid "Unicode" #~ msgstr "Unicode" #~ msgid "Chromium Bookmarks" #~ msgstr "Zaznamki Chromium" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Kazalo zaznamkov Chromium" #~ msgid "Claws Mail" #~ msgstr "Claws Mail" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Stiki in dejanja Claws Mail" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Sestavi novo pošto v ClawsMail" #~ msgid "Receive All Email" #~ msgstr "Prejmi vso pošto" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "oPrejme novo pošte za vse račune v ClawsMail" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Sestavi novo sporočiloo v Claws mail in pripne datoteko" #~ msgid "Claws Mail Address Book" #~ msgstr "Imenik Claws Mail" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Stiki iz imenika Claws Mail" #~ msgid "Configure a custom terminal emulator" #~ msgstr "Nastavi posnemovalnik terminala po meri" #~ msgid "Custom Theme" #~ msgstr "Tema po meri" #~ msgid "Use a custom color theme" #~ msgstr "Uporabi barvo teme po meri" #~ msgid "Theme:" #~ msgstr "Tema:" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Stiki Evolution" #~ msgid "Compose a new message in Evolution" #~ msgstr "Sestavi novo sporočilo v Evolution" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Sestavi novo sporočilo v Evolution in priloži datoteko" #~ msgid "Evolution Address Book" #~ msgstr "Imenik Evolution" #~ msgid "Filezilla" #~ msgstr "Filezilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Pokaže strani in upravlja naslove ftp s Filezillo" #~ msgid "Open Site with Filezilla" #~ msgstr "Odpri strani s programom Filezilla" #~ msgid "Filezilla Sites" #~ msgstr "Strani Filezille" #~ msgid "Sites from Filezilla" #~ msgstr "Strani s Filezille" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Dostop do stikov Gajim" #~ msgid "Free for Chat" #~ msgstr "Dostopen za pogovor" #~ msgid "Gajim Contacts" #~ msgstr "Stiki Gajim" #~ msgid "Gajim Account Status" #~ msgstr "Stanje računa Gajim" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Nalaganje stikov in sestavljanje nove elektronske pošte v Gmailu" #~ msgid "Load contacts' pictures" #~ msgstr "Naloži slike stikov" #~ msgid "Load additional information" #~ msgstr "Naloži dodatne podrobnosti" #~ msgid "Work email" #~ msgstr "Službena elektronska pošta" #~ msgid "Home email" #~ msgstr "Domača elektronska pošta" #~ msgid "Other email" #~ msgstr "Druga elektronska pošta" #~ msgid "Work address" #~ msgstr "Službeni naslov" #~ msgid "Home address" #~ msgstr "Domači naslov" #~ msgid "Other address" #~ msgstr "Drug naslov" #~ msgid "Car phone" #~ msgstr "Telefon v avtu" #~ msgid "Fax" #~ msgstr "Faks" #~ msgid "Home phone" #~ msgstr "Domači telefon" #~ msgid "Home fax" #~ msgstr "Domači faks" #~ msgid "Internal phone" #~ msgstr "Interni telefon" #~ msgid "Mobile" #~ msgstr "Mobilni telefon" #~ msgid "Other" #~ msgstr "Ostalo" #~ msgid "VOIP" #~ msgstr "VOIP" #~ msgid "Work phone" #~ msgstr "Službeni telefon" #~ msgid "Work fax" #~ msgstr "Službeni faks" #~ msgid "Compose Email in Gmail" #~ msgstr "Sestavi elektronsko pošto v Gmailu" #~ msgid "Open web browser and compose new email in Gmail" #~ msgstr "" #~ "Odpre spletno stran sestavljanja novega elektronskega sporočila v Gmailu" #~ msgid "Edit Contact in Gmail" #~ msgstr "Uredi stik v Gmailu" #~ msgid "Open web browser and edit contact in Gmail" #~ msgstr "Odpre spletno stran urejanja stikov v Gmailu" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Stiki iz storitev Google (Google pošta)" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Prikaz albumov in pošiljanje datotek v Picasa" #~ msgid "Users to show: (,-separated)" #~ msgstr "Uporabniki za prikaz: (,-ločeno)" #~ msgid "Load user and album icons" #~ msgstr "Nalaganje ikon uporabnikov in albumov" #~ msgid "Uploading Pictures" #~ msgstr "Pošiljanje slik" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Pošiljanje slik na spletni album Picasa" #~ msgid "Creating album:" #~ msgstr "Ustvarjanje albuma:" #~ msgid "Album created by Kupfer" #~ msgstr "Album je ustvarjen s Kupfer" #~ msgid "File:" #~ msgstr "Datoteka:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "%(num)d albumov" #~ msgstr[1] "%(num)d album" #~ msgstr[2] "%(num)d albuma" #~ msgstr[3] "%(num)d albumi" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "%(num)s fotografij" #~ msgstr[1] "%(num)s fotografija" #~ msgstr[2] "%(num)s fotografiji" #~ msgstr[3] "%(num)s fotografije" #~ msgid "Upload to Picasa Album..." #~ msgstr "Pošlji na album Picasa ..." #~ msgid "Upload files to Picasa album" #~ msgstr "Pošlji datoteke v album Picasa" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Pošlji na Picaso kot nov album" #~ msgid "Create album from selected local directory" #~ msgstr "Ustvari album iz izbrane krajevne mape" #~ msgid "Picasa Albums" #~ msgstr "Albumi Picasa" #~ msgid "User albums in Picasa" #~ msgstr "Uporabniški albumi v Picasi" #~ msgid "Google Search" #~ msgstr "Google iskalnik" #~ msgid "Search Google with results shown directly" #~ msgstr "Išči v Google z neposredno prikazanimi rezultati" #~ msgid "Show More Results For \"%s\"" #~ msgstr "Pokaži več rezultatov za \"%s\"" #~ msgid "%s total found" #~ msgstr "%s skupaj najdenih" #~ msgid "Gwibber" #~ msgstr "Gwibber" #~ msgid "" #~ "Microblogging with Gwibber. Allows sending and receiving messages from " #~ "social networks like Twitter, Identi.ca etc. Requires the package " #~ "'gwibber-service'." #~ msgstr "" #~ "Mikrobloganje v Gwibberju. Omogoča pošiljanje in prejemanje sporočil iz " #~ "družabnih omrežij kot so Twitter, Identi.ca, itd. Zahteva paket 'gwibber-" #~ "service'." #~ msgid "Maximum number of messages to show" #~ msgstr "Največje število prikazanih sporočil" #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s na %(service)s" #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s na %(where)s" #~ msgid "Send Message" #~ msgstr "Pošlji sporočilo" #~ msgid "Send message to all Gwibber accounts" #~ msgstr "Pošlji sporočilo na vse račune Gwibber" #~ msgid "Send Message To..." #~ msgstr "Pošlji sporočilo osebi ..." #~ msgid "Send message to a Gwibber account" #~ msgstr "Pošlji sporočilo za račun Gwibber" #~ msgid "Send message to selected Gwibber account" #~ msgstr "Pošlji sporočilo na izbran račun Gwibber" #~ msgid "Reply..." #~ msgstr "Odgovori ..." #~ msgid "Delete Message" #~ msgstr "Izbriši sporočilo" #~ msgid "Send Private Message..." #~ msgstr "Pošlji zasebno sporočilo ..." #~ msgid "Send direct message to user" #~ msgstr "Pošlji neposredno sporočilo uporabniku" #~ msgid "Retweet" #~ msgstr "Ponovno objavi" #~ msgid "Retweet To..." #~ msgstr "Ponovno objavi na ..." #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Ponovno objavi sporočilo na vse račune Gwibber" #~ msgid "Retweet message to a Gwibber account" #~ msgstr "Ponovno objavi sporočilo na račun Gwibber" #~ msgid "Open in Browser" #~ msgstr "Odpri v brskalniku" #~ msgid "Open message in default web browser" #~ msgstr "Odpri sporočilo v privzetem spletnem brkslaniku" #~ msgid "Gwibber Accounts" #~ msgstr "Računi Gwibber" #~ msgid "Accounts configured in Gwibber" #~ msgstr "Računi nastavljeni v Gwibberju" #~ msgid "Gwibber Messages" #~ msgstr "Sporočila Gwibber" #~ msgid "Recent messages received by Gwibber" #~ msgstr "Nedavna sporočila, ki jih je prejel Gwibber" #~ msgid "Gwibber Messages for %s" #~ msgstr "Sporočila Gwibber za %s" #~ msgid "Gwibber Streams" #~ msgstr "Pretoki Gwibber" #~ msgid "Streams configured in Gwibber" #~ msgstr "Pretoki nastavljeni v programu Gwibber" #~ msgid "Gwibber Messages in %s" #~ msgstr "Sporočila Gwibber v %s" #~ msgid "Gwibber (Simple)" #~ msgstr "Gwibber (enostavno)" #~ msgid "Send updates via the microblogging client Gwibber" #~ msgstr "Pošlji posodobitve preko odjemalca mikrobloganja Gwibber" #~ msgid "Send Update" #~ msgstr "Pošlji posodobitev" #~ msgid "Unable to activate Gwibber service" #~ msgstr "Ni mogoče omogočiti storitve Gwibber" #~ msgid "OpenOffice / LibreOffice" #~ msgstr "OpenOffice /LibreOffice" #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Nedavno uporabljeni dokumenti v OpenOffice/LIbreOffice" #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "Nedavni predmeti OpenOffice/LibreOffice" #~ msgid "Opera Mail" #~ msgstr "Opera pošta" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Stiki in dejanja Opera pošte" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Sestavi novo pošto v Opera pošti" #~ msgid "Opera Mail Contacts" #~ msgstr "Usklajevanje stikov Opera pošte" #~ msgid "Contacts from Opera Mail" #~ msgstr "Stiki iz Opera pošte" #~ msgid "Opera Bookmarks" #~ msgstr "Zaznamki Opera" #~ msgid "Index of Opera bookmarks" #~ msgstr "Kazalo zaznamkov Opera" #~ msgid "PuTTY Sessions" #~ msgstr "Seje PuTTY" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Hiter dostop do sej PuTTY" #~ msgid "Start Session" #~ msgstr "Zaženi sejo" # Kaže da je to neko ime, ki ga ni treba prevajati ... #~ msgid "reStructuredText" #~ msgstr "reStructuredText" #~ msgid "Render reStructuredText and show the result" #~ msgstr "Izris reStructuredText in prikaz rezultata" #~ msgid "View as HTML Document" #~ msgstr "Pogled kot dokument HTML" #~ msgid "System Services" #~ msgstr "Sistemske storitve" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "" #~ "Zagon, zaustavitev ali ponoven zagon sistemskih storitev preko skriptov " #~ "init" #~ msgid "Sudo-like Command" #~ msgstr "Sudo-podoben ukaz" #~ msgid "Start Service" #~ msgstr "Zaženi storitev" #~ msgid "Stop Service" #~ msgstr "Zaustavi storitev" #~ msgid "%s Service" #~ msgstr "Storitev %s" #~ msgid "Show QRCode" #~ msgstr "Pokaži QRKodo" #~ msgid "Display text as QRCode in a window" #~ msgstr "Pokaže besedilo kot QRKodo v oknu" #~ msgid "Access to Skype contacts" #~ msgstr "Dostop do stikov Skype" #~ msgid "Skype Me" #~ msgstr "Skype-aj me" #~ msgid "Logged Out" #~ msgstr "Odjavljen" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Pokliči" #~ msgid "Place a call to contact" #~ msgstr "Klic stika" #~ msgid "Skype Contacts" #~ msgstr "Stiki Skype" #~ msgid "Skype Statuses" #~ msgstr "Stanja Skype" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Nosilci iz zgodovine TrueCrypt" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "Nosilec TrueCrypt: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Priklopi nosilec" #~ msgid "Mount in Truecrypt" #~ msgstr "Priklopi v Truecrypt" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Poskusi priklopiti datoteko kot nosilec Truecrypt" #~ msgid "Dismount All Volumes" #~ msgstr "Odklopi vse nosilce" #~ msgid "TrueCrypt Volumes" #~ msgstr "Nosilci TrueCrypt" #~ msgid "Terminal Server Client" #~ msgstr "Terminalni strežniški odjemalec" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Seja shranjena v Terminalnem strežniškem odjemalcu" #~ msgid "TSClient sessions" #~ msgstr "Seje TSOdjemalca" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Shranjene seje v Terminalnem strežniškem odjemalcu" #~ msgid "Vim" #~ msgstr "Vim" #~ msgid "Recently used documents in Vim" #~ msgstr "Nedavno uporabljeni dokumenti v Vim" #~ msgid "Vim Recent Documents" #~ msgstr "Nedavni dokumenti Vim" #~ msgid "Close (Save All)" #~ msgstr "Zapri (shrani vse)" #~ msgid "Send..." #~ msgstr "Pošlji ..." #~ msgid "Send ex command" #~ msgstr "Pošlji ukaz ex" #~ msgid "Insert in Vim..." #~ msgstr "Vstavi v Vim ..." #~ msgid "Active Vim Sessions" #~ msgstr "Dejavne seje Vim" #~ msgid "Vim Session %s" #~ msgstr "Seja Vim %s" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Zaznamki in dejanja Vinarge" #~ msgid "Start Vinagre Session" #~ msgstr "Zaženi sejo Vinagre" #~ msgid "Vinagre Bookmarks" #~ msgstr "Zaznamki Vinagre" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "Nadzor navideznih računalnikov VirtualBox. Podpira Sun VirtualBox in " #~ "odprtokodno izdajo." #~ msgid "Force use CLI interface" #~ msgstr "Vsili uporabno vmesnika CLI" #~ msgid "Power On" #~ msgstr "Vključi" #~ msgid "Power On Headless" #~ msgstr "Vključi brez glave" #~ msgid "Send Power Off Signal" #~ msgstr "Pošlji signal izklopa" #~ msgid "Reboot" #~ msgstr "Ponovni zagon" #~ msgid "Resume" #~ msgstr "Nadaljuj" #~ msgid "Save State" #~ msgstr "Shrani stanje" #~ msgid "Power Off" #~ msgstr "Izklop" #~ msgid "VirtualBox Machines" #~ msgstr "Naprave VirtualBox" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "" #~ "Dostop do strani shranjenih v Zim - namiznemu Wikiju in načrtovalniku" #~ msgid "Page names start with :colon" #~ msgstr "Imena strani se začnejo s :stolpec" #~ msgid "Default page name for quick notes" #~ msgstr "Privzeto ime strani hitrih opomb" #~ msgid "Note %x %X" #~ msgstr "Opomba %x %X" #~ msgid "" #~ "Strftime tags can be used: %H - hour, %M - minutes, etc\n" #~ "Please check python documentation for details.\n" #~ "NOTE: comma will be replaced by _" #~ msgstr "" #~ "Oznake strftime, ki jih je mogoče uporabiti: %H - ure, %M - minute, idr.\n" #~ "Preverite dokumentacijo python za več podrobnosti.\n" #~ "OPOMBA: vejica bo zamenjana z vezajem (_)" #~ msgid "Default namespace for quick notes" #~ msgstr "Privzeti imenski prostor hitrih opomb" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Stran Zim iz beležke \"%s\"" #~ msgid "Create Zim Page" #~ msgstr "Ustvari stran Zim" #~ msgid "Create page in default notebook" #~ msgstr "Ustvari stran v privzeti beležki" #~ msgid "Create Zim Page In..." #~ msgstr "Ustvari stran Zim v ..." #~ msgid "Insert QuickNote into Zim" #~ msgstr "Vstavi hitro opombo v Zim" #~ msgid "Quick note selected text into Zim notebook" #~ msgstr "Izbrano besedilo hitre opombe v beležnici Zim" #~ msgid "Create Subpage..." #~ msgstr "Ustvari podstran ..." #~ msgid "Zim Notebooks" #~ msgstr "Beležke Zim" #~ msgid "Zim Pages" #~ msgstr "Strani Zim" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Strani shranjene v beležkah Zim" #~ msgid "Selected File" #~ msgstr "Izbrana datoteka" #~ msgid "" #~ "Provides current nautilus selection, using Kupfer's Nautilus Extension" #~ msgstr "" #~ "Zagotavlja trenuten izbor Nautilusa z uporabo Kupferjeve razširitve " #~ "Nautilus" #~ msgid "Selected File \"%s\"" #~ msgstr "Izbrana datoteka \"%s\"" #~ msgid "Selected Files" #~ msgstr "Izbrane datoteke" kupfer-328/po/sr.po000066400000000000000000002175561500175051100143010ustar00rootroot00000000000000# Serbian translation of # Courtesy of Prevod.org team (http://prevod.org/) -- 2014. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the kupfer package. # Саша Петровић , 2013. # Мирослав Николић , 2014. msgid "" msgstr "" "Project-Id-Version: kupfer\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2014-10-29 21:23+0200\n" "Last-Translator: Мирослав Николић \n" "Language-Team: Serbian \n" "Language: sr\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" msgid "User credentials" msgstr "Уверења корисника" msgid "_User:" msgstr "_Корисник:" msgid "_Password:" msgstr "_Лозинка:" msgid "_Change" msgstr "_Измени" msgid "Set Keyboard Shortcut" msgstr "Постави пречицу тастатуре" msgid "Please press desired key combination" msgstr "Притисните жељени низ тастера" msgid "Keybinding could not be bound" msgstr "Нисам успео да поставим пречицу" msgid "Kupfer Preferences" msgstr "Поставке Бакарника" msgid "Start automatically on login" msgstr "Самостално покрени при пријави" msgid "Start" msgstr "Покрени" msgid "Show icon in notification area" msgstr "Прикажи у обавештајној области" msgid "Icon set:" msgstr "Скуп икона:" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" msgid "Terminal emulator:" msgstr "Опонашавач терминала:" msgid "Desktop Environment" msgstr "Радно окружење" msgid "General" msgstr "Опште" msgid "Global Keyboard Shortcuts" msgstr "Опште пречице тастатуре" msgid "Reset" msgstr "Врати" msgid "Browser Keyboard Shortcuts" msgstr "Пречице тастатуре прегледника" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "Користи појединачне наредбе пречица (Размак, /, тачка, запета, итд.)" msgid "Keyboard" msgstr "Тастатура" msgid "Plugins" msgstr "Прикључци" msgid "Inclusion in Top Level Searches" msgstr "Укљученост у приоритетну претрагу" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "Означени извори имају своје предмете укључене у приоритетну претрагу.\n" "Необележени садржаји извора су једино доступни проналажењем својих подзбирки." msgid "Indexed Folders" msgstr "Фасцикле додате у садржај за претрагу" msgid "Folders whose files are always available in the catalog." msgstr "Фасцикле чије датотеке су увек доступне у збирци." msgid "Catalog" msgstr "Збирка" # Ово значи бакар. Бакар је добар проводник, а ово програмче брзо даје одзив. Немам идеју за превод назива, па сам оставио иако ми неприродно звучи -> пфер msgid "Kupfer" msgstr "Бакарник" msgid "Application Launcher" msgstr "Покретач програма" msgid "Convenient command and access tool for applications and documents" msgstr "Згодан алат за наредбе и приступ програмима и документима" msgid "Execute in Kupfer" msgstr "Изврши у Бакарнику" msgid "Saved Kupfer Command" msgstr "Сачувана наредба Бакарника" #, python-format msgid "Could not to carry out '%s'" msgstr "Нисам успео да остварим „%s“" #, python-format msgid "\"%s\" produced a result" msgstr "„%s“ је произвео излаз" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Немам овлашћења да покренем „%s“ (није извршна)" #, python-format msgid "Command in \"%s\" is not available" msgstr "Наредба у „%s“ није доступна" #, python-format msgid "Keyboard relay is active for display %s" msgstr "Пренос тастатуре је у погону за екран %s" msgid "do not present main interface on launch" msgstr "не приказује главно сучеље при покретању" msgid "list available plugins" msgstr "исписује доступне прикључаке" msgid "enable debug info" msgstr "омогућава податке за уклањање грешака" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "покреће помоћника прикључака" msgid "show usage help" msgstr "приказује упутство за употребу" msgid "show version information" msgstr "приказује податке о издању" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Употреба: kupfer [ МОГУЋНОСТИ | ДАТОТЕКА ... ]" msgid "Available plugins:" msgstr "Доступни прикључци:" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "Упишите за претрагу" #, python-format msgid "%s is empty" msgstr "%s је празан" msgid "Text" msgstr "Текст" msgid "Run after Delay..." msgstr "Покрени након застоја..." msgid "Perform command after a specified time interval" msgstr "Изврши наредбу после одређеног времена" msgid "Multiple Objects" msgstr "Вишеструки предмети" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s предмет" msgstr[1] "%s предмета" msgstr[2] "%s предмета" msgstr[3] "%s предмет" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "непознато" msgid "Aim" msgstr "АИМ" msgid "Google Talk" msgstr "Гугл разговор" msgid "ICQ" msgstr "ИЦКу" msgid "MSN" msgstr "МСН" msgid "QQ" msgstr "КуКу" msgid "Yahoo" msgstr "Јаху" msgid "Skype" msgstr "Скајп" #, python-format msgid "%s does not support this operation" msgstr "%s не подржава ову радњу" msgid "Can not be used with multiple objects" msgstr "Не може бити употребљаван са више предмета" msgid "Open" msgstr "Отвори" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Није одређена подразумевана радња за %(file)s (%(type)s)" #, python-format msgid "Please use \"%s\"" msgstr "Употребите „%s“" msgid "Set Default Application..." msgstr "Подеси основни програм..." msgid "Open with default application" msgstr "Отвори подразумеваним програмом" msgid "Reveal" msgstr "Откриј" msgid "Open parent folder" msgstr "Отвори надфасциклу" msgid "Open Terminal Here" msgstr "Овде отвори терминал" msgid "Open this location in a terminal" msgstr "Отвори путању у терминалу" msgid "Run in Terminal" msgstr "Покрени у терминалу" msgid "Run (Execute)" msgstr "Покрени (изврши)" msgid "Run this program in a Terminal" msgstr "Покрени овај програм у терминалу" msgid "Run this program" msgstr "Покрени овај програм" msgid "Go To" msgstr "Иди на" msgid "Open URL" msgstr "Отвори адресу" msgid "Open URL with default viewer" msgstr "Отвара адресу подразумеваним прегледником" msgid "Launch" msgstr "Покрени" msgid "Show application window" msgstr "Прикажи прозор програма" msgid "Launch application" msgstr "Покрени програм" msgid "Launch Again" msgstr "Покрени опет" msgid "Launch another instance of this application" msgstr "Покрени још један примерак овог програма" msgid "Close" msgstr "Затвори" msgid "Attempt to close all application windows" msgstr "Покушај да затвориш све прозоре овог програма" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Покрени" msgid "Perform command" msgstr "Изврши наредбу" msgid "(Empty Text)" msgstr "(Празан текст)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "(%(num)d линија) „%(text)s“" msgstr[1] "(%(num)d линије) „%(text)s“" msgstr[2] "(%(num)d линија) „%(text)s“" msgstr[3] "(%(num)d линија) „%(text)s“" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s и остали" # отдприлике #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Дубински извор %(dir)s, (%(levels)d нивоа)" #, python-format msgid "Directory source %s" msgstr "Изворна фасцикла %s" msgid "Home Folder" msgstr "Лична фасцикла" msgid "Catalog Index" msgstr "Садржај збирке" msgid "An index of all available sources" msgstr "Садржај свих доступних извора" msgid "Root catalog" msgstr "Корена збирка" msgid "Please Configure Plugin" msgstr "Подесите прикључак" #, python-format msgid "Plugin %s is not configured" msgstr "Прикључак „%s“ није подешен" #, python-format msgid "Invalid user credentials for %s" msgstr "Неисправно корисничко пуномоћје за %s" msgid "Applications" msgstr "Програми" msgid "All applications and preferences" msgstr "Сви програми и поставке" msgid "Applications for Desktop Environment" msgstr "Програми радног окружења" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "Отвори програмом..." msgid "Open with any application" msgstr "Отвори неким другим програмом" msgid "Set default application to open this file type" msgstr "Поставите подразумевани програм за отварање датотеке ове врсте" #, fuzzy msgid "Reset Associations" msgstr "Радње са адресама" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "Дубоке архиве" msgid "Allow browsing inside compressed archive files" msgstr "Дозволи преглед унутар сажете датотеке архиве" #, python-format msgid "Content of %s" msgstr "Садржај %s" msgid "Archive Manager" msgstr "Управник архиве" msgid "Use Archive Manager actions" msgstr "Користи радње управника архиве" msgid "Compressed archive type for 'Create Archive In'" msgstr "Врста архиве за сажимање за „Направи архиву у“" msgid "Extract Here" msgstr "Распакуј овде" msgid "Extract compressed archive" msgstr "Распакуј сажету архиву" msgid "Create Archive" msgstr "Направи архиву" msgid "Create a compressed archive from folder" msgstr "Направи сажету архиву од фасцикле" msgid "Create Archive In..." msgstr "Направи архиву у..." #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Архива" msgid "Audacious" msgstr "Безочник" msgid "Control Audacious playback and playlist" msgstr "Управља извођењем и списковима песама Безочника (Audacious)" msgid "Include songs in top level" msgstr "Укључи песме у приоритет претраге" msgid "Enqueue" msgstr "Закажи" msgid "Add track to the Audacious play queue" msgstr "Додаје нумере у заказане песме Безочника" msgid "Dequeue" msgstr "Откажи заказивање" msgid "Remove track from the Audacious play queue" msgstr "Уклоните нумеру из заказаних песама Безочника" msgid "Play" msgstr "Изведи" msgid "Jump to track in Audacious" msgstr "Пређи на песму у Безочнику" msgid "Resume playback in Audacious" msgstr "Настави извођење у Безочнику" msgid "Pause" msgstr "Застани" msgid "Pause playback in Audacious" msgstr "Застани са извођењем у Безочнику" msgid "Next" msgstr "Следеће" msgid "Jump to next track in Audacious" msgstr "Прелази на следећу песму у Безочнику" msgid "Previous" msgstr "Претходно" msgid "Jump to previous track in Audacious" msgstr "Прелази на претходну песму у Безочнику" msgid "Clear Queue" msgstr "Очисти заказано" msgid "Clear the Audacious play queue" msgstr "Очистите списак заказаних песама Безочника" msgid "Shuffle" msgstr "Насумично" msgid "Toggle shuffle in Audacious" msgstr "Прекидач насумичног извођења Безочника" msgid "Repeat" msgstr "Понављај" msgid "Toggle repeat in Audacious" msgstr "Прекидач понављања Безочника" msgid "Show Playing" msgstr "Прикажи извођено" msgid "Tell which song is currently playing" msgstr "Казује која се песма тренутно изводи" msgid "Playlist" msgstr "Списак за извођење" msgid "Calculator" msgstr "Рачунар" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "Израчунај" msgid "Clipboards" msgstr "Исечци" # Не знам шта је то прокси објект msgid "Recent clipboards and clipboard proxy objects" msgstr "Скорашњи исечци и предмети посредника исечака" msgid "Number of recent clipboards to remember" msgstr "Број недавно коришћених исечака за памћење" msgid "Include selected text in clipboard history" msgstr "Укључи означени текст у историју исечака" msgid "Copy selected text to primary clipboard" msgstr "Умножи означени текст у први исечак" msgid "Selected Text" msgstr "Означени текст" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Исечак са %(num)d линијом „%(desc)s“" msgstr[1] "Исечак са %(num)d линије „%(desc)s“" msgstr[2] "Исечак са %(num)d линија „%(desc)s“" msgstr[3] "Исечак са %(num)d линијом „%(desc)s“" msgid "Clipboard Text" msgstr "Текст исечка" msgid "Clipboard File" msgstr "Датотека исечка" msgid "Clipboard Files" msgstr "Датотеке исечка" msgid "Clear" msgstr "Очисти" msgid "Remove all recent clipboards" msgstr "Уклони све скорашње исечке" # или шкољке msgid "Shell Commands" msgstr "Наредбе љуске" # Python #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Извршава програме линије наредби. Радње означене знаком %s извршава у " "подљуски." msgid "Run (Get Output)" msgstr "Покрени (добави излаз)" msgid "Run program and return its output" msgstr "Покреће програм и враћа његов излаз" # или параметар, можда је јасније. #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "Проследи у наредбу..." # исто, ако не одговара одредница, онда је параметар. msgid "Run program with object as an additional parameter" msgstr "Покреће програм са предметом као додатном одредницом" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "Допиши у наредбу..." msgid "Run program and supply text on the standard input" msgstr "Извршава програм, и доставља текст на стандардни улаз" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "Издвоји кроз наредбу..." msgid "Run command-line programs" msgstr "Изврши програме нарадбене линије" msgid "GTK+" msgstr "Гтк+" msgid "GNOME Terminal" msgstr "Гномов терминал" msgid "XFCE Terminal" msgstr "Иксфце терминал" msgid "LXTerminal" msgstr "ЛИксТерминал" msgid "X Terminal" msgstr "Икс терминал" msgid "Urxvt" msgstr "Уриксвт" msgid "Konsole" msgstr "Конзола" msgid "Save As..." msgstr "Сачувај као..." #, fuzzy msgid "Restart Kupfer" msgstr "Поново покрени услугу" msgid "Quit" msgstr "Изађи" msgid "Quit Kupfer" msgstr "Напустите Бакарника" msgid "About Kupfer" msgstr "О Бакарнику" msgid "Show information about Kupfer authors and license" msgstr "Приказује податке о ствараоцима Бакарника и дозволи" msgid "Kupfer Help" msgstr "Помоћ за Бакарника" msgid "Get help with Kupfer" msgstr "Потражите помоћ за Бакарника" msgid "Show preferences window for Kupfer" msgstr "Прикажи прозор поставки Бакарника" msgid "Search Contents" msgstr "Садржај претраге" msgid "Search inside this catalog" msgstr "Претражи у збирци" msgid "Copy" msgstr "Умножи" msgid "Copy to clipboard" msgstr "Умножи у оставу" msgid "Rescan" msgstr "Поново провери" msgid "Force reindex of this source" msgstr "Силом провери садржај овог извора" msgid "Last Command" msgstr "Последња наредба" msgid "Internal Kupfer Objects" msgstr "Унутрашњи предмети Бакарника" # резултат? msgid "Last Result" msgstr "Последњи излаз" msgid "Command Results" msgstr "Излази наредбе" msgid "Custom Terminal" msgstr "Прилагођени терминал" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Наредба" msgid "Execute flag" msgstr "Изврши опцију" msgid "Default Email Client" msgstr "Подразумевани програм ел. поште" msgid "Compose email using the system's default mailto: handler" msgstr "" "Саставите ел. пошту користећи основни програм за слање поште на систему" #, fuzzy msgid "Compose Email To" msgstr "Састави ел. пошту" msgid "Dictionary" msgstr "Речник" msgid "Look up word in dictionary" msgstr "Тражите речи у речнику" msgid "Look Up" msgstr "Пронађи" msgid "Documents" msgstr "Документи" msgid "Recently used documents and bookmarked folders" msgstr "Скорашњи документи и забележене фасцикле" msgid "Max recent document days" msgstr "Највећа старост скорашњих докумената" msgid "Recent Items" msgstr "Скорашње ставке" msgid "Recently used documents" msgstr "Недавно коришћени документи" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "%s документи" #, python-format msgid "Recently used documents for %s" msgstr "Недавно коришћени документи за %s" msgid "Places" msgstr "Места" msgid "Bookmarked folders" msgstr "Забележене фасцикле" msgid "DuckDuckGo Search" msgstr "ДакДакГо претрага" msgid "Search the web securely with DuckDuckGo" msgstr "Безбедно претражујте веб погоном претраге Дакдакго" msgid "Favorites" msgstr "Омиљено" msgid "Mark commonly used items and store objects for later use" msgstr "Означи обично коришћене ставке и сачувај предмете за каснију употребу" msgid "Shelf of \"Favorite\" items" msgstr "Полица „омиљених“ ставки" msgid "Add to Favorites" msgstr "Додај у омиљене" msgid "Add item to favorites shelf" msgstr "Додајте ставку у полицу омиљених" msgid "Remove from Favorites" msgstr "Уклони из омиљених" msgid "Remove item from favorites shelf" msgstr "Уклоните ставку из полице омиљених" # могуће је да српски овд захтева множину -датотеке msgid "File Actions" msgstr "Радње над датотеком" msgid "More file actions" msgstr "Још радњи над датотеком" # Белешке: # Додај белешку msgid "Move To..." msgstr "Премести у..." msgid "Move file to new location" msgstr "Премести датотеку на ново одредиште" msgid "Rename To..." msgstr "Преименуј у..." msgid "Copy To..." msgstr "Умножи у..." msgid "Copy file to a chosen location" msgstr "Умножава датотеку на изабрано одредиште" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "Глоб" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "Радње више важности" msgid "Tools to work with commands as objects" msgstr "Прибор за рад са наредбама као предметима" msgid "Select in Kupfer" msgstr "Изабери у Бакарнику" #, python-format msgid "Result of %s (%s)" msgstr "Излаз из %s (%s)" msgid "Run (Take Result)" msgstr "Изврши (преузми излаз)" msgid "Take the command result as a proxy object" msgstr "Узима излаз из извршене наредбе као предмет" msgid "Run (Discard Result)" msgstr "Изврши (откажи излаз)" msgid "Image Tools" msgstr "Алатке за слике" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Алатке за обраду слика" msgid "Scale..." msgstr "Мењај величину сразмерно..." msgid "Scale image to fit inside given pixel measure(s)" msgstr "Мењај величину слике сразмерно до одређеног броја тачака" msgid "Rotate Clockwise" msgstr "Окрени у смеру казаљке на сату" msgid "Rotate Counter-Clockwise" msgstr "Окрени супротно смеру казаљке сата" msgid "Autorotate" msgstr "Самостално обрћи" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "Обрће ЈПЕГ (на месту) у складу са ЕксИФ метаподацима" msgid "Kupfer Plugins" msgstr "Прикључци Бакарника" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Приступ списку прикључака Бакарника" msgid "Show Information" msgstr "Прикажи податке" msgid "Show Source Code" msgstr "Прикажи изворни код" msgid "enabled" msgstr "омогућен" msgid "disabled" msgstr "онемогућен" # или белешке? msgid "Notes" msgstr "Бележница" msgid "Gnote or Tomboy notes" msgstr "Гномове или Томичине белешке" msgid "Work with application" msgstr "Рад са програмом" msgid "Open with notes application" msgstr "Отвори са програмом бележница" msgid "Append to Note..." msgstr "Додај на белешку..." msgid "Add text to existing note" msgstr "Додаје текст постојећој белешки" msgid "Create Note" msgstr "Направи нову белешку" msgid "Create a new note from this text" msgstr "Прави нову белешку од постојећег текста" msgid "Get Note Search Results..." msgstr "Добави излаз из претраге белешке..." msgid "Show search results for this query" msgstr "Приказује излаз претраге из овог упита" #, python-format msgid "today, %s" msgstr "данас, %s" #, python-format msgid "yesterday, %s" msgstr "јуче, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Последња измена %s" msgid "Quicksilver Icons" msgstr "Иконе Брзопотезника" msgid "Quick Image Viewer" msgstr "Брзи прегледник слика" msgid "View Image" msgstr "Погледај слику" msgid "GNU Screen" msgstr "Гнуов екран" msgid "Active GNU Screen sessions" msgstr "Покренуте сесије Гнуовог екрана" msgid "Attached" msgstr "Приложено" msgid "Detached" msgstr "Откачено" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "%(status)s сесија (%(pid)s) образована %(time)s" msgid "Screen Sessions" msgstr "Сесије екрана" msgid "Attach" msgstr "Приложи" msgid "Send Keys" msgstr "Пошаљи тастере" msgid "Send synthetic keyboard events using xautomation" msgstr "Пошаљи вештачке догађаје тастатуре уз помоћ иксаутомата (xautomation)" msgid "Paste to Foreground Window" msgstr "Налепи на издигнути прозор" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "Умножи у оставу исечака и пошаљи Ктрл+В на издигнути прозор" msgid "Send keys to foreground window" msgstr "Пошаљи низ дугмади на издигнути прозор" msgid "Type Text" msgstr "Упишите текст" msgid "Type the text to foreground window" msgstr "Унесите текст у издигнути прозор" msgid "GNOME Session Management" msgstr "Гномово управљање сесијом" msgid "Special items and actions for GNOME environment" msgstr "Ставке и радње нарочите за Гномово окружење" msgid "Log Out..." msgstr "Одјава..." msgid "Log out or change user" msgstr "Одјављује се или мења корисника" msgid "Shut Down..." msgstr "Искључи..." msgid "Shut down, restart or suspend computer" msgstr "Искључује, поново покреће или обуставља рачунар" msgid "Lock Screen" msgstr "Закључај екран" msgid "Enable screensaver and lock" msgstr "Омогућава чувара екрана и закључава га" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "ИксФЦЕ управљање сесијом" msgid "Special items and actions for XFCE environment" msgstr "Ставке и радње нарочите за ИксФЦЕ окружење" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "Домаћини безбедне шкољке" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "Додаје домаћине безбедне шкољке пронађене у „~/.ssh/config“." msgid "SSH host" msgstr "Домаћин безбедне шкољке" msgid "Connect" msgstr "Повежи се" msgid "Connect to SSH host" msgstr "Повежи се са домаћином безбедне шкољке" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "Домаћини безбедне шкољке наведени у датотеци „~/.ssh/config“" # Није ми најјасније. msgid "No D-Bus connection to desktop session" msgstr "Нема везе Д-сабирнице са сесијом окружења" msgid "GNOME Keyring" msgstr "Гномов привезак кључева" msgid "KWallet" msgstr "Кновчаник" msgid "Unencrypted File" msgstr "Нешифрована датотека" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "Наредба у „%s“ није доступна" msgid "Document Templates" msgstr "Обрасци докумената" msgid "Create new documents from your templates" msgstr "Направите нови документ од образаца" #, python-format msgid "%s template" msgstr "%s образац" msgid "Empty File" msgstr "Празна датотека" msgid "New Folder" msgstr "Нова фасцикла" msgid "Create New Document..." msgstr "Направи нови документ..." msgid "Create a new document from template" msgstr "Направи нови документ према обрасцу" msgid "Create Document In..." msgstr "Направи нови документ у..." msgid "Textfiles" msgstr "Текст датотека" msgid "Append To..." msgstr "Додај на..." msgid "Append..." msgstr "Додај..." msgid "Write To..." msgstr "Упиши на..." msgid "Get Text Contents" msgstr "Добави садржај текста" msgid "Thunar" msgstr "Тунар" msgid "File manager Thunar actions" msgstr "Радње Тунара управника датотека" msgid "Select in File Manager" msgstr "Означи у управнику датотека" msgid "Show Properties" msgstr "Прикажи особине" msgid "Show information about file in file manager" msgstr "Приказује податке о датотеци у управнику датотека" msgid "Send To..." msgstr "Пошаљи на..." msgid "Symlink In..." msgstr "Симболичка веза до..." msgid "Create a symlink to file in a chosen location" msgstr "Образује симболичку везу до датотеке у изабраној путањи" msgid "Empty Trash" msgstr "Испразни смеће" msgid "Thunar Send To Objects" msgstr "Слање датотека Тунаром" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Тандерберд" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Познаници и радње Тандерберда/Ледене голубице" msgid "Compose New Email" msgstr "Састави нову ел. поруку" msgid "Compose a new message in Thunderbird" msgstr "Састави нову поруку у Тандерберду" #, fuzzy msgid "Attach in Email To..." msgstr "Пошаљите ел. поруку за..." #, fuzzy msgid "Compose Email With" msgstr "Састави ел. пошту" #, fuzzy msgid "Compose a new message using the text as body" msgstr "Састави нову поруку у Тандерберду" msgid "Thunderbird Address Book" msgstr "Адресар Тандерберда" msgid "Contacts from Thunderbird Address Book" msgstr "Познаници из адресара Тандерберда" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Врх" msgid "Show running tasks and allow sending signals to them" msgstr "Приказује покренуте задатке и дозвољава слање знакова њима" msgid "Sort Order" msgstr "Правило разврставања" msgid "Commandline" msgstr "Наредбена линија" msgid "CPU usage (descending)" msgstr "Употреба процесора (силазно)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Употреба меморије (силазно)" msgid "Send Signal..." msgstr "Пошаљи знак..." msgid "Signals" msgstr "Знаци" msgid "Running Tasks" msgstr "Покренути задаци" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "либ: %(pid)s проц: %(cpu)g%% мем: %(mem)g%% време: %(time)s" msgid "Running tasks for current user" msgstr "Покренути задаци тренутног корисника" msgid "Trash" msgstr "Смеће" msgid "Access trash contents" msgstr "Приступ садржају корпе" msgid "Move to Trash" msgstr "Премести у смеће" msgid "Move this file to trash" msgstr "Премешта ову датотеку у смеће" msgid "Restore" msgstr "Поврати" msgid "Move file back to original location" msgstr "Враћа датотеку на изворно место" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "Корпа је празна" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "Корпа садржи %(num)s датотеку" msgstr[1] "Корпа садржи %(num)s датотеке" msgstr[2] "Корпа садржи %(num)s датотека" msgstr[3] "Корпа садржи %(num)s датотеку" msgid "Triggers" msgstr "Окидачи" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "Додели опште пречице (окидаче) предметима наредбом „састави“." msgid "Add Trigger..." msgstr "Додај окидач..." msgid "Remove Trigger" msgstr "Уклони окидач" msgid "URL Actions" msgstr "Радње са адресама" msgid "Download and Open" msgstr "Преузми и отвори" msgid "Download To..." msgstr "Преузми у..." msgid "Download URL to a chosen location" msgstr "Преузима адресу на изабрано одредиште" msgid "Wikipedia" msgstr "Википедија" msgid "Search in Wikipedia" msgstr "Претражи Википедију" msgid "Wikipedia language" msgstr "Језик Википедије" #. TRANS: Default wikipedia language code msgid "en" msgstr "ен" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Тражи израз у %s wikipedia.org" msgid "Window List" msgstr "Списак прозора" msgid "All windows on all workspaces" msgstr "Сви прозори на свим радним просторима" msgid "Activate" msgstr "Покрени" msgid "Shade" msgstr "Смотај" msgid "Unshade" msgstr "Одмотај" msgid "Minimize" msgstr "Умањи" msgid "Unminimize" msgstr "Поништи умањење" msgid "Maximize" msgstr "Увећај" msgid "Unmaximize" msgstr "Поништи увећање" msgid "Maximize Vertically" msgstr "Увећај усправно" msgid "Unmaximize Vertically" msgstr "Поништи усправно увећање" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Прозор на %(wkspc)s" msgid "Frontmost Window" msgstr "Најизложенији прозор" msgid "Next Window" msgstr "Наредни прозор" msgid "Jump to this window's workspace and focus" msgstr "Скочи на радни простор прозора и узми га у жижу" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "%d прозор" msgstr[1] "%d прозора" msgstr[2] "%d прозора" msgstr[3] "%d прозор" msgid "Active workspace" msgstr "Тренутни радни простор" msgid "Jump to this workspace" msgstr "Скочи на овај радни простор" msgid "Workspaces" msgstr "Радни простори" msgid "Volumes and Disks" msgstr "Уређаји и дискови" msgid "Mounted volumes and disks" msgstr "Прикачени уређаји и дискови" #, python-format msgid "Volume mounted at %s" msgstr "Уређај је прикачен на %s" msgid "Unmount" msgstr "Откачи" msgid "Unmount this volume" msgstr "Откачите овај уређај" msgid "Eject" msgstr "Избаци" msgid "Unmount and eject this media" msgstr "Откачиње и избацује овај уређај" msgid "Show Text" msgstr "Прикажи текст" msgid "Display text in a window" msgstr "Приказује текст у прозору" msgid "Large Type" msgstr "Велике врсте" msgid "Show Notification" msgstr "Прикажи обавештења" msgid "Tracker" msgstr "Трагач (Tracker)" msgid "Tracker desktop search integration" msgstr "Уграђени Трагач у окружењу" msgid "Search in Tracker" msgstr "Претражи у Трагачу" msgid "Open Tracker Search Tool and search for this term" msgstr "Отвори алат претраге Трагача и тражи следећи израз" msgid "Get Tracker Results..." msgstr "Добави излазе Трагача..." msgid "Show Tracker results for query" msgstr "Прикажи излазе из Трагача за упит" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "Излази претраге за „%s“" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "Нађи датотеке" msgid "Search filesystem using locate" msgstr "Претражите систем датотека употребом „locate“" msgid "Ignore case distinctions when searching files" msgstr "Занемари величину слова при претрази датотека" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Забелешке Фајерфокса" msgid "Index of Firefox bookmarks" msgstr "Садржај забелешки Фајерфокса" #, fuzzy msgid "Firefox Keywords" msgstr "Забелешке Фајерфокса" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "Претражује веб погонима претраге Отворене претраге" msgid "Search With..." msgstr "Претражи уз помоћ..." msgid "Search For..." msgstr "Тражи..." #, fuzzy msgid "Search Terms" msgstr "Погони претраге" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Употребите „%s“" #, fuzzy msgid "Resume playback" msgstr "Настави извођење у Безочнику" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Следеће" #, fuzzy msgid "Skip to next track" msgstr "Прелази на следећу песму у Безочнику" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Претходно" #, fuzzy msgid "Skip to previous track" msgstr "Прелази на претходну песму у Безочнику" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "Голупко (Pidgin)" msgid "Access to Pidgin Contacts" msgstr "Приступ познаника Голупка" msgid "Show offline contacts" msgstr "Приказује пријатеље ван мреже" msgid "Open Chat" msgstr "Отворите ћаскање" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d знак)" msgstr[1] "%s (%d знака)" msgstr[2] "%s (%d знакова)" msgstr[3] "%s (%d знак)" msgid "Send Message..." msgstr "Пошаљи поруку..." msgid "Available" msgstr "Доступан" msgid "Away" msgstr "Одсутан" msgid "Pidgin Contacts" msgstr "Познаници Голупка" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Скрати везе" msgid "Create short aliases of long URLs" msgstr "Направи скраћенице за дугачке адресе" msgid "Error" msgstr "Грешка" msgid "Shorten With..." msgstr "Скрати уз помоћ..." msgid "Services" msgstr "Услуге" msgid "Rhythmbox" msgstr "Музичка кутија" msgid "Play and enqueue tracks and browse the music library" msgstr "Изведи и закажи нумере, и разгледај музичку збирку" msgid "Include artists in top level" msgstr "Укључи извођаче у приоритет претраге" msgid "Include albums in top level" msgstr "Укључи албуме у приоритет претраге" msgid "Play tracks in Rhythmbox" msgstr "Изводи песме у музичкој кутији" msgid "Add tracks to the play queue" msgstr "Додаје нумере у заказане за извођење" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "од %(artist)s са %(album)s" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "од %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Песме од %s" msgid "Albums" msgstr "Албуми" msgid "Music albums in Rhythmbox Library" msgstr "Музички албуми у збирци Музичке кутије" msgid "Artists" msgstr "Извођачи" msgid "Music artists in Rhythmbox Library" msgstr "Извођачи музике у збирци Музичке кутије" msgid "Songs" msgstr "Песме" msgid "Songs in Rhythmbox library" msgstr "Песме у збирци Музичке кутије" msgid "Getting Things GNOME" msgstr "Гномов управник задатака" msgid "Browse and create new tasks in GTG" msgstr "Прегледа и образује нове задатке у ГТГ" #, python-format msgid "due: %s" msgstr "рок: %s" #, python-format msgid "start: %s" msgstr "почиње: %s" #, python-format msgid "tags: %s" msgstr "ознака: %s" msgid "Open task in Getting Things GNOME!" msgstr "Отворите задатак у Гномовом управнику задатака!" msgid "Delete" msgstr "Обриши" msgid "Permanently remove this task" msgstr "Трајно уклоните овај задатак" msgid "Mark Done" msgstr "Означи да је готово" msgid "Mark this task as done" msgstr "Означава овај задатак као завршен" msgid "Dismiss" msgstr "Откажи" msgid "Mark this task as not to be done anymore" msgstr "Означи овај задатак да се више не извршава" msgid "Create Task" msgstr "Направи задатак" msgid "Create new task in Getting Things GNOME" msgstr "Направите нови задатак у Гномовом управнику задатака" msgid "Devhelp" msgstr "Девхелп" msgid "Search in Devhelp" msgstr "Претражи у Девхелпу" msgid "Empathy" msgstr "Интернет писмоноша" msgid "Access to Empathy Contacts" msgstr "Приступ познаницима из Интернет писмоноше" msgid "Busy" msgstr "Заузет" msgid "Not Available" msgstr "Није доступан" msgid "Invisible" msgstr "Невидљив" msgid "Offline" msgstr "Ван мреже" msgid "Change Global Status To..." msgstr "Промените стање присутности на..." msgid "Empathy Contacts" msgstr "Познаници из Интернет писмоноше" msgid "Empathy Account Status" msgstr "Стање Интернет писмоноше" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Заменски покрени" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Вишеструки избор (чаролија запете)" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Састави наредбу" msgid "Mark Default Action" msgstr "Означи радњу као основну" msgid "Forget Object" msgstr "Заборави предмет" msgid "Reset All" msgstr "Врати све на подразумевано" msgid "Select Quit" msgstr "Означи напуштање" msgid "Select Selected File" msgstr "Означи означену датотеку" msgid "Select Selected Text" msgstr "Означи означени текст" msgid "Show Help" msgstr "Прикажи помоћ" msgid "Show Preferences" msgstr "Прикажи поставке" msgid "Switch to First Pane" msgstr "Пређи на прво окно" msgid "Toggle Text Mode" msgstr "Прекидач начина приказа текстом" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Нема поклапање у %(src)s за „%(query)s“" msgid "No matches" msgstr "Нема поклапања" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Нема поклапања" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Учини „%(action)s“ задатим за „%(object)s“" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "Заборави „%s“" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Прикажи главно сучеље" msgid "Show with Selection" msgstr "Приказ са избором" #. TRANS: Plugin info fields msgid "Description" msgstr "Опис" msgid "Author" msgstr "Стваралац" msgid "Version" msgstr "Издање" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Питонова јединица „%s“ је неопходна" msgid "Plugin could not be read due to an error:" msgstr "Нисам успео учитати прикључак због грешке:" msgid "Content of" msgstr "Садржај" #. TRANS: Plugin contents header msgid "Sources" msgstr "Извора" #. TRANS: Plugin contents header msgid "Actions" msgstr "Радњи" #, python-format msgid "Using encrypted password storage: %s" msgstr "Користим лозинку за сигурно складиште: %s" #, python-format msgid "Using password storage: %s" msgstr "Користим лозинку складиштења: %s" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Поставке" msgid "Set username and password" msgstr "Подесите корисничко име и лозинку" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Изаберите директоријум" msgid "Reset all shortcuts to default values?" msgstr "Да вратим сачуване пречице са тастатуре на почетне вредности?" msgid "Shortcut" msgstr "Пречица" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "Саша Петровић " msgid "A free software (GPLv3+) launcher" msgstr "Покретач слободног софтвера (ОЈЛв3+)" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Овај програм је слободан софтвер: можете га прослеђивати\n" "и/или мењати под условима Гнуове опште јавне лиценце коју\n" "је објавила Задужбина слободног софтвера; издања 3 лиценце\n" "или (по вашем избору) било којег новијег издања.\n" "\n" "Овај програм се расподељује у нади да ће бити користан,\n" "али БЕЗ ИКАКВЕ ГАРАНЦИЈЕ; чак и без примењене гаранције\n" "ТРЖИШНЕ ВРЕДНОСТИ или ПРИЛАГОЂЕНОСТИ ОДРЕЂЕНОЈ НАМЕНИ.\n" "Погледајте Гнуову Општу јавну лиценцу за више детаља.\n" "\n" "Требали сте да примите примерак Гнуове Опште јавне лиценце\n" "уз овај програм. Ако нисте, видите „http://www.gnu.org/licenses/“\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Не могу да пронађем покренутог Бакарника" #~ msgid "Compose Email" #~ msgstr "Састави ел. пошту" #~ msgid "Send in Email To..." #~ msgstr "Пошаљите ел. поруку за..." #~ msgid "Type to search %s" #~ msgstr "Упишите да потражите %s" #~ msgid "No action" #~ msgstr "Нема радње" #~ msgid "GNOME Terminal Profiles" #~ msgstr "Профили Гномовог терминала" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Покрени профил Гномовог терминала" #~ msgid "Multihead Support" #~ msgstr "Више екранска подршка" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Израчунавај изразе који почињу са „=“" #~ msgid "Epiphany Bookmarks" #~ msgstr "Забелешке Спознаје" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Садржај забелешки Спознаје" #~ msgid "Include visited sites" #~ msgstr "Укључи посећене странице" #~ msgid "Firefox tag" #~ msgstr "Ознака Фајерфокса" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Настави извођење у музичкој кутији" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Застани са извођењем у музичкој кутији" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Скаче на следећу нумеру у музичкој кутији" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Скаче на претходну нумеру у музичкој кутији" #~ msgid "Search the Web" #~ msgstr "Претражи веб" #~ msgid "Abiword" #~ msgstr "Абиворд" #~ msgid "Recently used documents in Abiword" #~ msgstr "Списак недавно коришћених докумената у Абиворду" #~ msgid "Abiword Recent Items" #~ msgstr "Скорашњи документи Абиворда" #~ msgid "APT" #~ msgstr "АПТ" #~ msgid "Interface with the package manager APT" #~ msgstr "Сучеље управника пакета АПТа" #~ msgid "Installation method" #~ msgstr "Начин уградње" #~ msgid "Show Package Information" #~ msgstr "Прикажи податке о пакетима" #~ msgid "Install" #~ msgstr "Угради" #~ msgid "Install package using the configured method" #~ msgstr "Угради пакет користећи подешени начин" #~ msgid "Packages matching \"%s\"" #~ msgstr "Поклапање пакета са „%s“" #~ msgid "Search Package Name..." #~ msgstr "Тражи назива пакета..." #~ msgid "Ascii & Unicode Icon Set" #~ msgstr "Скуп икона Аскри и Уникод" #~ msgid "" #~ "Provides the Ascii and Unicode icon sets that use letters and symbols to " #~ "produce icons for the objects found in Kupfer." #~ msgstr "" #~ "Обезбеђује скупове икона Аскри и Уникод које користе слова и знаке да " #~ "омогуће иконе предметима који се налазе у Бакарнику." #~ msgid "Ascii" #~ msgstr "Аскри" #~ msgid "Unicode" #~ msgstr "Уникод" #~ msgid "Chromium Bookmarks" #~ msgstr "Забелешке Кромиума" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Списак забелешки Кромиума" #~ msgid "Claws Mail" #~ msgstr "Клавс пошта" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Контакти и радње Клавс поште" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Састави нову поруку у Клавс пошти" #~ msgid "Receive All Email" #~ msgstr "Прими сву пошту" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "Преузима нове поруке на свим налозима Клавс поште" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Саставите нову поруку у Клавс пошти и додајте датотеку као прилог" #~ msgid "Claws Mail Address Book" #~ msgstr "Адресар Клавс поште" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Контакти из адресара Клавс поште" #~ msgid "Configure a custom terminal emulator" #~ msgstr "Подесите прилагођени емулатор терминала" #~ msgid "Custom Theme" #~ msgstr "Прилагођена тема" #~ msgid "Use a custom color theme" #~ msgstr "Коришћење произвољне теме боја" #~ msgid "Theme:" #~ msgstr "Тема:" #~ msgid "Evolution" #~ msgstr "Еволуција" #~ msgid "Evolution contacts" #~ msgstr "Контакти Еволуције" #~ msgid "Compose a new message in Evolution" #~ msgstr "Саставите нову поруку у Еволуцији" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Саставите нову поруку у Еволуцији и додајте прилог" #~ msgid "Evolution Address Book" #~ msgstr "Адресар Еволуције" #~ msgid "Filezilla" #~ msgstr "Фајлзила" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Прикажи сајтове и управљај фтп адресама Фајлзилом" #~ msgid "Open Site with Filezilla" #~ msgstr "Отвори страницу Фајлзилом" #~ msgid "Filezilla Sites" #~ msgstr "Сајтови Фајлзиле" #~ msgid "Sites from Filezilla" #~ msgstr "Сајтови са Фајлзиле" #~ msgid "Gajim" #~ msgstr "Брзе поруке (Гајим)" #~ msgid "Access to Gajim Contacts" #~ msgstr "Приступ контактима Гајима" #~ msgid "Free for Chat" #~ msgstr "Слободно ћаскање" #~ msgid "Gajim Contacts" #~ msgstr "Гајимови познаници" #~ msgid "Gajim Account Status" #~ msgstr "Стање налога Гајима" #~ msgid "Gmail" #~ msgstr "Г-пошта" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Учитава познанике и саставља нову поруку у Г-пошти" #~ msgid "Load contacts' pictures" #~ msgstr "Учитава слике познаника" #~ msgid "Load additional information" #~ msgstr "Учитај додатне податке" #~ msgid "Work email" #~ msgstr "Пословна ел. пошта" #~ msgid "Home email" #~ msgstr "Кућна ел. пошта" #~ msgid "Other email" #~ msgstr "Друга ел. пошта" #~ msgid "Work address" #~ msgstr "Адреса на послу" #~ msgid "Home address" #~ msgstr "Кућна адреса" #~ msgid "Other address" #~ msgstr "Друга адреса" #~ msgid "Car phone" #~ msgstr "Телефон у колима" #~ msgid "Fax" #~ msgstr "Факс" #~ msgid "Home phone" #~ msgstr "Кућни телефон" #~ msgid "Home fax" #~ msgstr "Кућни факс" #~ msgid "Internal phone" #~ msgstr "Унутрашњи телефон" #~ msgid "Mobile" #~ msgstr "Мобилни" #~ msgid "Other" #~ msgstr "Друго" #~ msgid "VOIP" #~ msgstr "Глас преко ИП-а" #~ msgid "Work phone" #~ msgstr "Телефон на послу" #~ msgid "Work fax" #~ msgstr "Пословни факс" #~ msgid "Compose Email in Gmail" #~ msgstr "Саставите поруку у Г-пошти" #~ msgid "Open web browser and compose new email in Gmail" #~ msgstr "Отвара веб прегледник за састављање нове поруке у Г-пошти" #~ msgid "Edit Contact in Gmail" #~ msgstr "Уредите податке познаника у Г-пошти" #~ msgid "Open web browser and edit contact in Gmail" #~ msgstr "Отвара веб прегледник за уређивање података познаника у Г-пошти" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Познаници из Гуглових услуга (Г-пошта)" #~ msgid "Google Picasa" #~ msgstr "Гугл Пикаса" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Приказује албуме и отпремљене датотеке са Пикасе" #~ msgid "Users to show: (,-separated)" #~ msgstr "Корисници за приказ (,-раздвојени)" #~ msgid "Load user and album icons" #~ msgstr "Учитај иконе корисника и албума" #~ msgid "Uploading Pictures" #~ msgstr "Отпремање слика" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Отпреми слике на веб албум Пикаса" #~ msgid "Creating album:" #~ msgstr "Образовање албума:" #~ msgid "Album created by Kupfer" #~ msgstr "Албум направљен Бакарником" #~ msgid "File:" #~ msgstr "Датотека:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "%(num)d албум" #~ msgstr[1] "%(num)d албума" #~ msgstr[2] "%(num)d албума" #~ msgstr[3] "%(num)d албум" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "%(num)s слика" #~ msgstr[1] "%(num)s слике" #~ msgstr[2] "%(num)s слика" #~ msgstr[3] "%(num)s слика" #~ msgid "Upload to Picasa Album..." #~ msgstr "Отпремање слика Пикаса албум..." #~ msgid "Upload files to Picasa album" #~ msgstr "Отпреми датотеке на Пикаса албум" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Отпреми слике на нови веб албум Пикасе" #~ msgid "Create album from selected local directory" #~ msgstr "Направи албум од изабране фасцикле на рачунару" #~ msgid "Picasa Albums" #~ msgstr "Пикаса албуми" #~ msgid "User albums in Picasa" #~ msgstr "Кориснички албуми на Пикаси" #~ msgid "Google Search" #~ msgstr "Гугл претрага" #~ msgid "Search Google with results shown directly" #~ msgstr "Гугл претрага са непосредно приказаним излазима" #~ msgid "Show More Results For \"%s\"" #~ msgstr "Прикажи још излаза претраге за „%s“" #~ msgid "%s total found" #~ msgstr "Пронашао сам %s" #~ msgid "Gwibber" #~ msgstr "Гвибер" #~ msgid "" #~ "Microblogging with Gwibber. Allows sending and receiving messages from " #~ "social networks like Twitter, Identi.ca etc. Requires the package " #~ "'gwibber-service'." #~ msgstr "" #~ "Микроблоговање Гвибером омогућава слање и примање порука од друштвених " #~ "мрежа као што је Твитер, Идентика, итд. Захтева пакет „gwibber-service“." #~ msgid "Maximum number of messages to show" #~ msgstr "Највећи број порука за приказивање" #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s на %(service)s" #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s на %(where)s" #~ msgid "Send Message" #~ msgstr "Пошаљи поруку" #~ msgid "Send message to all Gwibber accounts" #~ msgstr "Пошаљи поруку на све налоге Гвибера" #~ msgid "Send Message To..." #~ msgstr "Пошаљи поруку ка..." #~ msgid "Send message to a Gwibber account" #~ msgstr "Пошаљи поруку на налог Гвибера" #~ msgid "Send message to selected Gwibber account" #~ msgstr "Пошаљи поруку на означени налог Гвибера" #~ msgid "Reply..." #~ msgstr "Одговори..." #~ msgid "Delete Message" #~ msgstr "Обриши поруку" #~ msgid "Send Private Message..." #~ msgstr "Пошаљи личну поруку..." #~ msgid "Send direct message to user" #~ msgstr "Шаље непосредну поруку кориснику" # :D отцвркутаћу ја у лудару због оваквих порука:) #~ msgid "Retweet" #~ msgstr "Отцвркутај" #~ msgid "Retweet To..." #~ msgstr "Отцвркутај ка..." #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Отцвркутај поруку на све Гвиберове налоге" #~ msgid "Retweet message to a Gwibber account" #~ msgstr "Отцвркутај поруку на Гвиберов налог" #~ msgid "Open in Browser" #~ msgstr "Отвори у прегледнику" #~ msgid "Open message in default web browser" #~ msgstr "Отвара поруку у подразумеваном веб прегледнику" #~ msgid "Gwibber Accounts" #~ msgstr "Налози Гвибера" #~ msgid "Accounts configured in Gwibber" #~ msgstr "Подешени налози у Гвиберу" #~ msgid "Gwibber Messages" #~ msgstr "Поруке Гвибера" #~ msgid "Recent messages received by Gwibber" #~ msgstr "Скорашње поруке примљене у Гвиберу" #~ msgid "Gwibber Messages for %s" #~ msgstr "Гвиберове поруке за %s" #~ msgid "Gwibber Streams" #~ msgstr "Гвиберови токови" #~ msgid "Streams configured in Gwibber" #~ msgstr "Токови подешени у Гвиберу" #~ msgid "Gwibber Messages in %s" #~ msgstr "Гвиберове поруке у %s" #~ msgid "Gwibber (Simple)" #~ msgstr "Гвибер (једноставан)" # Освежење :) #~ msgid "Send updates via the microblogging client Gwibber" #~ msgstr "Пошаљи освежења преко микроблог клијента Гвибера" # Пиво, молим! #~ msgid "Send Update" #~ msgstr "Пошаљи освежење" #~ msgid "Unable to activate Gwibber service" #~ msgstr "Не могу да покренем услугу Гвибера" #~ msgid "OpenOffice / LibreOffice" #~ msgstr "Опен офис / Либре офис" #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Скорашњи документи у Опен офису / Либре офису" #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "Скорашњи документи у Опен офису / Либре офису" #~ msgid "Opera Mail" #~ msgstr "Опера пошта" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Радње и познаници из Опера поште" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Саставите нову поруку у Опера пошти" #~ msgid "Opera Mail Contacts" #~ msgstr "Познаници Опера поште" #~ msgid "Contacts from Opera Mail" #~ msgstr "Познаници из Опера поште" #~ msgid "Opera Bookmarks" #~ msgstr "Опера забелешке" #~ msgid "Index of Opera bookmarks" #~ msgstr "Садржај забелешки Опере" #~ msgid "PuTTY Sessions" #~ msgstr "Путти сесије (PuTTY)" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Брзи приступ ПуТТи сесијама" #~ msgid "Start Session" #~ msgstr "Започни сесију" #~ msgid "reStructuredText" #~ msgstr "ре‑структурни-текст" #~ msgid "Render reStructuredText and show the result" #~ msgstr "Исцртава ре-структурни-текст и показује резултат" #~ msgid "View as HTML Document" #~ msgstr "Прегледај као ХТМЛ документ" #~ msgid "System Services" #~ msgstr "Системске услуге" # Скрипта је увек множина. #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "" #~ "Покреће, зауставља или поново покреће услуге преко покретачких скрипти" #~ msgid "Sudo-like Command" #~ msgstr "Судо-лика наредба" #~ msgid "Start Service" #~ msgstr "Покрени услугу" #~ msgid "Stop Service" #~ msgstr "Заустави услугу" #~ msgid "%s Service" #~ msgstr "%s услуга" #~ msgid "Show QRCode" #~ msgstr "Прикажи КуРКод" #~ msgid "Display text as QRCode in a window" #~ msgstr "Приказује текст као КуРКод у прозору" #~ msgid "Access to Skype contacts" #~ msgstr "Приступите Скајп контактима" # А? Никад нисам користио тај власнички програм, па не знам шта би ово требало да значи:( #~ msgid "Skype Me" #~ msgstr "Скајпни ме" #~ msgid "Logged Out" #~ msgstr "Одјављен" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Позив" #~ msgid "Place a call to contact" #~ msgstr "Упутите позив свим контактима" #~ msgid "Skype Contacts" #~ msgstr "Контакти Скајпа" #~ msgid "Skype Statuses" #~ msgstr "Стања Скајпа" #~ msgid "TrueCrypt" #~ msgstr "Трукрипт" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Уређаји из Трукрипт историје" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "Уређај Трукрипта: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Прикачи уређај" #~ msgid "Mount in Truecrypt" #~ msgstr "Прикачи Трукриптом" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Покушава да прикачи датотеку као Трукрипт уређај" #~ msgid "Dismount All Volumes" #~ msgstr "Откачи све уређаје" #~ msgid "TrueCrypt Volumes" #~ msgstr "Трукрипт уређаји" #~ msgid "Terminal Server Client" #~ msgstr "Клијент за терминалску услугу" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Сесија сачувана у клијенту за терминалску услугу" #~ msgid "TSClient sessions" #~ msgstr "Сесије ТСклијента" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Сачуване сесије у клијенту за терминалску услугу" #~ msgid "Vim" #~ msgstr "Вим" #~ msgid "Recently used documents in Vim" #~ msgstr "Недавно коришћених документи у Виму" #~ msgid "Vim Recent Documents" #~ msgstr "Скорашњи документи Вима" #~ msgid "Close (Save All)" #~ msgstr "Затвори (сачувај све)" #~ msgid "Send..." #~ msgstr "Пошаљи..." #~ msgid "Send ex command" #~ msgstr "Пошаљи бившу наредбу" #~ msgid "Insert in Vim..." #~ msgstr "Убаци у Вим..." #~ msgid "Active Vim Sessions" #~ msgstr "Покренуте сесије Вима" #~ msgid "Vim Session %s" #~ msgstr "Сесија Вима %s" #~ msgid "Vinagre" #~ msgstr "Винагре" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Забелешке и радње Винагреа" #~ msgid "Start Vinagre Session" #~ msgstr "Покрени сесију Винагреа" #~ msgid "Vinagre Bookmarks" #~ msgstr "Забелешке Винагреа" #~ msgid "VirtualBox" #~ msgstr "Виртуалбокс" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "Управљајте нестварним машинама Виртуалбокса. Подржава Виртуалбокс Сан, и " #~ "издање отвореног извора." #~ msgid "Force use CLI interface" #~ msgstr "Присили употребу наредбене линије" #~ msgid "Power On" #~ msgstr "Укључи" #~ msgid "Power On Headless" #~ msgstr "Укључи безглави" #~ msgid "Send Power Off Signal" #~ msgstr "Пошаљи знак за искључење" #~ msgid "Reboot" #~ msgstr "Поново покрени" #~ msgid "Resume" #~ msgstr "Настави" #~ msgid "Save State" #~ msgstr "Сачувај стање" #~ msgid "Power Off" #~ msgstr "Искључи" #~ msgid "VirtualBox Machines" #~ msgstr "Машине Виртуалбокса" #~ msgid "Zim" #~ msgstr "Зим" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "Приступ страницама сачуваним у Зиму — Викију окружења и обложивачу" #~ msgid "Page names start with :colon" #~ msgstr "Називи страница почињу :двотачком" #~ msgid "Default page name for quick notes" #~ msgstr "Подразумеван назив странице за брзе белешке" #~ msgid "Note %x %X" #~ msgstr "Белешка %x %X" #~ msgid "" #~ "Strftime tags can be used: %H - hour, %M - minutes, etc\n" #~ "Please check python documentation for details.\n" #~ "NOTE: comma will be replaced by _" #~ msgstr "" #~ "Ознаке ниске функције времена које могу бити коришћене: %H — сати, %M — " #~ "минути, итд\n" #~ "Проверите Питонову документацију за појединости.\n" #~ "Примедба: запета ће бити замењена знаком _" #~ msgid "Default namespace for quick notes" #~ msgstr "Подразумевани наслов за брзу белешку" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Страница Зима из бележнице „%s“" #~ msgid "Create Zim Page" #~ msgstr "Направите страницу Зима" #~ msgid "Create page in default notebook" #~ msgstr "Направите страницу у подразумеваној бележници" #~ msgid "Create Zim Page In..." #~ msgstr "Направи страницу Зима у..." #~ msgid "Insert QuickNote into Zim" #~ msgstr "Унесите брзу белешку у Зим" #~ msgid "Quick note selected text into Zim notebook" #~ msgstr "Означени текст брзе белешке у бележници Зима" #~ msgid "Create Subpage..." #~ msgstr "Направи подстраницу..." #~ msgid "Zim Notebooks" #~ msgstr "Бележнице Зима" #~ msgid "Zim Pages" #~ msgstr "Странице Зима" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Странице сачуване у бележницама Зима" kupfer-328/po/sr@latin.po000066400000000000000000001622301500175051100154150ustar00rootroot00000000000000# Serbian translation of # Courtesy of Prevod.org team (http://prevod.org/) -- 2014. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the kupfer package. # Saša Petrović , 2013. # Miroslav Nikolić , 2014. msgid "" msgstr "" "Project-Id-Version: kupfer\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2014-10-29 21:23+0200\n" "Last-Translator: Miroslav Nikolić \n" "Language-Team: Serbian \n" "Language: sr\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" msgid "User credentials" msgstr "Uverenja korisnika" msgid "_User:" msgstr "_Korisnik:" msgid "_Password:" msgstr "_Lozinka:" msgid "_Change" msgstr "_Izmeni" msgid "Set Keyboard Shortcut" msgstr "Postavi prečicu tastature" msgid "Please press desired key combination" msgstr "Pritisnite željeni niz tastera" msgid "Keybinding could not be bound" msgstr "Nisam uspeo da postavim prečicu" msgid "Kupfer Preferences" msgstr "Postavke Bakarnika" msgid "Start automatically on login" msgstr "Samostalno pokreni pri prijavi" msgid "Start" msgstr "Pokreni" msgid "Show icon in notification area" msgstr "Prikaži u obaveštajnoj oblasti" msgid "Icon set:" msgstr "Skup ikona:" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" msgid "Terminal emulator:" msgstr "Oponašavač terminala:" msgid "Desktop Environment" msgstr "Radno okruženje" msgid "General" msgstr "Opšte" msgid "Global Keyboard Shortcuts" msgstr "Opšte prečice tastature" msgid "Reset" msgstr "Vrati" msgid "Browser Keyboard Shortcuts" msgstr "Prečice tastature preglednika" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "Koristi pojedinačne naredbe prečica (Razmak, /, tačka, zapeta, itd.)" msgid "Keyboard" msgstr "Tastatura" msgid "Plugins" msgstr "Priključci" msgid "Inclusion in Top Level Searches" msgstr "Uključenost u prioritetnu pretragu" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "Označeni izvori imaju svoje predmete uključene u prioritetnu pretragu.\n" "Neobeleženi sadržaji izvora su jedino dostupni pronalaženjem svojih " "podzbirki." msgid "Indexed Folders" msgstr "Fascikle dodate u sadržaj za pretragu" msgid "Folders whose files are always available in the catalog." msgstr "Fascikle čije datoteke su uvek dostupne u zbirci." msgid "Catalog" msgstr "Zbirka" # Ovo znači bakar. Bakar je dobar provodnik, a ovo programče brzo daje odziv. Nemam ideju za prevod naziva, pa sam ostavio iako mi neprirodno zvuči -> pfer msgid "Kupfer" msgstr "Bakarnik" msgid "Application Launcher" msgstr "Pokretač programa" msgid "Convenient command and access tool for applications and documents" msgstr "Zgodan alat za naredbe i pristup programima i dokumentima" msgid "Execute in Kupfer" msgstr "Izvrši u Bakarniku" msgid "Saved Kupfer Command" msgstr "Sačuvana naredba Bakarnika" #, python-format msgid "Could not to carry out '%s'" msgstr "Nisam uspeo da ostvarim „%s“" #, python-format msgid "\"%s\" produced a result" msgstr "„%s“ je proizveo izlaz" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Nemam ovlašćenja da pokrenem „%s“ (nije izvršna)" #, python-format msgid "Command in \"%s\" is not available" msgstr "Naredba u „%s“ nije dostupna" #, python-format msgid "Keyboard relay is active for display %s" msgstr "Prenos tastature je u pogonu za ekran %s" msgid "do not present main interface on launch" msgstr "ne prikazuje glavno sučelje pri pokretanju" msgid "list available plugins" msgstr "ispisuje dostupne priključake" msgid "enable debug info" msgstr "omogućava podatke za uklanjanje grešaka" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "pokreće pomoćnika priključaka" msgid "show usage help" msgstr "prikazuje uputstvo za upotrebu" msgid "show version information" msgstr "prikazuje podatke o izdanju" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Upotreba: kupfer [ MOGUĆNOSTI | DATOTEKA ... ]" msgid "Available plugins:" msgstr "Dostupni priključci:" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "Upišite za pretragu" #, python-format msgid "%s is empty" msgstr "%s je prazan" msgid "Text" msgstr "Tekst" msgid "Run after Delay..." msgstr "Pokreni nakon zastoja..." msgid "Perform command after a specified time interval" msgstr "Izvrši naredbu posle određenog vremena" msgid "Multiple Objects" msgstr "Višestruki predmeti" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s predmet" msgstr[1] "%s predmeta" msgstr[2] "%s predmeta" msgstr[3] "%s predmet" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "nepoznato" msgid "Aim" msgstr "AIM" msgid "Google Talk" msgstr "Gugl razgovor" msgid "ICQ" msgstr "ICKu" msgid "MSN" msgstr "MSN" msgid "QQ" msgstr "KuKu" msgid "Yahoo" msgstr "Jahu" msgid "Skype" msgstr "Skajp" #, python-format msgid "%s does not support this operation" msgstr "%s ne podržava ovu radnju" msgid "Can not be used with multiple objects" msgstr "Ne može biti upotrebljavan sa više predmeta" msgid "Open" msgstr "Otvori" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Nije određena podrazumevana radnja za %(file)s (%(type)s)" #, python-format msgid "Please use \"%s\"" msgstr "Upotrebite „%s“" msgid "Set Default Application..." msgstr "Podesi osnovni program..." msgid "Open with default application" msgstr "Otvori podrazumevanim programom" msgid "Reveal" msgstr "Otkrij" msgid "Open parent folder" msgstr "Otvori nadfasciklu" msgid "Open Terminal Here" msgstr "Ovde otvori terminal" msgid "Open this location in a terminal" msgstr "Otvori putanju u terminalu" msgid "Run in Terminal" msgstr "Pokreni u terminalu" msgid "Run (Execute)" msgstr "Pokreni (izvrši)" msgid "Run this program in a Terminal" msgstr "Pokreni ovaj program u terminalu" msgid "Run this program" msgstr "Pokreni ovaj program" msgid "Go To" msgstr "Idi na" msgid "Open URL" msgstr "Otvori adresu" msgid "Open URL with default viewer" msgstr "Otvara adresu podrazumevanim preglednikom" msgid "Launch" msgstr "Pokreni" msgid "Show application window" msgstr "Prikaži prozor programa" msgid "Launch application" msgstr "Pokreni program" msgid "Launch Again" msgstr "Pokreni opet" msgid "Launch another instance of this application" msgstr "Pokreni još jedan primerak ovog programa" msgid "Close" msgstr "Zatvori" msgid "Attempt to close all application windows" msgstr "Pokušaj da zatvoriš sve prozore ovog programa" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Pokreni" msgid "Perform command" msgstr "Izvrši naredbu" msgid "(Empty Text)" msgstr "(Prazan tekst)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "(%(num)d linija) „%(text)s“" msgstr[1] "(%(num)d linije) „%(text)s“" msgstr[2] "(%(num)d linija) „%(text)s“" msgstr[3] "(%(num)d linija) „%(text)s“" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s i ostali" # otdprilike #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Dubinski izvor %(dir)s, (%(levels)d nivoa)" #, python-format msgid "Directory source %s" msgstr "Izvorna fascikla %s" msgid "Home Folder" msgstr "Lična fascikla" msgid "Catalog Index" msgstr "Sadržaj zbirke" msgid "An index of all available sources" msgstr "Sadržaj svih dostupnih izvora" msgid "Root catalog" msgstr "Korena zbirka" msgid "Please Configure Plugin" msgstr "Podesite priključak" #, python-format msgid "Plugin %s is not configured" msgstr "Priključak „%s“ nije podešen" #, python-format msgid "Invalid user credentials for %s" msgstr "Neispravno korisničko punomoćje za %s" msgid "Applications" msgstr "Programi" msgid "All applications and preferences" msgstr "Svi programi i postavke" msgid "Applications for Desktop Environment" msgstr "Programi radnog okruženja" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "Otvori programom..." msgid "Open with any application" msgstr "Otvori nekim drugim programom" msgid "Set default application to open this file type" msgstr "Postavite podrazumevani program za otvaranje datoteke ove vrste" #, fuzzy msgid "Reset Associations" msgstr "Radnje sa adresama" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "Duboke arhive" msgid "Allow browsing inside compressed archive files" msgstr "Dozvoli pregled unutar sažete datoteke arhive" #, python-format msgid "Content of %s" msgstr "Sadržaj %s" msgid "Archive Manager" msgstr "Upravnik arhive" msgid "Use Archive Manager actions" msgstr "Koristi radnje upravnika arhive" msgid "Compressed archive type for 'Create Archive In'" msgstr "Vrsta arhive za sažimanje za „Napravi arhivu u“" msgid "Extract Here" msgstr "Raspakuj ovde" msgid "Extract compressed archive" msgstr "Raspakuj sažetu arhivu" msgid "Create Archive" msgstr "Napravi arhivu" msgid "Create a compressed archive from folder" msgstr "Napravi sažetu arhivu od fascikle" msgid "Create Archive In..." msgstr "Napravi arhivu u..." #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Arhiva" msgid "Audacious" msgstr "Bezočnik" msgid "Control Audacious playback and playlist" msgstr "Upravlja izvođenjem i spiskovima pesama Bezočnika (Audacious)" msgid "Include songs in top level" msgstr "Uključi pesme u prioritet pretrage" msgid "Enqueue" msgstr "Zakaži" msgid "Add track to the Audacious play queue" msgstr "Dodaje numere u zakazane pesme Bezočnika" msgid "Dequeue" msgstr "Otkaži zakazivanje" msgid "Remove track from the Audacious play queue" msgstr "Uklonite numeru iz zakazanih pesama Bezočnika" msgid "Play" msgstr "Izvedi" msgid "Jump to track in Audacious" msgstr "Pređi na pesmu u Bezočniku" msgid "Resume playback in Audacious" msgstr "Nastavi izvođenje u Bezočniku" msgid "Pause" msgstr "Zastani" msgid "Pause playback in Audacious" msgstr "Zastani sa izvođenjem u Bezočniku" msgid "Next" msgstr "Sledeće" msgid "Jump to next track in Audacious" msgstr "Prelazi na sledeću pesmu u Bezočniku" msgid "Previous" msgstr "Prethodno" msgid "Jump to previous track in Audacious" msgstr "Prelazi na prethodnu pesmu u Bezočniku" msgid "Clear Queue" msgstr "Očisti zakazano" msgid "Clear the Audacious play queue" msgstr "Očistite spisak zakazanih pesama Bezočnika" msgid "Shuffle" msgstr "Nasumično" msgid "Toggle shuffle in Audacious" msgstr "Prekidač nasumičnog izvođenja Bezočnika" msgid "Repeat" msgstr "Ponavljaj" msgid "Toggle repeat in Audacious" msgstr "Prekidač ponavljanja Bezočnika" msgid "Show Playing" msgstr "Prikaži izvođeno" msgid "Tell which song is currently playing" msgstr "Kazuje koja se pesma trenutno izvodi" msgid "Playlist" msgstr "Spisak za izvođenje" msgid "Calculator" msgstr "Računar" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "Izračunaj" msgid "Clipboards" msgstr "Isečci" # Ne znam šta je to proksi objekt msgid "Recent clipboards and clipboard proxy objects" msgstr "Skorašnji isečci i predmeti posrednika isečaka" msgid "Number of recent clipboards to remember" msgstr "Broj nedavno korišćenih isečaka za pamćenje" msgid "Include selected text in clipboard history" msgstr "Uključi označeni tekst u istoriju isečaka" msgid "Copy selected text to primary clipboard" msgstr "Umnoži označeni tekst u prvi isečak" msgid "Selected Text" msgstr "Označeni tekst" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Isečak sa %(num)d linijom „%(desc)s“" msgstr[1] "Isečak sa %(num)d linije „%(desc)s“" msgstr[2] "Isečak sa %(num)d linija „%(desc)s“" msgstr[3] "Isečak sa %(num)d linijom „%(desc)s“" msgid "Clipboard Text" msgstr "Tekst isečka" msgid "Clipboard File" msgstr "Datoteka isečka" msgid "Clipboard Files" msgstr "Datoteke isečka" msgid "Clear" msgstr "Očisti" msgid "Remove all recent clipboards" msgstr "Ukloni sve skorašnje isečke" # ili školjke msgid "Shell Commands" msgstr "Naredbe ljuske" # Python #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Izvršava programe linije naredbi. Radnje označene znakom %s izvršava u " "podljuski." msgid "Run (Get Output)" msgstr "Pokreni (dobavi izlaz)" msgid "Run program and return its output" msgstr "Pokreće program i vraća njegov izlaz" # ili parametar, možda je jasnije. #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "Prosledi u naredbu..." # isto, ako ne odgovara odrednica, onda je parametar. msgid "Run program with object as an additional parameter" msgstr "Pokreće program sa predmetom kao dodatnom odrednicom" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "Dopiši u naredbu..." msgid "Run program and supply text on the standard input" msgstr "Izvršava program, i dostavlja tekst na standardni ulaz" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "Izdvoji kroz naredbu..." msgid "Run command-line programs" msgstr "Izvrši programe naradbene linije" msgid "GTK+" msgstr "Gtk+" msgid "GNOME Terminal" msgstr "Gnomov terminal" msgid "XFCE Terminal" msgstr "Iksfce terminal" msgid "LXTerminal" msgstr "LIksTerminal" msgid "X Terminal" msgstr "Iks terminal" msgid "Urxvt" msgstr "Uriksvt" msgid "Konsole" msgstr "Konzola" msgid "Save As..." msgstr "Sačuvaj kao..." #, fuzzy msgid "Restart Kupfer" msgstr "Ponovo pokreni uslugu" msgid "Quit" msgstr "Izađi" msgid "Quit Kupfer" msgstr "Napustite Bakarnika" msgid "About Kupfer" msgstr "O Bakarniku" msgid "Show information about Kupfer authors and license" msgstr "Prikazuje podatke o stvaraocima Bakarnika i dozvoli" msgid "Kupfer Help" msgstr "Pomoć za Bakarnika" msgid "Get help with Kupfer" msgstr "Potražite pomoć za Bakarnika" msgid "Show preferences window for Kupfer" msgstr "Prikaži prozor postavki Bakarnika" msgid "Search Contents" msgstr "Sadržaj pretrage" msgid "Search inside this catalog" msgstr "Pretraži u zbirci" msgid "Copy" msgstr "Umnoži" msgid "Copy to clipboard" msgstr "Umnoži u ostavu" msgid "Rescan" msgstr "Ponovo proveri" msgid "Force reindex of this source" msgstr "Silom proveri sadržaj ovog izvora" msgid "Last Command" msgstr "Poslednja naredba" msgid "Internal Kupfer Objects" msgstr "Unutrašnji predmeti Bakarnika" # rezultat? msgid "Last Result" msgstr "Poslednji izlaz" msgid "Command Results" msgstr "Izlazi naredbe" msgid "Custom Terminal" msgstr "Prilagođeni terminal" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Naredba" msgid "Execute flag" msgstr "Izvrši opciju" msgid "Default Email Client" msgstr "Podrazumevani program el. pošte" msgid "Compose email using the system's default mailto: handler" msgstr "" "Sastavite el. poštu koristeći osnovni program za slanje pošte na sistemu" #, fuzzy msgid "Compose Email To" msgstr "Sastavi el. poštu" msgid "Dictionary" msgstr "Rečnik" msgid "Look up word in dictionary" msgstr "Tražite reči u rečniku" msgid "Look Up" msgstr "Pronađi" msgid "Documents" msgstr "Dokumenti" msgid "Recently used documents and bookmarked folders" msgstr "Skorašnji dokumenti i zabeležene fascikle" msgid "Max recent document days" msgstr "Najveća starost skorašnjih dokumenata" msgid "Recent Items" msgstr "Skorašnje stavke" msgid "Recently used documents" msgstr "Nedavno korišćeni dokumenti" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "%s dokumenti" #, python-format msgid "Recently used documents for %s" msgstr "Nedavno korišćeni dokumenti za %s" msgid "Places" msgstr "Mesta" msgid "Bookmarked folders" msgstr "Zabeležene fascikle" msgid "DuckDuckGo Search" msgstr "DakDakGo pretraga" msgid "Search the web securely with DuckDuckGo" msgstr "Bezbedno pretražujte veb pogonom pretrage Dakdakgo" msgid "Favorites" msgstr "Omiljeno" msgid "Mark commonly used items and store objects for later use" msgstr "Označi obično korišćene stavke i sačuvaj predmete za kasniju upotrebu" msgid "Shelf of \"Favorite\" items" msgstr "Polica „omiljenih“ stavki" msgid "Add to Favorites" msgstr "Dodaj u omiljene" msgid "Add item to favorites shelf" msgstr "Dodajte stavku u policu omiljenih" msgid "Remove from Favorites" msgstr "Ukloni iz omiljenih" msgid "Remove item from favorites shelf" msgstr "Uklonite stavku iz police omiljenih" # moguće je da srpski ovd zahteva množinu -datoteke msgid "File Actions" msgstr "Radnje nad datotekom" msgid "More file actions" msgstr "Još radnji nad datotekom" # Beleške: # Dodaj belešku msgid "Move To..." msgstr "Premesti u..." msgid "Move file to new location" msgstr "Premesti datoteku na novo odredište" msgid "Rename To..." msgstr "Preimenuj u..." msgid "Copy To..." msgstr "Umnoži u..." msgid "Copy file to a chosen location" msgstr "Umnožava datoteku na izabrano odredište" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "Glob" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "Radnje više važnosti" msgid "Tools to work with commands as objects" msgstr "Pribor za rad sa naredbama kao predmetima" msgid "Select in Kupfer" msgstr "Izaberi u Bakarniku" #, python-format msgid "Result of %s (%s)" msgstr "Izlaz iz %s (%s)" msgid "Run (Take Result)" msgstr "Izvrši (preuzmi izlaz)" msgid "Take the command result as a proxy object" msgstr "Uzima izlaz iz izvršene naredbe kao predmet" msgid "Run (Discard Result)" msgstr "Izvrši (otkaži izlaz)" msgid "Image Tools" msgstr "Alatke za slike" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Alatke za obradu slika" msgid "Scale..." msgstr "Menjaj veličinu srazmerno..." msgid "Scale image to fit inside given pixel measure(s)" msgstr "Menjaj veličinu slike srazmerno do određenog broja tačaka" msgid "Rotate Clockwise" msgstr "Okreni u smeru kazaljke na satu" msgid "Rotate Counter-Clockwise" msgstr "Okreni suprotno smeru kazaljke sata" msgid "Autorotate" msgstr "Samostalno obrći" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "Obrće JPEG (na mestu) u skladu sa EksIF metapodacima" msgid "Kupfer Plugins" msgstr "Priključci Bakarnika" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Pristup spisku priključaka Bakarnika" msgid "Show Information" msgstr "Prikaži podatke" msgid "Show Source Code" msgstr "Prikaži izvorni kod" msgid "enabled" msgstr "omogućen" msgid "disabled" msgstr "onemogućen" # ili beleške? msgid "Notes" msgstr "Beležnica" msgid "Gnote or Tomboy notes" msgstr "Gnomove ili Tomičine beleške" msgid "Work with application" msgstr "Rad sa programom" msgid "Open with notes application" msgstr "Otvori sa programom beležnica" msgid "Append to Note..." msgstr "Dodaj na belešku..." msgid "Add text to existing note" msgstr "Dodaje tekst postojećoj beleški" msgid "Create Note" msgstr "Napravi novu belešku" msgid "Create a new note from this text" msgstr "Pravi novu belešku od postojećeg teksta" msgid "Get Note Search Results..." msgstr "Dobavi izlaz iz pretrage beleške..." msgid "Show search results for this query" msgstr "Prikazuje izlaz pretrage iz ovog upita" #, python-format msgid "today, %s" msgstr "danas, %s" #, python-format msgid "yesterday, %s" msgstr "juče, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Poslednja izmena %s" msgid "Quicksilver Icons" msgstr "Ikone Brzopoteznika" msgid "Quick Image Viewer" msgstr "Brzi preglednik slika" msgid "View Image" msgstr "Pogledaj sliku" msgid "GNU Screen" msgstr "Gnuov ekran" msgid "Active GNU Screen sessions" msgstr "Pokrenute sesije Gnuovog ekrana" msgid "Attached" msgstr "Priloženo" msgid "Detached" msgstr "Otkačeno" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "%(status)s sesija (%(pid)s) obrazovana %(time)s" msgid "Screen Sessions" msgstr "Sesije ekrana" msgid "Attach" msgstr "Priloži" msgid "Send Keys" msgstr "Pošalji tastere" msgid "Send synthetic keyboard events using xautomation" msgstr "Pošalji veštačke događaje tastature uz pomoć iksautomata (xautomation)" msgid "Paste to Foreground Window" msgstr "Nalepi na izdignuti prozor" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "Umnoži u ostavu isečaka i pošalji Ktrl+V na izdignuti prozor" msgid "Send keys to foreground window" msgstr "Pošalji niz dugmadi na izdignuti prozor" msgid "Type Text" msgstr "Upišite tekst" msgid "Type the text to foreground window" msgstr "Unesite tekst u izdignuti prozor" msgid "GNOME Session Management" msgstr "Gnomovo upravljanje sesijom" msgid "Special items and actions for GNOME environment" msgstr "Stavke i radnje naročite za Gnomovo okruženje" msgid "Log Out..." msgstr "Odjava..." msgid "Log out or change user" msgstr "Odjavljuje se ili menja korisnika" msgid "Shut Down..." msgstr "Isključi..." msgid "Shut down, restart or suspend computer" msgstr "Isključuje, ponovo pokreće ili obustavlja računar" msgid "Lock Screen" msgstr "Zaključaj ekran" msgid "Enable screensaver and lock" msgstr "Omogućava čuvara ekrana i zaključava ga" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "IksFCE upravljanje sesijom" msgid "Special items and actions for XFCE environment" msgstr "Stavke i radnje naročite za IksFCE okruženje" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "Domaćini bezbedne školjke" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "Dodaje domaćine bezbedne školjke pronađene u „~/.ssh/config“." msgid "SSH host" msgstr "Domaćin bezbedne školjke" msgid "Connect" msgstr "Poveži se" msgid "Connect to SSH host" msgstr "Poveži se sa domaćinom bezbedne školjke" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "Domaćini bezbedne školjke navedeni u datoteci „~/.ssh/config“" # Nije mi najjasnije. msgid "No D-Bus connection to desktop session" msgstr "Nema veze D-sabirnice sa sesijom okruženja" msgid "GNOME Keyring" msgstr "Gnomov privezak ključeva" msgid "KWallet" msgstr "Knovčanik" msgid "Unencrypted File" msgstr "Nešifrovana datoteka" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "Naredba u „%s“ nije dostupna" msgid "Document Templates" msgstr "Obrasci dokumenata" msgid "Create new documents from your templates" msgstr "Napravite novi dokument od obrazaca" #, python-format msgid "%s template" msgstr "%s obrazac" msgid "Empty File" msgstr "Prazna datoteka" msgid "New Folder" msgstr "Nova fascikla" msgid "Create New Document..." msgstr "Napravi novi dokument..." msgid "Create a new document from template" msgstr "Napravi novi dokument prema obrascu" msgid "Create Document In..." msgstr "Napravi novi dokument u..." msgid "Textfiles" msgstr "Tekst datoteka" msgid "Append To..." msgstr "Dodaj na..." msgid "Append..." msgstr "Dodaj..." msgid "Write To..." msgstr "Upiši na..." msgid "Get Text Contents" msgstr "Dobavi sadržaj teksta" msgid "Thunar" msgstr "Tunar" msgid "File manager Thunar actions" msgstr "Radnje Tunara upravnika datoteka" msgid "Select in File Manager" msgstr "Označi u upravniku datoteka" msgid "Show Properties" msgstr "Prikaži osobine" msgid "Show information about file in file manager" msgstr "Prikazuje podatke o datoteci u upravniku datoteka" msgid "Send To..." msgstr "Pošalji na..." msgid "Symlink In..." msgstr "Simbolička veza do..." msgid "Create a symlink to file in a chosen location" msgstr "Obrazuje simboličku vezu do datoteke u izabranoj putanji" msgid "Empty Trash" msgstr "Isprazni smeće" msgid "Thunar Send To Objects" msgstr "Slanje datoteka Tunarom" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Tanderberd" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Poznanici i radnje Tanderberda/Ledene golubice" msgid "Compose New Email" msgstr "Sastavi novu el. poruku" msgid "Compose a new message in Thunderbird" msgstr "Sastavi novu poruku u Tanderberdu" #, fuzzy msgid "Attach in Email To..." msgstr "Pošaljite el. poruku za..." #, fuzzy msgid "Compose Email With" msgstr "Sastavi el. poštu" #, fuzzy msgid "Compose a new message using the text as body" msgstr "Sastavi novu poruku u Tanderberdu" msgid "Thunderbird Address Book" msgstr "Adresar Tanderberda" msgid "Contacts from Thunderbird Address Book" msgstr "Poznanici iz adresara Tanderberda" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Vrh" msgid "Show running tasks and allow sending signals to them" msgstr "Prikazuje pokrenute zadatke i dozvoljava slanje znakova njima" msgid "Sort Order" msgstr "Pravilo razvrstavanja" msgid "Commandline" msgstr "Naredbena linija" msgid "CPU usage (descending)" msgstr "Upotreba procesora (silazno)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Upotreba memorije (silazno)" msgid "Send Signal..." msgstr "Pošalji znak..." msgid "Signals" msgstr "Znaci" msgid "Running Tasks" msgstr "Pokrenuti zadaci" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "lib: %(pid)s proc: %(cpu)g%% mem: %(mem)g%% vreme: %(time)s" msgid "Running tasks for current user" msgstr "Pokrenuti zadaci trenutnog korisnika" msgid "Trash" msgstr "Smeće" msgid "Access trash contents" msgstr "Pristup sadržaju korpe" msgid "Move to Trash" msgstr "Premesti u smeće" msgid "Move this file to trash" msgstr "Premešta ovu datoteku u smeće" msgid "Restore" msgstr "Povrati" msgid "Move file back to original location" msgstr "Vraća datoteku na izvorno mesto" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "Korpa je prazna" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "Korpa sadrži %(num)s datoteku" msgstr[1] "Korpa sadrži %(num)s datoteke" msgstr[2] "Korpa sadrži %(num)s datoteka" msgstr[3] "Korpa sadrži %(num)s datoteku" msgid "Triggers" msgstr "Okidači" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "Dodeli opšte prečice (okidače) predmetima naredbom „sastavi“." msgid "Add Trigger..." msgstr "Dodaj okidač..." msgid "Remove Trigger" msgstr "Ukloni okidač" msgid "URL Actions" msgstr "Radnje sa adresama" msgid "Download and Open" msgstr "Preuzmi i otvori" msgid "Download To..." msgstr "Preuzmi u..." msgid "Download URL to a chosen location" msgstr "Preuzima adresu na izabrano odredište" msgid "Wikipedia" msgstr "Vikipedija" msgid "Search in Wikipedia" msgstr "Pretraži Vikipediju" msgid "Wikipedia language" msgstr "Jezik Vikipedije" #. TRANS: Default wikipedia language code msgid "en" msgstr "en" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Traži izraz u %s wikipedia.org" msgid "Window List" msgstr "Spisak prozora" msgid "All windows on all workspaces" msgstr "Svi prozori na svim radnim prostorima" msgid "Activate" msgstr "Pokreni" msgid "Shade" msgstr "Smotaj" msgid "Unshade" msgstr "Odmotaj" msgid "Minimize" msgstr "Umanji" msgid "Unminimize" msgstr "Poništi umanjenje" msgid "Maximize" msgstr "Uvećaj" msgid "Unmaximize" msgstr "Poništi uvećanje" msgid "Maximize Vertically" msgstr "Uvećaj uspravno" msgid "Unmaximize Vertically" msgstr "Poništi uspravno uvećanje" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Prozor na %(wkspc)s" msgid "Frontmost Window" msgstr "Najizloženiji prozor" msgid "Next Window" msgstr "Naredni prozor" msgid "Jump to this window's workspace and focus" msgstr "Skoči na radni prostor prozora i uzmi ga u žižu" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "%d prozor" msgstr[1] "%d prozora" msgstr[2] "%d prozora" msgstr[3] "%d prozor" msgid "Active workspace" msgstr "Trenutni radni prostor" msgid "Jump to this workspace" msgstr "Skoči na ovaj radni prostor" msgid "Workspaces" msgstr "Radni prostori" msgid "Volumes and Disks" msgstr "Uređaji i diskovi" msgid "Mounted volumes and disks" msgstr "Prikačeni uređaji i diskovi" #, python-format msgid "Volume mounted at %s" msgstr "Uređaj je prikačen na %s" msgid "Unmount" msgstr "Otkači" msgid "Unmount this volume" msgstr "Otkačite ovaj uređaj" msgid "Eject" msgstr "Izbaci" msgid "Unmount and eject this media" msgstr "Otkačinje i izbacuje ovaj uređaj" msgid "Show Text" msgstr "Prikaži tekst" msgid "Display text in a window" msgstr "Prikazuje tekst u prozoru" msgid "Large Type" msgstr "Velike vrste" msgid "Show Notification" msgstr "Prikaži obaveštenja" msgid "Tracker" msgstr "Tragač (Tracker)" msgid "Tracker desktop search integration" msgstr "Ugrađeni Tragač u okruženju" msgid "Search in Tracker" msgstr "Pretraži u Tragaču" msgid "Open Tracker Search Tool and search for this term" msgstr "Otvori alat pretrage Tragača i traži sledeći izraz" msgid "Get Tracker Results..." msgstr "Dobavi izlaze Tragača..." msgid "Show Tracker results for query" msgstr "Prikaži izlaze iz Tragača za upit" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "Izlazi pretrage za „%s“" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "Nađi datoteke" msgid "Search filesystem using locate" msgstr "Pretražite sistem datoteka upotrebom „locate“" msgid "Ignore case distinctions when searching files" msgstr "Zanemari veličinu slova pri pretrazi datoteka" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Zabeleške Fajerfoksa" msgid "Index of Firefox bookmarks" msgstr "Sadržaj zabeleški Fajerfoksa" #, fuzzy msgid "Firefox Keywords" msgstr "Zabeleške Fajerfoksa" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "Pretražuje veb pogonima pretrage Otvorene pretrage" msgid "Search With..." msgstr "Pretraži uz pomoć..." msgid "Search For..." msgstr "Traži..." #, fuzzy msgid "Search Terms" msgstr "Pogoni pretrage" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Upotrebite „%s“" #, fuzzy msgid "Resume playback" msgstr "Nastavi izvođenje u Bezočniku" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Sledeće" #, fuzzy msgid "Skip to next track" msgstr "Prelazi na sledeću pesmu u Bezočniku" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Prethodno" #, fuzzy msgid "Skip to previous track" msgstr "Prelazi na prethodnu pesmu u Bezočniku" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "Golupko (Pidgin)" msgid "Access to Pidgin Contacts" msgstr "Pristup poznanika Golupka" msgid "Show offline contacts" msgstr "Prikazuje prijatelje van mreže" msgid "Open Chat" msgstr "Otvorite ćaskanje" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d znak)" msgstr[1] "%s (%d znaka)" msgstr[2] "%s (%d znakova)" msgstr[3] "%s (%d znak)" msgid "Send Message..." msgstr "Pošalji poruku..." msgid "Available" msgstr "Dostupan" msgid "Away" msgstr "Odsutan" msgid "Pidgin Contacts" msgstr "Poznanici Golupka" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Skrati veze" msgid "Create short aliases of long URLs" msgstr "Napravi skraćenice za dugačke adrese" msgid "Error" msgstr "Greška" msgid "Shorten With..." msgstr "Skrati uz pomoć..." msgid "Services" msgstr "Usluge" msgid "Rhythmbox" msgstr "Muzička kutija" msgid "Play and enqueue tracks and browse the music library" msgstr "Izvedi i zakaži numere, i razgledaj muzičku zbirku" msgid "Include artists in top level" msgstr "Uključi izvođače u prioritet pretrage" msgid "Include albums in top level" msgstr "Uključi albume u prioritet pretrage" msgid "Play tracks in Rhythmbox" msgstr "Izvodi pesme u muzičkoj kutiji" msgid "Add tracks to the play queue" msgstr "Dodaje numere u zakazane za izvođenje" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "od %(artist)s sa %(album)s" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "od %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Pesme od %s" msgid "Albums" msgstr "Albumi" msgid "Music albums in Rhythmbox Library" msgstr "Muzički albumi u zbirci Muzičke kutije" msgid "Artists" msgstr "Izvođači" msgid "Music artists in Rhythmbox Library" msgstr "Izvođači muzike u zbirci Muzičke kutije" msgid "Songs" msgstr "Pesme" msgid "Songs in Rhythmbox library" msgstr "Pesme u zbirci Muzičke kutije" msgid "Getting Things GNOME" msgstr "Gnomov upravnik zadataka" msgid "Browse and create new tasks in GTG" msgstr "Pregleda i obrazuje nove zadatke u GTG" #, python-format msgid "due: %s" msgstr "rok: %s" #, python-format msgid "start: %s" msgstr "počinje: %s" #, python-format msgid "tags: %s" msgstr "oznaka: %s" msgid "Open task in Getting Things GNOME!" msgstr "Otvorite zadatak u Gnomovom upravniku zadataka!" msgid "Delete" msgstr "Obriši" msgid "Permanently remove this task" msgstr "Trajno uklonite ovaj zadatak" msgid "Mark Done" msgstr "Označi da je gotovo" msgid "Mark this task as done" msgstr "Označava ovaj zadatak kao završen" msgid "Dismiss" msgstr "Otkaži" msgid "Mark this task as not to be done anymore" msgstr "Označi ovaj zadatak da se više ne izvršava" msgid "Create Task" msgstr "Napravi zadatak" msgid "Create new task in Getting Things GNOME" msgstr "Napravite novi zadatak u Gnomovom upravniku zadataka" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "Pretraži u Devhelpu" msgid "Empathy" msgstr "Internet pismonoša" msgid "Access to Empathy Contacts" msgstr "Pristup poznanicima iz Internet pismonoše" msgid "Busy" msgstr "Zauzet" msgid "Not Available" msgstr "Nije dostupan" msgid "Invisible" msgstr "Nevidljiv" msgid "Offline" msgstr "Van mreže" msgid "Change Global Status To..." msgstr "Promenite stanje prisutnosti na..." msgid "Empathy Contacts" msgstr "Poznanici iz Internet pismonoše" msgid "Empathy Account Status" msgstr "Stanje Internet pismonoše" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Zamenski pokreni" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Višestruki izbor (čarolija zapete)" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Sastavi naredbu" msgid "Mark Default Action" msgstr "Označi radnju kao osnovnu" msgid "Forget Object" msgstr "Zaboravi predmet" msgid "Reset All" msgstr "Vrati sve na podrazumevano" msgid "Select Quit" msgstr "Označi napuštanje" msgid "Select Selected File" msgstr "Označi označenu datoteku" msgid "Select Selected Text" msgstr "Označi označeni tekst" msgid "Show Help" msgstr "Prikaži pomoć" msgid "Show Preferences" msgstr "Prikaži postavke" msgid "Switch to First Pane" msgstr "Pređi na prvo okno" msgid "Toggle Text Mode" msgstr "Prekidač načina prikaza tekstom" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Nema poklapanje u %(src)s za „%(query)s“" msgid "No matches" msgstr "Nema poklapanja" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Nema poklapanja" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Učini „%(action)s“ zadatim za „%(object)s“" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "Zaboravi „%s“" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Prikaži glavno sučelje" msgid "Show with Selection" msgstr "Prikaz sa izborom" #. TRANS: Plugin info fields msgid "Description" msgstr "Opis" msgid "Author" msgstr "Stvaralac" msgid "Version" msgstr "Izdanje" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Pitonova jedinica „%s“ je neophodna" msgid "Plugin could not be read due to an error:" msgstr "Nisam uspeo učitati priključak zbog greške:" msgid "Content of" msgstr "Sadržaj" #. TRANS: Plugin contents header msgid "Sources" msgstr "Izvora" #. TRANS: Plugin contents header msgid "Actions" msgstr "Radnji" #, python-format msgid "Using encrypted password storage: %s" msgstr "Koristim lozinku za sigurno skladište: %s" #, python-format msgid "Using password storage: %s" msgstr "Koristim lozinku skladištenja: %s" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Postavke" msgid "Set username and password" msgstr "Podesite korisničko ime i lozinku" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Izaberite direktorijum" msgid "Reset all shortcuts to default values?" msgstr "Da vratim sačuvane prečice sa tastature na početne vrednosti?" msgid "Shortcut" msgstr "Prečica" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "Saša Petrović " msgid "A free software (GPLv3+) launcher" msgstr "Pokretač slobodnog softvera (OJLv3+)" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Ovaj program je slobodan softver: možete ga prosleđivati\n" "i/ili menjati pod uslovima Gnuove opšte javne licence koju\n" "je objavila Zadužbina slobodnog softvera; izdanja 3 licence\n" "ili (po vašem izboru) bilo kojeg novijeg izdanja.\n" "\n" "Ovaj program se raspodeljuje u nadi da će biti koristan,\n" "ali BEZ IKAKVE GARANCIJE; čak i bez primenjene garancije\n" "TRŽIŠNE VREDNOSTI ili PRILAGOĐENOSTI ODREĐENOJ NAMENI.\n" "Pogledajte Gnuovu Opštu javnu licencu za više detalja.\n" "\n" "Trebali ste da primite primerak Gnuove Opšte javne licence\n" "uz ovaj program. Ako niste, vidite „http://www.gnu.org/licenses/“\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Ne mogu da pronađem pokrenutog Bakarnika" #~ msgid "Compose Email" #~ msgstr "Sastavi el. poštu" #~ msgid "Send in Email To..." #~ msgstr "Pošaljite el. poruku za..." #~ msgid "Type to search %s" #~ msgstr "Upišite da potražite %s" #~ msgid "No action" #~ msgstr "Nema radnje" #~ msgid "GNOME Terminal Profiles" #~ msgstr "Profili Gnomovog terminala" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Pokreni profil Gnomovog terminala" #~ msgid "Multihead Support" #~ msgstr "Više ekranska podrška" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Izračunavaj izraze koji počinju sa „=“" #~ msgid "Epiphany Bookmarks" #~ msgstr "Zabeleške Spoznaje" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Sadržaj zabeleški Spoznaje" #~ msgid "Include visited sites" #~ msgstr "Uključi posećene stranice" #~ msgid "Firefox tag" #~ msgstr "Oznaka Fajerfoksa" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Nastavi izvođenje u muzičkoj kutiji" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Zastani sa izvođenjem u muzičkoj kutiji" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Skače na sledeću numeru u muzičkoj kutiji" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Skače na prethodnu numeru u muzičkoj kutiji" #~ msgid "Search the Web" #~ msgstr "Pretraži veb" #~ msgid "Abiword" #~ msgstr "Abivord" #~ msgid "Recently used documents in Abiword" #~ msgstr "Spisak nedavno korišćenih dokumenata u Abivordu" #~ msgid "Abiword Recent Items" #~ msgstr "Skorašnji dokumenti Abivorda" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "Sučelje upravnika paketa APTa" #~ msgid "Installation method" #~ msgstr "Način ugradnje" #~ msgid "Show Package Information" #~ msgstr "Prikaži podatke o paketima" #~ msgid "Install" #~ msgstr "Ugradi" #~ msgid "Install package using the configured method" #~ msgstr "Ugradi paket koristeći podešeni način" #~ msgid "Packages matching \"%s\"" #~ msgstr "Poklapanje paketa sa „%s“" #~ msgid "Search Package Name..." #~ msgstr "Traži naziva paketa..." #~ msgid "Ascii & Unicode Icon Set" #~ msgstr "Skup ikona Askri i Unikod" #~ msgid "" #~ "Provides the Ascii and Unicode icon sets that use letters and symbols to " #~ "produce icons for the objects found in Kupfer." #~ msgstr "" #~ "Obezbeđuje skupove ikona Askri i Unikod koje koriste slova i znake da " #~ "omoguće ikone predmetima koji se nalaze u Bakarniku." #~ msgid "Ascii" #~ msgstr "Askri" #~ msgid "Unicode" #~ msgstr "Unikod" #~ msgid "Chromium Bookmarks" #~ msgstr "Zabeleške Kromiuma" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Spisak zabeleški Kromiuma" #~ msgid "Claws Mail" #~ msgstr "Klavs pošta" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Kontakti i radnje Klavs pošte" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Sastavi novu poruku u Klavs pošti" #~ msgid "Receive All Email" #~ msgstr "Primi svu poštu" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "Preuzima nove poruke na svim nalozima Klavs pošte" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Sastavite novu poruku u Klavs pošti i dodajte datoteku kao prilog" #~ msgid "Claws Mail Address Book" #~ msgstr "Adresar Klavs pošte" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Kontakti iz adresara Klavs pošte" #~ msgid "Configure a custom terminal emulator" #~ msgstr "Podesite prilagođeni emulator terminala" #~ msgid "Custom Theme" #~ msgstr "Prilagođena tema" #~ msgid "Use a custom color theme" #~ msgstr "Korišćenje proizvoljne teme boja" #~ msgid "Theme:" #~ msgstr "Tema:" #~ msgid "Evolution" #~ msgstr "Evolucija" #~ msgid "Evolution contacts" #~ msgstr "Kontakti Evolucije" #~ msgid "Compose a new message in Evolution" #~ msgstr "Sastavite novu poruku u Evoluciji" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Sastavite novu poruku u Evoluciji i dodajte prilog" #~ msgid "Evolution Address Book" #~ msgstr "Adresar Evolucije" #~ msgid "Filezilla" #~ msgstr "Fajlzila" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Prikaži sajtove i upravljaj ftp adresama Fajlzilom" #~ msgid "Open Site with Filezilla" #~ msgstr "Otvori stranicu Fajlzilom" #~ msgid "Filezilla Sites" #~ msgstr "Sajtovi Fajlzile" #~ msgid "Sites from Filezilla" #~ msgstr "Sajtovi sa Fajlzile" #~ msgid "Gajim" #~ msgstr "Brze poruke (Gajim)" #~ msgid "Access to Gajim Contacts" #~ msgstr "Pristup kontaktima Gajima" #~ msgid "Free for Chat" #~ msgstr "Slobodno ćaskanje" #~ msgid "Gajim Contacts" #~ msgstr "Gajimovi poznanici" #~ msgid "Gajim Account Status" #~ msgstr "Stanje naloga Gajima" #~ msgid "Gmail" #~ msgstr "G-pošta" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Učitava poznanike i sastavlja novu poruku u G-pošti" #~ msgid "Load contacts' pictures" #~ msgstr "Učitava slike poznanika" #~ msgid "Load additional information" #~ msgstr "Učitaj dodatne podatke" #~ msgid "Work email" #~ msgstr "Poslovna el. pošta" #~ msgid "Home email" #~ msgstr "Kućna el. pošta" #~ msgid "Other email" #~ msgstr "Druga el. pošta" #~ msgid "Work address" #~ msgstr "Adresa na poslu" #~ msgid "Home address" #~ msgstr "Kućna adresa" #~ msgid "Other address" #~ msgstr "Druga adresa" #~ msgid "Car phone" #~ msgstr "Telefon u kolima" #~ msgid "Fax" #~ msgstr "Faks" #~ msgid "Home phone" #~ msgstr "Kućni telefon" #~ msgid "Home fax" #~ msgstr "Kućni faks" #~ msgid "Internal phone" #~ msgstr "Unutrašnji telefon" #~ msgid "Mobile" #~ msgstr "Mobilni" #~ msgid "Other" #~ msgstr "Drugo" #~ msgid "VOIP" #~ msgstr "Glas preko IP-a" #~ msgid "Work phone" #~ msgstr "Telefon na poslu" #~ msgid "Work fax" #~ msgstr "Poslovni faks" #~ msgid "Compose Email in Gmail" #~ msgstr "Sastavite poruku u G-pošti" #~ msgid "Open web browser and compose new email in Gmail" #~ msgstr "Otvara veb preglednik za sastavljanje nove poruke u G-pošti" #~ msgid "Edit Contact in Gmail" #~ msgstr "Uredite podatke poznanika u G-pošti" #~ msgid "Open web browser and edit contact in Gmail" #~ msgstr "Otvara veb preglednik za uređivanje podataka poznanika u G-pošti" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Poznanici iz Guglovih usluga (G-pošta)" #~ msgid "Google Picasa" #~ msgstr "Gugl Pikasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Prikazuje albume i otpremljene datoteke sa Pikase" #~ msgid "Users to show: (,-separated)" #~ msgstr "Korisnici za prikaz (,-razdvojeni)" #~ msgid "Load user and album icons" #~ msgstr "Učitaj ikone korisnika i albuma" #~ msgid "Uploading Pictures" #~ msgstr "Otpremanje slika" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Otpremi slike na veb album Pikasa" #~ msgid "Creating album:" #~ msgstr "Obrazovanje albuma:" #~ msgid "Album created by Kupfer" #~ msgstr "Album napravljen Bakarnikom" #~ msgid "File:" #~ msgstr "Datoteka:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "%(num)d album" #~ msgstr[1] "%(num)d albuma" #~ msgstr[2] "%(num)d albuma" #~ msgstr[3] "%(num)d album" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "%(num)s slika" #~ msgstr[1] "%(num)s slike" #~ msgstr[2] "%(num)s slika" #~ msgstr[3] "%(num)s slika" #~ msgid "Upload to Picasa Album..." #~ msgstr "Otpremanje slika Pikasa album..." #~ msgid "Upload files to Picasa album" #~ msgstr "Otpremi datoteke na Pikasa album" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Otpremi slike na novi veb album Pikase" #~ msgid "Create album from selected local directory" #~ msgstr "Napravi album od izabrane fascikle na računaru" #~ msgid "Picasa Albums" #~ msgstr "Pikasa albumi" #~ msgid "User albums in Picasa" #~ msgstr "Korisnički albumi na Pikasi" #~ msgid "Google Search" #~ msgstr "Gugl pretraga" #~ msgid "Search Google with results shown directly" #~ msgstr "Gugl pretraga sa neposredno prikazanim izlazima" #~ msgid "Show More Results For \"%s\"" #~ msgstr "Prikaži još izlaza pretrage za „%s“" #~ msgid "%s total found" #~ msgstr "Pronašao sam %s" #~ msgid "Gwibber" #~ msgstr "Gviber" #~ msgid "" #~ "Microblogging with Gwibber. Allows sending and receiving messages from " #~ "social networks like Twitter, Identi.ca etc. Requires the package " #~ "'gwibber-service'." #~ msgstr "" #~ "Mikroblogovanje Gviberom omogućava slanje i primanje poruka od društvenih " #~ "mreža kao što je Tviter, Identika, itd. Zahteva paket „gwibber-service“." #~ msgid "Maximum number of messages to show" #~ msgstr "Najveći broj poruka za prikazivanje" #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s na %(service)s" #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s na %(where)s" #~ msgid "Send Message" #~ msgstr "Pošalji poruku" #~ msgid "Send message to all Gwibber accounts" #~ msgstr "Pošalji poruku na sve naloge Gvibera" #~ msgid "Send Message To..." #~ msgstr "Pošalji poruku ka..." #~ msgid "Send message to a Gwibber account" #~ msgstr "Pošalji poruku na nalog Gvibera" #~ msgid "Send message to selected Gwibber account" #~ msgstr "Pošalji poruku na označeni nalog Gvibera" #~ msgid "Reply..." #~ msgstr "Odgovori..." #~ msgid "Delete Message" #~ msgstr "Obriši poruku" #~ msgid "Send Private Message..." #~ msgstr "Pošalji ličnu poruku..." #~ msgid "Send direct message to user" #~ msgstr "Šalje neposrednu poruku korisniku" # :D otcvrkutaću ja u ludaru zbog ovakvih poruka:) #~ msgid "Retweet" #~ msgstr "Otcvrkutaj" #~ msgid "Retweet To..." #~ msgstr "Otcvrkutaj ka..." #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Otcvrkutaj poruku na sve Gviberove naloge" #~ msgid "Retweet message to a Gwibber account" #~ msgstr "Otcvrkutaj poruku na Gviberov nalog" #~ msgid "Open in Browser" #~ msgstr "Otvori u pregledniku" #~ msgid "Open message in default web browser" #~ msgstr "Otvara poruku u podrazumevanom veb pregledniku" #~ msgid "Gwibber Accounts" #~ msgstr "Nalozi Gvibera" #~ msgid "Accounts configured in Gwibber" #~ msgstr "Podešeni nalozi u Gviberu" #~ msgid "Gwibber Messages" #~ msgstr "Poruke Gvibera" #~ msgid "Recent messages received by Gwibber" #~ msgstr "Skorašnje poruke primljene u Gviberu" #~ msgid "Gwibber Messages for %s" #~ msgstr "Gviberove poruke za %s" #~ msgid "Gwibber Streams" #~ msgstr "Gviberovi tokovi" #~ msgid "Streams configured in Gwibber" #~ msgstr "Tokovi podešeni u Gviberu" #~ msgid "Gwibber Messages in %s" #~ msgstr "Gviberove poruke u %s" #~ msgid "Gwibber (Simple)" #~ msgstr "Gviber (jednostavan)" # Osveženje :) #~ msgid "Send updates via the microblogging client Gwibber" #~ msgstr "Pošalji osveženja preko mikroblog klijenta Gvibera" # Pivo, molim! #~ msgid "Send Update" #~ msgstr "Pošalji osveženje" #~ msgid "Unable to activate Gwibber service" #~ msgstr "Ne mogu da pokrenem uslugu Gvibera" #~ msgid "OpenOffice / LibreOffice" #~ msgstr "Open ofis / Libre ofis" #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Skorašnji dokumenti u Open ofisu / Libre ofisu" #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "Skorašnji dokumenti u Open ofisu / Libre ofisu" #~ msgid "Opera Mail" #~ msgstr "Opera pošta" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Radnje i poznanici iz Opera pošte" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Sastavite novu poruku u Opera pošti" #~ msgid "Opera Mail Contacts" #~ msgstr "Poznanici Opera pošte" #~ msgid "Contacts from Opera Mail" #~ msgstr "Poznanici iz Opera pošte" #~ msgid "Opera Bookmarks" #~ msgstr "Opera zabeleške" #~ msgid "Index of Opera bookmarks" #~ msgstr "Sadržaj zabeleški Opere" #~ msgid "PuTTY Sessions" #~ msgstr "Putti sesije (PuTTY)" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Brzi pristup PuTTi sesijama" #~ msgid "Start Session" #~ msgstr "Započni sesiju" #~ msgid "reStructuredText" #~ msgstr "re‑strukturni-tekst" #~ msgid "Render reStructuredText and show the result" #~ msgstr "Iscrtava re-strukturni-tekst i pokazuje rezultat" #~ msgid "View as HTML Document" #~ msgstr "Pregledaj kao HTML dokument" #~ msgid "System Services" #~ msgstr "Sistemske usluge" # Skripta je uvek množina. #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "" #~ "Pokreće, zaustavlja ili ponovo pokreće usluge preko pokretačkih skripti" #~ msgid "Sudo-like Command" #~ msgstr "Sudo-lika naredba" #~ msgid "Start Service" #~ msgstr "Pokreni uslugu" #~ msgid "Stop Service" #~ msgstr "Zaustavi uslugu" #~ msgid "%s Service" #~ msgstr "%s usluga" #~ msgid "Show QRCode" #~ msgstr "Prikaži KuRKod" #~ msgid "Display text as QRCode in a window" #~ msgstr "Prikazuje tekst kao KuRKod u prozoru" #~ msgid "Access to Skype contacts" #~ msgstr "Pristupite Skajp kontaktima" # A? Nikad nisam koristio taj vlasnički program, pa ne znam šta bi ovo trebalo da znači:( #~ msgid "Skype Me" #~ msgstr "Skajpni me" #~ msgid "Logged Out" #~ msgstr "Odjavljen" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Poziv" #~ msgid "Place a call to contact" #~ msgstr "Uputite poziv svim kontaktima" #~ msgid "Skype Contacts" #~ msgstr "Kontakti Skajpa" #~ msgid "Skype Statuses" #~ msgstr "Stanja Skajpa" #~ msgid "TrueCrypt" #~ msgstr "Trukript" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Uređaji iz Trukript istorije" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "Uređaj Trukripta: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Prikači uređaj" #~ msgid "Mount in Truecrypt" #~ msgstr "Prikači Trukriptom" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Pokušava da prikači datoteku kao Trukript uređaj" #~ msgid "Dismount All Volumes" #~ msgstr "Otkači sve uređaje" #~ msgid "TrueCrypt Volumes" #~ msgstr "Trukript uređaji" #~ msgid "Terminal Server Client" #~ msgstr "Klijent za terminalsku uslugu" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Sesija sačuvana u klijentu za terminalsku uslugu" #~ msgid "TSClient sessions" #~ msgstr "Sesije TSklijenta" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Sačuvane sesije u klijentu za terminalsku uslugu" #~ msgid "Vim" #~ msgstr "Vim" #~ msgid "Recently used documents in Vim" #~ msgstr "Nedavno korišćenih dokumenti u Vimu" #~ msgid "Vim Recent Documents" #~ msgstr "Skorašnji dokumenti Vima" #~ msgid "Close (Save All)" #~ msgstr "Zatvori (sačuvaj sve)" #~ msgid "Send..." #~ msgstr "Pošalji..." #~ msgid "Send ex command" #~ msgstr "Pošalji bivšu naredbu" #~ msgid "Insert in Vim..." #~ msgstr "Ubaci u Vim..." #~ msgid "Active Vim Sessions" #~ msgstr "Pokrenute sesije Vima" #~ msgid "Vim Session %s" #~ msgstr "Sesija Vima %s" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Zabeleške i radnje Vinagrea" #~ msgid "Start Vinagre Session" #~ msgstr "Pokreni sesiju Vinagrea" #~ msgid "Vinagre Bookmarks" #~ msgstr "Zabeleške Vinagrea" #~ msgid "VirtualBox" #~ msgstr "Virtualboks" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "Upravljajte nestvarnim mašinama Virtualboksa. Podržava Virtualboks San, i " #~ "izdanje otvorenog izvora." #~ msgid "Force use CLI interface" #~ msgstr "Prisili upotrebu naredbene linije" #~ msgid "Power On" #~ msgstr "Uključi" #~ msgid "Power On Headless" #~ msgstr "Uključi bezglavi" #~ msgid "Send Power Off Signal" #~ msgstr "Pošalji znak za isključenje" #~ msgid "Reboot" #~ msgstr "Ponovo pokreni" #~ msgid "Resume" #~ msgstr "Nastavi" #~ msgid "Save State" #~ msgstr "Sačuvaj stanje" #~ msgid "Power Off" #~ msgstr "Isključi" #~ msgid "VirtualBox Machines" #~ msgstr "Mašine Virtualboksa" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "Pristup stranicama sačuvanim u Zimu — Vikiju okruženja i obloživaču" #~ msgid "Page names start with :colon" #~ msgstr "Nazivi stranica počinju :dvotačkom" #~ msgid "Default page name for quick notes" #~ msgstr "Podrazumevan naziv stranice za brze beleške" #~ msgid "Note %x %X" #~ msgstr "Beleška %x %X" #~ msgid "" #~ "Strftime tags can be used: %H - hour, %M - minutes, etc\n" #~ "Please check python documentation for details.\n" #~ "NOTE: comma will be replaced by _" #~ msgstr "" #~ "Oznake niske funkcije vremena koje mogu biti korišćene: %H — sati, %M — " #~ "minuti, itd\n" #~ "Proverite Pitonovu dokumentaciju za pojedinosti.\n" #~ "Primedba: zapeta će biti zamenjena znakom _" #~ msgid "Default namespace for quick notes" #~ msgstr "Podrazumevani naslov za brzu belešku" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Stranica Zima iz beležnice „%s“" #~ msgid "Create Zim Page" #~ msgstr "Napravite stranicu Zima" #~ msgid "Create page in default notebook" #~ msgstr "Napravite stranicu u podrazumevanoj beležnici" #~ msgid "Create Zim Page In..." #~ msgstr "Napravi stranicu Zima u..." #~ msgid "Insert QuickNote into Zim" #~ msgstr "Unesite brzu belešku u Zim" #~ msgid "Quick note selected text into Zim notebook" #~ msgstr "Označeni tekst brze beleške u beležnici Zima" #~ msgid "Create Subpage..." #~ msgstr "Napravi podstranicu..." #~ msgid "Zim Notebooks" #~ msgstr "Beležnice Zima" #~ msgid "Zim Pages" #~ msgstr "Stranice Zima" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Stranice sačuvane u beležnicama Zima" kupfer-328/po/sv.po000066400000000000000000001600441500175051100142720ustar00rootroot00000000000000# Swedish translations for the kupfer package # Svenska översättningar för paketet kupfer. # Copyright © 2009 Ulrik Sverdrup # This file is distributed under the same license as the kupfer package. (GPLv3) # Ulrik Sverdrup , 2009. # Anders Jonsson , 2015. # msgid "" msgstr "" "Project-Id-Version: kupfer beta\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-24 22:19+0100\n" "PO-Revision-Date: 2017-02-24 22:19+0100\n" "Last-Translator: US\n" "Language-Team: Swedish \n" "Language: sv\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: Poedit 1.8.11\n" msgid "User credentials" msgstr "Användaruppgifter" msgid "_User:" msgstr "_Användare:" msgid "_Password:" msgstr "_Lösenord:" msgid "_Change" msgstr "_Ändra" msgid "Set Keyboard Shortcut" msgstr "Ställ in tangentgenväg" msgid "Please press desired key combination" msgstr "Tryck önskad tangentkombination" msgid "Keybinding could not be bound" msgstr "Snabbtangenten kunde inte bindas" msgid "Kupfer Preferences" msgstr "Inställningar för Kupfer" msgid "Start automatically on login" msgstr "Starta automatiskt vid inloggning" msgid "Show icon in notification area" msgstr "Visa ikon i aviseringsytan" msgid "Terminal emulator:" msgstr "Terminalemulator:" msgid "Desktop Environment" msgstr "Skrivbordsmiljö" msgid "Icon set:" msgstr "Ikonuppsättning:" msgid "Large Icon Size:" msgstr "Stor ikonstorlek" msgid "Small Icon Size:" msgstr "Liten ikonstorlek" msgid "Appearance" msgstr "Utseende" msgid "General" msgstr "Allmänt" msgid "Global Keyboard Shortcuts" msgstr "Globala tangentbordsgenvägar" msgid "Reset" msgstr "Återställ" msgid "Browser Keyboard Shortcuts" msgstr "Tangentbordsgenvägar i bläddrare" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "" "Använd enstaka tangenter som kommandon (Blanksteg, /, punkt, komma etc.)" msgid "Action accelerators use Alt" msgstr "Kommandosnabbtangenter använder Alt" msgid "Action accelerators use Ctrl" msgstr "Kommandosnabbtangenter använder Ctrl" msgid "Keyboard" msgstr "Tangentbord" msgid "Plugins" msgstr "Insticksmoduler" msgid "Inclusion in Top Level Searches" msgstr "Inkluderade i sökningar på toppnivån" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "Objekt från markerade källor är inkluderade i sökningar på toppnivån.\n" "Använd kommandot ‘Sök inuti’ på en avmarkerad källa för att söka i dess " "innehåll." msgid "Indexed Folders" msgstr "Indexerade mappar" msgid "Folders whose files are always available in the catalog." msgstr "Mappar vars innehåll alltid finns tillgängligt i katalogen." msgid "Catalog" msgstr "Katalog" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Programstartare" msgid "Convenient command and access tool for applications and documents" msgstr "Praktiskt kommandoprogram för åtkomst av program och dokument" msgid "Execute in Kupfer" msgstr "Kör i Kupfer" msgid "Saved Kupfer Command" msgstr "Sparat Kupfer-kommando" #, python-format msgid "Could not to carry out '%s'" msgstr "Kunde inte utföra ”%s”" #, python-format msgid "\"%s\" produced a result" msgstr "”%s” lämnade ett resultat" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "Utan rättighet att utföra ”%s” (ej körbar)" #, python-format msgid "Command in \"%s\" is not available" msgstr "Kommando i ”%s” är ej tillgängligt" #, python-format msgid "Keyboard relay is active for display %s" msgstr "Vidaresänding av snabbtangenter är aktivt på display %s" msgid "do not present main interface on launch" msgstr "visa ej fönster vid start" msgid "list available plugins" msgstr "lista tillgängliga insticksmoduler" msgid "enable debug info" msgstr "felsökningsläge" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "kör hjälpprogram för insticksmodul" msgid "show usage help" msgstr "visa hjälpmeddelande" msgid "show version information" msgstr "visa programversion" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Användning: kupfer [ FLAGGOR | FIL ... ]" msgid "Available plugins:" msgstr "Tillgängliga insticksmoduler:" #, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgid "Type to search" msgstr "Skriv för att söka" #, python-format msgid "%s is empty" msgstr "%s är tom" msgid "Text" msgstr "Text" msgid "Run after Delay..." msgstr "Utför med fördröjning..." msgid "Perform command after a specified time interval" msgstr "Utför kommando efter angivet tidsintervall" msgid "Multiple Objects" msgstr "Flera objekt" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s objekt" msgstr[1] "%s objekt" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "okänd" msgid "Aim" msgstr "Aim" msgid "Google Talk" msgstr "Google Talk" msgid "ICQ" msgstr "ICQ" msgid "MSN" msgstr "MSN" msgid "QQ" msgstr "QQ" msgid "Yahoo" msgstr "Yahoo" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "%s stödjer inte operationen" msgid "Can not be used with multiple objects" msgstr "Kan inte användas med flera objekt" msgid "Open" msgstr "Öppna" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "Det finns inget förvalt program för ”%(file)s” (%(type)s)." #, python-format msgid "Please use \"%s\"" msgstr "V.v. använd ”%s”" msgid "Set Default Application..." msgstr "Välj standardprogram..." msgid "Open with default application" msgstr "Öppna med förvalt program" msgid "Get Parent Folder" msgstr "Välj föräldermapp" msgid "Open Terminal Here" msgstr "Öppna i terminalfönster" msgid "Open this location in a terminal" msgstr "Öppna platsen i terminalfönster" msgid "Run in Terminal" msgstr "Kör i terminalfönster" msgid "Run (Execute)" msgstr "Kör" msgid "Run this program in a Terminal" msgstr "Kör programmet i terminalfönster" msgid "Run this program" msgstr "Kör programmet" msgid "Go To" msgstr "Gå till" msgid "Open URL" msgstr "Öppna URL" msgid "Open URL with default viewer" msgstr "Öppna URL med standardprogram" msgid "Launch" msgstr "Starta" msgid "Show application window" msgstr "Visa programfönster" msgid "Launch application" msgstr "Starta program" msgid "Launch Again" msgstr "Starta igen" msgid "Launch another instance of this application" msgstr "Starta programmet igen" msgid "Close" msgstr "Stäng" msgid "Attempt to close all application windows" msgstr "Försök att stänga alla programmets fönster" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Utför" msgid "Perform command" msgstr "Utför kommando" msgid "(Empty Text)" msgstr "(Tom text)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "”%(text)s”" msgstr[1] "(%(num)d rader) ”%(text)s”" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s et. al." #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "Rekursiv källa %(dir)s, (%(levels)d nivåer)" #, python-format msgid "Directory source %s" msgstr "Katalogkälla %s" msgid "Home Folder" msgstr "Hemmapp" msgid "Catalog Index" msgstr "Katalogindex" msgid "An index of all available sources" msgstr "Index över alla tilgängliga kataloger" msgid "Root catalog" msgstr "Rotkatalog" msgid "Please Configure Plugin" msgstr "V.v. konfigurera insticksmodulen" #, python-format msgid "Plugin %s is not configured" msgstr "%s är inte konfigurerad" #, python-format msgid "Invalid user credentials for %s" msgstr "Ogiltiga användaruppgifter för %s" msgid "Applications" msgstr "Program" msgid "All applications and preferences" msgstr "Alla program och inställningspaneler" msgid "Applications for Desktop Environment" msgstr "Program för skrivbordsmiljö" msgid "Use Desktop Filter" msgstr "Använd skrivbords-filter" msgid "Open With..." msgstr "Öppna med..." msgid "Open with any application" msgstr "Öppna med godtyckligt program" msgid "Set default application to open this file type" msgstr "Välj förvalsprogram att öppna filer av den här typen med." msgid "Reset Associations" msgstr "Återställ associationer" msgid "Reset program associations for files of this type." msgstr "Återställ associerade program för filer av den här typen." msgid "Deep Archives" msgstr "Djupa arkiv" msgid "Allow browsing inside compressed archive files" msgstr "Tillåt att titta inuti komprimerade filer" #, python-format msgid "Content of %s" msgstr "Innehåll för %s" msgid "Archive Manager" msgstr "Arkivhanterare" msgid "Use Archive Manager actions" msgstr "Använd funktioner i arkivhanteraren" msgid "Compressed archive type for 'Create Archive In'" msgstr "Arkivtyp för ‘Skapa arkiv i’" msgid "Extract Here" msgstr "Extrahera här" msgid "Extract compressed archive" msgstr "Packa upp komprimerad fil" msgid "Create Archive" msgstr "Skapa arkiv" msgid "Create a compressed archive from folder" msgstr "Skapa komprimerat arkiv av mappen" msgid "Create Archive In..." msgstr "Skapa arkiv i..." #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Arkiv" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "Kontrollera Audacious uppspelning och spellista" msgid "Include songs in top level" msgstr "Inkludera låtar i toppnivån" msgid "Enqueue" msgstr "Köa" msgid "Add track to the Audacious play queue" msgstr "Lägg till spår i spelkön" msgid "Dequeue" msgstr "Ta ur kön" msgid "Remove track from the Audacious play queue" msgstr "Ta bort spår från spelkön" msgid "Play" msgstr "Spela upp" msgid "Jump to track in Audacious" msgstr "Hoppa till nästa spår i Audacious" msgid "Resume playback in Audacious" msgstr "Starta uppspelning i Audacious" msgid "Pause" msgstr "Paus" msgid "Pause playback in Audacious" msgstr "Pausa uppspelning i Audacious" msgid "Next" msgstr "Nästa" msgid "Jump to next track in Audacious" msgstr "Hoppa till nästa spår i Audacious" msgid "Previous" msgstr "Föregående" msgid "Jump to previous track in Audacious" msgstr "Hoppa till föregående spår i Audacious" msgid "Clear Queue" msgstr "Rensa kön" msgid "Clear the Audacious play queue" msgstr "Rensa Audacious spelkö" msgid "Shuffle" msgstr "Blanda" msgid "Toggle shuffle in Audacious" msgstr "Växla blandad uppspelning i Audacious" msgid "Repeat" msgstr "Upprepa" msgid "Toggle repeat in Audacious" msgstr "Växla repetera i Audacious" msgid "Show Playing" msgstr "Vilken låt?" msgid "Tell which song is currently playing" msgstr "Visa vilken låt som spelas just nu" msgid "Playlist" msgstr "Spellista" msgid "Calculator" msgstr "Miniräknare" msgid "Calculate mathematical expressions" msgstr "Beräka matematiska uttryck" msgid "Calculate" msgstr "Beräkna" msgid "Clipboards" msgstr "Urklipp" msgid "Recent clipboards and clipboard proxy objects" msgstr "Senaste urklipp och proxyobjekt till urklipp" msgid "Number of recent clipboards to remember" msgstr "Antal senaste urklipp som sparas" msgid "Include selected text in clipboard history" msgstr "Inkludera markerad text i historiken" msgid "Copy selected text to primary clipboard" msgstr "Kopiera markerad text till urklippet" msgid "Selected Text" msgstr "Markering" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "Urklipp ”%(desc)s”" msgstr[1] "Urklipp med %(num)d rader ”%(desc)s”" msgid "Clipboard Text" msgstr "Urklippt text" msgid "Clipboard File" msgstr "Urklippt fil" msgid "Clipboard Files" msgstr "Urklippta filer" msgid "Clear" msgstr "Rensa" msgid "Remove all recent clipboards" msgstr "Ta bort senaste urklipp" msgid "Shell Commands" msgstr "Skalkommandon" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Kör skalkommandon. Kommandon markerade med symbolen %s kör i ett underskal." msgid "Run (Get Output)" msgstr "Kör (Hämta utdata)" msgid "Run program and return its output" msgstr "Kör ett program och returnera dess utdata" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "Skicka till kommando..." msgid "Run program with object as an additional parameter" msgstr "Kör ett program och skicka objektet som sista parameter" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "Skriv till kommando..." msgid "Run program and supply text on the standard input" msgstr "Kör ett program och skriv texten på std. in" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "Filtrera genom kommando..." msgid "Run command-line programs" msgstr "Kör kommandoradsprogram" msgid "GTK+" msgstr "GTK+" msgid "GNOME Terminal" msgstr "GNOME-terminal" msgid "XFCE Terminal" msgstr "XFCE-terminal" msgid "LXTerminal" msgstr "LXTerminal" msgid "X Terminal" msgstr "X-terminal" msgid "Urxvt" msgstr "Urxvt" msgid "Konsole" msgstr "Konsole" msgid "Save As..." msgstr "Spara som..." msgid "Restart Kupfer" msgstr "Starta om Kupfer" msgid "Quit" msgstr "Avsluta" msgid "Quit Kupfer" msgstr "Avsluta Kupfer" msgid "About Kupfer" msgstr "Om Kupfer" msgid "Show information about Kupfer authors and license" msgstr "Visa information om Kupfers upphovsmän och licens" msgid "Kupfer Help" msgstr "Hjälp med Kupfer" msgid "Get help with Kupfer" msgstr "Öppna Kupfers användardokumentation" msgid "Show preferences window for Kupfer" msgstr "Visa Kupfers inställningsfönster" msgid "Search Contents" msgstr "Sök inuti" msgid "Search inside this catalog" msgstr "Sök bland objekt i katalogen" msgid "Copy" msgstr "Kopiera" msgid "Copy to clipboard" msgstr "Kopiera till urklipp" msgid "Rescan" msgstr "Uppdatera" msgid "Force reindex of this source" msgstr "Tvinga omläsning av källan" msgid "Last Command" msgstr "Senaste kommando" msgid "Internal Kupfer Objects" msgstr "Interna Kupfer-objekt" msgid "Last Result" msgstr "Senaste resultat" msgid "Command Results" msgstr "Kommandoresultat" msgid "Custom Terminal" msgstr "Valfri terminal" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" "Konfigurera valfri terminal.\n" "\n" "Ett till terminalalternativ läggs till (välj på första sidan)." msgid "Command" msgstr "Kommando" msgid "Execute flag" msgstr "Kör-flagga" msgid "Default Email Client" msgstr "Förvald e-postläsare" msgid "Compose email using the system's default mailto: handler" msgstr "Skriv nytt e-postmeddelande m.h.a systemets mailto:-hanterare" msgid "Compose Email To" msgstr "Skriv e-postmeddelande till" msgid "Dictionary" msgstr "Ordbok" msgid "Look up word in dictionary" msgstr "Slå upp ord i ordboken" msgid "Look Up" msgstr "Slå upp" msgid "Documents" msgstr "Dokument" msgid "Recently used documents and bookmarked folders" msgstr "Senaste dokument och bokmärkta platser" msgid "Max recent document days" msgstr "Maximal ålder för senaste dokument (dagar)" msgid "Recent Items" msgstr "Senaste dokument" msgid "Recently used documents" msgstr "Senast använda dokument" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "%s-dokument" #, python-format msgid "Recently used documents for %s" msgstr "Senaste dokument för %s" msgid "Places" msgstr "Platser" msgid "Bookmarked folders" msgstr "Bokmärkta mappar" msgid "Toggle Recent Documents" msgstr "Slå på/av senaste dokument" msgid "Enable/disable listing recent documents in content for this application" msgstr "Aktivera/deaktivera senaste dokument som innehåll i programmet" msgid "DuckDuckGo Search" msgstr "Sök med DuckDuckGo" msgid "Search the web securely with DuckDuckGo" msgstr "Säker webbsökning med DuckDuckGo" msgid "Favorites" msgstr "Favoriter" msgid "Mark commonly used items and store objects for later use" msgstr "Märk ofta använda objekt eller lagra objekt för senare användning" msgid "Shelf of \"Favorite\" items" msgstr "Plats för favoritobjekt" msgid "Add to Favorites" msgstr "Lägg till favorit" msgid "Add item to favorites shelf" msgstr "Lägg till objekt till favorithyllan" msgid "Remove from Favorites" msgstr "Ta bort favorit" msgid "Remove item from favorites shelf" msgstr "Ta bort objekt från favorithyllan" msgid "File Actions" msgstr "Filkommandon" msgid "More file actions" msgstr "Fler filkommandon" msgid "Move To..." msgstr "Flytta till..." msgid "Move file to new location" msgstr "Flytta till ny plats" msgid "Rename To..." msgstr "Byt namn..." msgid "Copy To..." msgstr "Kopiera till..." msgid "Copy file to a chosen location" msgstr "Kopiera filen till vald plats" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "Glob" msgid "Select objects using '*' and '?' as wildcards." msgstr "Välj objekt med glob (* och ? är jokertecken)." msgid "Higher-order Actions" msgstr "Högre ordningens kommandon" msgid "Tools to work with commands as objects" msgstr "Verktyg för att jobba med kommandon som objekt" msgid "Select in Kupfer" msgstr "Välj i Kupfer" #, python-format msgid "Result of %s (%s)" msgstr "Resultat av %s (%s)" msgid "Run (Take Result)" msgstr "Utför (Ta resultat)" msgid "Take the command result as a proxy object" msgstr "Ta kommandoresultat som proxyobjekt" msgid "Run (Discard Result)" msgstr "Utför (Kasta bort resultat)" msgid "Image Tools" msgstr "Bildverktyg" msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Bildtranformeringskommandon (använder 'convert' från ImageMagick)" msgid "Scale..." msgstr "Skala..." msgid "Scale image to fit inside given pixel measure(s)" msgstr "Skala bilden för att passa inom given storlek" msgid "Rotate Clockwise" msgstr "Rotera medurs" msgid "Rotate Counter-Clockwise" msgstr "Rotera moturs" msgid "Autorotate" msgstr "Autorotera" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "Rotera JPEG (på plats) enligt EXIF-metadata" msgid "Kupfer Plugins" msgstr "Kupfers insticksmoduler" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Lista Kupfers insticksmoduler i Kupfer" msgid "Show Information" msgstr "Visa information" msgid "Show Source Code" msgstr "Visa källkod" msgid "enabled" msgstr "aktiverad" msgid "disabled" msgstr "ej aktiverad" msgid "Notes" msgstr "Anteckningar" msgid "Gnote or Tomboy notes" msgstr "Gnote- eller Tomboy-anteckningar" msgid "Work with application" msgstr "Använd program" msgid "Open with notes application" msgstr "Öppna med anteckningsprogarm" msgid "Append to Note..." msgstr "Lägg till anteckning..." msgid "Add text to existing note" msgstr "Tillfoga texten till existerande anteckning" msgid "Append..." msgstr "Lägg till..." msgid "Create Note" msgstr "Skapa anteckning" msgid "Create a new note from this text" msgstr "Skapa en ny anteckning från texten" msgid "Get Note Search Results..." msgstr "Hämta träffar i anteckningar..." msgid "Show search results for this query" msgstr "Visa träffar för denna sökning" #, python-format msgid "today, %s" msgstr "idag, %s" #, python-format msgid "yesterday, %s" msgstr "igår, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "Senast ändrad %s" msgid "Quicksilver Icons" msgstr "Quicksilver-ikoner" msgid "Quick Image Viewer" msgstr "Snabb bildvisare" msgid "View Image" msgstr "Visa bild" msgid "GNU Screen" msgstr "GNU Screen" msgid "Active GNU Screen sessions" msgstr "Aktiva GNU Screen-sessioner" msgid "Attached" msgstr "Ansluten" msgid "Detached" msgstr "Frånkopplad" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "%(status)s session (%(pid)s) skapad %(time)s" msgid "Screen Sessions" msgstr "Screen-sessioner" msgid "Attach" msgstr "Anslut till" msgid "Send Keys" msgstr "Skicka tangenter" msgid "Send synthetic keyboard events using xautomation" msgstr "Skicka syntetiska tangentbordshändelser m.h.a. xautomation" msgid "Paste to Foreground Window" msgstr "Klistra in i främsta fönstret" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "Kopiera till urklippet och skicka Ctrl+V till främsta fönstret" msgid "Send keys to foreground window" msgstr "Skicka tangenter till främsta fönstret" msgid "Type Text" msgstr "Skriv text" msgid "Type the text to foreground window" msgstr "Skriv texten till främsta fönstret" msgid "GNOME Session Management" msgstr "Sessionshantering i GNOME" msgid "Special items and actions for GNOME environment" msgstr "Speicella objekt och kommandon för GNOME" msgid "Log Out..." msgstr "Logga ut..." msgid "Log out or change user" msgstr "Logga ut eller byt användare" msgid "Shut Down..." msgstr "Stäng av..." msgid "Shut down, restart or suspend computer" msgstr "Stäng av, starta om eller sätt datorn i vänteläge" msgid "Lock Screen" msgstr "Lås skärmen" msgid "Enable screensaver and lock" msgstr "Aktivera skärmsläckaren och lås skärmen" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "Sessionshantering i XFCE" msgid "Special items and actions for XFCE environment" msgstr "Speicella objekt och kommandon för XFCE" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "SSH-värdar" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "Tillhandahåller SSH-värdar från ~/.ssh/config" msgid "SSH host" msgstr "SSH-värd" msgid "Connect" msgstr "Anslut" msgid "Connect to SSH host" msgstr "Anslut till SSH-värd" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "SSH-värdar konfigurerade i ~/.ssh/config" msgid "No D-Bus connection to desktop session" msgstr "Ingen D-Bus-anslutning till sessionen" #, python-format msgid "Dependency '%s' is not available" msgstr "Beroende ”%s” är ej tillgängligt" msgid "Document Templates" msgstr "Dokumentmallar" msgid "Create new documents from your templates" msgstr "Skapa dokument från mallar" #, python-format msgid "%s template" msgstr "%s-mall" msgid "Empty File" msgstr "Tom fil" msgid "New Folder" msgstr "Ny mapp" msgid "Create New Document..." msgstr "Skapa nytt dokument..." msgid "Create a new document from template" msgstr "Skapa nytt dokument från mall" msgid "Create Document In..." msgstr "Skapa dokument i..." msgid "Textfiles" msgstr "Textfiler" msgid "Append To..." msgstr "Lägg till..." msgid "Write To..." msgstr "Skriv till..." msgid "Write the text to a new file in specified directory" msgstr "Skriv texten till en ny fil i den angivna katalogen" msgid "Get Text Contents" msgstr "Hämta textinnehåll" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "Kommandon i filhanteraren Thunar" msgid "Select in File Manager" msgstr "Välj i filhanteraren" msgid "Show Properties" msgstr "Visa egenskaper" msgid "Show information about file in file manager" msgstr "Visa information om filen i filhanteraren" msgid "Send To..." msgstr "Skicka till..." msgid "Symlink In..." msgstr "Mjuk länk (symlink) i..." msgid "Create a symlink to file in a chosen location" msgstr "Skapa mjuk länk till filen vid vald plats" msgid "Empty Trash" msgstr "Töm papperskorgen" msgid "Thunar Send To Objects" msgstr "Thunar Skicka till-objekt" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Thunderbird eller Icedove-kontakter och kommandon" msgid "Compose New Email" msgstr "Skriv nytt e-postmeddelande" msgid "Compose a new message in Thunderbird" msgstr "Skriv nytt mail i Thunderbird" msgid "Attach in Email To..." msgstr "Bifoga i e-post till..." msgid "Compose Email With" msgstr "Skriv e-postmeddelande med" msgid "Compose a new message using the text as body" msgstr "Skriv nytt mail med texten" msgid "Thunderbird Address Book" msgstr "Thunderbird adressbok" msgid "Contacts from Thunderbird Address Book" msgstr "Kontakter från Thunderbird" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Aktiviteter" msgid "Show running tasks and allow sending signals to them" msgstr "Visa aktuella processer och skicka signaler till dem" msgid "Sort Order" msgstr "Sortering" msgid "Commandline" msgstr "Kommandorad" msgid "CPU usage (descending)" msgstr "Processoranvändning" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Minnesanvändning" msgid "Send Signal..." msgstr "Skicka signal..." msgid "Signals" msgstr "Signaler" msgid "Running Tasks" msgstr "Aktuella processer" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgid "Running tasks for current user" msgstr "Aktuella processer för nuvarande användare" msgid "Trash" msgstr "Papperskorg" msgid "Access trash contents" msgstr "Tillgång till papperskorgens innehåll" msgid "Move to Trash" msgstr "Flytta till papperskorgen" msgid "Move this file to trash" msgstr "Flytta filen till papperskorgen" msgid "Restore" msgstr "Återskapa" msgid "Move file back to original location" msgstr "Flytta tillbaka till ursprunglig plats" msgid "" "Could not delete files:\n" " " msgstr "" "Kunde ej radera filer:\n" " " msgid "Trash is empty" msgstr "Papperskorgen är tom" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "Papperskorgen innehåller ett objekt" msgstr[1] "Papperskorgen innehåller %(num)s objekt" msgid "Triggers" msgstr "Utlösare" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "Tilldela globala tangentbordsgenvägar till kommandon skapade med ‘Bygg " "kommando’" msgid "Add Trigger..." msgstr "Lägg till utlösare..." msgid "Remove Trigger" msgstr "Ta bort utlösare" msgid "URL Actions" msgstr "URL-kommandon" msgid "Download and Open" msgstr "Hämta och öppna" msgid "Download To..." msgstr "Hämta till..." msgid "Download URL to a chosen location" msgstr "Hämta till en vald plats" msgid "Wikipedia" msgstr "Wikipedia" msgid "Search in Wikipedia" msgstr "Sök i Wikipedia" msgid "Wikipedia language" msgstr "Wikipedia-språk" #. TRANS: Default wikipedia language code msgid "en" msgstr "sv" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Sök efter denna termen i %s.wikipedia.org" msgid "Window List" msgstr "Fönsterlista" msgid "All windows on all workspaces" msgstr "Alla fönster på alla arbetsytor" msgid "Activate" msgstr "Aktivera" msgid "Shade" msgstr "Rulla upp" msgid "Unshade" msgstr "Rulla ner" msgid "Minimize" msgstr "Minimera" msgid "Unminimize" msgstr "Avminimera" msgid "Maximize" msgstr "Maximera" msgid "Unmaximize" msgstr "Avmaximera" msgid "Maximize Vertically" msgstr "Maximera vertikalt" msgid "Unmaximize Vertically" msgstr "Avmaximera vertikalt" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "Fönster på %(wkspc)s" msgid "Frontmost Window" msgstr "Främsta fönster" msgid "Next Window" msgstr "Nästa fönster" msgid "Jump to this window's workspace and focus" msgstr "Gå till fönstrets arbetsyta och aktivera" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "%d fönster" msgstr[1] "%d fönster" msgid "Active workspace" msgstr "Aktiv arbetsyta" msgid "Jump to this workspace" msgstr "Hoppa till arbetsytan" msgid "Workspaces" msgstr "Arbetsytor" msgid "Volumes and Disks" msgstr "Volymer" msgid "Mounted volumes and disks" msgstr "Monterade volymer och löstagbara enheter" #, python-format msgid "Volume mounted at %s" msgstr "Volym monterad vid %s" msgid "Unmount" msgstr "Avmontera" msgid "Unmount finished" msgstr "Avmontering avslutad" #, python-format msgid "\"%s\" was successfully unmounted" msgstr "”%s” avmonterades utan problem" msgid "Unmount this volume" msgstr "Avmontera volym" msgid "Eject" msgstr "Mata ut" msgid "Unmount and eject this media" msgstr "Avmontera och mata ut media" msgid "Show Text" msgstr "Visa text" msgid "Display text in a window" msgstr "Visa text i ett fönster" msgid "Large Type" msgstr "Visa med stor text" msgid "Show Notification" msgstr "Visa avisering" msgid "Tracker" msgstr "Tracker" msgid "Tracker desktop search integration" msgstr "Integration med sökprogrammet Tracker" msgid "Search in Tracker" msgstr "Sök i Tracker" msgid "Open Tracker Search Tool and search for this term" msgstr "Sök efter denna term i Sökverktyget Tracker" msgid "Get Tracker Results..." msgstr "Hämta träffar från Tracker..." msgid "Show Tracker results for query" msgstr "Visa träffar för sökning med Tracker" #, python-format msgid "Tracker Search for \"%s\"" msgstr "Tracker-sökning efter \"%s\"" #, python-format msgid "Results for \"%s\"" msgstr "Resultat för ”%s”" msgid "Tracker Full Text Search" msgstr "Fulltextsökning i Tracker" msgid "Use '?' prefix to get full text results" msgstr "Använd ?-prefix för att få fulltextresultat" msgid "Locate Files" msgstr "Locate" msgid "Search filesystem using locate" msgstr "Sök filsystemet med ‘locate’" msgid "Ignore case distinctions when searching files" msgstr "Ignorera skillnad i gemener och VERSALER" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Firefox-bokmärken" msgid "Index of Firefox bookmarks" msgstr "Index över Firefox-bokmärken" msgid "Firefox Keywords" msgstr "Firefox nyckelord" msgid "Search the web with Firefox keywords" msgstr "Webbsökning med Firefox nyckelord" msgid "Search With..." msgstr "Sök med..." msgid "Search For..." msgstr "Sök efter..." msgid "Search Terms" msgstr "Söktermer" msgid "Media Player Control" msgstr "Mediaspelarkontroll" msgid "Playback control for media players" msgstr "Kontrollera uppspelning i mediaspelare" #. TRANS: %s is a media player name #, python-format msgid "Play/Pause (%s)" msgstr "Spela/Pausa (%s)" msgid "Resume playback" msgstr "Starta uppspelning" msgid "Pause All" msgstr "Pausa alla" #. TRANS: %s is a media player name #, python-format msgid "Next (%s)" msgstr "Nästa (%s)" msgid "Skip to next track" msgstr "Hoppa till nästa spår" #. TRANS: %s is a media player name #, python-format msgid "Previous (%s)" msgstr "Föregående (%s)" msgid "Skip to previous track" msgstr "Hoppa till föregående spår" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "Stoppa (%s)" msgid "Stop playback" msgstr "Stoppa uppspelning" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "Tillgång till Pidgin-kontakter" msgid "Show offline contacts" msgstr "Visa frånkopplade kontakter" msgid "Open Chat" msgstr "Öppna chatt" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d tecken)" msgstr[1] "%s (%d tecken)" msgid "Send Message..." msgstr "Skicka meddelande..." msgid "Available" msgstr "Tillgänglig" msgid "Away" msgstr "Frånvarande" msgid "Pidgin Contacts" msgstr "Pidgin-kontakter" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Förkorta länkar" msgid "Create short aliases of long URLs" msgstr "Skapa korta alias för långa webbadresser" msgid "Error" msgstr "Fel" msgid "Shorten With..." msgstr "Förkorta med..." msgid "Services" msgstr "Service" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "Spela spår och sök i musikbiblioteket" msgid "Include artists in top level" msgstr "Inkludera artister i toppnivån" msgid "Include albums in top level" msgstr "Inkludera album i toppnivån" msgid "Play tracks in Rhythmbox" msgstr "Spela upp spår i Rhythmbox" msgid "Add tracks to the play queue" msgstr "Lägg till spår i spelkön" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "av %(artist)s från %(album)s" msgid "Get File" msgstr "Hämta Fil" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "av %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "Spår av %s" msgid "Albums" msgstr "Album" msgid "Music albums in Rhythmbox Library" msgstr "Album i Rhythmboxs bibliotek" msgid "Artists" msgstr "Artister" msgid "Music artists in Rhythmbox Library" msgstr "Artister i Rhythmboxs bibliotek" msgid "Songs" msgstr "Låtar" msgid "Songs in Rhythmbox library" msgstr "Låtar i Rhythmboxs bibliotek" msgid "Getting Things GNOME" msgstr "Getting Things GNOME!" msgid "Browse and create new tasks in GTG" msgstr "Bläddra i och skapa nya uppgifter i GTG" #, python-format msgid "due: %s" msgstr "förfaller: %s" #, python-format msgid "start: %s" msgstr "start: %s" #, python-format msgid "tags: %s" msgstr "taggar: %s" msgid "Open task in Getting Things GNOME!" msgstr "Öppna uppgift i Getting Things GNOME" msgid "Delete" msgstr "Radera" msgid "Permanently remove this task" msgstr "Ta bort uppgift permanent" msgid "Mark Done" msgstr "Markera som slutförd" msgid "Mark this task as done" msgstr "Markera uppgift som slutförd" msgid "Dismiss" msgstr "Avfärda" msgid "Mark this task as not to be done anymore" msgstr "Markera att uppgiften inte ska göras längre" msgid "Create Task" msgstr "Skapa uppgift" msgid "Create new task in Getting Things GNOME" msgstr "Skapa ny uppgift i Getting Things GNOME" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "Sök i Devhelp" msgid "Nemo" msgstr "Nemo" msgid "File manager actions" msgstr "Kommandon i filhanteraren" msgid "Prefer Dark Theme" msgstr "Föredra mörkt tema" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Alternativ aktivera" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Kommatricket" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Bygg kommando" msgid "Mark Default Action" msgstr "Sätt standardkommando" msgid "Forget Object" msgstr "Glöm objekt" msgid "Reset All" msgstr "Återställ alla" msgid "Select Quit" msgstr "Välj Avsluta" msgid "Select Selected File" msgstr "Välj markerad fil" msgid "Select Selected Text" msgstr "Välj markering" msgid "Select Clipboard File" msgstr "Välj urklippt fil" msgid "Select Clipboard Text" msgstr "Välj urklippt text" msgid "Show Help" msgstr "Visa hjälp" msgid "Show Preferences" msgstr "Visa inställningar" msgid "Switch to 1st Pane" msgstr "Välj 1:a rutan" msgid "Switch to 2nd Pane" msgstr "Välj 2:a rutan" msgid "Switch to 3rd Pane" msgstr "Välj 3:e rutan" msgid "Toggle Text Mode" msgstr "Växla fritextläge" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "Inga träffar i %(src)s för ”%(query)s”" msgid "No matches" msgstr "Inga träffar" #, python-format msgid "No action matches \"%s\"" msgstr "Inga kommandon för ”%s”" #, python-format msgid "Assign Accelerator to \"%(action)s\"" msgstr "Välj snabbtangent för ”%(action)s”" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Gör ”%(action)s” till standard för ”%(object)s”" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "Glöm bort ”%s”" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Visa huvudgränssnitt" msgid "Show with Selection" msgstr "Visa med markering" #. TRANS: Plugin info fields msgid "Description" msgstr "Beskrivning" msgid "Author" msgstr "Upphovsman" msgid "Version" msgstr "Version" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "Behöver Python-modulen ‘%s’" msgid "Plugin could not be read due to an error:" msgstr "Insticksmodulen kunde inte läsas in på grund av ett fel:" msgid "Content of" msgstr "Innehålls i" #. TRANS: Plugin contents header msgid "Sources" msgstr "Källor" #. TRANS: Plugin contents header msgid "Actions" msgstr "Kommandon" #, python-format msgid "Using encrypted password storage: %s" msgstr "Använder krypterad lösenordslagring: %s" #, python-format msgid "Using password storage: %s" msgstr "Använder lösenordslagring: %s" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Inställningar" msgid "Set username and password" msgstr "Ställ in användaruppgifter" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Välj mapp" msgid "Reset all shortcuts to default values?" msgstr "Återställ alla genvägar till standardinställningen?" msgid "Shortcut" msgstr "Genväg" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "Ulrik Sverdrup " msgid "A free software (GPLv3+) launcher" msgstr "En startare och ett stycke fri programvara (GPLv3+)" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Detta program är fri programvara. Du kan distribuera det och/eller\n" "modifiera det under villkoren i GNU General Public License, publicerad\n" "av Free Software Foundation, antingen version 3 eller (om du så vill)\n" "någon senare version. \n" "\n" "Detta program distribueras i hopp om att det ska vara användbart, men\n" "UTAN NÅGON SOM HELST GARANTI, även utan underförstådd garanti om\n" "SÄLJBARHET eller LÄMPLIGHET FÖR NÅGOT SPECIELLT ÄNDAMÅL.\n" "Se GNU General Public License för ytterligare information.\n" "\n" "Du bör ha fått en kopia av GNU General Public License tillsammans med\n" "detta program. Om inte, .\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Hittade ingen aktiv Kupfer-process" #~ msgid "Start" #~ msgstr "Start" #~ msgid "Reveal" #~ msgstr "Visa" #~ msgid "GNOME Keyring" #~ msgstr "GNOME-nyckelring" #~ msgid "KWallet" #~ msgstr "KWallet" #~ msgid "Unencrypted File" #~ msgstr "Ej krypterad fil" #~ msgid "Empathy" #~ msgstr "Empathy" #~ msgid "Access to Empathy Contacts" #~ msgstr "Tillgång till Empathy-kontakter" #~ msgid "Busy" #~ msgstr "Stör inte" #~ msgid "Not Available" #~ msgstr "Ej tillgänglig" #~ msgid "Invisible" #~ msgstr "Osynlig" #~ msgid "Offline" #~ msgstr "Frånkopplad" #~ msgid "Change Global Status To..." #~ msgstr "Ändra global status till..." #~ msgid "Empathy Contacts" #~ msgstr "Empathy-kontakter" #~ msgid "Empathy Account Status" #~ msgstr "Empathy-status" #~ msgid "Type to search %s" #~ msgstr "Skriv för att söka i %s" #~ msgid "No action" #~ msgstr "Inget kommando" #~ msgid "Compose Email" #~ msgstr "Skriv e-postmeddelande" #~ msgid "Send in Email To..." #~ msgstr "Skicka med e-post till..." #~ msgid "GNOME Terminal Profiles" #~ msgstr "GNOME-terminal-profiler" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "Starta GNOME-terminal-profiler" #~ msgid "Multihead Support" #~ msgstr "Stöd för flera skärmar (”multihead”)" #~ msgid "Calculate expressions starting with '='" #~ msgstr "Beräkna uttryck som börjar med ”=”" #~ msgid "Epiphany Bookmarks" #~ msgstr "Epiphany-bokmärken" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Index över Epiphany-bokmärken" #~ msgid "Include visited sites" #~ msgstr "Inkludera besökta sidor" #~ msgid "Firefox tag" #~ msgstr "Firefox-tagg" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Starta uppspelning i Rhythmbox" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Pausa uppspelning i Rhythmbox" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Hoppa till nästa spår i Rhythmbox" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Hoppa till föregående spår i Rhythmbox" #~ msgid "Search the Web" #~ msgstr "Webbsökning" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Senaste dokument i Abiword" #~ msgid "Abiword Recent Items" #~ msgstr "Abiwords senaste dokument" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "Arbeta med pakethanteraren APT" #~ msgid "Installation method" #~ msgstr "Installationsmetod" #~ msgid "Show Package Information" #~ msgstr "Visa paketinformation" #~ msgid "Install" #~ msgstr "Installera" #~ msgid "Install package using the configured method" #~ msgstr "Installera paket m.h.a den konfigurerade metoden" #~ msgid "Packages matching \"%s\"" #~ msgstr "Paketträffar för ”%s”" #~ msgid "Search Package Name..." #~ msgstr "Sök paketnamn..." #~ msgid "Ascii & Unicode Icon Set" #~ msgstr "Ascii & Unicode ikonuppsättningar" #~ msgid "" #~ "Provides the Ascii and Unicode icon sets that use letters and symbols to " #~ "produce icons for the objects found in Kupfer." #~ msgstr "" #~ "Ikonuppsättningarna Ascii respektive Unicode använder bokstäver och " #~ "symboler som ikoner för objekt i Kupfer." #~ msgid "Ascii" #~ msgstr "Ascii" #~ msgid "Unicode" #~ msgstr "Unicode" #~ msgid "Chromium Bookmarks" #~ msgstr "Chromium-bokmärken" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Index över Chromium-bokmärken" #~ msgid "Claws Mail" #~ msgstr "Claws Mail" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Claws Mail-kontakter och kommandon" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Skriv nytt meddelande med Claws Mail" #~ msgid "Receive All Email" #~ msgstr "Hämta all e-post" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "Hämta nya meddelanden från alla konton i Claws Mail" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Skapa nytt meddelande i ClawsMail och bifoga filen" #~ msgid "Claws Mail Address Book" #~ msgstr "Claws Mail-adressbok" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Kontakter från Claws Mail" #~ msgid "Configure a custom terminal emulator" #~ msgstr "Konfigurera en valfri terminal" #~ msgid "Custom Theme" #~ msgstr "Valfritt tema" #~ msgid "Use a custom color theme" #~ msgstr "Använd ett valfritt färgtema" #~ msgid "Theme:" #~ msgstr "Tema:" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Evolution-kontakter" #~ msgid "Compose a new message in Evolution" #~ msgstr "Skriv nytt meddelande med Evolution" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Skapa nytt meddelande i Evolution och bifoga filen" #~ msgid "Evolution Address Book" #~ msgstr "Evolution-adressbok" #~ msgid "Filezilla" #~ msgstr "Filezilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "Visa platser och hantera ftp-adresser från Filezilla" #~ msgid "Open Site with Filezilla" #~ msgstr "Öppna plats med Filezilla" #~ msgid "Filezilla Sites" #~ msgstr "Filezilla-platser" #~ msgid "Sites from Filezilla" #~ msgstr "Platser från Filezilla" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Tillgång till Gajim-kontakter" #~ msgid "Free for Chat" #~ msgstr "Free for Chat" #~ msgid "Gajim Contacts" #~ msgstr "Gajim-kontakter" #~ msgid "Gajim Account Status" #~ msgstr "Gajim status" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Lista kontakter och skriv nya meddelanden i Gmail" #~ msgid "Load contacts' pictures" #~ msgstr "Läs in kontaktikoner" #~ msgid "Load additional information" #~ msgstr "Visa ytterligare information" #~ msgid "Work email" #~ msgstr "E-post (arbete)" #~ msgid "Home email" #~ msgstr "E-post (hem)" #~ msgid "Other email" #~ msgstr "Annan e-post" #~ msgid "Work address" #~ msgstr "Adress (arbete)" #~ msgid "Home address" #~ msgstr "Adress (hem)" #~ msgid "Other address" #~ msgstr "Annan adress" #~ msgid "Car phone" #~ msgstr "Biltelefon" #~ msgid "Fax" #~ msgstr "Fax" #~ msgid "Home phone" #~ msgstr "Telefon (hem)" #~ msgid "Home fax" #~ msgstr "Fax (hem)" #~ msgid "Internal phone" #~ msgstr "Intern telefon" #~ msgid "Mobile" #~ msgstr "Mobiltelefon" #~ msgid "Other" #~ msgstr "Annan" #~ msgid "VOIP" #~ msgstr "VOIP" #~ msgid "Work phone" #~ msgstr "Telefon (Arbete)" #~ msgid "Work fax" #~ msgstr "Fax (arbete)" #~ msgid "Compose Email in Gmail" #~ msgstr "Skriv e-postmeddelande i Gmail" #~ msgid "Open web browser and compose new email in Gmail" #~ msgstr "Skriv nytt meddelande i Gmail (i webbläsare)" #~ msgid "Edit Contact in Gmail" #~ msgstr "Redigera kontakt i Gmail" #~ msgid "Open web browser and edit contact in Gmail" #~ msgstr "Skriv nytt meddelande i Gmail (i webbläsare)" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Kontakter från Google-tjänster (Gmail)" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Visa album och ladda upp bilder till Picasa" #~ msgid "Users to show: (,-separated)" #~ msgstr "Användare att visa: (,-separerade)" #~ msgid "Load user and album icons" #~ msgstr "Läs in användar- och albumikoner" #~ msgid "Uploading Pictures" #~ msgstr "Skickar foton" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Skickar foton till Picasa Webbalbum" #~ msgid "Creating album:" #~ msgstr "Skapar album:" #~ msgid "Album created by Kupfer" #~ msgstr "Album skapat av Kupfer" #~ msgid "File:" #~ msgstr "Fil:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "Ett album" #~ msgstr[1] "%(num)d album" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "ett foto" #~ msgstr[1] "%(num)s foton" #~ msgid "Upload to Picasa Album..." #~ msgstr "Skicka till Picasa-album..." #~ msgid "Upload files to Picasa album" #~ msgstr "Skicka foton till ett album" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Skicka till Picasa som nytt album" #~ msgid "Create album from selected local directory" #~ msgstr "Skapa album från markerad mapp" #~ msgid "Picasa Albums" #~ msgstr "Picasa-album" #~ msgid "User albums in Picasa" #~ msgstr "Användaralbum i Picasa" #~ msgid "Google Search" #~ msgstr "Sök med Google" #~ msgid "Search Google with results shown directly" #~ msgstr "Sök med Google och visa resultat direkt" #~ msgid "Show More Results For \"%s\"" #~ msgstr "Visa fler resultat för ”%s”" #~ msgid "%s total found" #~ msgstr "%s funna totalt" #~ msgid "Gwibber" #~ msgstr "Gwibber" #~ msgid "" #~ "Microblogging with Gwibber. Allows sending and receiving messages from " #~ "social networks like Twitter, Identi.ca etc. Requires the package " #~ "'gwibber-service'." #~ msgstr "" #~ "Mikroblogga med Gwibber. Skicka och ta emot meddeladen från sociala " #~ "nätverk som Twitter, Identi.ca etc. Kräver paketet ‘gwibber-service’." #~ msgid "Maximum number of messages to show" #~ msgstr "Maximalt antal visade meddelanden" #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s på %(service)s" #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s på %(where)s" #~ msgid "Send Message" #~ msgstr "Skicka meddelande" #~ msgid "Send message to all Gwibber accounts" #~ msgstr "Skicka meddelande till alla Gwibber-konton" #~ msgid "Send Message To..." #~ msgstr "Skicka meddelande till..." #~ msgid "Send message to a Gwibber account" #~ msgstr "Skicka meddelande till ett Gwibber-konton" #~ msgid "Send message to selected Gwibber account" #~ msgstr "Skicka meddelande till valt Gwibber-konto" #~ msgid "Reply..." #~ msgstr "Svara..." #~ msgid "Delete Message" #~ msgstr "Radera meddelande" #~ msgid "Send Private Message..." #~ msgstr "Skicka direktmeddelande..." #~ msgid "Send direct message to user" #~ msgstr "Skicka direktmeddelande till..." #~ msgid "Retweet" #~ msgstr "Upprepa" #~ msgid "Retweet To..." #~ msgstr "Upprepa på..." #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Upprepa meddelandet på alla konton i Gwibber" #~ msgid "Retweet message to a Gwibber account" #~ msgstr "Upprepa meddelandet på ett konto i Gwibber" #~ msgid "Open in Browser" #~ msgstr "Öppna i webbläsaren" #~ msgid "Open message in default web browser" #~ msgstr "Öppna meddelandet med webbläsaren" #~ msgid "Gwibber Accounts" #~ msgstr "Gwibber-konton" #~ msgid "Accounts configured in Gwibber" #~ msgstr "Konton konfigurerade i Gwibber" #~ msgid "Gwibber Messages" #~ msgstr "Gwibber-meddelanden" #~ msgid "Recent messages received by Gwibber" #~ msgstr "Nyligen mottagna meddelanden i Gwibber" #~ msgid "Gwibber Messages for %s" #~ msgstr "Gwibber-meddelanden för %s" #~ msgid "Gwibber Streams" #~ msgstr "Gwibber-flöden" #~ msgid "Streams configured in Gwibber" #~ msgstr "Flöden konfigurerade i Gwibber" #~ msgid "Gwibber Messages in %s" #~ msgstr "Gwibber-meddelanden i %s" #~ msgid "Gwibber (Simple)" #~ msgstr "Gwibber (enkel)" #~ msgid "Send updates via the microblogging client Gwibber" #~ msgstr "Skicka uppdateringar via mikrobloggklienten Gwibber" #~ msgid "Send Update" #~ msgstr "Skicka uppdatering" #~ msgid "Unable to activate Gwibber service" #~ msgstr "Kunde inte aktivera Gwibber-tjänsten" #~ msgid "OpenOffice / LibreOffice" #~ msgstr "OpenOffice / LibreOffice" #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "Senaste dokument i OpenOffice/LibreOffice" #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "OpenOffice/LibreOffice senaste dokument" #~ msgid "Opera Mail" #~ msgstr "Opera Mail" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Opera Mail-kontakter och kommandon" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Skriv nytt meddelande med Opera Mail" #~ msgid "Opera Mail Contacts" #~ msgstr "Opera Mail-kontakter" #~ msgid "Contacts from Opera Mail" #~ msgstr "Kontakter från Opera Mail" #~ msgid "Opera Bookmarks" #~ msgstr "Opera-bokmärken" #~ msgid "Index of Opera bookmarks" #~ msgstr "Index över Opera-bokmärken" #~ msgid "PuTTY Sessions" #~ msgstr "PuTTY-sessioner" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "Snabb access till PuTTY-sessioner" #~ msgid "Start Session" #~ msgstr "Starta Session" #~ msgid "reStructuredText" #~ msgstr "reStructuredText" #~ msgid "Render reStructuredText and show the result" #~ msgstr "Rendera reStructuredText-dokument och visa resultatet" #~ msgid "View as HTML Document" #~ msgstr "Visa som HTML-dokument" #~ msgid "System Services" #~ msgstr "Systemtjänster" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "Starta, stoppa eller starta om systemtjänster m.h.a initskript" #~ msgid "Sudo-like Command" #~ msgstr "Sudo-likt kommando" #~ msgid "Start Service" #~ msgstr "Starta tjänst" #~ msgid "Stop Service" #~ msgstr "Stoppa tjänst" #~ msgid "%s Service" #~ msgstr "%s" #~ msgid "Show QRCode" #~ msgstr "Visa QRCode" #~ msgid "Display text as QRCode in a window" #~ msgstr "Visa text som QRCode i ett fönster" #~ msgid "Access to Skype contacts" #~ msgstr "Tillgång till Skype-kontakter" #~ msgid "Skype Me" #~ msgstr "Skype Me" #~ msgid "Logged Out" #~ msgstr "Frånkopplad" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Ring" #~ msgid "Place a call to contact" #~ msgstr "Påbörja samtal med kontakten" #~ msgid "Skype Contacts" #~ msgstr "Skype-kontakter" #~ msgid "Skype Statuses" #~ msgstr "Skype-status" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "Volymer från TrueCrypt-historien" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "TrueCrypt-volym %(file)s" #~ msgid "Mount Volume" #~ msgstr "Montera volym" #~ msgid "Mount in Truecrypt" #~ msgstr "Montera i Truecrypt" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Försök montera filen som Truecrypt-volym" #~ msgid "Dismount All Volumes" #~ msgstr "Avmontera alla volymer" #~ msgid "TrueCrypt Volumes" #~ msgstr "TrueCrypt-volymer" #~ msgid "Terminal Server Client" #~ msgstr "Terminal Server Client" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Sparad session in Terminal Server Client" #~ msgid "TSClient sessions" #~ msgstr "TSClient-sessioner" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Sparade sessioner in Terminal Server Client" #~ msgid "Vim" #~ msgstr "Vim" #~ msgid "Recently used documents in Vim" #~ msgstr "Senaste dokument i Vim" #~ msgid "Close (Save All)" #~ msgstr "Stäng (Spara alla)" #~ msgid "Send..." #~ msgstr "Skicka till..." #~ msgid "Send ex command" #~ msgstr "Sparat Kupfer-kommando" #~ msgid "Insert in Vim..." #~ msgstr "Infoga i Vim..." #~ msgid "Active Vim Sessions" #~ msgstr "Aktiva Vim-sessioner" #~ msgid "Vim Session %s" #~ msgstr "Vim-session %s" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Vinagre-kommandon och bokmärken" #~ msgid "Start Vinagre Session" #~ msgstr "Starta Vinagre-session" #~ msgid "Vinagre Bookmarks" #~ msgstr "Vinagre-bokmärken" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "Kontrollera VirtualBox virtuella maskiner. Stöder både Sun VirtualBox och " #~ "Open Source Edition." #~ msgid "Force use CLI interface" #~ msgstr "Tvinga CLI-gränssnitt" #~ msgid "Power On" #~ msgstr "Starta" #~ msgid "Power On Headless" #~ msgstr "Starta headless" #~ msgid "Send Power Off Signal" #~ msgstr "Skicka avstängningssignal" #~ msgid "Reboot" #~ msgstr "Starta om" #~ msgid "Resume" #~ msgstr "Återuppta" #~ msgid "Save State" #~ msgstr "Spara tillstånd" #~ msgid "Power Off" #~ msgstr "Stäng av" #~ msgid "VirtualBox Machines" #~ msgstr "VirtualBox virtuella maskiner" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "Tillgång till sidor i Zim" #~ msgid "Page names start with :colon" #~ msgstr "Sidnamn börjar med :kolon" #~ msgid "Default page name for quick notes" #~ msgstr "Namn för snabbanteckningar" #~ msgid "Note %x %X" #~ msgstr "Anteckning %x %X" #~ msgid "" #~ "Strftime tags can be used: %H - hour, %M - minutes, etc\n" #~ "Please check python documentation for details.\n" #~ "NOTE: comma will be replaced by _" #~ msgstr "" #~ "Du kan använda ’strftime’-format: %H - timme, %M - minut, etc\n" #~ "Se pythons dokumentation för detaljer\n" #~ "Notera att kommatecken ersätts med _" #~ msgid "Default namespace for quick notes" #~ msgstr "Namnrymd för snabbanteckningar" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Zim-sida från anteckningsblock ”%s”" #~ msgid "Create Zim Page" #~ msgstr "Skapa Zim-sida" #~ msgid "Create page in default notebook" #~ msgstr "Skapa sida i förvalt anteckningsblock" #~ msgid "Create Zim Page In..." #~ msgstr "Skapa Zim-sida i..." #~ msgid "Insert QuickNote into Zim" #~ msgstr "Infoga snabbanteckning i Zim" #~ msgid "Quick note selected text into Zim notebook" #~ msgstr "Markerad text som snabbanteckning i Zim" #~ msgid "Create Subpage..." #~ msgstr "Skapa undersida..." #~ msgid "Zim Notebooks" #~ msgstr "Zim-anteckingsblock" #~ msgid "Zim Pages" #~ msgstr "Zim-sidor" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Sidor i Zim-anteckningsblock" kupfer-328/po/tr.po000066400000000000000000001654531500175051100143000ustar00rootroot00000000000000# Simge Sezgin , 2015. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2015-05-30 11:28+0000\n" "Last-Translator: Simge Sezgin \n" "Language-Team: Türkçe \n" "Language: tr\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: Pootle 2.5.1.1\n" "X-POOTLE-MTIME: 1432985322.000000\n" msgid "User credentials" msgstr "Kullanıcı kimlik bilgileri" msgid "_User:" msgstr "_Kullanıcı:" msgid "_Password:" msgstr "_Şifre:" msgid "_Change" msgstr "_Değiştir" msgid "Set Keyboard Shortcut" msgstr "Klavye Kısayolu Ayarla" msgid "Please press desired key combination" msgstr "Lütfen istenen tuş bileşimini girin" msgid "Keybinding could not be bound" msgstr "Klavye kısayolu bulunamadı" msgid "Kupfer Preferences" msgstr "Kupfer Özellikleri" msgid "Start automatically on login" msgstr "Oturum açıldığında başlat" msgid "Start" msgstr "Başlat" msgid "Show icon in notification area" msgstr "Bildirim alanında simge görüntüle" msgid "Icon set:" msgstr "Simge kümesi:" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" msgid "Terminal emulator:" msgstr "Uçbirim öykünücüsü:" msgid "Desktop Environment" msgstr "Masaüstü Ortamı" msgid "General" msgstr "Genel" msgid "Global Keyboard Shortcuts" msgstr "Genel Klavye Kısayolları" msgid "Reset" msgstr "Sıfırla" msgid "Browser Keyboard Shortcuts" msgstr "Klavye Kısayollarını Görüntüle" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "Tek klavye kısayolu komutu kullan (Boşluk,/,virgül gibi)" msgid "Keyboard" msgstr "Klavye" msgid "Plugins" msgstr "Eklentiler" msgid "Inclusion in Top Level Searches" msgstr "En Yüksek Seviye Aramalarda Dahil Etme" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" "İşaretlenmiş kaynaklar nesnelerini en yüksek seviye aramalarına dahil etti.\n" "İşaretlenmemiş bir kaynağın içerikleri sadece onun alt katolağu bulunarak " "kullanabilirler." msgid "Indexed Folders" msgstr "Dizinlenmiş Klasörler" msgid "Folders whose files are always available in the catalog." msgstr "Katalogdaki her zaman kullanılabilir dosyaların klasörleri." msgid "Catalog" msgstr "Katalog" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "Uygulama Çalıştırıcı" msgid "Convenient command and access tool for applications and documents" msgstr "Uygulamalar ve belgeler için uygun komut ve erişim aracı" msgid "Execute in Kupfer" msgstr "Kupfer içinde çalıştır" msgid "Saved Kupfer Command" msgstr "Kayıtlı Kupfer Komutu" #, python-format msgid "Could not to carry out '%s'" msgstr "'%s' taşınamıyor" #, python-format msgid "\"%s\" produced a result" msgstr "\"%s\" bir sonuç üretti" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "" "\"%s\" dosyasını çalıştırmak için yeterli izniniz yok (çalıştırılabilir " "değil)" #, python-format msgid "Command in \"%s\" is not available" msgstr "\"%s\" komutu mevcut değil" #, python-format msgid "Keyboard relay is active for display %s" msgstr "%s görüntülemek için klavye anahtarlama etkin" msgid "do not present main interface on launch" msgstr "açılışta uygulama penceresini gösterme" msgid "list available plugins" msgstr "kullanılabilir eklenti listesi" msgid "enable debug info" msgstr "hata ayıklama bilgisini etkinleştir" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "helper eklentisini çalıştır" msgid "show usage help" msgstr "kullanım yardımını göster" msgid "show version information" msgstr "sürüm bilgisini göster" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "Kullanımı: kupfer [ OPTIONS | FILE ... ]" msgid "Available plugins:" msgstr "Uygun eklentiler:" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "Aramak için yazın" #, python-format msgid "%s is empty" msgstr "%s boş" msgid "Text" msgstr "Metin" msgid "Run after Delay..." msgstr "Gecikmeden sonra çalıştır..." msgid "Perform command after a specified time interval" msgstr "Belirtilen süre gecikmesinin ardından komutu çalıştır" msgid "Multiple Objects" msgstr "Çoklu Nesneler" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s nesne" msgstr[1] "%s nesne" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "bilinmeyen" msgid "Aim" msgstr "Aim" msgid "Google Talk" msgstr "Google Talk" msgid "ICQ" msgstr "ICQ" msgid "MSN" msgstr "MSN" msgid "QQ" msgstr "QQ" msgid "Yahoo" msgstr "Yahoo" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "%s bu işlemi desteklemiyor" msgid "Can not be used with multiple objects" msgstr "Birden fazla nesne ile kullanılamıyor" msgid "Open" msgstr "Aç" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "%(file)s (%(type)s) dosya türü için öntenımlı uygulama yok" #, python-format msgid "Please use \"%s\"" msgstr "Lütfen \"%s\" kullanın" msgid "Set Default Application..." msgstr "Öntanımlı Uygulama Olarak Ayarla...." msgid "Open with default application" msgstr "Öntanımlı uygulama ile aç" msgid "Reveal" msgstr "Göster" msgid "Open parent folder" msgstr "Üst dizini aç" msgid "Open Terminal Here" msgstr "Uçbirimi Burada Aç" msgid "Open this location in a terminal" msgstr "Bu konumu uçbirimde aç" msgid "Run in Terminal" msgstr "Uçbirimde çalıştır" msgid "Run (Execute)" msgstr "Çalıştır" msgid "Run this program in a Terminal" msgstr "Bu uygulamayı uçbirimde çalıştır" msgid "Run this program" msgstr "Bu uygulamayı çalıştır" msgid "Go To" msgstr "Git" msgid "Open URL" msgstr "Bağlantı aç" msgid "Open URL with default viewer" msgstr "Öntanımlı görüntüleyici ile bağlantı aç" msgid "Launch" msgstr "Çalıştır" msgid "Show application window" msgstr "Uygulama penceresini göster" msgid "Launch application" msgstr "Uygulamayı çalıştır" msgid "Launch Again" msgstr "Tekrar Çalıştır" msgid "Launch another instance of this application" msgstr "Bu uygulamadan bir tane daha çalıştır" msgid "Close" msgstr "Kapat" msgid "Attempt to close all application windows" msgstr "Tüm uygulama pencereleri kapatılmaya çalışıldı" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "Çalıştır" msgid "Perform command" msgstr "Komutu uygula" msgid "(Empty Text)" msgstr "(Boş Metin)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "\"%(text)s\"" msgstr[1] "(%(num)d satır) \"%(text)s\"" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s ve diğerleri" #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "%(dir)s yinelemeli kaynağı, (%(levels)d seviye)" #, python-format msgid "Directory source %s" msgstr "%s Sözlük Kaynağı" msgid "Home Folder" msgstr "Ev Klasörü" msgid "Catalog Index" msgstr "Katalog İçeriği" msgid "An index of all available sources" msgstr "Uygun tüm kaynakların listesi" msgid "Root catalog" msgstr "Yönetici katalogu" msgid "Please Configure Plugin" msgstr "Lütfen Eklentiyi Yapılandırın" #, python-format msgid "Plugin %s is not configured" msgstr "%s eklentisi yapılandırılmamış" #, python-format msgid "Invalid user credentials for %s" msgstr "%s için geçersiz kullanıcı bilgisi" msgid "Applications" msgstr "Uygulamalar" msgid "All applications and preferences" msgstr "Tüm uygulamalar ve ayarları" msgid "Applications for Desktop Environment" msgstr "Masaüstü Ortamı İçin Uygulamalar" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "Birlikte Aç..." msgid "Open with any application" msgstr "Herhangi bir uygulama ile aç" msgid "Set default application to open this file type" msgstr "Bu dosya türü için öntanımlı uygulama olarak ayarla" #, fuzzy msgid "Reset Associations" msgstr "URL Eylemleri" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "Karışık Arşivler" msgid "Allow browsing inside compressed archive files" msgstr "Sıkıştırılmış arşiv dosyalarının içini görmenizi sağlar" #, python-format msgid "Content of %s" msgstr "%s İçeriği" msgid "Archive Manager" msgstr "Arşiv Yöneticisi" msgid "Use Archive Manager actions" msgstr "Arşiv Yönetici eylemleri kullan" msgid "Compressed archive type for 'Create Archive In'" msgstr "'Arşiv İçinde Oluştur' için sıkıştırılmış arşiv türü" msgid "Extract Here" msgstr "Buraya Aç" msgid "Extract compressed archive" msgstr "Sıkıştırılmış arşivi çıkar" msgid "Create Archive" msgstr "Arşiv Oluştur" msgid "Create a compressed archive from folder" msgstr "Klasörü sıkıştır" msgid "Create Archive In..." msgstr "Arşiv Oluştur..." #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "Arşiv" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr " Audacious Oynatım ve Çalma listesini denetle" msgid "Include songs in top level" msgstr "En üst seviyedeki şarkıları dahil et" msgid "Enqueue" msgstr "Çalma Listesi" msgid "Add track to the Audacious play queue" msgstr "Şarkıyı Audacious oynatma listesine ekle" msgid "Dequeue" msgstr "Çalma Listesinden Çıkar" msgid "Remove track from the Audacious play queue" msgstr "Şarkıyı Audacious parça listesinden sil" msgid "Play" msgstr "Oynat" msgid "Jump to track in Audacious" msgstr "Audacious içinde şarkıya geç" msgid "Resume playback in Audacious" msgstr "Audacious'ta oynatımı sürdür" msgid "Pause" msgstr "Duraklat" msgid "Pause playback in Audacious" msgstr "Audacious'ta oynatımı durdur" msgid "Next" msgstr "Sonraki" msgid "Jump to next track in Audacious" msgstr "Audacious'ta sonraki şarkıya geç" msgid "Previous" msgstr "Önceki" msgid "Jump to previous track in Audacious" msgstr "Audacious'ta önceki şarkıya dön" msgid "Clear Queue" msgstr "Çalma Listesini Temizle" msgid "Clear the Audacious play queue" msgstr "Audacious Çalıma listesini temizle" msgid "Shuffle" msgstr "Karışık" msgid "Toggle shuffle in Audacious" msgstr "Audacious içinde karışık değiştir" msgid "Repeat" msgstr "Tekrarla" msgid "Toggle repeat in Audacious" msgstr "Audacious içinde tekrarlamayı değiştir" msgid "Show Playing" msgstr "Oynatılan Dosyayı Göster" msgid "Tell which song is currently playing" msgstr "Hangi şarkının çaldığını söyle" msgid "Playlist" msgstr "Oynatma Listesi" msgid "Calculator" msgstr "Hesap Makinesi" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "Hesapla" msgid "Clipboards" msgstr "Panolar" msgid "Recent clipboards and clipboard proxy objects" msgstr "Son panolar ve pano vekil nesneleri" msgid "Number of recent clipboards to remember" msgstr "Hatırlanacak son panoların sayısı" msgid "Include selected text in clipboard history" msgstr "Pano geçmişinde seçilen metni dahil et" msgid "Copy selected text to primary clipboard" msgstr "Seçilen metni birincil panoya kopyala" msgid "Selected Text" msgstr "Seçili Yazı" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "\"%(desc)s\" Pano" msgstr[1] "%(num)d satır \"%(desc)s\" ile Pano" msgid "Clipboard Text" msgstr "Pano Metni" msgid "Clipboard File" msgstr "Pano Dosyası" msgid "Clipboard Files" msgstr "Pano Dosyaları" msgid "Clear" msgstr "Temizle" msgid "Remove all recent clipboards" msgstr "Son kullanılan panoları sil" msgid "Shell Commands" msgstr "Kabuk Komutları" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" "Komut satırı programları çalıştır. %s sembolü ile işaretlenmiş eylemleri bir " "alt kabukta çalıştırır." msgid "Run (Get Output)" msgstr "Çalıştır (Sonuçları Getir)" msgid "Run program and return its output" msgstr "Uygulamayı çalıştır ve sonucunu getir" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "Komuta Geçir..." msgid "Run program with object as an additional parameter" msgstr "Ek bir parametre olarak nesne ile program çalıştır" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin msgid "Write to Command..." msgstr "Komuta Yaz..." msgid "Run program and supply text on the standard input" msgstr "Programı çalıştır ve standart girdi üzerinde metin sağla" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "Komut aracılığıyla Süz..." msgid "Run command-line programs" msgstr "Komut satırı programları çalıştır" msgid "GTK+" msgstr "GTK+" msgid "GNOME Terminal" msgstr "GNOME Uçbirimi" msgid "XFCE Terminal" msgstr "XFCE Uçbirimi" msgid "LXTerminal" msgstr "LXTerminal" msgid "X Terminal" msgstr "X Terminal" msgid "Urxvt" msgstr "Urxvt" msgid "Konsole" msgstr "Konsole" msgid "Save As..." msgstr "Farklı Kaydet..." #, fuzzy msgid "Restart Kupfer" msgstr "Servisi Yeniden Başlat" msgid "Quit" msgstr "Çıkış" msgid "Quit Kupfer" msgstr "Kupfer'dan çık" msgid "About Kupfer" msgstr "Kupfer Hakkında" msgid "Show information about Kupfer authors and license" msgstr "Kupfer geliştiricileri ve lisansı hakkında bilgileri göster" msgid "Kupfer Help" msgstr "Kupfer Yardım" msgid "Get help with Kupfer" msgstr "Kupfer ile ilgili yardım alın" msgid "Show preferences window for Kupfer" msgstr "Kupfer seçenekleri penceresini göster" msgid "Search Contents" msgstr "İçeriği Ara" msgid "Search inside this catalog" msgstr "Bu katalog içinde ara" msgid "Copy" msgstr "Kopyala" msgid "Copy to clipboard" msgstr "Panoya kopyala" msgid "Rescan" msgstr "Yeniden Tara" msgid "Force reindex of this source" msgstr "Bu kaynağı yeniden taramak için zorla" msgid "Last Command" msgstr "Son Komut" msgid "Internal Kupfer Objects" msgstr "Dahili Kupfer Nesneleri" msgid "Last Result" msgstr "Son Sonuçlar" msgid "Command Results" msgstr "Komut Sonuçları" msgid "Custom Terminal" msgstr "Özel Uçbirim" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "Komut" msgid "Execute flag" msgstr "Bayrak yürüt" msgid "Default Email Client" msgstr "Öntanımlı E-posta İstemcisi" msgid "Compose email using the system's default mailto: handler" msgstr "Öntanımlı sistem eposta adresi kullanan eposta oluştur: işleyici" #, fuzzy msgid "Compose Email To" msgstr "E-Posta yaz" msgid "Dictionary" msgstr "Sözlük" msgid "Look up word in dictionary" msgstr "Sözlükte kelime ara" msgid "Look Up" msgstr "Gözat" msgid "Documents" msgstr "Belgeler" msgid "Recently used documents and bookmarked folders" msgstr "En son kullanılan belgeler ve yerimlenmiş dizinler" msgid "Max recent document days" msgstr "En son kullanılan belgelere eklenmesi için en geç süre" msgid "Recent Items" msgstr "Son Kullanılan Öğeler" msgid "Recently used documents" msgstr "Son kullanılan belgeler" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "%s Belgeleri" #, python-format msgid "Recently used documents for %s" msgstr "%s için son kullanılan belgeler" msgid "Places" msgstr "Yerler" msgid "Bookmarked folders" msgstr "Yerimi dizinleri" msgid "DuckDuckGo Search" msgstr "DuckDuckGo Arama" msgid "Search the web securely with DuckDuckGo" msgstr "DuckDuckGo ile güvenli web arama" msgid "Favorites" msgstr "Sık Kullanılanlar" msgid "Mark commonly used items and store objects for later use" msgstr "Sıkça kullanılan öğleri işaretle ve daha sonra kullanmak için sakla" msgid "Shelf of \"Favorite\" items" msgstr "\"Sık Kullanılanlar\" Bölümü öğeleri" msgid "Add to Favorites" msgstr "Beğenilenlere Ekle" msgid "Add item to favorites shelf" msgstr "Öğeyi sık kullanılanlara ekle" msgid "Remove from Favorites" msgstr "Beğenilenlerden Kaldır" msgid "Remove item from favorites shelf" msgstr "Öğeyi sık kullanılanlardan kaldır" msgid "File Actions" msgstr "Dosya İşlemleri" msgid "More file actions" msgstr "Daha fazla dosya eylemi" msgid "Move To..." msgstr "Taşı..." msgid "Move file to new location" msgstr "Dosyayı yeni bir konuma taşı" msgid "Rename To..." msgstr "Yeniden Adlandır..." msgid "Copy To..." msgstr "Kopyala..." msgid "Copy file to a chosen location" msgstr "Dosyayı seçilen konuma kopyala" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "Glob" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "Yüksek Öncelikli Eylemler" msgid "Tools to work with commands as objects" msgstr "Komutlar ile nesneler gibi çalışmak için araçlar" msgid "Select in Kupfer" msgstr "Kupfer'da seç" #, python-format msgid "Result of %s (%s)" msgstr " %s (%s) sonuçları" msgid "Run (Take Result)" msgstr "Çalıştır (Sonuçları al)" msgid "Take the command result as a proxy object" msgstr "Komut sonucunu bir vekil nesnesi gibi al" msgid "Run (Discard Result)" msgstr "Çalıştır (Sonuçları Alma)" msgid "Image Tools" msgstr "Resim Araçları" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "Resim dönüştürme araçları" msgid "Scale..." msgstr "Boyutlandır..." msgid "Scale image to fit inside given pixel measure(s)" msgstr "Resimi verilen piksel uzunluğuna göre boyutlandır" msgid "Rotate Clockwise" msgstr "Saat Yönünde Döndür" msgid "Rotate Counter-Clockwise" msgstr "Saat Yönünün Tersine Döndür" msgid "Autorotate" msgstr "Otomatik Döndür" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "JPEG(yerinde) dosyasını EXIF üstverisine göre döndür" msgid "Kupfer Plugins" msgstr "Kupfer Eklentileri" msgid "Access Kupfer's plugin list in Kupfer" msgstr "Kupfer eklenti listesine Kupfer içinde erişin" msgid "Show Information" msgstr "Bilgi Göster" msgid "Show Source Code" msgstr "Kaynak Kodu Göster" msgid "enabled" msgstr "etkin" msgid "disabled" msgstr "devre dışı" msgid "Notes" msgstr "Notlar" msgid "Gnote or Tomboy notes" msgstr "Gnote veya Tomboy notları" msgid "Work with application" msgstr "Uygulama ile çalıştır" msgid "Open with notes application" msgstr "Not uygulaması ile aç" msgid "Append to Note..." msgstr "Nota Ekle..." msgid "Add text to existing note" msgstr "Varolan bir nota yazı ekle" msgid "Create Note" msgstr "Not Oluştur" msgid "Create a new note from this text" msgstr "Bu yazıdan yeni bir not oluştur" msgid "Get Note Search Results..." msgstr "Not Arama Sonuçlarını Getir..." msgid "Show search results for this query" msgstr "Bu sorgu için arama sonuçlarını göster" #, python-format msgid "today, %s" msgstr "bugün, %s" #, python-format msgid "yesterday, %s" msgstr "dün, %s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "son güncelleme%s" msgid "Quicksilver Icons" msgstr "Quicksilver Simgeleri" msgid "Quick Image Viewer" msgstr "Hızlı Görüntü Görüntüleyicisi" msgid "View Image" msgstr "Görüntüyü Göster" msgid "GNU Screen" msgstr "GNU Ekranı" msgid "Active GNU Screen sessions" msgstr "Etkin GNU Ekran oturumları" msgid "Attached" msgstr "Eklenmiş" msgid "Detached" msgstr "Ayrılmış" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "%(status)s oturumu (%(pid)s) %(time)s tarihinde oluşturuldu" msgid "Screen Sessions" msgstr "Ekran Oturumları" msgid "Attach" msgstr "Ekle" msgid "Send Keys" msgstr "Anahtarları Gönder" msgid "Send synthetic keyboard events using xautomation" msgstr "xautomation kullanarak yapay klavye olayları gönder" msgid "Paste to Foreground Window" msgstr "Önplan Penceresine Yapıştır" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "Panoya kopyala ve önplan penceresine Ctrl+V gönder" msgid "Send keys to foreground window" msgstr "Önplan penceresine anahtarlar gönder" msgid "Type Text" msgstr "Metin Gir" msgid "Type the text to foreground window" msgstr "Pencere önplanına metin gir" msgid "GNOME Session Management" msgstr "GNOME Oturum Yönetimi" msgid "Special items and actions for GNOME environment" msgstr "GNOME masaüstü ortamı için özel öğeler ve eylemler" msgid "Log Out..." msgstr "Oturumu Kapat..." msgid "Log out or change user" msgstr "Oturumu kapat veya kullanıcı değiştir" msgid "Shut Down..." msgstr "Kapat..." msgid "Shut down, restart or suspend computer" msgstr "Kapat, yeniden başlat veya askıya al" msgid "Lock Screen" msgstr "Ekranı Kilitle" msgid "Enable screensaver and lock" msgstr "Ekran koruyucu ve kilitleme etkin" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "XFCE Oturum Yönetimi" msgid "Special items and actions for XFCE environment" msgstr "XFCE masaüstü ortamı için özel öğeler ve eylemler" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "SSH Sunucular" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "~/.ssh/config dosyasında ki SSH sunucularına ekler" msgid "SSH host" msgstr "SSH Sunucu" msgid "Connect" msgstr "Bağlan" msgid "Connect to SSH host" msgstr "SSH Sunucuya Bağlan" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "~/.ssh/config dosyasında belirtilen SSH sunucuları" msgid "No D-Bus connection to desktop session" msgstr "Masaüstü oturumu için D-Bus bağlantısı yok" msgid "GNOME Keyring" msgstr "GNOME Anahtarlığı" msgid "KWallet" msgstr "KWallet" msgid "Unencrypted File" msgstr "Şifrelenmemiş Dosya" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "\"%s\" komutu mevcut değil" msgid "Document Templates" msgstr "Şablonlar" msgid "Create new documents from your templates" msgstr "Şablonlarından yeni belge oluştur" #, python-format msgid "%s template" msgstr "%s şablonu" msgid "Empty File" msgstr "Boş Dosya" msgid "New Folder" msgstr "Yeni Klasör" msgid "Create New Document..." msgstr "Yeni Belge Oluştur..." msgid "Create a new document from template" msgstr "Şablondan yeni belge oluştur" msgid "Create Document In..." msgstr "Belge Oluştur..." msgid "Textfiles" msgstr "Yazıdosyaları" msgid "Append To..." msgstr "Şuraya Ekle..." msgid "Append..." msgstr "Ekle..." msgid "Write To..." msgstr "Yaz..." msgid "Get Text Contents" msgstr "Yazı içeriğini getir" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "Dosya yöneticisi Thunar eylemleri" msgid "Select in File Manager" msgstr "Dosya Yöneticisinde Seç" msgid "Show Properties" msgstr "Özellikleri Göster" msgid "Show information about file in file manager" msgstr "Dosya bilgilerini dosya yöneticisinde göster" msgid "Send To..." msgstr "Gönder..." msgid "Symlink In..." msgstr "Sembolik Bağlantı..." msgid "Create a symlink to file in a chosen location" msgstr "Seçilen konumdaki dosyaya bir sembolik bağlantı oluştur" msgid "Empty Trash" msgstr "Çöpü Boşalt" msgid "Thunar Send To Objects" msgstr "Thunar Nesnelere Gönder" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Thunderbird/Icedove Kişi ve Eylemleri" msgid "Compose New Email" msgstr "Yeni E-posta yaz" msgid "Compose a new message in Thunderbird" msgstr "Thunderbird'de yeni ileti yaz" #, fuzzy msgid "Attach in Email To..." msgstr "E-posta gönder..." #, fuzzy msgid "Compose Email With" msgstr "E-Posta yaz" #, fuzzy msgid "Compose a new message using the text as body" msgstr "Thunderbird'de yeni ileti yaz" msgid "Thunderbird Address Book" msgstr "Thunderbird Adres Defteri" msgid "Contacts from Thunderbird Address Book" msgstr "Thunderbird Adres defteri kişileri" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "Üst" msgid "Show running tasks and allow sending signals to them" msgstr "Yürütülen işlemleri gösterir ve onlara sinyal göndermenizi sağlar" msgid "Sort Order" msgstr "Sıralama Düzeni" msgid "Commandline" msgstr "Komutsatırı" msgid "CPU usage (descending)" msgstr "CPU kullanımı (azalan)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "Bellek kullanımı (azalan)" msgid "Send Signal..." msgstr "Sinyal Gönder..." msgid "Signals" msgstr "Sinyaller" msgid "Running Tasks" msgstr "Çaşılan İşlemler" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid: %(pid)s işl: %(cpu)g%% haf: %(mem)g%% süre: %(time)s" msgid "Running tasks for current user" msgstr "Aktif kullanıcı içi yürütülen işlemler" msgid "Trash" msgstr "Çöp" msgid "Access trash contents" msgstr "Çöpün içeriğine erişin" msgid "Move to Trash" msgstr "Çöpe Taşı" msgid "Move this file to trash" msgstr "Bu dosyayı çöpe gönder" msgid "Restore" msgstr "Geri Yükle" msgid "Move file back to original location" msgstr "Dosyayı eski konumuna döndür" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "Çöp boş" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "Çöpte bir dosya var" msgstr[1] "Çöpte %(num)s dosya var" msgid "Triggers" msgstr "Tetikleyiciler" msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "" "'Komut Oluştur' ile oluşturulan nesneler için genel klavye kısayolları " "(tetikleyici) ata." msgid "Add Trigger..." msgstr "Tetikleyici Ekle..." msgid "Remove Trigger" msgstr "Tetikleyiciyi Kaldır" msgid "URL Actions" msgstr "URL Eylemleri" msgid "Download and Open" msgstr "İndir ve Aç" msgid "Download To..." msgstr "İndir..." msgid "Download URL to a chosen location" msgstr "Seçili konuma bağlantıyı indirin" msgid "Wikipedia" msgstr "Vikipedi" msgid "Search in Wikipedia" msgstr "Vikipedi'de ara" msgid "Wikipedia language" msgstr "Vikipedi Dili" #. TRANS: Default wikipedia language code msgid "en" msgstr "tr" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "Bu ifadeyi %s.wikipedia.org 'da ara" msgid "Window List" msgstr "Pencere Listesi" msgid "All windows on all workspaces" msgstr "Tüm çalışma alanlarındaki bütün pencereler" msgid "Activate" msgstr "Etkin" msgid "Shade" msgstr "Sar" msgid "Unshade" msgstr "Genişlet" msgid "Minimize" msgstr "Küçült" msgid "Unminimize" msgstr "Büyüt" msgid "Maximize" msgstr "Ekranı Kapla" msgid "Unmaximize" msgstr "Küçült" msgid "Maximize Vertically" msgstr "Dikey Büyüt" msgid "Unmaximize Vertically" msgstr "Dikey Küçült" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "%(wkspc)s alanında pencere" msgid "Frontmost Window" msgstr "Öndeki Pencere" msgid "Next Window" msgstr "Sonraki Pencere" msgid "Jump to this window's workspace and focus" msgstr "Bu pencerenin çalışma alanına geç ve odaklan" #, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "%d pencere" msgstr[1] "%d pencere" msgid "Active workspace" msgstr "Çalışma alanını etkinleştir" msgid "Jump to this workspace" msgstr "Bu çalışma alanına geç" msgid "Workspaces" msgstr "Çalışma Alanları" msgid "Volumes and Disks" msgstr "Diskler ve Bölümler" msgid "Mounted volumes and disks" msgstr "Bağlı birim ve diskler" #, python-format msgid "Volume mounted at %s" msgstr "%s bölüm bağlı" msgid "Unmount" msgstr "Ayır" msgid "Unmount this volume" msgstr "Bölümü ayır" msgid "Eject" msgstr "Çıkar" msgid "Unmount and eject this media" msgstr "Ayır ve ortam aygıtını çıkar" msgid "Show Text" msgstr "Yazıyı Göster" msgid "Display text in a window" msgstr "Yazıyı pencere içinde göster" msgid "Large Type" msgstr "Büyük Yaz" msgid "Show Notification" msgstr "Uyarı Görüntüle" msgid "Tracker" msgstr "İzleyici" msgid "Tracker desktop search integration" msgstr "Tracker masaüstü arama bütünleşmesi" msgid "Search in Tracker" msgstr "Tracker'da ara" msgid "Open Tracker Search Tool and search for this term" msgstr "Tracker arama aracını aç ve bu terim için ara" msgid "Get Tracker Results..." msgstr "Tracker sonuçlarını getir" msgid "Show Tracker results for query" msgstr "Bu sorgu için Tracker sonuçlarını göster" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "\"%s\" için sonuçlar" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "Dosyaların Yerini Belirle" msgid "Search filesystem using locate" msgstr "Yer belirleme kullanarak dosya sistemi ara" msgid "Ignore case distinctions when searching files" msgstr "Dosyaları ararken karakter boyutunu önemseme" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Firefox Yerimleri" msgid "Index of Firefox bookmarks" msgstr "Firefox yerimleri içeriği" #, fuzzy msgid "Firefox Keywords" msgstr "Firefox Yerimleri" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "OpenSearch destekleyen arama motorları ile web'de ara" msgid "Search With..." msgstr "Birlikte Ara...." msgid "Search For..." msgstr "Ara..." #, fuzzy msgid "Search Terms" msgstr "Arama Motorları" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "Lütfen \"%s\" kullanın" #, fuzzy msgid "Resume playback" msgstr "Audacious'ta oynatımı sürdür" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "Sonraki" #, fuzzy msgid "Skip to next track" msgstr "Audacious'ta sonraki şarkıya geç" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "Önceki" #, fuzzy msgid "Skip to previous track" msgstr "Audacious'ta önceki şarkıya dön" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "Pidgin Kişilerine Eriş" msgid "Show offline contacts" msgstr "Çevrimdışı kişileri göster" msgid "Open Chat" msgstr "Sohbet Başlat" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d karakter)" msgstr[1] "%s (%d karakter)" msgid "Send Message..." msgstr "Mesaj Gönder..." msgid "Available" msgstr "Uygun" msgid "Away" msgstr "Uzakta" msgid "Pidgin Contacts" msgstr "Pidgin Kişileri" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "Kısaltılmış Bağlantılar" msgid "Create short aliases of long URLs" msgstr "Uzun bağlantılarınızı kısaltın" msgid "Error" msgstr "HatA" msgid "Shorten With..." msgstr "Kısaltıldı..." msgid "Services" msgstr "Servisler" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "" "Müzik kütüphanenize göz atın, şarkıları çalma listesine ekleyi ve oynatın" msgid "Include artists in top level" msgstr "En üst seviyedeki sanatçıları dahil et" msgid "Include albums in top level" msgstr "En üst seviyedeki albümleri dahil et" msgid "Play tracks in Rhythmbox" msgstr "Şarkıları Rhythmbox'ta çal" msgid "Add tracks to the play queue" msgstr "Şarkıları çalma listesine ekle" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "%(artist)s tarafından %(album)s albümünde" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "%s tarafından" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "%s Şarkıları" msgid "Albums" msgstr "Albümler" msgid "Music albums in Rhythmbox Library" msgstr "Rhythmbox Kütüphanesindeki albümler" msgid "Artists" msgstr "Sanatçılar" msgid "Music artists in Rhythmbox Library" msgstr "Rhythmbox Kütüphanesindeki şarkıcılar" msgid "Songs" msgstr "Şarkılar" msgid "Songs in Rhythmbox library" msgstr "Rhythmbox Kütüphanesindeki şarkılar" msgid "Getting Things GNOME" msgstr "GNOME'la, hayatını yaşa!" msgid "Browse and create new tasks in GTG" msgstr "GHY'da bulunan görevlere göz at ve yenilerini oluştur" #, python-format msgid "due: %s" msgstr "nedeniyle: %s" #, python-format msgid "start: %s" msgstr "başlat: %s" #, python-format msgid "tags: %s" msgstr "etiket: %s" msgid "Open task in Getting Things GNOME!" msgstr "Gnome'la, Hayatını Yaşa'da görev aç" msgid "Delete" msgstr "Sil" msgid "Permanently remove this task" msgstr "Bu görevi kalıcı olark sil" msgid "Mark Done" msgstr "Tamamlanmış Olarak İşaretle" msgid "Mark this task as done" msgstr "Bunu Tamamlandı Olarak İşaretle" msgid "Dismiss" msgstr "Kapat" msgid "Mark this task as not to be done anymore" msgstr "Yapılmayacak olarak işaretle" msgid "Create Task" msgstr "Görev Oluştur" msgid "Create new task in Getting Things GNOME" msgstr "GNOME'la, hayatını yaşa'da yeni görev oluştur" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "Devhelp'te ara" msgid "Empathy" msgstr "Empathy" msgid "Access to Empathy Contacts" msgstr "Empathy Kişilerine Erişim" msgid "Busy" msgstr "Meşgul" msgid "Not Available" msgstr "Uygun Değil" msgid "Invisible" msgstr "Görünmez" msgid "Offline" msgstr "Çevrimdışı" msgid "Change Global Status To..." msgstr "Genel durumu değiştir..." msgid "Empathy Contacts" msgstr "Empathy Kişileri" msgid "Empathy Account Status" msgstr "Empathy Hesap Durumları" #. TRANS: Names of accelerators in the interface msgid "Alternate Activate" msgstr "Alternatif Etkinleştirme" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action msgid "Comma Trick" msgstr "Virgül Hileleri" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "Komut Oluştur" msgid "Mark Default Action" msgstr "Öntanımlı Eylem İşaretle" msgid "Forget Object" msgstr "Nesneyi Unut" msgid "Reset All" msgstr "Tümünü Sıfırla" msgid "Select Quit" msgstr "Çıkış Yap" msgid "Select Selected File" msgstr "Seçilmiş Dosyayı Seç" msgid "Select Selected Text" msgstr "Seçilmiş Yazıyı Seç" msgid "Show Help" msgstr "Yardımı Göster" msgid "Show Preferences" msgstr "Ayarları Göster" msgid "Switch to First Pane" msgstr "Birinci Bölmeye Geç" msgid "Toggle Text Mode" msgstr "Metin Kipine Geç" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "\"%(query)s\" için eşleşen %(src)s yok" msgid "No matches" msgstr "Eşleşme bulunamadı" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "Eşleşme bulunamadı" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "Öntanımlı \"%(object)s\" için \"%(action)s\" oluştur" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "\"%s\" Unut" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "Uygulama Penceresini Göster" msgid "Show with Selection" msgstr "Seçim ile Göster" #. TRANS: Plugin info fields msgid "Description" msgstr "Açıklama" msgid "Author" msgstr "Yazar" msgid "Version" msgstr "Sürüm" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "'%s' Python modülü gerekli" msgid "Plugin could not be read due to an error:" msgstr "Eklenti bir hata nedeniyle okunamadı:" msgid "Content of" msgstr "İçeriği" #. TRANS: Plugin contents header msgid "Sources" msgstr "Kaynaklar" #. TRANS: Plugin contents header msgid "Actions" msgstr "Eylemler" #, python-format msgid "Using encrypted password storage: %s" msgstr "Şifrelenmiş parola deposu kullanma: %s" #, python-format msgid "Using password storage: %s" msgstr "Parola deposu kullanma: %s" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "Ayarlar" msgid "Set username and password" msgstr "Kullanıcı adı, şifre ayarla" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "Bir klasör seçin" msgid "Reset all shortcuts to default values?" msgstr "Tüm kısayollar öntanımlı değerlerine sıfırlansın mı ?" msgid "Shortcut" msgstr "Kısayol" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "M. Deran Delice" msgid "A free software (GPLv3+) launcher" msgstr "Özgür Yazılım Lisanslı (GPLv3+) Başlatıcı yazılımı" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "Kupfer özgür yazılımdır ve Özgür Yazılım Vakfı tarafından yayınlanan\n" "GNU Genel Kamu Lisansı sürüm 2 veya daha sonraki bir sürümün şartları\n" "altında yeniden dağıtabilir ve/veya değiştirebilirsiniz.\n" "Bu program HERHANGİ BİR GARANTİ OLMADAN; hatta dolaylı olarak ORTALAMA\n" "BİR KALİTE GARANTİSİ veya ÖZEL BİR AMAÇ İÇİN UYGUNLUĞU bile olmadan \n" "faydalı olması umuduyla dağıtılmaktadır.Bu program ile birlikte GNU Genel " "Kamu Lisansının\n" "bir kopyasını almış olmanız gereklidir; eğer almadıysanız adresinden gözatabilirsiniz.\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "Çalışan Kupfer bulunamadı." #~ msgid "Compose Email" #~ msgstr "E-Posta yaz" #~ msgid "Send in Email To..." #~ msgstr "E-posta gönder..." #~ msgid "Type to search %s" #~ msgstr "%s aramak için girin" #~ msgid "No action" #~ msgstr "Eylem yok" #~ msgid "GNOME Terminal Profiles" #~ msgstr "GNOME Uçbirim Profilleri" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "GNOME Uçbirim Profillerini çalıştır" #~ msgid "Multihead Support" #~ msgstr "Çokluekran Desteği" #~ msgid "Calculate expressions starting with '='" #~ msgstr "'=' ile başlayan ifadeleri hesapla" #~ msgid "Epiphany Bookmarks" #~ msgstr "Epiphany Yerimleri" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Epiphany Yerimleri İçeriği" #~ msgid "Include visited sites" #~ msgstr "Ziyaret edilen siteleride içer" #~| msgid "Firefox Bookmarks" #~ msgid "Firefox tag" #~ msgstr "Firefox etiketi" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "Rhythmbox'da çalmayı sürdür" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "Rhythmbox'da çalmayı duraklat" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "Rhythmbox'da sonraki şarkıya atla" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "Rhythmbox'da önceki şarkıya atla" #~ msgid "Search the Web" #~ msgstr "Web'de ara" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Abiword'de en son kullanılan dosyalar" #~ msgid "Abiword Recent Items" #~ msgstr "Abiword Son Öğeler" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "Paket yöneticisi APT arayüzü" #~ msgid "Installation method" #~ msgstr "Yükleme Yöntemi" #~ msgid "Show Package Information" #~ msgstr "Paket Bilgisini Göster" #~ msgid "Install" #~ msgstr "Yükle" #~ msgid "Install package using the configured method" #~ msgstr "Yapılandırılmış yöntemi kullanan paketi kur" #~ msgid "Packages matching \"%s\"" #~ msgstr "\"%s\" ile eşleşen paketler" #~ msgid "Search Package Name..." #~ msgstr "Paket İsmi Ara." #~ msgid "Ascii & Unicode Icon Set" #~ msgstr "Ascii & Unicode Simge Kümesi" #~ msgid "" #~ "Provides the Ascii and Unicode icon sets that use letters and symbols to " #~ "produce icons for the objects found in Kupfer." #~ msgstr "" #~ "Kupfer uygulamasında bulunan nesneler için simge üretme amaçlı semboller " #~ "ve harfler kullanan Ascii ve Unicode simge kümelerini sağlar." #~ msgid "Ascii" #~ msgstr "Ascii" #~ msgid "Unicode" #~ msgstr "Unicode" #~ msgid "Chromium Bookmarks" #~ msgstr "Chromium Yerimleri" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Chromium yerimleri içeriği" #~ msgid "Claws Mail" #~ msgstr "Claws Mail" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Claws Mail Kişi ve eylemleri" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "Claws Mail'de yeni ileti yaz" #~ msgid "Receive All Email" #~ msgstr "Tüm E-postaları al" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "ClawsMail'de ki tüm hesapların yeni iletilerini al" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "Claws Mail eposta istemcisinde yeni ileti oluştur ve dosya ekle" #~ msgid "Claws Mail Address Book" #~ msgstr "Claws Mail Adres Defteri" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Claws Mail Adres Defterindeki Kişiler" #~ msgid "Configure a custom terminal emulator" #~ msgstr "Özel uçbirim öykünücüsü yapılandır" #~ msgid "Custom Theme" #~ msgstr "Özel Tema" #~ msgid "Use a custom color theme" #~ msgstr "Özel renk teması kullan" #~ msgid "Theme:" #~ msgstr "Tema:" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Evolution kişileri" #~ msgid "Compose a new message in Evolution" #~ msgstr "Evolution'da yeni ileti yaz" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "Evolution'da yeni ileti yaz ve dosya ekle" #~ msgid "Evolution Address Book" #~ msgstr "Evolution Adres Defteri" #~ msgid "Filezilla" #~ msgstr "Filezilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "" #~ "Filezilla kullanarak siteleri görüntüleyin veya ftp adreslerinizi yönetin." #~ msgid "Open Site with Filezilla" #~ msgstr "Siteyi Filezilla ile aç" #~ msgid "Filezilla Sites" #~ msgstr "Filezilla Siteleri" #~ msgid "Sites from Filezilla" #~ msgstr "Filezilla'da ki siteler" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "Gajim Kişilerine Erişin" #~ msgid "Free for Chat" #~ msgstr "Sohbet için uygun" #~ msgid "Gajim Contacts" #~ msgstr "Gajim Kişileri" #~ msgid "Gajim Account Status" #~ msgstr "Gajim Hesap Durumu" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "Kişileri yükle ve Gmail'de yeni e-posta yaz" #~ msgid "Load contacts' pictures" #~ msgstr "Kişi resimlerini yükle" #~| msgid "show version information" #~ msgid "Load additional information" #~ msgstr "Ek bilgi yükle" #~ msgid "Work email" #~ msgstr "İş epostası" #~| msgid "Compose Email" #~ msgid "Home email" #~ msgstr "Ev epostası" #~ msgid "Other email" #~ msgstr "Diğer eposta" #~| msgid "Workspaces" #~ msgid "Work address" #~ msgstr "İş adresi" #~| msgid "Home Folder" #~ msgid "Home address" #~ msgstr "Ev adresi" #~ msgid "Other address" #~ msgstr "Diğer adres" #~ msgid "Car phone" #~ msgstr "Araç telefonu" #~ msgid "Fax" #~ msgstr "Faks" #~| msgid "Home Folder" #~ msgid "Home phone" #~ msgstr "Ev telefonu" #~ msgid "Home fax" #~ msgstr "Ev Faksı" #~ msgid "Internal phone" #~ msgstr "Dahili telefon" #~ msgid "Mobile" #~ msgstr "Mobil" #~ msgid "Other" #~ msgstr "Diğer" #~ msgid "VOIP" #~ msgstr "VOIP" #~| msgid "Workspaces" #~ msgid "Work phone" #~ msgstr "İş telefonu" #~ msgid "Work fax" #~ msgstr "İş faksı" #~| msgid "Compose Email in GMail" #~ msgid "Compose Email in Gmail" #~ msgstr "Gmail'de Eposta Oluştur" #~| msgid "Open web browser and compose new email in GMail" #~ msgid "Open web browser and compose new email in Gmail" #~ msgstr "Web tarayıcısı aç ve Gmail'de yeni eposta oluştur" #~ msgid "Edit Contact in Gmail" #~ msgstr "Gmail'deki Kişiyi Düzenle" #~| msgid "Open web browser and compose new email in GMail" #~ msgid "Open web browser and edit contact in Gmail" #~ msgstr "Web tarayıcı aç ve Gmail'deki kişiyi düzenle" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "Google Servis Kişileri (Gmail)" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "Albümleri göster ve Picasa'ya dosyları yükle" #~ msgid "Users to show: (,-separated)" #~ msgstr "Gösterilecek kullanıcılar: (,-virgülle ayrılmış)" #~ msgid "Load user and album icons" #~ msgstr "Kullanıcıları ve albüm simgelerini yükle" #~ msgid "Uploading Pictures" #~ msgstr "Resimler yükleniyor" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "Resimler, Picasa Web Albümleri'ne yükleniyor" #~ msgid "Creating album:" #~ msgstr "Oluşturulan albüm:" #~ msgid "Album created by Kupfer" #~ msgstr "Albüm Kupfer tarafından oluşturulmuştur." #~ msgid "File:" #~ msgstr "Dosya:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "Bir albüm" #~ msgstr[1] "%(num)d albüm" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "Bir fotoğraf" #~ msgstr[1] "%(num)s fotoğraf" #~ msgid "Upload to Picasa Album..." #~ msgstr "Picasa Albümlerine Yükle..." #~ msgid "Upload files to Picasa album" #~ msgstr "Dosyaları Picasa albümlerine yükle" #~ msgid "Upload to Picasa as New Album" #~ msgstr "Picasa'ya Yeni Albüm Olarak Yükle" #~ msgid "Create album from selected local directory" #~ msgstr "Seçili yerel klasörden albüm oluştur" #~ msgid "Picasa Albums" #~ msgstr "Picasa Albümleri" #~ msgid "User albums in Picasa" #~ msgstr "Picasa'da ki kullanıcı albümleri" #~ msgid "Google Search" #~ msgstr "Google Arama" #~ msgid "Search Google with results shown directly" #~ msgstr "Google'da hemen görüntülenen sonuçlar ile arama yapın" #~ msgid "Show More Results For \"%s\"" #~ msgstr " \"%s\" İçin Daha Fazla Sonuç Göster" #~ msgid "%s total found" #~ msgstr "Toplam %s bulundu" #~ msgid "Gwibber" #~ msgstr "Gwibber" #~ msgid "" #~ "Microblogging with Gwibber. Allows sending and receiving messages from " #~ "social networks like Twitter, Identi.ca etc. Requires the package " #~ "'gwibber-service'." #~ msgstr "" #~ "GWibber ile mikroblog. Twitter, Indenti.ca vb. sosyal ağlardan iletileri " #~ "almaya ve göndermeye izin verir. 'gwibber service' paketini ister." #~ msgid "Maximum number of messages to show" #~ msgstr "Gösterilecek azami ileti sayısı" #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s %(service)s" #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s %(where)s" #~ msgid "Send Message" #~ msgstr "İleti Gönder" #~ msgid "Send message to all Gwibber accounts" #~ msgstr "Bütün Gwibber hesaplarına ileti gönder" #~ msgid "Send Message To..." #~ msgstr "İleti Gönder..." #~ msgid "Send message to a Gwibber account" #~ msgstr "Bir Gwibber hesabına ileti gönder" #~ msgid "Send message to selected Gwibber account" #~ msgstr "Seçilen Gwibber hesabına ileti gönder" #~ msgid "Reply..." #~ msgstr "Yanıtla..." #~ msgid "Delete Message" #~ msgstr "İleti Sil" #~ msgid "Send Private Message..." #~ msgstr "Özel İleti Gönder..." #~ msgid "Send direct message to user" #~ msgstr "Kullanıcıya doğrudan ileti gönder" #~ msgid "Retweet" #~ msgstr "Retweet" #~ msgid "Retweet To..." #~ msgstr "Şuna Retweetle..." #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "Tüm GWibber hesaplarına iletiyi yönlendir" #~ msgid "Retweet message to a Gwibber account" #~ msgstr "Bir GWibber hesabına iletiyi yönlendir" #~ msgid "Open in Browser" #~ msgstr "Tarayıcıda Aç" #~ msgid "Open message in default web browser" #~ msgstr "İletiyi öntanımlı web tarayıcısında aç" #~ msgid "Gwibber Accounts" #~ msgstr "Gwibber Hesapları" #~ msgid "Accounts configured in Gwibber" #~ msgstr "Hesaplar GWibber'da yapılandırıldı" #~ msgid "Gwibber Messages" #~ msgstr "Gwibber İletileri" #~ msgid "Recent messages received by Gwibber" #~ msgstr "GWibber tarafından alınan son iletiler" #~ msgid "Gwibber Messages for %s" #~ msgstr "%s için Gwibber İletileri" #~ msgid "Gwibber Streams" #~ msgstr "Gwibber Akışları" #~ msgid "Streams configured in Gwibber" #~ msgstr "Akışlar GWibber'da yapılandırıldı" #~ msgid "Gwibber Messages in %s" #~ msgstr "%s akışında Gwibber İletileri" #~ msgid "Gwibber (Simple)" #~ msgstr "Gwibber (Basit)" #~ msgid "Send updates via the microblogging client Gwibber" #~ msgstr "Güncellemeleri Gwibber istemci mikrobloglama yoluyla gönder" #~ msgid "Send Update" #~ msgstr "Güncelleme Gönder" #~ msgid "Unable to activate Gwibber service" #~ msgstr "Gwibber hizmeti etkinleştirilemedi" #~ msgid "OpenOffice / LibreOffice" #~ msgstr "OpenOffice / LibreOffice" #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "OpenOffice/LibreOffice'de son zamanlarda kullanılan belgeler" #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "OpenOffice/LibreOffice Son Kullanılan Öğeler" #~ msgid "Opera Mail" #~ msgstr "Opera Mail" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Opera Mail Kişi ve Eylemleri" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "Opera Mail'de yeni bir mesaj yaz" #~ msgid "Opera Mail Contacts" #~ msgstr "Opera Mail Kişileri" #~ msgid "Contacts from Opera Mail" #~ msgstr "Opera Mail'de ki kişiler" #~ msgid "Opera Bookmarks" #~ msgstr "Opera Yerimleri" #~ msgid "Index of Opera bookmarks" #~ msgstr "Opera Yerimleri İçeriği" #~ msgid "PuTTY Sessions" #~ msgstr "PuTTY Oturumları" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "PuTTY Oturumlarına hızlı erişim" #~ msgid "Start Session" #~ msgstr "Oturum Başlat" #~ msgid "reStructuredText" #~ msgstr "yenidenYapılandırılmışMetin" #~ msgid "Render reStructuredText and show the result" #~ msgstr "yenidenYapılandırılmışMetni gerçekle ve sonucu göster" #~ msgid "View as HTML Document" #~ msgstr "HTML olarak görüntüle" #~ msgid "System Services" #~ msgstr "Sistem Servisleri" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "" #~ "init betikleri yoluyla sistem servislerini başlat, durdur ya da yeniden " #~ "başlat" #~ msgid "Sudo-like Command" #~ msgstr "Sudo benzeri Komut" #~ msgid "Start Service" #~ msgstr "Servisi Başlat" #~ msgid "Stop Service" #~ msgstr "Servisi Durdur" #~ msgid "%s Service" #~ msgstr "%s Servisi" #~ msgid "Show QRCode" #~ msgstr "Kare Kodu Göster" #~ msgid "Display text as QRCode in a window" #~ msgstr "Pencerede metni kare kod olarak göster" #~ msgid "Access to Skype contacts" #~ msgstr "Skype kişilerine erişin" #~ msgid "Skype Me" #~ msgstr "Bana Skype at " #~ msgid "Logged Out" #~ msgstr "Oturum Kapatılmış" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "Ara" #~ msgid "Place a call to contact" #~ msgstr "Kişi arayın" #~ msgid "Skype Contacts" #~ msgstr "Skype Kişileri" #~ msgid "Skype Statuses" #~ msgstr "Skype Durumları" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "TrueCrypt geçmişinden birimler" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "TrueCrypt Birimi: %(file)s" #~ msgid "Mount Volume" #~ msgstr "Birimi Bağla" #~ msgid "Mount in Truecrypt" #~ msgstr "TrueCrypt'ta bağla" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "Dosyayı TrueCrypt Birimi olarak bağlamayı dene" #~ msgid "Dismount All Volumes" #~ msgstr "Bütün Birimlerin Bağını Kaldır" #~ msgid "TrueCrypt Volumes" #~ msgstr "TrueCrypt Birimleri" #~ msgid "Terminal Server Client" #~ msgstr "Uçbirim sunucu istemcisi" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "Oturum, uçbirim sunucu istemcisine kayıt edildi" #~ msgid "TSClient sessions" #~ msgstr "TSClient oturumları" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "Uçbirim sunucu istemcisine kayıtlı oturumlar" #~ msgid "Vim" #~ msgstr "Vim" #~ msgid "Recently used documents in Vim" #~ msgstr "Vim'de en son kullanılan belgeler" #~ msgid "Vim Recent Documents" #~ msgstr "Vim En son kullanılan belgeler" #~ msgid "Close (Save All)" #~ msgstr "Kapat (Tümünü Kaydet)" #~| msgid "Send To..." #~ msgid "Send..." #~ msgstr "Gönder..." #~| msgid "Saved Kupfer Command" #~ msgid "Send ex command" #~ msgstr "ex komutu gönder" #~ msgid "Insert in Vim..." #~ msgstr "Vim içinde ekle..." #~| msgid "Screen Sessions" #~ msgid "Active Vim Sessions" #~ msgstr "Etkin Vim Oturumları" #~| msgid "PuTTY Sessions" #~ msgid "Vim Session %s" #~ msgstr "Vim Oturumu %s" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Vinagre Yerimleri ve Eylemleri" #~ msgid "Start Vinagre Session" #~ msgstr "Vinagre Oturumu Başlat" #~ msgid "Vinagre Bookmarks" #~ msgstr "Vinagre Yerimleri" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "" #~ "VirtualBox Sanal makinelerini yönetin. Sun VirtualBox veya Açık kaynaklı " #~ "sürümlerini destekler." #~ msgid "Force use CLI interface" #~ msgstr "CLI arayüzünü kullanmayı zorla" #~ msgid "Power On" #~ msgstr "Aç" #~ msgid "Power On Headless" #~ msgstr "Grafik Arayüzü Olmadan Aç" #~ msgid "Send Power Off Signal" #~ msgstr "Makineye Kapatma Sinyali Gönder" #~ msgid "Reboot" #~ msgstr "Yeniden Başlat" #~ msgid "Resume" #~ msgstr "Sürdür" #~ msgid "Save State" #~ msgstr "Şu an ki durumu kaydet" #~ msgid "Power Off" #~ msgstr "Kapat" #~ msgid "VirtualBox Machines" #~ msgstr "VirtualBox Makineleri" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "" #~ "Zim içinde depolanan Sayfalara Erişim - Masaüstü Wiki ve Anahat " #~ "Düzenleyicisi" #~ msgid "Page names start with :colon" #~ msgstr "Sayfa adları :colon ile başlar" #~ msgid "Default page name for quick notes" #~ msgstr "Hızlı notlar için öntanımlı sayfa adı" #~ msgid "Note %x %X" #~ msgstr "Not %x %X" #~ msgid "" #~ "Strftime tags can be used: %H - hour, %M - minutes, etc\n" #~ "Please check python documentation for details.\n" #~ "NOTE: comma will be replaced by _" #~ msgstr "" #~ "Strftime etiketleri kullanılabilir: %H - saat, %M - dakika gibi\n" #~ "Lütfen ayrıntılar için python belgesini kontrol edin.\n" #~ "NOT: Virgül _ ile yer değiştirilecektir" #~ msgid "Default namespace for quick notes" #~ msgstr "Hızlı notlar için öntanımlı ad alanı" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "\"%s\" Not Defterinden Zim Sayfası" #~ msgid "Create Zim Page" #~ msgstr "Zim Sayfası Oluştur" #~ msgid "Create page in default notebook" #~ msgstr "Öntanımlı not defterinde sayfa oluştur" #~ msgid "Create Zim Page In..." #~ msgstr "Şurada Zim Sayfası Oluştur..." #~ msgid "Insert QuickNote into Zim" #~ msgstr "Zim içine HızlıNot ekle" #~ msgid "Quick note selected text into Zim notebook" #~ msgstr "Hızlı not Zim not defterinde metin seçti" #~ msgid "Create Subpage..." #~ msgstr "Alt Sayfa Oluştur..." #~ msgid "Zim Notebooks" #~ msgstr "Zim Not Defteri" #~ msgid "Zim Pages" #~ msgstr "Zim Sayfaları" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Sayfalar Zim Not Defterinde depolandı" #, fuzzy #~ msgid "Selected Text \"%s\"" #~ msgstr "\"%s\" Seçili Yazı" #~ msgid "Recent clipboards" #~ msgstr "En son kullanılan panolar" #~ msgid "Include recent selections" #~ msgstr "Son seçilenleri içer" #, fuzzy #~ msgid "Selected File \"%s\"" #~ msgstr " \"%s\" Seçili Dosya" #~ msgid "Selected Files" #~ msgstr "Seçili Dosyalar" #~ msgid "Translate text with Google Translate" #~ msgstr "Google Çeviri kullanarak yazıyı tercüme et" #~ msgid "Google Translate connection timed out" #~ msgstr "Google Çeviri bağlantısı zaman aşımına uğradı." #~ msgid "Error connecting to Google Translate" #~ msgstr "Google Çeviriye bağlanırken hata" #~ msgid "Translate To..." #~ msgstr "Çevir..." #, fuzzy #~ msgid "Translate into %s" #~ msgstr "%s Çevir" #~ msgid "Languages" #~ msgstr "Diller" #~ msgid "Show translated page in browser" #~ msgstr "Çevirilen sayfayı tarayıcıda göster" #~ msgid "Show Translation To..." #~ msgstr "Çeviriyi göster..." #~ msgid "Show translation in browser" #~ msgstr "Çeviriyi tarayıcıda göster" #~ msgid "Tracker 0.6" #~ msgstr "Tracker 0.6" #~ msgid "Tracker tags" #~ msgstr "Tracker etiketleri" #~ msgid "Tracker Tags" #~ msgstr "Tracker etiketleri" #~ msgid "Browse Tracker's tags" #~ msgstr "Tracker etiketlerine gözat" #~ msgid "Tag %s" #~ msgstr "%s Etiket" #~ msgid "Objects tagged %s with Tracker" #~ msgstr "Tracker'da %s ile etiketlenmiş dosyalar" #~ msgid "Add Tag..." #~ msgstr "Etiket Ekle..." #~ msgid "Add tracker tag to file" #~ msgstr "Dosyaya Tracker etiketi ekle" #~ msgid "Remove Tag..." #~ msgstr "Etiketi Sil..." #~ msgid "Remove tracker tag from file" #~ msgstr "Dosyanın Tracker etiketini sil" #~ msgid "Directories" #~ msgstr "Klasörler" #~ msgid "Interface" #~ msgstr "Arayüz" #~ msgid "Hide Kupfer when focus is lost" #~ msgstr "Başka pencereye odaklanıldığında uygulamayı gizle" #~ msgid "Text Matches" #~ msgstr "Eşleşmeler" #~ msgid "noun" #~ msgstr "isim" #~ msgid "verb" #~ msgstr "fiil" #~ msgid "adjective" #~ msgstr "sıfat" #~ msgid "Twitter" #~ msgstr "Twitter" #~ msgid "Load friends' pictures" #~ msgstr "Arkadaşlarının resimlerini yükle" #~ msgid "Load timeline" #~ msgstr "Zaman çizelgesini yülke" #~ msgid "Post Update to Twitter" #~ msgstr "Twitter hesabınıza güncellemeleri gönderin" #~ msgid "Twitter Timeline" #~ msgstr "Twitter Zaman Çizelgesi" #~ msgid "Twitter Friends" #~ msgstr "Twitter Arkadaşları" #~ msgid "Timeline for %s" #~ msgstr "%s için zaman çizelgesi" #~ msgid "OpenOffice" #~ msgstr "OpenOffice" #~ msgid "Preferred terminal" #~ msgstr "Tercih edilen uçbirim" #~ msgid "Tracker 0.8" #~ msgstr "Tracker 0.8" kupfer-328/po/wscript000066400000000000000000000001141500175051100147070ustar00rootroot00000000000000def build(bld): bld(features="intltool_po", appname=bld.env["PACKAGE"]) kupfer-328/po/zh_CN.po000066400000000000000000001505041500175051100146430ustar00rootroot00000000000000# Simplified Chinese translation of kupfer # Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. # This file is distributed under the same license as the kupfer package. # lh , 2009. # du baodao , 2010. # Yinghua Wang , 2011. # Aron Xu , 2011. # msgid "" msgstr "" "Project-Id-Version: kupfer master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-22 23:26+0100\n" "PO-Revision-Date: 2011-03-05 15:03+0800\n" "Last-Translator: Yinghua Wang \n" "Language-Team: Chinese (simplified) \n" "Language: zh_CN\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" msgid "User credentials" msgstr "用户证书" msgid "_User:" msgstr "用户(_U)" msgid "_Password:" msgstr "密码(_P):" msgid "_Change" msgstr "更改(_C)" msgid "Set Keyboard Shortcut" msgstr "设置键盘快捷键" msgid "Please press desired key combination" msgstr "请按下想使用的组合键" msgid "Keybinding could not be bound" msgstr "无法进行按键绑定" msgid "Kupfer Preferences" msgstr "首选项" msgid "Start automatically on login" msgstr "登录后自启动" msgid "Start" msgstr "开始" msgid "Show icon in notification area" msgstr "在系统通知区域显示图标" msgid "Icon set:" msgstr "" msgid "Large Icon Size:" msgstr "" msgid "Small Icon Size:" msgstr "" #, fuzzy msgid "Terminal emulator:" msgstr "在此处开启终端" #, fuzzy msgid "Desktop Environment" msgstr "桌面环境的应用程序" msgid "General" msgstr "常规" msgid "Global Keyboard Shortcuts" msgstr "全局快捷键" msgid "Reset" msgstr "重置" msgid "Browser Keyboard Shortcuts" msgstr "浏览键盘快捷键" msgid "Use single keystroke commands (Space, /, period, comma etc.)" msgstr "使用单键命令(空格键、/ 键、逗号键等)" msgid "Keyboard" msgstr "键盘" msgid "Plugins" msgstr "插件" #, fuzzy msgid "Inclusion in Top Level Searches" msgstr "把歌曲放到顶端" msgid "" "Marked sources have their objects included in top level searches.\n" "An unmarked source's contents are only available by locating its subcatalog." msgstr "" #, fuzzy msgid "Indexed Folders" msgstr "新文件夹" msgid "Folders whose files are always available in the catalog." msgstr "" msgid "Catalog" msgstr "类别" msgid "Kupfer" msgstr "Kupfer" msgid "Application Launcher" msgstr "程序启动器" msgid "Convenient command and access tool for applications and documents" msgstr "方便的命令和操作程序或文档的工具" msgid "Execute in Kupfer" msgstr "在 Kupfer 中执行" msgid "Saved Kupfer Command" msgstr "已保存的 Kupfer 命令" #, python-format msgid "Could not to carry out '%s'" msgstr "无法执行 “%s”" #, python-format msgid "\"%s\" produced a result" msgstr "“%s”产生了一个结果" #, python-format msgid "No permission to run \"%s\" (not executable)" msgstr "没有权限运行“%s”(缺少可执行属性)" #, python-format msgid "Command in \"%s\" is not available" msgstr "“%s”命令无效" #, python-format msgid "Keyboard relay is active for display %s" msgstr "" msgid "do not present main interface on launch" msgstr "启动后不显示主界面" msgid "list available plugins" msgstr "列出可用插件" msgid "enable debug info" msgstr "显示调试信息" #. TRANS: --exec-helper=HELPER is an internal command #. TRANS: that executes a helper program that is part of kupfer msgid "run plugin helper" msgstr "" msgid "show usage help" msgstr "显示用法帮助" msgid "show version information" msgstr "显示版本信息" msgid "Usage: kupfer [ OPTIONS | FILE ... ]" msgstr "用法:kupfer [选项|文件 ... ]" msgid "Available plugins:" msgstr "可用插件:" #, fuzzy, python-format msgid "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" " %(COPYRIGHT)s\n" " %(WEBSITE)s\n" msgstr "" "%(PROGRAM_NAME)s: %(SHORT_DESCRIPTION)s\n" "\t%(COPYRIGHT)s\n" "\t%(WEBSITE)s\n" msgid "Type to search" msgstr "输入进行搜索" #, python-format msgid "%s is empty" msgstr "%s 是空的" #, fuzzy msgid "Text" msgstr "显示文本" msgid "Run after Delay..." msgstr "延迟后运行..." msgid "Perform command after a specified time interval" msgstr "在指定时长后运行命令" msgid "Multiple Objects" msgstr "多个对象" #, python-format msgid "%s object" msgid_plural "%s objects" msgstr[0] "%s 个对象" msgstr[1] "%s 个对象" #, python-format msgid "[%(status)s] %(userid)s/%(service)s" msgstr "[%(status)s] %(userid)s/%(service)s" msgid "unknown" msgstr "" #, fuzzy msgid "Aim" msgstr "Vim" #, fuzzy msgid "Google Talk" msgstr "Google Transalte" msgid "ICQ" msgstr "" msgid "MSN" msgstr "" msgid "QQ" msgstr "" msgid "Yahoo" msgstr "" msgid "Skype" msgstr "Skype" #, python-format msgid "%s does not support this operation" msgstr "" msgid "Can not be used with multiple objects" msgstr "" msgid "Open" msgstr "打开" #, python-format msgid "No default application for %(file)s (%(type)s)" msgstr "没有打开 %(file)s (%(type)s) 文件的默认程序" #, fuzzy, python-format msgid "Please use \"%s\"" msgstr "选择文件“%s”" msgid "Set Default Application..." msgstr "设置默认程序..." msgid "Open with default application" msgstr "使用默认程序打开" msgid "Reveal" msgstr "显示" msgid "Open parent folder" msgstr "打开所在目录" msgid "Open Terminal Here" msgstr "在此处开启终端" msgid "Open this location in a terminal" msgstr "在终端中进入这个位置" msgid "Run in Terminal" msgstr "终端中运行" msgid "Run (Execute)" msgstr "运行(执行)" msgid "Run this program in a Terminal" msgstr "在终端中运行此程序" msgid "Run this program" msgstr "运行这个程序" msgid "Go To" msgstr "转到" msgid "Open URL" msgstr "打开链接" msgid "Open URL with default viewer" msgstr "用默认查看器打开链接" msgid "Launch" msgstr "启动" msgid "Show application window" msgstr "显示程序窗口" msgid "Launch application" msgstr "启动程序" msgid "Launch Again" msgstr "再次启动" msgid "Launch another instance of this application" msgstr "开启此程序的另一个实例" msgid "Close" msgstr "关闭" msgid "Attempt to close all application windows" msgstr "尝试关闭所有程序窗口" #. TRANS: 'Run' as in Perform a (saved) command msgid "Run" msgstr "运行" msgid "Perform command" msgstr "执行命令" msgid "(Empty Text)" msgstr "(空文本)" #. TRANS: This is description for a TextLeaf, a free-text search #. TRANS: The plural parameter is the number of lines %(num)d #, python-format msgid "\"%(text)s\"" msgid_plural "(%(num)d lines) \"%(text)s\"" msgstr[0] "\"%(text)s\"" msgstr[1] "(%(num)d 行) ”%(text)s“" #. TRANS: Multiple artist description "Artist1 et. al. " #, python-format msgid "%s et. al." msgstr "%s 等" #, python-format msgid "Recursive source of %(dir)s, (%(levels)d levels)" msgstr "%(dir)s 有 %(levels)d 层" #, python-format msgid "Directory source %s" msgstr "目录资源 %s" msgid "Home Folder" msgstr "主文件夹" msgid "Catalog Index" msgstr "类别索引" msgid "An index of all available sources" msgstr "一个所有可用资源的索引" msgid "Root catalog" msgstr "主类别" msgid "Please Configure Plugin" msgstr "请配置插件" #, python-format msgid "Plugin %s is not configured" msgstr "插件 %s 没有配置" #, python-format msgid "Invalid user credentials for %s" msgstr "%s 的用户证书无效" msgid "Applications" msgstr "应用程序" msgid "All applications and preferences" msgstr "所有的应用程序和设置" msgid "Applications for Desktop Environment" msgstr "桌面环境的应用程序" msgid "Use Desktop Filter" msgstr "" msgid "Open With..." msgstr "打开方式..." msgid "Open with any application" msgstr "使用任意可用程序打开" msgid "Set default application to open this file type" msgstr "设置打开此类文件的默认程序" #, fuzzy msgid "Reset Associations" msgstr "超链接操作" msgid "Reset program associations for files of this type." msgstr "" msgid "Deep Archives" msgstr "深层档案" msgid "Allow browsing inside compressed archive files" msgstr "允许浏览压缩文档内的内容" #, python-format msgid "Content of %s" msgstr "%s 的内容" #, fuzzy msgid "Archive Manager" msgstr "压缩包" #, fuzzy msgid "Use Archive Manager actions" msgstr "文件管理器 Thunar 动作" msgid "Compressed archive type for 'Create Archive In'" msgstr "'创建压缩包'的压缩档案类型" msgid "Extract Here" msgstr "解压到这里" msgid "Extract compressed archive" msgstr "解压压缩包" msgid "Create Archive" msgstr "创建压缩包" msgid "Create a compressed archive from folder" msgstr "将文件夹打包" msgid "Create Archive In..." msgstr "创建压缩包..." #. TRANS: Default filename (no extension) for 'Create Archive In...' msgid "Archive" msgstr "压缩包" msgid "Audacious" msgstr "Audacious" msgid "Control Audacious playback and playlist" msgstr "控制 Audacious 的回放和播放列表" msgid "Include songs in top level" msgstr "把歌曲放到顶端" msgid "Enqueue" msgstr "打开" msgid "Add track to the Audacious play queue" msgstr "向 Audacious 播放队列添加音轨" msgid "Dequeue" msgstr "离队" msgid "Remove track from the Audacious play queue" msgstr "从 Audacious 播放队列中移除音轨" msgid "Play" msgstr "播放" msgid "Jump to track in Audacious" msgstr "跳到 Audacious 中的音轨" msgid "Resume playback in Audacious" msgstr "恢复 Audacious 回放" msgid "Pause" msgstr "暂停" msgid "Pause playback in Audacious" msgstr "暂停 Audacious 回放" msgid "Next" msgstr "下一首" msgid "Jump to next track in Audacious" msgstr "跳到 Audacious 中的下一音轨" msgid "Previous" msgstr "前一首" msgid "Jump to previous track in Audacious" msgstr "跳到 Audacious 中的前一音轨" msgid "Clear Queue" msgstr "清除队列" msgid "Clear the Audacious play queue" msgstr "清空 Audacious 播放队列" msgid "Shuffle" msgstr "打乱" msgid "Toggle shuffle in Audacious" msgstr "在 Audacious 中切换乱序" msgid "Repeat" msgstr "反复" msgid "Toggle repeat in Audacious" msgstr "切换 Audacious 中的重复" msgid "Show Playing" msgstr "显示正在播放" msgid "Tell which song is currently playing" msgstr "显示正在播放的歌曲" msgid "Playlist" msgstr "播放列表" msgid "Calculator" msgstr "计算器" msgid "Calculate mathematical expressions" msgstr "" msgid "Calculate" msgstr "计算" msgid "Clipboards" msgstr "剪贴板" msgid "Recent clipboards and clipboard proxy objects" msgstr "" #, fuzzy msgid "Number of recent clipboards to remember" msgstr "最近剪贴板的数目" msgid "Include selected text in clipboard history" msgstr "" #, fuzzy msgid "Copy selected text to primary clipboard" msgstr "复制选定内容到剪贴板" msgid "Selected Text" msgstr "选中文本" #, python-format msgid "Clipboard \"%(desc)s\"" msgid_plural "Clipboard with %(num)d lines \"%(desc)s\"" msgstr[0] "剪贴板 \"%(desc)s\"" msgstr[1] "剪贴板 %(num)d 行 \"%(desc)s\"" #, fuzzy msgid "Clipboard Text" msgstr "剪贴板" #, fuzzy msgid "Clipboard File" msgstr "剪贴板" #, fuzzy msgid "Clipboard Files" msgstr "剪贴板" msgid "Clear" msgstr "清除" msgid "Remove all recent clipboards" msgstr "清除所有最近的剪贴板" msgid "Shell Commands" msgstr "命令行" #, python-format msgid "" "Run command-line programs. Actions marked with the symbol %s run in a " "subshell." msgstr "" msgid "Run (Get Output)" msgstr "运行(获得输出)" msgid "Run program and return its output" msgstr "运行程序并返回它的结果" #. TRANS: The user starts a program (command) and the text #. TRANS: is an argument to the command msgid "Pass to Command..." msgstr "传递给命令..." msgid "Run program with object as an additional parameter" msgstr "以对象为附加参数运行程序" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin #, fuzzy msgid "Write to Command..." msgstr "发送到命令..." msgid "Run program and supply text on the standard input" msgstr "运行程序并在标准输出上提供文本反馈" #. TRANS: The user starts a program (command) and #. TRANS: the text is written on stdin, and we #. TRANS: present the output (stdout) to the user. msgid "Filter through Command..." msgstr "筛选命令..." #, fuzzy msgid "Run command-line programs" msgstr "运行命令行程序" msgid "GTK+" msgstr "" #, fuzzy msgid "GNOME Terminal" msgstr "GNOME 终端配置" #, fuzzy msgid "XFCE Terminal" msgstr "终端中运行" #, fuzzy msgid "LXTerminal" msgstr "终端中运行" #, fuzzy msgid "X Terminal" msgstr "终端中运行" msgid "Urxvt" msgstr "" msgid "Konsole" msgstr "" msgid "Save As..." msgstr "另存为..." #, fuzzy msgid "Restart Kupfer" msgstr "重启服务" msgid "Quit" msgstr "退出" msgid "Quit Kupfer" msgstr "退出 Kupfer" msgid "About Kupfer" msgstr "关于 Kupfer" msgid "Show information about Kupfer authors and license" msgstr "显示有关 Kupfer 作者和许可证的信息" msgid "Kupfer Help" msgstr "Kupfer 帮助" msgid "Get help with Kupfer" msgstr "获取 Kupfer 帮助" msgid "Show preferences window for Kupfer" msgstr "显示 Kupfer 首选项窗口" msgid "Search Contents" msgstr "搜索内容" msgid "Search inside this catalog" msgstr "在此类别中搜索" msgid "Copy" msgstr "复制" msgid "Copy to clipboard" msgstr "复制到剪切板" msgid "Rescan" msgstr "重新检索" msgid "Force reindex of this source" msgstr "强行重新索引这个资源" msgid "Last Command" msgstr "最近的命令" msgid "Internal Kupfer Objects" msgstr "Kupfer 内部对象" msgid "Last Result" msgstr "最近的结果" msgid "Command Results" msgstr "命令结果" #, fuzzy msgid "Custom Terminal" msgstr "终端中运行" msgid "" "Configure a custom terminal emulator.\n" "\n" "The plugin adds another terminal alternative (select it on the main page)." msgstr "" msgid "Command" msgstr "命令" msgid "Execute flag" msgstr "执行标志" msgid "Default Email Client" msgstr "默认电子邮件客户端" msgid "Compose email using the system's default mailto: handler" msgstr "使用系统默认的 mailto: 处理器编辑邮件" #, fuzzy msgid "Compose Email To" msgstr "编写新邮件" msgid "Dictionary" msgstr "字典" msgid "Look up word in dictionary" msgstr "在字典中查找单词" msgid "Look Up" msgstr "寻找" msgid "Documents" msgstr "文档" msgid "Recently used documents and bookmarked folders" msgstr "最近使用的文档和保存为书签的文件夹" msgid "Max recent document days" msgstr "最大最近文档天数" msgid "Recent Items" msgstr "最近的项目" msgid "Recently used documents" msgstr "最近打开文档" #. TRANS: Recent Documents for application %s #, python-format msgid "%s Documents" msgstr "%s 个文档" #, python-format msgid "Recently used documents for %s" msgstr "%s 最近使用的文档" msgid "Places" msgstr "位置" msgid "Bookmarked folders" msgstr "加入书签的文件夹" #, fuzzy msgid "DuckDuckGo Search" msgstr "Google 搜索" msgid "Search the web securely with DuckDuckGo" msgstr "" msgid "Favorites" msgstr "收藏" msgid "Mark commonly used items and store objects for later use" msgstr "标记常用项并存储对象以备后用" msgid "Shelf of \"Favorite\" items" msgstr "项目的“收藏”夹" msgid "Add to Favorites" msgstr "添加到收藏" msgid "Add item to favorites shelf" msgstr "添加项目到收藏夹" msgid "Remove from Favorites" msgstr "从收藏中删除" msgid "Remove item from favorites shelf" msgstr "从收藏夹中删除项目" msgid "File Actions" msgstr "文件操作" msgid "More file actions" msgstr "更多文件操作" msgid "Move To..." msgstr "移动到..." msgid "Move file to new location" msgstr "移动文件到一个新位置" msgid "Rename To..." msgstr "重命名为..." msgid "Copy To..." msgstr "复制到..." msgid "Copy file to a chosen location" msgstr "复制文件到一个选择好的位置" #. TRANS: "Glob" is the matching files like a shell with "*.py" etc. msgid "Glob" msgstr "" msgid "Select objects using '*' and '?' as wildcards." msgstr "" msgid "Higher-order Actions" msgstr "高优先级操作" msgid "Tools to work with commands as objects" msgstr "将命令视为对象进行操作的工具" msgid "Select in Kupfer" msgstr "在 Kupfer 中选择" #, python-format msgid "Result of %s (%s)" msgstr "“%s”的结果(%s)" msgid "Run (Take Result)" msgstr "运行(得到结果)" msgid "Take the command result as a proxy object" msgstr "把此命令的结果作为代理对象" msgid "Run (Discard Result)" msgstr "运行(忽略结果)" msgid "Image Tools" msgstr "图像工具" #, fuzzy msgid "Image transformation tools using 'convert' from ImageMagick" msgstr "图像转换工具" msgid "Scale..." msgstr "缩放..." msgid "Scale image to fit inside given pixel measure(s)" msgstr "缩放图像来适合内部指定的像素单位" msgid "Rotate Clockwise" msgstr "顺时针旋转" msgid "Rotate Counter-Clockwise" msgstr "逆时针旋转" msgid "Autorotate" msgstr "自动旋转" msgid "Rotate JPEG (in-place) according to its EXIF metadata" msgstr "根据自身 EXIF 数据旋转 JPEG 文件" msgid "Kupfer Plugins" msgstr "Kupfer 插件" msgid "Access Kupfer's plugin list in Kupfer" msgstr "在 Kupfer 中访问 Kupfer 插件" msgid "Show Information" msgstr "显示信息" msgid "Show Source Code" msgstr "显示源代码" msgid "enabled" msgstr "已启用" msgid "disabled" msgstr "已禁用" msgid "Notes" msgstr "便笺" msgid "Gnote or Tomboy notes" msgstr "Gnote 或者 Tomboy 便笺" msgid "Work with application" msgstr "和应用程序一同工作" msgid "Open with notes application" msgstr "用便笺程序打开" msgid "Append to Note..." msgstr "添加到便笺..." msgid "Add text to existing note" msgstr "添加文本到已有的便笺" msgid "Create Note" msgstr "创建便笺" msgid "Create a new note from this text" msgstr "用此文本创建新的便笺" msgid "Get Note Search Results..." msgstr "获得便笺搜索结果..." msgid "Show search results for this query" msgstr "显示本次查询的搜索结果结果" #, python-format msgid "today, %s" msgstr "今天,%s" #, python-format msgid "yesterday, %s" msgstr "昨天,%s" #. TRANS: Note description, %s is last changed time in locale format #, python-format msgid "Last updated %s" msgstr "上次更新 %s" msgid "Quicksilver Icons" msgstr "" msgid "Quick Image Viewer" msgstr "" msgid "View Image" msgstr "" msgid "GNU Screen" msgstr "GNU Screen" msgid "Active GNU Screen sessions" msgstr "活动的 GNU Screen 会话" msgid "Attached" msgstr "已连接" msgid "Detached" msgstr "已断开" #, python-format msgid "%(status)s session (%(pid)s) created %(time)s" msgstr "%(status)s 会话 (%(pid)s) 创建 %(time)s" msgid "Screen Sessions" msgstr "Screen 会话" msgid "Attach" msgstr "附加" #, fuzzy msgid "Send Keys" msgstr "发送更新" msgid "Send synthetic keyboard events using xautomation" msgstr "" msgid "Paste to Foreground Window" msgstr "" msgid "Copy to clipboard and send Ctrl+V to foreground window" msgstr "" msgid "Send keys to foreground window" msgstr "" msgid "Type Text" msgstr "" msgid "Type the text to foreground window" msgstr "" msgid "GNOME Session Management" msgstr "GNOME 会话管理器" msgid "Special items and actions for GNOME environment" msgstr "GNOME 环境的特殊项目和操作" msgid "Log Out..." msgstr "注销..." msgid "Log out or change user" msgstr "注销或者更改用户" msgid "Shut Down..." msgstr "关机..." msgid "Shut down, restart or suspend computer" msgstr "关机,重启或者待机" msgid "Lock Screen" msgstr "锁住屏幕" msgid "Enable screensaver and lock" msgstr "启用屏保和锁屏" #. -*- coding: utf-8 -* msgid "XFCE Session Management" msgstr "XFCE 会话管理器" msgid "Special items and actions for XFCE environment" msgstr "XFCE 环境的特殊项目和操作" #. -*- coding: UTF-8 -*- msgid "SSH Hosts" msgstr "SSH 主机" msgid "Adds the SSH hosts found in ~/.ssh/config." msgstr "添加此 SSH 主机到 ~/.ssh/config 。" msgid "SSH host" msgstr "SSH 主机" msgid "Connect" msgstr "连接" msgid "Connect to SSH host" msgstr "连接到 SSH 主机" msgid "SSH hosts as specified in ~/.ssh/config" msgstr "~/.ssh/config 中指定的 SSH 主机" msgid "No D-Bus connection to desktop session" msgstr "没有到桌面会话的 D-Bus 连接" #, fuzzy msgid "GNOME Keyring" msgstr "GNOME 终端配置" msgid "KWallet" msgstr "" #, fuzzy msgid "Unencrypted File" msgstr "选择的文件" #, fuzzy, python-format msgid "Dependency '%s' is not available" msgstr "“%s”命令无效" msgid "Document Templates" msgstr "文档模板" msgid "Create new documents from your templates" msgstr "从你的模板创建新文档" #, python-format msgid "%s template" msgstr "%s 模板" msgid "Empty File" msgstr "空文件" msgid "New Folder" msgstr "新文件夹" msgid "Create New Document..." msgstr "创建新文档..." msgid "Create a new document from template" msgstr "从模板创建新文档" msgid "Create Document In..." msgstr "创建文档到..." msgid "Textfiles" msgstr "文本文件" msgid "Append To..." msgstr "追加到..." msgid "Append..." msgstr "追加..." msgid "Write To..." msgstr "写入..." msgid "Get Text Contents" msgstr "获得文本内容" msgid "Thunar" msgstr "Thunar" msgid "File manager Thunar actions" msgstr "文件管理器 Thunar 动作" msgid "Select in File Manager" msgstr "在文件管理器中选择" msgid "Show Properties" msgstr "显示属性" msgid "Show information about file in file manager" msgstr "显示有关文件管理器的信息" msgid "Send To..." msgstr "发送到..." msgid "Symlink In..." msgstr "" #, fuzzy msgid "Create a symlink to file in a chosen location" msgstr "复制文件到一个选择好的位置" msgid "Empty Trash" msgstr "清空回收站" msgid "Thunar Send To Objects" msgstr "Thunar 发送到对象" #. -*- coding: utf-8 -*- msgid "Thunderbird" msgstr "Thunderbird" msgid "Thunderbird/Icedove Contacts and Actions" msgstr "Thunderbird/Icedove 邮件联系人和操作" msgid "Compose New Email" msgstr "编写新邮件" msgid "Compose a new message in Thunderbird" msgstr "在 Thunderbird 中编辑新消息" #, fuzzy msgid "Attach in Email To..." msgstr "发送邮件到..." #, fuzzy msgid "Compose Email With" msgstr "编写新邮件" #, fuzzy msgid "Compose a new message using the text as body" msgstr "在 Thunderbird 中编辑新消息" msgid "Thunderbird Address Book" msgstr "Thunderbird 地址薄" msgid "Contacts from Thunderbird Address Book" msgstr "Thunderbird 地址簿中的联系人" #. -*- coding: UTF-8 -*- msgid "Top" msgstr "顶部" msgid "Show running tasks and allow sending signals to them" msgstr "显示运行的任务并允许向它们发送信号" msgid "Sort Order" msgstr "排列顺序" msgid "Commandline" msgstr "命令行" msgid "CPU usage (descending)" msgstr "CPU 使用量(降序)" #. sort processes (top don't allow to sort via cmd line) msgid "Memory usage (descending)" msgstr "内存使用量(降序)" msgid "Send Signal..." msgstr "发送信号..." msgid "Signals" msgstr "信号" msgid "Running Tasks" msgstr "运行任务" #. default: by cpu #, python-format msgid "pid: %(pid)s cpu: %(cpu)g%% mem: %(mem)g%% time: %(time)s" msgstr "pid: %(pid)s cpu: %(cpu)g%% 内存: %(mem)g%% 时间: %(time)s" msgid "Running tasks for current user" msgstr "为当前用户运行任务" msgid "Trash" msgstr "回收站" msgid "Access trash contents" msgstr "访问回收站的内容" msgid "Move to Trash" msgstr "移动到回收站" msgid "Move this file to trash" msgstr "移动这个文件到回收站" msgid "Restore" msgstr "还原" msgid "Move file back to original location" msgstr "移动文件回原来的位置" msgid "" "Could not delete files:\n" " " msgstr "" msgid "Trash is empty" msgstr "回收站为空" #. proper translation of plural #, python-format msgid "Trash contains one file" msgid_plural "Trash contains %(num)s files" msgstr[0] "回收站有一个文件" msgstr[1] "回收站有%(num)s个文件" msgid "Triggers" msgstr "触发器" #, fuzzy msgid "" "Assign global keybindings (triggers) to objects created with 'Compose " "Command'." msgstr "将全局按键绑定(触发器)分配给使用“复合命令”(Ctrl+回车键)创建的对象。" msgid "Add Trigger..." msgstr "添加触发器..." msgid "Remove Trigger" msgstr "删除触发器" msgid "URL Actions" msgstr "超链接操作" msgid "Download and Open" msgstr "下载并打开" msgid "Download To..." msgstr "下载到..." msgid "Download URL to a chosen location" msgstr "下载目标到一个选定的路径" msgid "Wikipedia" msgstr "维基百科" msgid "Search in Wikipedia" msgstr "在维基百科中搜索" msgid "Wikipedia language" msgstr "维基百科语言" #. TRANS: Default wikipedia language code msgid "en" msgstr "en" #, python-format msgid "Search for this term in %s.wikipedia.org" msgstr "在 %s.wikipedia.org 中搜索项目" msgid "Window List" msgstr "窗口列表" msgid "All windows on all workspaces" msgstr "所有工作区的所有窗口" msgid "Activate" msgstr "激活" msgid "Shade" msgstr "卷起" msgid "Unshade" msgstr "取消卷起" msgid "Minimize" msgstr "最小化" msgid "Unminimize" msgstr "取消最小化" msgid "Maximize" msgstr "最大化" msgid "Unmaximize" msgstr "还原大小" msgid "Maximize Vertically" msgstr "垂直最大化" msgid "Unmaximize Vertically" msgstr "垂直最大化还原" #. TRANS: Window on (Workspace name), window description #, python-format msgid "Window on %(wkspc)s" msgstr "在 %(wkspc)s 中的窗口" msgid "Frontmost Window" msgstr "最前端的窗口" msgid "Next Window" msgstr "下个窗口" msgid "Jump to this window's workspace and focus" msgstr "跳转到此窗口所在工作区并激活此窗口" #, fuzzy, python-format msgid "%d window" msgid_plural "%d windows" msgstr[0] "下个窗口" msgstr[1] "下个窗口" #, fuzzy msgid "Active workspace" msgstr "跳转到此工作区" msgid "Jump to this workspace" msgstr "跳转到此工作区" msgid "Workspaces" msgstr "工作区" msgid "Volumes and Disks" msgstr "磁盘和分区" msgid "Mounted volumes and disks" msgstr "挂载的磁盘和分区" #, python-format msgid "Volume mounted at %s" msgstr "分区挂载在 %s" msgid "Unmount" msgstr "卸载" msgid "Unmount this volume" msgstr "卸载此分区" msgid "Eject" msgstr "弹出" msgid "Unmount and eject this media" msgstr "卸载和弹出此媒体" msgid "Show Text" msgstr "显示文本" msgid "Display text in a window" msgstr "在窗口中显示文本" msgid "Large Type" msgstr "大字体显示" msgid "Show Notification" msgstr "在系统通知区域显示图标" #, fuzzy msgid "Tracker" msgstr "Tracker 0.6" msgid "Tracker desktop search integration" msgstr "集成 Tracker 桌面搜索" msgid "Search in Tracker" msgstr "在 Tracker 中搜索" msgid "Open Tracker Search Tool and search for this term" msgstr "开启 Tracker 搜索工具然后搜索这个项目" msgid "Get Tracker Results..." msgstr "取得 Tracker 结果..." msgid "Show Tracker results for query" msgstr "显示 Tracker 结果" #, python-format msgid "Tracker Search for \"%s\"" msgstr "" #, python-format msgid "Results for \"%s\"" msgstr "“%s”的结果" msgid "Tracker Full Text Search" msgstr "" msgid "Use '?' prefix to get full text results" msgstr "" msgid "Locate Files" msgstr "查找文件" msgid "Search filesystem using locate" msgstr "使用 locate 搜索文件系统" msgid "Ignore case distinctions when searching files" msgstr "搜索文件时忽略大小写" #. encoding: utf-8 msgid "Firefox Bookmarks" msgstr "Firefox 网络浏览器书签" msgid "Index of Firefox bookmarks" msgstr "Firefox 网络浏览器书签索引" #, fuzzy msgid "Firefox Keywords" msgstr "Firefox 网络浏览器书签" #, fuzzy msgid "Search the web with Firefox keywords" msgstr "使用 OpenSearch 搜索引擎搜索互联网" msgid "Search With..." msgstr "搜索方式..." msgid "Search For..." msgstr "搜索内容..." #, fuzzy msgid "Search Terms" msgstr "搜索引擎" msgid "Media Player Control" msgstr "" msgid "Playback control for media players" msgstr "" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Play/Pause (%s)" msgstr "选择文件“%s”" #, fuzzy msgid "Resume playback" msgstr "恢复 Audacious 回放" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Next (%s)" msgstr "下一首" #, fuzzy msgid "Skip to next track" msgstr "跳到 Audacious 中的下一音轨" #. TRANS: %s is a media player name #, fuzzy, python-format msgid "Previous (%s)" msgstr "前一首" #, fuzzy msgid "Skip to previous track" msgstr "跳到 Audacious 中的前一音轨" #. TRANS: %s is a media player name #, python-format msgid "Stop (%s)" msgstr "" msgid "Stop playback" msgstr "" msgid "Pidgin" msgstr "Pidgin" msgid "Access to Pidgin Contacts" msgstr "访问 Pidgin 联系人" msgid "Show offline contacts" msgstr "显示离线联系人" msgid "Open Chat" msgstr "开始聊天" #, python-format msgid "%s (%d character)" msgid_plural "%s (%d characters)" msgstr[0] "%s (%d 个字符)" msgstr[1] "%s (%d 个字符)" msgid "Send Message..." msgstr "发送消息..." msgid "Available" msgstr "在线" msgid "Away" msgstr "离开" msgid "Pidgin Contacts" msgstr "Pidgin 联系人" #. -*- coding: UTF-8 -*- msgid "Shorten Links" msgstr "缩短的链接" msgid "Create short aliases of long URLs" msgstr "为长 URLs 创建短别名" msgid "Error" msgstr "错误" msgid "Shorten With..." msgstr "取短方式..." msgid "Services" msgstr "服务" msgid "Rhythmbox" msgstr "Rhythmbox" msgid "Play and enqueue tracks and browse the music library" msgstr "播放,新增音轨,浏览音乐库" msgid "Include artists in top level" msgstr "把艺术家放到顶端" msgid "Include albums in top level" msgstr "把专辑放到顶端" msgid "Play tracks in Rhythmbox" msgstr "在 Rhythmbox 里面播放音轨" msgid "Add tracks to the play queue" msgstr "新增音轨到播放队列" #. TRANS: Song description #, python-format msgid "by %(artist)s from %(album)s" msgstr "艺术家 %(artist)s 专辑 %(album)s" #. TRANS: Album description "by Artist" #, python-format msgid "by %s" msgstr "艺术家 %s" #. TRANS: Artist songs collection description #, python-format msgid "Tracks by %s" msgstr "音轨 %s " msgid "Albums" msgstr "专辑" msgid "Music albums in Rhythmbox Library" msgstr "Rhythmbox 媒体库中的音乐专辑" msgid "Artists" msgstr "艺术家" msgid "Music artists in Rhythmbox Library" msgstr "媒体库中的音乐艺术家" msgid "Songs" msgstr "歌曲" msgid "Songs in Rhythmbox library" msgstr "媒体库中的歌曲" msgid "Getting Things GNOME" msgstr "Getting Things GNOME" msgid "Browse and create new tasks in GTG" msgstr "在 GTG 中浏览和创建新任务" #, python-format msgid "due: %s" msgstr "到期:%s" #, python-format msgid "start: %s" msgstr "开始:%s" #, python-format msgid "tags: %s" msgstr "标签 %s" msgid "Open task in Getting Things GNOME!" msgstr "在 Getting Things GNOME 中打开新任务" msgid "Delete" msgstr "删除" msgid "Permanently remove this task" msgstr "永远移除此任务" msgid "Mark Done" msgstr "标记完成" msgid "Mark this task as done" msgstr "将此任务标记为已完成" msgid "Dismiss" msgstr "解除" msgid "Mark this task as not to be done anymore" msgstr "标志此任务为未完成" msgid "Create Task" msgstr "创建任务" msgid "Create new task in Getting Things GNOME" msgstr "在 Getting Things GNOME 中创建新任务" msgid "Devhelp" msgstr "Devhelp" msgid "Search in Devhelp" msgstr "在 Devhelp 中查找" #, fuzzy msgid "Empathy" msgstr "Gajim 联系人" #, fuzzy msgid "Access to Empathy Contacts" msgstr "访问 Gajim 联系人" msgid "Busy" msgstr "忙碌" msgid "Not Available" msgstr "不可用" msgid "Invisible" msgstr "隐身" msgid "Offline" msgstr "离线" msgid "Change Global Status To..." msgstr "更改全局状态为..." #, fuzzy msgid "Empathy Contacts" msgstr "Gajim 联系人" #, fuzzy msgid "Empathy Account Status" msgstr "Gajim 账户状态" #. TRANS: Names of accelerators in the interface #, fuzzy msgid "Alternate Activate" msgstr "备选激活键" #. TRANS: The "Comma Trick"/"Put Selection on Stack" allows the #. TRANS: user to select many objects to be used for one action #, fuzzy msgid "Comma Trick" msgstr "逗号键增强" #. TRANS: "Compose Command" makes one object out of the selected #. TRANS: object + action (+iobject) msgid "Compose Command" msgstr "编辑命令" #, fuzzy msgid "Mark Default Action" msgstr "设置默认程序..." msgid "Forget Object" msgstr "" msgid "Reset All" msgstr "全部重置" msgid "Select Quit" msgstr "选择退出" msgid "Select Selected File" msgstr "选择已选的文件" msgid "Select Selected Text" msgstr "选择已选的文本" msgid "Show Help" msgstr "显示帮助" msgid "Show Preferences" msgstr "显示属性" msgid "Switch to First Pane" msgstr "切换到第一个窗格" msgid "Toggle Text Mode" msgstr "切换文本模式" #, python-format msgid "No matches in %(src)s for \"%(query)s\"" msgstr "在 %(src)s 中没有符合“%(query)s”的" msgid "No matches" msgstr "无匹配" #, fuzzy, python-format msgid "No action matches \"%s\"" msgstr "无匹配" #, python-format msgid "Make \"%(action)s\" Default for \"%(object)s\"" msgstr "" #. TRANS: Removing learned and/or configured bonus search score #, python-format msgid "Forget About \"%s\"" msgstr "" #. TRANS: Names of global keyboard shortcuts msgid "Show Main Interface" msgstr "显示主界面" msgid "Show with Selection" msgstr "选择时显示" #. TRANS: Plugin info fields msgid "Description" msgstr "描述" msgid "Author" msgstr "作者" msgid "Version" msgstr "版本" #. TRANS: Error message when Plugin needs a Python module to load #, python-format msgid "Python module '%s' is needed" msgstr "需要 Python 模块“%s”" msgid "Plugin could not be read due to an error:" msgstr "因为如下原因插件无法启用:" msgid "Content of" msgstr "此项的内容" #. TRANS: Plugin contents header msgid "Sources" msgstr "资源" #. TRANS: Plugin contents header msgid "Actions" msgstr "操作" #, python-format msgid "Using encrypted password storage: %s" msgstr "" #, python-format msgid "Using password storage: %s" msgstr "" #. TRANS: Plugin-specific configuration (header) msgid "Configuration" msgstr "配置" msgid "Set username and password" msgstr "设置用户名和密码" #. TRANS: File Chooser Title msgid "Choose a Directory" msgstr "选择一个目录" msgid "Reset all shortcuts to default values?" msgstr "重置所有的快捷键为默认值?" msgid "Shortcut" msgstr "快捷键" #. TRANS: Don't translate literally! #. TRANS: This should be a list of all translators of this language msgid "translator-credits" msgstr "lh " msgid "A free software (GPLv3+) launcher" msgstr "一个启动器(自由软件(GPLv3+))" msgid "" "\n" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation, either version 3 of the License, or\n" "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "本程序是自由软件;您可以在自由软件基金会发布的 GNU 通用公共许可证\n" "下重新发布或修改它;许可证应使用第三版本或您所选择的更新的版本。\n" "\n" "发布本程序的目的是希望它对您有用。但我们并不为它提供任何形式的担保,\n" "也无法保证它可以在特定用途中得到您希望的结果。请参看 GNU GPL 许\n" "可中的更多细节。\n" "\n" "您应该在收到此程序的同时收到了 GNU GPL 协议的副本;如果您没有收\n" "到的话,请参见 。\n" #. follows strings used elsewhere msgid "Could not find running Kupfer" msgstr "找不到运行中的 Kupfer" #~ msgid "Compose Email" #~ msgstr "编写新邮件" #~ msgid "Send in Email To..." #~ msgstr "发送邮件到..." #~ msgid "Type to search %s" #~ msgstr "输入以搜索 %s" #~ msgid "No action" #~ msgstr "无操作" #~ msgid "GNOME Terminal Profiles" #~ msgstr "GNOME 终端配置" #~ msgid "Launch GNOME Terminal profiles" #~ msgstr "启动 GNOME 终端配置" #~ msgid "Selected Text \"%s\"" #~ msgstr "选中文本“%s”" #~ msgid "Calculate expressions starting with '='" #~ msgstr "输入'='开始计算" #~ msgid "Recent clipboards" #~ msgstr "最近的剪贴板" #~ msgid "Include recent selections" #~ msgstr "包括最近选取" #~ msgid "Epiphany Bookmarks" #~ msgstr "Epiphany 书签" #~ msgid "Index of Epiphany bookmarks" #~ msgstr "Epiphany 书签的索引" #~ msgid "Include visited sites" #~ msgstr "包含访问过的站点" #~ msgid "" #~ "Provides current nautilus selection, using Kupfer's Nautilus Extension" #~ msgstr "提供当前 Nautilus 的选择,使用 Kupfer 的 Nautilus 扩展" #~ msgid "Selected File \"%s\"" #~ msgstr "选择文件“%s”" #~ msgid "Selected Files" #~ msgstr "选中的文件" #~ msgid "Resume playback in Rhythmbox" #~ msgstr "恢复 Rhythmbox 播放" #~ msgid "Pause playback in Rhythmbox" #~ msgstr "暂停 Rhythmbox 播放" #~ msgid "Jump to next track in Rhythmbox" #~ msgstr "跳到下一首歌曲" #~ msgid "Jump to previous track in Rhythmbox" #~ msgstr "跳到前一首歌曲" #~ msgid "Search the Web" #~ msgstr "搜索互联网" #~ msgid "Abiword" #~ msgstr "Abiword" #~ msgid "Recently used documents in Abiword" #~ msgstr "Abiword 最近使用的文档" #~ msgid "Abiword Recent Items" #~ msgstr "Abiword 的最近项目" #~ msgid "APT" #~ msgstr "APT" #~ msgid "Interface with the package manager APT" #~ msgstr "APT 包管理器接口" #~ msgid "Installation method" #~ msgstr "安装方法" #~ msgid "Show Package Information" #~ msgstr "显示软件包信息" #~ msgid "Install" #~ msgstr "安装" #~ msgid "Install package using the configured method" #~ msgstr "使用配置的方法安装软件包" #~ msgid "Packages matching \"%s\"" #~ msgstr "符合“%s”的软件包" #~ msgid "Search Package Name..." #~ msgstr "搜索软件包(按名称)..." #~ msgid "Chromium Bookmarks" #~ msgstr "Chromium 书签" #~ msgid "Index of Chromium bookmarks" #~ msgstr "Chromium 书签的索引" #~ msgid "Claws Mail" #~ msgstr "Claws 邮件" #~ msgid "Claws Mail Contacts and Actions" #~ msgstr "Claws 邮件联系人和操作" #~ msgid "Compose a new message in Claws Mail" #~ msgstr "使用 Claws 编写新邮件" #~ msgid "Receive All Email" #~ msgstr "接收所有邮件" #~ msgid "Receive new messages from all accounts in ClawsMail" #~ msgstr "通过 Claws 接收所有账户的新邮件" #~ msgid "Compose new message in Claws Mail and attach file" #~ msgstr "使用 Claws 编写新邮件并添加附件" #~ msgid "Claws Mail Address Book" #~ msgstr "Claws 邮件地址簿" #~ msgid "Contacts from Claws Mail Address Book" #~ msgstr "Claws 地址簿中的联系人" #~ msgid "Evolution" #~ msgstr "Evolution" #~ msgid "Evolution contacts" #~ msgstr "Evolution 联系人" #~ msgid "Compose a new message in Evolution" #~ msgstr "使用 Evolution 编写新邮件" #~ msgid "Compose new message in Evolution and attach file" #~ msgstr "使用 Evolution 编写新邮件并添加附件" #~ msgid "Evolution Address Book" #~ msgstr "Evolution 地址簿" #~ msgid "Filezilla" #~ msgstr "Filezilla" #~ msgid "Show sites and handle ftp addresses by Filezilla" #~ msgstr "显示站点并使用 Filezilla 处理 ftp 地址" #~ msgid "Open Site with Filezilla" #~ msgstr "用 Filezilla 打开站点" #~ msgid "Filezilla Sites" #~ msgstr "Filezilla 网站" #~ msgid "Sites from Filezilla" #~ msgstr "来自 filezilla 的网站" #~ msgid "Gajim" #~ msgstr "Gajim" #~ msgid "Access to Gajim Contacts" #~ msgstr "访问 Gajim 联系人" #~ msgid "Free for Chat" #~ msgstr "可以交谈" #~ msgid "Gajim Contacts" #~ msgstr "Gajim 联系人" #~ msgid "Gajim Account Status" #~ msgstr "Gajim 账户状态" #~ msgid "Gmail" #~ msgstr "Gmail" #~ msgid "Load contacts and compose new email in Gmail" #~ msgstr "载入联系人并在 Gmail 中编写新邮件" #~ msgid "Load contacts' pictures" #~ msgstr "载入联系人图片" #~ msgid "Compose Email in GMail" #~ msgstr "在 GMail 中编写新邮件" #~ msgid "Open web browser and compose new email in GMail" #~ msgstr "打开浏览器并在 Gmail 中创作一封新的电子邮件" #~ msgid "Contacts from Google services (Gmail)" #~ msgstr "来自 Google 服务(Gmail) 的联系人" #~ msgid "Google Picasa" #~ msgstr "Google Picasa" #~ msgid "Show albums and upload files to Picasa" #~ msgstr "在 Picasa 中显示相册和上传的文件" #~ msgid "Users to show: (,-separated)" #~ msgstr "要显示的用户:(用 , 分隔)" #~ msgid "Load user and album icons" #~ msgstr "载入用户和相册图标" #~ msgid "Uploading Pictures" #~ msgstr "正在上传图片" #~ msgid "Uploading pictures to Picasa Web Album" #~ msgstr "正在上传图片到 Picasa Web 相册" #~ msgid "Creating album:" #~ msgstr "正在创建相册:" #~ msgid "Album created by Kupfer" #~ msgstr "Kupfer 创建的相册" #~ msgid "File:" #~ msgstr "文件:" #~ msgid "One album" #~ msgid_plural "%(num)d albums" #~ msgstr[0] "一个相册" #~ msgstr[1] "%(num)d 个相册" #~ msgid "one photo" #~ msgid_plural "%(num)s photos" #~ msgstr[0] "一幅照片" #~ msgstr[1] "%(num)s 幅照片" #~ msgid "Upload to Picasa Album..." #~ msgstr "上传到 Picasa 相册..." #~ msgid "Upload files to Picasa album" #~ msgstr "上传文件到 Picasa 相册" #~ msgid "Upload to Picasa as New Album" #~ msgstr "上传到 Picasa 的新相册" #~ msgid "Create album from selected local directory" #~ msgstr "从选中的本地目录创建相册" #~ msgid "Picasa Albums" #~ msgstr "Picasa 相册" #~ msgid "User albums in Picasa" #~ msgstr "在 Picasa 中使用相册" #~ msgid "Search Google with results shown directly" #~ msgstr "搜索 Google 并直接显示结果" #~ msgid "Show More Results For \"%s\"" #~ msgstr "显示更多“%s”的结果" #~ msgid "%s total found" #~ msgstr "总共发现:%s" #~ msgid "Translate text with Google Translate" #~ msgstr "使用 Google Translate 翻译文本" #~ msgid "Google Translate connection timed out" #~ msgstr "连接到 Google Translate 超时" #~ msgid "Error connecting to Google Translate" #~ msgstr "连接到 Google Translate 出错" #~ msgid "Translate To..." #~ msgstr "翻译为..." #~ msgid "Translate into %s" #~ msgstr "翻译为 %s" #~ msgid "Languages" #~ msgstr "语言" #~ msgid "Show translated page in browser" #~ msgstr "在浏览器中显示翻译后的页面" #~ msgid "Show Translation To..." #~ msgstr "显示翻译到..." #~ msgid "Show translation in browser" #~ msgstr "在浏览器显示翻译" #~ msgid "Gwibber" #~ msgstr "Gwibber" #, fuzzy #~ msgid "%(user)s on %(service)s" #~ msgstr "%(user)s %(when)s" #, fuzzy #~ msgid "%(user)s %(when)s on %(where)s" #~ msgstr "%(user)s %(when)s" #, fuzzy #~ msgid "Send Message" #~ msgstr "发送消息..." #, fuzzy #~ msgid "Send Message To..." #~ msgstr "发送消息..." #~ msgid "Reply..." #~ msgstr "回复..." #, fuzzy #~ msgid "Delete Message" #~ msgstr "发送消息..." #, fuzzy #~ msgid "Send Private Message..." #~ msgstr "发送直接消息..." #, fuzzy #~ msgid "Send direct message to user" #~ msgstr "发送直接消息到..." #, fuzzy #~ msgid "Retweet To..." #~ msgstr "重命名为..." #, fuzzy #~ msgid "Retweet message to all Gwibber accounts" #~ msgstr "通过 Claws 接收所有账户的新邮件" #, fuzzy #~ msgid "Open in Browser" #~ msgstr "打开所在目录" #, fuzzy #~ msgid "Open message in default web browser" #~ msgstr "用默认查看器打开链接" #, fuzzy #~ msgid "Gwibber Accounts" #~ msgstr "Gajim 账户状态" #, fuzzy #~ msgid "Gwibber Messages" #~ msgstr "Gwibber" #, fuzzy #~ msgid "Gwibber Streams" #~ msgstr "Gwibber" #, fuzzy #~ msgid "Gwibber (Simple)" #~ msgstr "Gwibber" #~ msgid "Send updates via the microblogging client Gwibber" #~ msgstr "通过微博客户端 Gwibber(硅博)发送更新" #~ msgid "Send Update" #~ msgstr "发送更新" #~ msgid "Unable to activate Gwibber service" #~ msgstr "无法激活 Gwibber 服务" #~ msgid "OpenOffice / LibreOffice" #~ msgstr "OpenOffice / LibreOffice" #~ msgid "Recently used documents in OpenOffice/LibreOffice" #~ msgstr "OpenOffice/LibreOffice 最近使用的文档" #~ msgid "OpenOffice/LibreOffice Recent Items" #~ msgstr "OpenOffice/LibreOffice 最近项目" #~ msgid "Opera Bookmarks" #~ msgstr "Opera 书签" #~ msgid "Index of Opera bookmarks" #~ msgstr "Opera 书签的索引" #~ msgid "Opera Mail" #~ msgstr "Opera 邮件" #~ msgid "Opera Mail contacts and actions" #~ msgstr "Opera Mail 邮件联系人和操作" #~ msgid "Compose a new message in Opera Mail" #~ msgstr "在 Opera Mail 中创建新消息" #~ msgid "Opera Mail Contacts" #~ msgstr "Opera Mail 联系人" #~ msgid "Contacts from Opera Mail" #~ msgstr "Opera Mail 地址簿中的联系人" #~ msgid "PuTTY Sessions" #~ msgstr "PuTTY 会话" #~ msgid "Quick access to PuTTY Sessions" #~ msgstr "快速操作 PuTTY 会话" #~ msgid "Start Session" #~ msgstr "开始新的会话" #~ msgid "reStructuredText" #~ msgstr "重构文本" #~ msgid "Render reStructuredText and show the result" #~ msgstr "渲染重构文本然后显示结果" #~ msgid "View as HTML Document" #~ msgstr "以 HTML 文档方式查看" #~ msgid "System Services" #~ msgstr "系统服务" #~ msgid "Start, stop or restart system services via init scripts" #~ msgstr "通过脚本开始、停止或者重启系统服务" #~ msgid "Sudo-like Command" #~ msgstr "类 Sudo 命令" #~ msgid "Start Service" #~ msgstr "开始服务" #~ msgid "Stop Service" #~ msgstr "停止服务" #~ msgid "%s Service" #~ msgstr "%s 服务" #, fuzzy #~ msgid "Show QRCode" #~ msgstr "显示源代码" #, fuzzy #~ msgid "Display text as QRCode in a window" #~ msgstr "在窗口中显示文本" #~ msgid "Access to Skype contacts" #~ msgstr "联系 Spype 中的联系人" #~ msgid "Skype Me" #~ msgstr "Skype 我" #~ msgid "Logged Out" #~ msgstr "注销" #~ msgid "[%(status)s] %(userid)s" #~ msgstr "[%(status)s] %(userid)s" #~ msgid "Call" #~ msgstr "呼叫" #~ msgid "Place a call to contact" #~ msgstr "呼叫联系人" #~ msgid "Skype Contacts" #~ msgstr "Skype 联系人" #~ msgid "Skype Statuses" #~ msgstr "Skype 状态" #~ msgid "Tracker 0.6" #~ msgstr "Tracker 0.6" #~ msgid "Tracker tags" #~ msgstr "Tracker 标签" #~ msgid "Tracker Tags" #~ msgstr "Tracker 标签" #~ msgid "Browse Tracker's tags" #~ msgstr "浏览 Tracker 的标签" #~ msgid "Tag %s" #~ msgstr "标签 %s" #~ msgid "Objects tagged %s with Tracker" #~ msgstr "用 Tracker 给目标加上标签%s" #~ msgid "Add Tag..." #~ msgstr "添加标签..." #~ msgid "Add tracker tag to file" #~ msgstr "给文件添加 tracker 标签" #~ msgid "Remove Tag..." #~ msgstr "删除标签..." #~ msgid "Remove tracker tag from file" #~ msgstr "删除文件的 tracker 标签" #~ msgid "TrueCrypt" #~ msgstr "TrueCrypt" #~ msgid "Volumes from TrueCrypt history" #~ msgstr "TrueCrypt 历史记录中的分区" #~ msgid "TrueCrypt volume: %(file)s" #~ msgstr "Truecrypt 分区:%(file)s" #~ msgid "Mount Volume" #~ msgstr "挂载分区" #~ msgid "Mount in Truecrypt" #~ msgstr "在 Truecrypt 中挂载" #~ msgid "Try to mount file as Truecrypt volume" #~ msgstr "尝试挂载为 Truecrypt 分区" #~ msgid "Dismount All Volumes" #~ msgstr "卸载全部分区" #~ msgid "TrueCrypt Volumes" #~ msgstr "%(file)s 分区" #~ msgid "Terminal Server Client" #~ msgstr "终端服务器客户端" #~ msgid "Session saved in Terminal Server Client" #~ msgstr "终端服务客户端中保存的会话" #~ msgid "TSClient sessions" #~ msgstr "TSClient 会话" #~ msgid "Saved sessions in Terminal Server Client" #~ msgstr "终端服务客户端中保存的会话" #~ msgid "Vinagre" #~ msgstr "Vinagre" #~ msgid "Vinagre bookmarks and actions" #~ msgstr "Vinagre 书签和操作" #~ msgid "Start Vinagre Session" #~ msgstr "开始 Vinagre 会话" #~ msgid "Vinagre Bookmarks" #~ msgstr "Vinagre 的书签" #~ msgid "Recently used documents in Vim" #~ msgstr "Vim 最近使用的文档" #~ msgid "Vim Recent Documents" #~ msgstr "Vim 最近打开文档" #~ msgid "VirtualBox" #~ msgstr "VirtualBox" #~ msgid "" #~ "Control VirtualBox Virtual Machines. Supports both Sun VirtualBox and " #~ "Open Source Edition." #~ msgstr "操作 VirtualBox 虚拟机。支持 Sun VirtualBox 和开源版本。" #~ msgid "Power On" #~ msgstr "开机" #~ msgid "Power On Headless" #~ msgstr "黑屏开机" #~ msgid "Send Power Off Signal" #~ msgstr "发送关机信号" #~ msgid "Reboot" #~ msgstr "重启" #~ msgid "Resume" #~ msgstr "恢复" #~ msgid "Save State" #~ msgstr "保存状态" #~ msgid "Power Off" #~ msgstr "关闭" #~ msgid "VirtualBox Machines" #~ msgstr "VirtualBox 机器" #~ msgid "Zim" #~ msgstr "Zim" #~ msgid "Access to Pages stored in Zim - A Desktop Wiki and Outliner" #~ msgstr "连接到 Zim 中保存的页面, Zim - 一个桌面笔记和注释工具" #~ msgid "Page names start with :colon" #~ msgstr "页面名称以 :colon 开始" #~ msgid "Zim Page from Notebook \"%s\"" #~ msgstr "Zim 中笔记本的页面\"%s\"" #~ msgid "Create Zim Page" #~ msgstr "创建 Zim 新页" #~ msgid "Create page in default notebook" #~ msgstr "在默认 Zim 记事本中创建新页面" #~ msgid "Create Zim Page In..." #~ msgstr "创建 Zim 页面到..." #~ msgid "Create Subpage..." #~ msgstr "新建子页面..." #~ msgid "Zim Notebooks" #~ msgstr "Zim 笔记本" #~ msgid "Zim Pages" #~ msgstr "Zim 页面" #~ msgid "Pages stored in Zim Notebooks" #~ msgstr "Zim 笔记本中保存的页面" #~ msgid "Directories" #~ msgstr "目录" #~ msgid "Interface" #~ msgstr "界面" #~ msgid "Hide Kupfer when focus is lost" #~ msgstr "在失去焦点时隐藏 Kupfer" #, fuzzy #~ msgid "" #~ "Tick the box next to a source to make sure its objects are exported to " #~ "the top level of the catalog. An unticked source's contents are only " #~ "available by locating its subcatalog and entering it.\n" #~ "\n" #~ "Note: Kupfer is an integrator, not an indexer itself. Kupfer is not " #~ "designed to carry a catalog larger than a couple of thousand objects, and " #~ "may become slow if overly large subcatalogs are included in the top level." #~ msgstr "" #~ "勾选资源边的选择框来确保其对象导出到顶层分类中。未勾选的资源的内容只能通过" #~ "定位它的子分类并进入分类才能使用。\n" #~ "\n" #~ "注意:Kupfer 是一个解释器,本身不是索引程序。Kupfer 不能操作有好几千个对象" #~ "的分类。如果顶层分类的子类过多,它可能会变得很慢。" #~ msgid "Text Matches" #~ msgstr "符合的文本" #~ msgid "noun" #~ msgstr "名词" #~ msgid "verb" #~ msgstr "动词" #~ msgid "adjective" #~ msgstr "形容词" #~ msgid "Twitter" #~ msgstr "Twitter" #~ msgid "Microblogging with Twitter: send updates and show friends' tweets" #~ msgstr "使用 Twitter 微博:发送更新并显示朋友的推特" #~ msgid "Load friends' pictures" #~ msgstr "载入朋友的图片" #~ msgid "Load friends' public tweets" #~ msgstr "加载朋友的公共推特" #~ msgid "Load timeline" #~ msgstr "载入时间轴" #~ msgid "Post Update to Twitter" #~ msgstr "向 Twitter 投递更新" #~ msgid "Twitter Timeline" #~ msgstr "Twitter 时间轴" #~ msgid "Twitter Friends" #~ msgstr "Twitter 好友" #~ msgid "Timeline for %s" #~ msgstr "%s 的 时间轴" #~ msgid "Preferred terminal" #~ msgstr "首选的终端" #~ msgid "" #~ "The preferred terminal emulator. It's used to launch the SSH sessions." #~ msgstr "首选的终端模拟器。用来启动 SSH 会话。" #~ msgid "" #~ "The flag which makes the terminal execute everything following it inside " #~ "the terminal (e.g. '-x' for gnome-terminal and terminal, '-e' for konsole " #~ "and urxvt)." #~ msgstr "" #~ "让终端后面的所有命令在该终端中执行的标志选项(如“-x”代表 gnome-terminal 和" #~ "终端,“-e”代表 konsole 和 urxvt)。" #~ msgid "Tracker 0.8" #~ msgstr "Tracker 0.8" #~ msgid "OpenOffice" #~ msgstr "OpenOffice" kupfer-328/pyproject.toml000066400000000000000000000064411500175051100156000ustar00rootroot00000000000000[project] name = "kupfer" version = "323" description = "Kupfer is an interface for quick and convenient access to applications and their documents." readme = "README.rst" requires-python = ">=3.9" license = {file = "COPYING"} keywords = [] authors = [ {name = "Ulrik Sverdrup"}, {name = "Karol Będkowski"}, {name = "Francesco Marella"}, {name = "Chmouel Boudjnah"}, {name = "Horia V. Corcalciuc"}, {name = "Grigory Javadyan"}, {name = "Chris Parsons"}, {name = "Fabian Carlström"}, {name = "Jakh Daven"}, {name = "Thomas Renard"} ] maintainers = [ {name = "Karol Będkowski"}, ] classifiers = [ "Development Status :: 4 - Beta", "Programming Language :: Python" ] dependencies = [ "gi.repository.Gtk", "gi.repository.GLib", "gi.repository.Gio", "pyxdg", "dbus" ] [project.optional-dependencies] optional = [ "gi.repository.Wnck", "gi.repository.Keybinder" ] test = [ "pytest" ] plugins = [ "vboxapi", "pinboard", "libvirt", "brotab" ] [project.urls] homepage = "https://kupferlauncher.github.io/" #documentation = "" repository = "http://github.com:kupferlauncher/kupfer" #changelog = "" [tool.black] line-length = 80 target-version = ['py39'] extend-exclude = ''' /( | waf | waflib | contrib | oldplugins )/ ''' [tool.isort] line_length = 80 multi_line_output = 3 profile = "black" skip = "migrations" skip_glob = ["waf", "waflib", "oldplugins", "contrib"] skip_gitignore = true [tool.bandit] skips = ["B101", "B410", "B303", "B110", "B404", "B311", "B405", "B201"] [tool.mypy] python_version = 3.9 strict = true exclude = [ '_test\.py$', "waflib", "oldplugins", ] allow_untyped_defs = true allow_untyped_calls = true ignore_missing_imports = true [tool.flake8] builtins = "_" [tool.pylint.main] ignore=["build", "dist", "oldplugins", "contrib", "waflib", "waf"] jobs=4 extension-pkg-allow-list="lxml" extension-pkg-whitelist="lxml" py-version = [3, 9] disable = [ "missing-docstring", "format", "unused-argument", "fixme", "useless-return", "too-many-positional-arguments", ] [tool.pylint.basic] good-names=["i", "j", "k", "ex", "Run", "_", "db", "err", "ok", "x", "y", "id", "ts"] [tool.pylint.imports] ext-import-graph = "" import-graph = "" int-import-graph = "imports.svg" [tool.pylint.exceptions] overgeneral-exceptions = [""] [tool.pylint.design] max-args = 8 max-attributes = 10 [tool.pylint.variables] additional-builtins = ["_", "ngettext", "ic"] [tool.ruff] lint.select = ["E", "F", "I", "W"] output-format = "full" line-length = 79 builtins = ["_", "ic", "ic_stack", "ngettext"] exclude = ["waflib", "waf", "oldplugins", "contrib/**"] #lint.fixable = ["I"] lint.extend-select = [ # "C", "N", "FBT", "B", "A", "COM", "C4", "EM", "ISC", "ICN", "LOG", "G", "PIE", "PYI", "Q", "RSE", "RET", "SLF", "SLOT", "SIM", "TID", "TCH", "ARG", # "PTH", # "TD", # "FIX", "PL", "R", "TRY", "PERF", "RUF", ] lint.ignore = [ "FBT001", "FBT002", "EM101", "TRY003", "FBT003", "COM812", "ARG001", "ARG002", "TC004", "RUF001", "E501", "EM102", "B008", "TRY300", "ISC001", "PLR0913", ] [tool.ruff.lint.per-file-ignores] "**/*_test.py" = ["ANN", "PTH", "DTZ", 'SLF001', "ARG", "PLR"] [tool.pytest] addopts = "--doctest-modules" collect_ignore_glob = ["contrib/*", "oldplugins/*"] kupfer-328/waf000077500000000000000000000102261500175051100133630ustar00rootroot00000000000000#!/usr/bin/env python # encoding: latin-1 # Thomas Nagy, 2005-2018 # """ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ import os, sys, inspect VERSION="2.0.25" REVISION="x" GIT="x" INSTALL="x" C1='x' C2='x' C3='x' cwd = os.getcwd() join = os.path.join if sys.hexversion<0x206000f: raise ImportError('Python >= 2.6 is required to create the waf file') WAF='waf' def b(x): return x if sys.hexversion>0x300000f: WAF='waf3' def b(x): return x.encode() def err(m): print(('\033[91mError: %s\033[0m' % m)) sys.exit(1) def unpack_wafdir(dir, src): f = open(src,'rb') c = 'corrupt archive (%d)' while 1: line = f.readline() if not line: err('run waf-light from a folder containing waflib') if line == b('#==>\n'): txt = f.readline() if not txt: err(c % 1) if f.readline() != b('#<==\n'): err(c % 2) break if not txt: err(c % 3) txt = txt[1:-1].replace(b(C1), b('\n')).replace(b(C2), b('\r')).replace(b(C3), b('\x00')) import shutil, tarfile try: shutil.rmtree(dir) except OSError: pass try: for x in ('Tools', 'extras'): os.makedirs(join(dir, 'waflib', x)) except OSError: err("Cannot unpack waf lib into %s\nMove waf in a writable directory" % dir) os.chdir(dir) tmp = 't.bz2' t = open(tmp,'wb') try: t.write(txt) finally: t.close() try: t = tarfile.open(tmp) except: try: os.system('bunzip2 t.bz2') t = tarfile.open('t') tmp = 't' except: os.chdir(cwd) try: shutil.rmtree(dir) except OSError: pass err("Waf cannot be unpacked, check that bzip2 support is present") try: for x in t: t.extract(x) finally: t.close() for x in ('Tools', 'extras'): os.chmod(join('waflib',x), 493) if sys.hexversion<0x300000f: sys.path = [join(dir, 'waflib')] + sys.path import fixpy2 fixpy2.fixdir(dir) os.remove(tmp) os.chdir(cwd) try: dir = unicode(dir, 'mbcs') except: pass try: from ctypes import windll windll.kernel32.SetFileAttributesW(dir, 2) except: pass def test(dir): try: os.stat(join(dir, 'waflib')) return os.path.abspath(dir) except OSError: pass def find_lib(): src = os.path.abspath(inspect.getfile(inspect.getmodule(err))) base, name = os.path.split(src) #devs use $WAFDIR w=test(os.environ.get('WAFDIR', '')) if w: return w #waf-light if name.endswith('waf-light'): w = test(base) if w: return w for dir in sys.path: if test(dir): return dir err('waf-light requires waflib -> export WAFDIR=/folder') dirname = '%s-%s-%s' % (WAF, VERSION, REVISION) for i in (INSTALL,'/usr','/usr/local','/opt'): w = test(i + '/lib/' + dirname) if w: return w #waf-local dir = join(base, (sys.platform != 'win32' and '.' or '') + dirname) w = test(dir) if w: return w #unpack unpack_wafdir(dir, src) return dir wafdir = find_lib() sys.path.insert(0, wafdir) if __name__ == '__main__': #import waflib.extras.compat15#PRELUDE from waflib import Scripting Scripting.waf_entry_point(cwd, VERSION, wafdir) kupfer-328/waflib/000077500000000000000000000000001500175051100141235ustar00rootroot00000000000000kupfer-328/waflib/Build.py000066400000000000000000001250001500175051100155320ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2018 (ita) """ Classes related to the build phase (build, clean, install, step, etc) The inheritance tree is the following: """ import os, sys, errno, re, shutil, stat try: import cPickle except ImportError: import pickle as cPickle from waflib import Node, Runner, TaskGen, Utils, ConfigSet, Task, Logs, Options, Context, Errors CACHE_DIR = 'c4che' """Name of the cache directory""" CACHE_SUFFIX = '_cache.py' """ConfigSet cache files for variants are written under :py:attr:´waflib.Build.CACHE_DIR´ in the form ´variant_name´_cache.py""" INSTALL = 1337 """Positive value '->' install, see :py:attr:`waflib.Build.BuildContext.is_install`""" UNINSTALL = -1337 """Negative value '<-' uninstall, see :py:attr:`waflib.Build.BuildContext.is_install`""" SAVED_ATTRS = 'root node_sigs task_sigs imp_sigs raw_deps node_deps'.split() """Build class members to save between the runs; these should be all dicts except for `root` which represents a :py:class:`waflib.Node.Node` instance """ CFG_FILES = 'cfg_files' """Files from the build directory to hash before starting the build (``config.h`` written during the configuration)""" POST_AT_ONCE = 0 """Post mode: all task generators are posted before any task executed""" POST_LAZY = 1 """Post mode: post the task generators group after group, the tasks in the next group are created when the tasks in the previous groups are done""" PROTOCOL = -1 if sys.platform == 'cli': PROTOCOL = 0 class BuildContext(Context.Context): '''executes the build''' cmd = 'build' variant = '' def __init__(self, **kw): super(BuildContext, self).__init__(**kw) self.is_install = 0 """Non-zero value when installing or uninstalling file""" self.top_dir = kw.get('top_dir', Context.top_dir) """See :py:attr:`waflib.Context.top_dir`; prefer :py:attr:`waflib.Build.BuildContext.srcnode`""" self.out_dir = kw.get('out_dir', Context.out_dir) """See :py:attr:`waflib.Context.out_dir`; prefer :py:attr:`waflib.Build.BuildContext.bldnode`""" self.run_dir = kw.get('run_dir', Context.run_dir) """See :py:attr:`waflib.Context.run_dir`""" self.launch_dir = Context.launch_dir """See :py:attr:`waflib.Context.out_dir`; prefer :py:meth:`waflib.Build.BuildContext.launch_node`""" self.post_mode = POST_LAZY """Whether to post the task generators at once or group-by-group (default is group-by-group)""" self.cache_dir = kw.get('cache_dir') if not self.cache_dir: self.cache_dir = os.path.join(self.out_dir, CACHE_DIR) self.all_envs = {} """Map names to :py:class:`waflib.ConfigSet.ConfigSet`, the empty string must map to the default environment""" # ======================================= # # cache variables self.node_sigs = {} """Dict mapping build nodes to task identifier (uid), it indicates whether a task created a particular file (persists across builds)""" self.task_sigs = {} """Dict mapping task identifiers (uid) to task signatures (persists across builds)""" self.imp_sigs = {} """Dict mapping task identifiers (uid) to implicit task dependencies used for scanning targets (persists across builds)""" self.node_deps = {} """Dict mapping task identifiers (uid) to node dependencies found by :py:meth:`waflib.Task.Task.scan` (persists across builds)""" self.raw_deps = {} """Dict mapping task identifiers (uid) to custom data returned by :py:meth:`waflib.Task.Task.scan` (persists across builds)""" self.task_gen_cache_names = {} self.jobs = Options.options.jobs """Amount of jobs to run in parallel""" self.targets = Options.options.targets """List of targets to build (default: \\*)""" self.keep = Options.options.keep """Whether the build should continue past errors""" self.progress_bar = Options.options.progress_bar """ Level of progress status: 0. normal output 1. progress bar 2. IDE output 3. No output at all """ # Manual dependencies. self.deps_man = Utils.defaultdict(list) """Manual dependencies set by :py:meth:`waflib.Build.BuildContext.add_manual_dependency`""" # just the structure here self.current_group = 0 """ Current build group """ self.groups = [] """ List containing lists of task generators """ self.group_names = {} """ Map group names to the group lists. See :py:meth:`waflib.Build.BuildContext.add_group` """ for v in SAVED_ATTRS: if not hasattr(self, v): setattr(self, v, {}) def get_variant_dir(self): """Getter for the variant_dir attribute""" if not self.variant: return self.out_dir return os.path.join(self.out_dir, os.path.normpath(self.variant)) variant_dir = property(get_variant_dir, None) def __call__(self, *k, **kw): """ Create a task generator and add it to the current build group. The following forms are equivalent:: def build(bld): tg = bld(a=1, b=2) def build(bld): tg = bld() tg.a = 1 tg.b = 2 def build(bld): tg = TaskGen.task_gen(a=1, b=2) bld.add_to_group(tg, None) :param group: group name to add the task generator to :type group: string """ kw['bld'] = self ret = TaskGen.task_gen(*k, **kw) self.task_gen_cache_names = {} # reset the cache, each time self.add_to_group(ret, group=kw.get('group')) return ret def __copy__(self): """ Build contexts cannot be copied :raises: :py:class:`waflib.Errors.WafError` """ raise Errors.WafError('build contexts cannot be copied') def load_envs(self): """ The configuration command creates files of the form ``build/c4che/NAMEcache.py``. This method creates a :py:class:`waflib.ConfigSet.ConfigSet` instance for each ``NAME`` by reading those files and stores them in :py:attr:`waflib.Build.BuildContext.allenvs`. """ node = self.root.find_node(self.cache_dir) if not node: raise Errors.WafError('The project was not configured: run "waf configure" first!') lst = node.ant_glob('**/*%s' % CACHE_SUFFIX, quiet=True) if not lst: raise Errors.WafError('The cache directory is empty: reconfigure the project') for x in lst: name = x.path_from(node).replace(CACHE_SUFFIX, '').replace('\\', '/') env = ConfigSet.ConfigSet(x.abspath()) self.all_envs[name] = env for f in env[CFG_FILES]: newnode = self.root.find_resource(f) if not newnode or not newnode.exists(): raise Errors.WafError('Missing configuration file %r, reconfigure the project!' % f) def init_dirs(self): """ Initialize the project directory and the build directory by creating the nodes :py:attr:`waflib.Build.BuildContext.srcnode` and :py:attr:`waflib.Build.BuildContext.bldnode` corresponding to ``top_dir`` and ``variant_dir`` respectively. The ``bldnode`` directory is created if necessary. """ if not (os.path.isabs(self.top_dir) and os.path.isabs(self.out_dir)): raise Errors.WafError('The project was not configured: run "waf configure" first!') self.path = self.srcnode = self.root.find_dir(self.top_dir) self.bldnode = self.root.make_node(self.variant_dir) self.bldnode.mkdir() def execute(self): """ Restore data from previous builds and call :py:meth:`waflib.Build.BuildContext.execute_build`. Overrides from :py:func:`waflib.Context.Context.execute` """ self.restore() if not self.all_envs: self.load_envs() self.execute_build() def execute_build(self): """ Execute the build by: * reading the scripts (see :py:meth:`waflib.Context.Context.recurse`) * calling :py:meth:`waflib.Build.BuildContext.pre_build` to call user build functions * calling :py:meth:`waflib.Build.BuildContext.compile` to process the tasks * calling :py:meth:`waflib.Build.BuildContext.post_build` to call user build functions """ Logs.info("Waf: Entering directory `%s'", self.variant_dir) self.recurse([self.run_dir]) self.pre_build() # display the time elapsed in the progress bar self.timer = Utils.Timer() try: self.compile() finally: if self.progress_bar == 1 and sys.stderr.isatty(): c = self.producer.processed or 1 m = self.progress_line(c, c, Logs.colors.BLUE, Logs.colors.NORMAL) Logs.info(m, extra={'stream': sys.stderr, 'c1': Logs.colors.cursor_off, 'c2' : Logs.colors.cursor_on}) Logs.info("Waf: Leaving directory `%s'", self.variant_dir) try: self.producer.bld = None del self.producer except AttributeError: pass self.post_build() def restore(self): """ Load data from a previous run, sets the attributes listed in :py:const:`waflib.Build.SAVED_ATTRS` """ try: env = ConfigSet.ConfigSet(os.path.join(self.cache_dir, 'build.config.py')) except EnvironmentError: pass else: if env.version < Context.HEXVERSION: raise Errors.WafError('Project was configured with a different version of Waf, please reconfigure it') for t in env.tools: self.setup(**t) dbfn = os.path.join(self.variant_dir, Context.DBFILE) try: data = Utils.readf(dbfn, 'rb') except (EnvironmentError, EOFError): # handle missing file/empty file Logs.debug('build: Could not load the build cache %s (missing)', dbfn) else: try: Node.pickle_lock.acquire() Node.Nod3 = self.node_class try: data = cPickle.loads(data) except Exception as e: Logs.debug('build: Could not pickle the build cache %s: %r', dbfn, e) else: for x in SAVED_ATTRS: setattr(self, x, data.get(x, {})) finally: Node.pickle_lock.release() self.init_dirs() def store(self): """ Store data for next runs, set the attributes listed in :py:const:`waflib.Build.SAVED_ATTRS`. Uses a temporary file to avoid problems on ctrl+c. """ data = {} for x in SAVED_ATTRS: data[x] = getattr(self, x) db = os.path.join(self.variant_dir, Context.DBFILE) try: Node.pickle_lock.acquire() Node.Nod3 = self.node_class x = cPickle.dumps(data, PROTOCOL) finally: Node.pickle_lock.release() Utils.writef(db + '.tmp', x, m='wb') try: st = os.stat(db) os.remove(db) if not Utils.is_win32: # win32 has no chown but we're paranoid os.chown(db + '.tmp', st.st_uid, st.st_gid) except (AttributeError, OSError): pass # do not use shutil.move (copy is not thread-safe) os.rename(db + '.tmp', db) def compile(self): """ Run the build by creating an instance of :py:class:`waflib.Runner.Parallel` The cache file is written when at least a task was executed. :raises: :py:class:`waflib.Errors.BuildError` in case the build fails """ Logs.debug('build: compile()') # delegate the producer-consumer logic to another object to reduce the complexity self.producer = Runner.Parallel(self, self.jobs) self.producer.biter = self.get_build_iterator() try: self.producer.start() except KeyboardInterrupt: if self.is_dirty(): self.store() raise else: if self.is_dirty(): self.store() if self.producer.error: raise Errors.BuildError(self.producer.error) def is_dirty(self): return self.producer.dirty def setup(self, tool, tooldir=None, funs=None): """ Import waf tools defined during the configuration:: def configure(conf): conf.load('glib2') def build(bld): pass # glib2 is imported implicitly :param tool: tool list :type tool: list :param tooldir: optional tool directory (sys.path) :type tooldir: list of string :param funs: unused variable """ if isinstance(tool, list): for i in tool: self.setup(i, tooldir) return module = Context.load_tool(tool, tooldir) if hasattr(module, "setup"): module.setup(self) def get_env(self): """Getter for the env property""" try: return self.all_envs[self.variant] except KeyError: return self.all_envs[''] def set_env(self, val): """Setter for the env property""" self.all_envs[self.variant] = val env = property(get_env, set_env) def add_manual_dependency(self, path, value): """ Adds a dependency from a node object to a value:: def build(bld): bld.add_manual_dependency( bld.path.find_resource('wscript'), bld.root.find_resource('/etc/fstab')) :param path: file path :type path: string or :py:class:`waflib.Node.Node` :param value: value to depend :type value: :py:class:`waflib.Node.Node`, byte object, or function returning a byte object """ if not path: raise ValueError('Invalid input path %r' % path) if isinstance(path, Node.Node): node = path elif os.path.isabs(path): node = self.root.find_resource(path) else: node = self.path.find_resource(path) if not node: raise ValueError('Could not find the path %r' % path) if isinstance(value, list): self.deps_man[node].extend(value) else: self.deps_man[node].append(value) def launch_node(self): """Returns the launch directory as a :py:class:`waflib.Node.Node` object (cached)""" try: # private cache return self.p_ln except AttributeError: self.p_ln = self.root.find_dir(self.launch_dir) return self.p_ln def hash_env_vars(self, env, vars_lst): """ Hashes configuration set variables:: def build(bld): bld.hash_env_vars(bld.env, ['CXX', 'CC']) This method uses an internal cache. :param env: Configuration Set :type env: :py:class:`waflib.ConfigSet.ConfigSet` :param vars_lst: list of variables :type vars_list: list of string """ if not env.table: env = env.parent if not env: return Utils.SIG_NIL idx = str(id(env)) + str(vars_lst) try: cache = self.cache_env except AttributeError: cache = self.cache_env = {} else: try: return self.cache_env[idx] except KeyError: pass lst = [env[a] for a in vars_lst] cache[idx] = ret = Utils.h_list(lst) Logs.debug('envhash: %s %r', Utils.to_hex(ret), lst) return ret def get_tgen_by_name(self, name): """ Fetches a task generator by its name or its target attribute; the name must be unique in a build:: def build(bld): tg = bld(name='foo') tg == bld.get_tgen_by_name('foo') This method use a private internal cache. :param name: Task generator name :raises: :py:class:`waflib.Errors.WafError` in case there is no task genenerator by that name """ cache = self.task_gen_cache_names if not cache: # create the index lazily for g in self.groups: for tg in g: try: cache[tg.name] = tg except AttributeError: # raised if not a task generator, which should be uncommon pass try: return cache[name] except KeyError: raise Errors.WafError('Could not find a task generator for the name %r' % name) def progress_line(self, idx, total, col1, col2): """ Computes a progress bar line displayed when running ``waf -p`` :returns: progress bar line :rtype: string """ if not sys.stderr.isatty(): return '' n = len(str(total)) Utils.rot_idx += 1 ind = Utils.rot_chr[Utils.rot_idx % 4] pc = (100. * idx)/total fs = "[%%%dd/%%d][%%s%%2d%%%%%%s][%s][" % (n, ind) left = fs % (idx, total, col1, pc, col2) right = '][%s%s%s]' % (col1, self.timer, col2) cols = Logs.get_term_cols() - len(left) - len(right) + 2*len(col1) + 2*len(col2) if cols < 7: cols = 7 ratio = ((cols * idx)//total) - 1 bar = ('='*ratio+'>').ljust(cols) msg = Logs.indicator % (left, bar, right) return msg def declare_chain(self, *k, **kw): """ Wraps :py:func:`waflib.TaskGen.declare_chain` for convenience """ return TaskGen.declare_chain(*k, **kw) def pre_build(self): """Executes user-defined methods before the build starts, see :py:meth:`waflib.Build.BuildContext.add_pre_fun`""" for m in getattr(self, 'pre_funs', []): m(self) def post_build(self): """Executes user-defined methods after the build is successful, see :py:meth:`waflib.Build.BuildContext.add_post_fun`""" for m in getattr(self, 'post_funs', []): m(self) def add_pre_fun(self, meth): """ Binds a callback method to execute after the scripts are read and before the build starts:: def mycallback(bld): print("Hello, world!") def build(bld): bld.add_pre_fun(mycallback) """ try: self.pre_funs.append(meth) except AttributeError: self.pre_funs = [meth] def add_post_fun(self, meth): """ Binds a callback method to execute immediately after the build is successful:: def call_ldconfig(bld): bld.exec_command('/sbin/ldconfig') def build(bld): if bld.cmd == 'install': bld.add_pre_fun(call_ldconfig) """ try: self.post_funs.append(meth) except AttributeError: self.post_funs = [meth] def get_group(self, x): """ Returns the build group named `x`, or the current group if `x` is None :param x: name or number or None :type x: string, int or None """ if not self.groups: self.add_group() if x is None: return self.groups[self.current_group] if x in self.group_names: return self.group_names[x] return self.groups[x] def add_to_group(self, tgen, group=None): """Adds a task or a task generator to the build; there is no attempt to remove it if it was already added.""" assert(isinstance(tgen, TaskGen.task_gen) or isinstance(tgen, Task.Task)) tgen.bld = self self.get_group(group).append(tgen) def get_group_name(self, g): """ Returns the name of the input build group :param g: build group object or build group index :type g: integer or list :return: name :rtype: string """ if not isinstance(g, list): g = self.groups[g] for x in self.group_names: if id(self.group_names[x]) == id(g): return x return '' def get_group_idx(self, tg): """ Returns the index of the group containing the task generator given as argument:: def build(bld): tg = bld(name='nada') 0 == bld.get_group_idx(tg) :param tg: Task generator object :type tg: :py:class:`waflib.TaskGen.task_gen` :rtype: int """ se = id(tg) for i, tmp in enumerate(self.groups): for t in tmp: if id(t) == se: return i return None def add_group(self, name=None, move=True): """ Adds a new group of tasks/task generators. By default the new group becomes the default group for new task generators (make sure to create build groups in order). :param name: name for this group :type name: string :param move: set this new group as default group (True by default) :type move: bool :raises: :py:class:`waflib.Errors.WafError` if a group by the name given already exists """ if name and name in self.group_names: raise Errors.WafError('add_group: name %s already present', name) g = [] self.group_names[name] = g self.groups.append(g) if move: self.current_group = len(self.groups) - 1 def set_group(self, idx): """ Sets the build group at position idx as current so that newly added task generators are added to this one by default:: def build(bld): bld(rule='touch ${TGT}', target='foo.txt') bld.add_group() # now the current group is 1 bld(rule='touch ${TGT}', target='bar.txt') bld.set_group(0) # now the current group is 0 bld(rule='touch ${TGT}', target='truc.txt') # build truc.txt before bar.txt :param idx: group name or group index :type idx: string or int """ if isinstance(idx, str): g = self.group_names[idx] for i, tmp in enumerate(self.groups): if id(g) == id(tmp): self.current_group = i break else: self.current_group = idx def total(self): """ Approximate task count: this value may be inaccurate if task generators are posted lazily (see :py:attr:`waflib.Build.BuildContext.post_mode`). The value :py:attr:`waflib.Runner.Parallel.total` is updated during the task execution. :rtype: int """ total = 0 for group in self.groups: for tg in group: try: total += len(tg.tasks) except AttributeError: total += 1 return total def get_targets(self): """ This method returns a pair containing the index of the last build group to post, and the list of task generator objects corresponding to the target names. This is used internally by :py:meth:`waflib.Build.BuildContext.get_build_iterator` to perform partial builds:: $ waf --targets=myprogram,myshlib :return: the minimum build group index, and list of task generators :rtype: tuple """ to_post = [] min_grp = 0 for name in self.targets.split(','): tg = self.get_tgen_by_name(name) m = self.get_group_idx(tg) if m > min_grp: min_grp = m to_post = [tg] elif m == min_grp: to_post.append(tg) return (min_grp, to_post) def get_all_task_gen(self): """ Returns a list of all task generators for troubleshooting purposes. """ lst = [] for g in self.groups: lst.extend(g) return lst def post_group(self): """ Post task generators from the group indexed by self.current_group; used internally by :py:meth:`waflib.Build.BuildContext.get_build_iterator` """ def tgpost(tg): try: f = tg.post except AttributeError: pass else: f() if self.targets == '*': for tg in self.groups[self.current_group]: tgpost(tg) elif self.targets: if self.current_group < self._min_grp: for tg in self.groups[self.current_group]: tgpost(tg) else: for tg in self._exact_tg: tg.post() else: ln = self.launch_node() if ln.is_child_of(self.bldnode): if Logs.verbose > 1: Logs.warn('Building from the build directory, forcing --targets=*') ln = self.srcnode elif not ln.is_child_of(self.srcnode): if Logs.verbose > 1: Logs.warn('CWD %s is not under %s, forcing --targets=* (run distclean?)', ln.abspath(), self.srcnode.abspath()) ln = self.srcnode def is_post(tg, ln): try: p = tg.path except AttributeError: pass else: if p.is_child_of(ln): return True def is_post_group(): for i, g in enumerate(self.groups): if i > self.current_group: for tg in g: if is_post(tg, ln): return True if self.post_mode == POST_LAZY and ln != self.srcnode: # partial folder builds require all targets from a previous build group if is_post_group(): ln = self.srcnode for tg in self.groups[self.current_group]: if is_post(tg, ln): tgpost(tg) def get_tasks_group(self, idx): """ Returns all task instances for the build group at position idx, used internally by :py:meth:`waflib.Build.BuildContext.get_build_iterator` :rtype: list of :py:class:`waflib.Task.Task` """ tasks = [] for tg in self.groups[idx]: try: tasks.extend(tg.tasks) except AttributeError: # not a task generator tasks.append(tg) return tasks def get_build_iterator(self): """ Creates a Python generator object that returns lists of tasks that may be processed in parallel. :return: tasks which can be executed immediately :rtype: generator returning lists of :py:class:`waflib.Task.Task` """ if self.targets and self.targets != '*': (self._min_grp, self._exact_tg) = self.get_targets() if self.post_mode != POST_LAZY: for self.current_group, _ in enumerate(self.groups): self.post_group() for self.current_group, _ in enumerate(self.groups): # first post the task generators for the group if self.post_mode != POST_AT_ONCE: self.post_group() # then extract the tasks tasks = self.get_tasks_group(self.current_group) # if the constraints are set properly (ext_in/ext_out, before/after) # the call to set_file_constraints may be removed (can be a 15% penalty on no-op rebuilds) # (but leave set_file_constraints for the installation step) # # if the tasks have only files, set_file_constraints is required but set_precedence_constraints is not necessary # Task.set_file_constraints(tasks) Task.set_precedence_constraints(tasks) self.cur_tasks = tasks if tasks: yield tasks while 1: # the build stops once there are no tasks to process yield [] def install_files(self, dest, files, **kw): """ Creates a task generator to install files on the system:: def build(bld): bld.install_files('${DATADIR}', self.path.find_resource('wscript')) :param dest: path representing the destination directory :type dest: :py:class:`waflib.Node.Node` or string (absolute path) :param files: input files :type files: list of strings or list of :py:class:`waflib.Node.Node` :param env: configuration set to expand *dest* :type env: :py:class:`waflib.ConfigSet.ConfigSet` :param relative_trick: preserve the folder hierarchy when installing whole folders :type relative_trick: bool :param cwd: parent node for searching srcfile, when srcfile is not an instance of :py:class:`waflib.Node.Node` :type cwd: :py:class:`waflib.Node.Node` :param postpone: execute the task immediately to perform the installation (False by default) :type postpone: bool """ assert(dest) tg = self(features='install_task', install_to=dest, install_from=files, **kw) tg.dest = tg.install_to tg.type = 'install_files' if not kw.get('postpone', True): tg.post() return tg def install_as(self, dest, srcfile, **kw): """ Creates a task generator to install a file on the system with a different name:: def build(bld): bld.install_as('${PREFIX}/bin', 'myapp', chmod=Utils.O755) :param dest: destination file :type dest: :py:class:`waflib.Node.Node` or string (absolute path) :param srcfile: input file :type srcfile: string or :py:class:`waflib.Node.Node` :param cwd: parent node for searching srcfile, when srcfile is not an instance of :py:class:`waflib.Node.Node` :type cwd: :py:class:`waflib.Node.Node` :param env: configuration set for performing substitutions in dest :type env: :py:class:`waflib.ConfigSet.ConfigSet` :param postpone: execute the task immediately to perform the installation (False by default) :type postpone: bool """ assert(dest) tg = self(features='install_task', install_to=dest, install_from=srcfile, **kw) tg.dest = tg.install_to tg.type = 'install_as' if not kw.get('postpone', True): tg.post() return tg def symlink_as(self, dest, src, **kw): """ Creates a task generator to install a symlink:: def build(bld): bld.symlink_as('${PREFIX}/lib/libfoo.so', 'libfoo.so.1.2.3') :param dest: absolute path of the symlink :type dest: :py:class:`waflib.Node.Node` or string (absolute path) :param src: link contents, which is a relative or absolute path which may exist or not :type src: string :param env: configuration set for performing substitutions in dest :type env: :py:class:`waflib.ConfigSet.ConfigSet` :param add: add the task created to a build group - set ``False`` only if the installation task is created after the build has started :type add: bool :param postpone: execute the task immediately to perform the installation :type postpone: bool :param relative_trick: make the symlink relative (default: ``False``) :type relative_trick: bool """ assert(dest) tg = self(features='install_task', install_to=dest, install_from=src, **kw) tg.dest = tg.install_to tg.type = 'symlink_as' tg.link = src # TODO if add: self.add_to_group(tsk) if not kw.get('postpone', True): tg.post() return tg @TaskGen.feature('install_task') @TaskGen.before_method('process_rule', 'process_source') def process_install_task(self): """Creates the installation task for the current task generator; uses :py:func:`waflib.Build.add_install_task` internally.""" self.add_install_task(**self.__dict__) @TaskGen.taskgen_method def add_install_task(self, **kw): """ Creates the installation task for the current task generator, and executes it immediately if necessary :returns: An installation task :rtype: :py:class:`waflib.Build.inst` """ if not self.bld.is_install: return if not kw['install_to']: return if kw['type'] == 'symlink_as' and Utils.is_win32: if kw.get('win32_install'): kw['type'] = 'install_as' else: # just exit return tsk = self.install_task = self.create_task('inst') tsk.chmod = kw.get('chmod', Utils.O644) tsk.link = kw.get('link', '') or kw.get('install_from', '') tsk.relative_trick = kw.get('relative_trick', False) tsk.type = kw['type'] tsk.install_to = tsk.dest = kw['install_to'] tsk.install_from = kw['install_from'] tsk.relative_base = kw.get('cwd') or kw.get('relative_base', self.path) tsk.install_user = kw.get('install_user') tsk.install_group = kw.get('install_group') tsk.init_files() if not kw.get('postpone', True): tsk.run_now() return tsk @TaskGen.taskgen_method def add_install_files(self, **kw): """ Creates an installation task for files :returns: An installation task :rtype: :py:class:`waflib.Build.inst` """ kw['type'] = 'install_files' return self.add_install_task(**kw) @TaskGen.taskgen_method def add_install_as(self, **kw): """ Creates an installation task for a single file :returns: An installation task :rtype: :py:class:`waflib.Build.inst` """ kw['type'] = 'install_as' return self.add_install_task(**kw) @TaskGen.taskgen_method def add_symlink_as(self, **kw): """ Creates an installation task for a symbolic link :returns: An installation task :rtype: :py:class:`waflib.Build.inst` """ kw['type'] = 'symlink_as' return self.add_install_task(**kw) class inst(Task.Task): """Task that installs files or symlinks; it is typically executed by :py:class:`waflib.Build.InstallContext` and :py:class:`waflib.Build.UnInstallContext`""" def __str__(self): """Returns an empty string to disable the standard task display""" return '' def uid(self): """Returns a unique identifier for the task""" lst = self.inputs + self.outputs + [self.link, self.generator.path.abspath()] return Utils.h_list(lst) def init_files(self): """ Initializes the task input and output nodes """ if self.type == 'symlink_as': inputs = [] else: inputs = self.generator.to_nodes(self.install_from) if self.type == 'install_as': assert len(inputs) == 1 self.set_inputs(inputs) dest = self.get_install_path() outputs = [] if self.type == 'symlink_as': if self.relative_trick: self.link = os.path.relpath(self.link, os.path.dirname(dest)) outputs.append(self.generator.bld.root.make_node(dest)) elif self.type == 'install_as': outputs.append(self.generator.bld.root.make_node(dest)) else: for y in inputs: if self.relative_trick: destfile = os.path.join(dest, y.path_from(self.relative_base)) else: destfile = os.path.join(dest, y.name) outputs.append(self.generator.bld.root.make_node(destfile)) self.set_outputs(outputs) def runnable_status(self): """ Installation tasks are always executed, so this method returns either :py:const:`waflib.Task.ASK_LATER` or :py:const:`waflib.Task.RUN_ME`. """ ret = super(inst, self).runnable_status() if ret == Task.SKIP_ME and self.generator.bld.is_install: return Task.RUN_ME return ret def post_run(self): """ Disables any post-run operations """ pass def get_install_path(self, destdir=True): """ Returns the destination path where files will be installed, pre-pending `destdir`. Relative paths will be interpreted relative to `PREFIX` if no `destdir` is given. :rtype: string """ if isinstance(self.install_to, Node.Node): dest = self.install_to.abspath() else: dest = os.path.normpath(Utils.subst_vars(self.install_to, self.env)) if not os.path.isabs(dest): dest = os.path.join(self.env.PREFIX, dest) if destdir and Options.options.destdir: dest = Options.options.destdir.rstrip(os.sep) + os.sep + os.path.splitdrive(dest)[1].lstrip(os.sep) return dest def copy_fun(self, src, tgt): """ Copies a file from src to tgt, preserving permissions and trying to work around path limitations on Windows platforms. On Unix-like platforms, the owner/group of the target file may be set through install_user/install_group :param src: absolute path :type src: string :param tgt: absolute path :type tgt: string """ # override this if you want to strip executables # kw['tsk'].source is the task that created the files in the build if Utils.is_win32 and len(tgt) > 259 and not tgt.startswith('\\\\?\\'): tgt = '\\\\?\\' + tgt shutil.copy2(src, tgt) self.fix_perms(tgt) def rm_empty_dirs(self, tgt): """ Removes empty folders recursively when uninstalling. :param tgt: absolute path :type tgt: string """ while tgt: tgt = os.path.dirname(tgt) try: os.rmdir(tgt) except OSError: break def run(self): """ Performs file or symlink installation """ is_install = self.generator.bld.is_install if not is_install: # unnecessary? return for x in self.outputs: if is_install == INSTALL: x.parent.mkdir() if self.type == 'symlink_as': fun = is_install == INSTALL and self.do_link or self.do_unlink fun(self.link, self.outputs[0].abspath()) else: fun = is_install == INSTALL and self.do_install or self.do_uninstall launch_node = self.generator.bld.launch_node() for x, y in zip(self.inputs, self.outputs): fun(x.abspath(), y.abspath(), x.path_from(launch_node)) def run_now(self): """ Try executing the installation task right now :raises: :py:class:`waflib.Errors.TaskNotReady` """ status = self.runnable_status() if status not in (Task.RUN_ME, Task.SKIP_ME): raise Errors.TaskNotReady('Could not process %r: status %r' % (self, status)) self.run() self.hasrun = Task.SUCCESS def do_install(self, src, tgt, lbl, **kw): """ Copies a file from src to tgt with given file permissions. The actual copy is only performed if the source and target file sizes or timestamps differ. When the copy occurs, the file is always first removed and then copied so as to prevent stale inodes. :param src: file name as absolute path :type src: string :param tgt: file destination, as absolute path :type tgt: string :param lbl: file source description :type lbl: string :param chmod: installation mode :type chmod: int :raises: :py:class:`waflib.Errors.WafError` if the file cannot be written """ if not Options.options.force: # check if the file is already there to avoid a copy try: st1 = os.stat(tgt) st2 = os.stat(src) except OSError: pass else: # same size and identical timestamps -> make no copy if st1.st_mtime + 2 >= st2.st_mtime and st1.st_size == st2.st_size: if not self.generator.bld.progress_bar: c1 = Logs.colors.NORMAL c2 = Logs.colors.BLUE Logs.info('%s- install %s%s%s (from %s)', c1, c2, tgt, c1, lbl) return False if not self.generator.bld.progress_bar: c1 = Logs.colors.NORMAL c2 = Logs.colors.BLUE Logs.info('%s+ install %s%s%s (from %s)', c1, c2, tgt, c1, lbl) # Give best attempt at making destination overwritable, # like the 'install' utility used by 'make install' does. try: os.chmod(tgt, Utils.O644 | stat.S_IMODE(os.stat(tgt).st_mode)) except EnvironmentError: pass # following is for shared libs and stale inodes (-_-) try: os.remove(tgt) except OSError: pass try: self.copy_fun(src, tgt) except EnvironmentError as e: if not os.path.exists(src): Logs.error('File %r does not exist', src) elif not os.path.isfile(src): Logs.error('Input %r is not a file', src) raise Errors.WafError('Could not install the file %r' % tgt, e) def fix_perms(self, tgt): """ Change the ownership of the file/folder/link pointed by the given path This looks up for `install_user` or `install_group` attributes on the task or on the task generator:: def build(bld): bld.install_as('${PREFIX}/wscript', 'wscript', install_user='nobody', install_group='nogroup') bld.symlink_as('${PREFIX}/wscript_link', Utils.subst_vars('${PREFIX}/wscript', bld.env), install_user='nobody', install_group='nogroup') """ if not Utils.is_win32: user = getattr(self, 'install_user', None) or getattr(self.generator, 'install_user', None) group = getattr(self, 'install_group', None) or getattr(self.generator, 'install_group', None) if user or group: Utils.lchown(tgt, user or -1, group or -1) if not os.path.islink(tgt): os.chmod(tgt, self.chmod) def do_link(self, src, tgt, **kw): """ Creates a symlink from tgt to src. :param src: file name as absolute path :type src: string :param tgt: file destination, as absolute path :type tgt: string """ if os.path.islink(tgt) and os.readlink(tgt) == src: if not self.generator.bld.progress_bar: c1 = Logs.colors.NORMAL c2 = Logs.colors.BLUE Logs.info('%s- symlink %s%s%s (to %s)', c1, c2, tgt, c1, src) else: try: os.remove(tgt) except OSError: pass if not self.generator.bld.progress_bar: c1 = Logs.colors.NORMAL c2 = Logs.colors.BLUE Logs.info('%s+ symlink %s%s%s (to %s)', c1, c2, tgt, c1, src) os.symlink(src, tgt) self.fix_perms(tgt) def do_uninstall(self, src, tgt, lbl, **kw): """ See :py:meth:`waflib.Build.inst.do_install` """ if not self.generator.bld.progress_bar: c1 = Logs.colors.NORMAL c2 = Logs.colors.BLUE Logs.info('%s- remove %s%s%s', c1, c2, tgt, c1) #self.uninstall.append(tgt) try: os.remove(tgt) except OSError as e: if e.errno != errno.ENOENT: if not getattr(self, 'uninstall_error', None): self.uninstall_error = True Logs.warn('build: some files could not be uninstalled (retry with -vv to list them)') if Logs.verbose > 1: Logs.warn('Could not remove %s (error code %r)', e.filename, e.errno) self.rm_empty_dirs(tgt) def do_unlink(self, src, tgt, **kw): """ See :py:meth:`waflib.Build.inst.do_link` """ try: if not self.generator.bld.progress_bar: c1 = Logs.colors.NORMAL c2 = Logs.colors.BLUE Logs.info('%s- remove %s%s%s', c1, c2, tgt, c1) os.remove(tgt) except OSError: pass self.rm_empty_dirs(tgt) class InstallContext(BuildContext): '''installs the targets on the system''' cmd = 'install' def __init__(self, **kw): super(InstallContext, self).__init__(**kw) self.is_install = INSTALL class UninstallContext(InstallContext): '''removes the targets installed''' cmd = 'uninstall' def __init__(self, **kw): super(UninstallContext, self).__init__(**kw) self.is_install = UNINSTALL class CleanContext(BuildContext): '''cleans the project''' cmd = 'clean' def execute(self): """ See :py:func:`waflib.Build.BuildContext.execute`. """ self.restore() if not self.all_envs: self.load_envs() self.recurse([self.run_dir]) try: self.clean() finally: self.store() def clean(self): """ Remove most files from the build directory, and reset all caches. Custom lists of files to clean can be declared as `bld.clean_files`. For example, exclude `build/program/myprogram` from getting removed:: def build(bld): bld.clean_files = bld.bldnode.ant_glob('**', excl='.lock* config.log c4che/* config.h program/myprogram', quiet=True, generator=True) """ Logs.debug('build: clean called') if hasattr(self, 'clean_files'): for n in self.clean_files: n.delete() elif self.bldnode != self.srcnode: # would lead to a disaster if top == out lst = [] for env in self.all_envs.values(): lst.extend(self.root.find_or_declare(f) for f in env[CFG_FILES]) excluded_dirs = '.lock* *conf_check_*/** config.log %s/*' % CACHE_DIR for n in self.bldnode.ant_glob('**/*', excl=excluded_dirs, quiet=True): if n in lst: continue n.delete() self.root.children = {} for v in SAVED_ATTRS: if v == 'root': continue setattr(self, v, {}) class ListContext(BuildContext): '''lists the targets to execute''' cmd = 'list' def execute(self): """ In addition to printing the name of each build target, a description column will include text for each task generator which has a "description" field set. See :py:func:`waflib.Build.BuildContext.execute`. """ self.restore() if not self.all_envs: self.load_envs() self.recurse([self.run_dir]) self.pre_build() # display the time elapsed in the progress bar self.timer = Utils.Timer() for g in self.groups: for tg in g: try: f = tg.post except AttributeError: pass else: f() try: # force the cache initialization self.get_tgen_by_name('') except Errors.WafError: pass targets = sorted(self.task_gen_cache_names) # figure out how much to left-justify, for largest target name line_just = max(len(t) for t in targets) if targets else 0 for target in targets: tgen = self.task_gen_cache_names[target] # Support displaying the description for the target # if it was set on the tgen descript = getattr(tgen, 'description', '') if descript: target = target.ljust(line_just) descript = ': %s' % descript Logs.pprint('GREEN', target, label=descript) class StepContext(BuildContext): '''executes tasks in a step-by-step fashion, for debugging''' cmd = 'step' def __init__(self, **kw): super(StepContext, self).__init__(**kw) self.files = Options.options.files def compile(self): """ Overrides :py:meth:`waflib.Build.BuildContext.compile` to perform a partial build on tasks matching the input/output pattern given (regular expression matching):: $ waf step --files=foo.c,bar.c,in:truc.c,out:bar.o $ waf step --files=in:foo.cpp.1.o # link task only """ if not self.files: Logs.warn('Add a pattern for the debug build, for example "waf step --files=main.c,app"') BuildContext.compile(self) return targets = [] if self.targets and self.targets != '*': targets = self.targets.split(',') for g in self.groups: for tg in g: if targets and tg.name not in targets: continue try: f = tg.post except AttributeError: pass else: f() for pat in self.files.split(','): matcher = self.get_matcher(pat) for tg in g: if isinstance(tg, Task.Task): lst = [tg] else: lst = tg.tasks for tsk in lst: do_exec = False for node in tsk.inputs: if matcher(node, output=False): do_exec = True break for node in tsk.outputs: if matcher(node, output=True): do_exec = True break if do_exec: ret = tsk.run() Logs.info('%s -> exit %r', tsk, ret) def get_matcher(self, pat): """ Converts a step pattern into a function :param: pat: pattern of the form in:truc.c,out:bar.o :returns: Python function that uses Node objects as inputs and returns matches :rtype: function """ # this returns a function inn = True out = True if pat.startswith('in:'): out = False pat = pat.replace('in:', '') elif pat.startswith('out:'): inn = False pat = pat.replace('out:', '') anode = self.root.find_node(pat) pattern = None if not anode: if not pat.startswith('^'): pat = '^.+?%s' % pat if not pat.endswith('$'): pat = '%s$' % pat pattern = re.compile(pat) def match(node, output): if output and not out: return False if not output and not inn: return False if anode: return anode == node else: return pattern.match(node.abspath()) return match class EnvContext(BuildContext): """Subclass EnvContext to create commands that require configuration data in 'env'""" fun = cmd = None def execute(self): """ See :py:func:`waflib.Build.BuildContext.execute`. """ self.restore() if not self.all_envs: self.load_envs() self.recurse([self.run_dir]) kupfer-328/waflib/ConfigSet.py000066400000000000000000000201461500175051100163610ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2018 (ita) """ ConfigSet: a special dict The values put in :py:class:`ConfigSet` must be serializable (dicts, lists, strings) """ import copy, re, os from waflib import Logs, Utils re_imp = re.compile(r'^(#)*?([^#=]*?)\ =\ (.*?)$', re.M) class ConfigSet(object): """ A copy-on-write dict with human-readable serialized format. The serialization format is human-readable (python-like) and performed by using eval() and repr(). For high performance prefer pickle. Do not store functions as they are not serializable. The values can be accessed by attributes or by keys:: from waflib.ConfigSet import ConfigSet env = ConfigSet() env.FOO = 'test' env['FOO'] = 'test' """ __slots__ = ('table', 'parent') def __init__(self, filename=None): self.table = {} """ Internal dict holding the object values """ #self.parent = None if filename: self.load(filename) def __contains__(self, key): """ Enables the *in* syntax:: if 'foo' in env: print(env['foo']) """ if key in self.table: return True try: return self.parent.__contains__(key) except AttributeError: return False # parent may not exist def keys(self): """Dict interface""" keys = set() cur = self while cur: keys.update(cur.table.keys()) cur = getattr(cur, 'parent', None) keys = list(keys) keys.sort() return keys def __iter__(self): return iter(self.keys()) def __str__(self): """Text representation of the ConfigSet (for debugging purposes)""" return "\n".join(["%r %r" % (x, self.__getitem__(x)) for x in self.keys()]) def __getitem__(self, key): """ Dictionary interface: get value from key:: def configure(conf): conf.env['foo'] = {} print(env['foo']) """ try: while 1: x = self.table.get(key) if not x is None: return x self = self.parent except AttributeError: return [] def __setitem__(self, key, value): """ Dictionary interface: set value from key """ self.table[key] = value def __delitem__(self, key): """ Dictionary interface: mark the value as missing """ self[key] = [] def __getattr__(self, name): """ Attribute access provided for convenience. The following forms are equivalent:: def configure(conf): conf.env.value conf.env['value'] """ if name in self.__slots__: return object.__getattribute__(self, name) else: return self[name] def __setattr__(self, name, value): """ Attribute access provided for convenience. The following forms are equivalent:: def configure(conf): conf.env.value = x env['value'] = x """ if name in self.__slots__: object.__setattr__(self, name, value) else: self[name] = value def __delattr__(self, name): """ Attribute access provided for convenience. The following forms are equivalent:: def configure(conf): del env.value del env['value'] """ if name in self.__slots__: object.__delattr__(self, name) else: del self[name] def derive(self): """ Returns a new ConfigSet deriving from self. The copy returned will be a shallow copy:: from waflib.ConfigSet import ConfigSet env = ConfigSet() env.append_value('CFLAGS', ['-O2']) child = env.derive() child.CFLAGS.append('test') # warning! this will modify 'env' child.CFLAGS = ['-O3'] # new list, ok child.append_value('CFLAGS', ['-O3']) # ok Use :py:func:`ConfigSet.detach` to detach the child from the parent. """ newenv = ConfigSet() newenv.parent = self return newenv def detach(self): """ Detaches this instance from its parent (if present) Modifying the parent :py:class:`ConfigSet` will not change the current object Modifying this :py:class:`ConfigSet` will not modify the parent one. """ tbl = self.get_merged_dict() try: delattr(self, 'parent') except AttributeError: pass else: keys = tbl.keys() for x in keys: tbl[x] = copy.deepcopy(tbl[x]) self.table = tbl return self def get_flat(self, key): """ Returns a value as a string. If the input is a list, the value returned is space-separated. :param key: key to use :type key: string """ s = self[key] if isinstance(s, str): return s return ' '.join(s) def _get_list_value_for_modification(self, key): """ Returns a list value for further modification. The list may be modified inplace and there is no need to do this afterwards:: self.table[var] = value """ try: value = self.table[key] except KeyError: try: value = self.parent[key] except AttributeError: value = [] else: if isinstance(value, list): # force a copy value = value[:] else: value = [value] self.table[key] = value else: if not isinstance(value, list): self.table[key] = value = [value] return value def append_value(self, var, val): """ Appends a value to the specified config key:: def build(bld): bld.env.append_value('CFLAGS', ['-O2']) The value must be a list or a tuple """ if isinstance(val, str): # if there were string everywhere we could optimize this val = [val] current_value = self._get_list_value_for_modification(var) current_value.extend(val) def prepend_value(self, var, val): """ Prepends a value to the specified item:: def configure(conf): conf.env.prepend_value('CFLAGS', ['-O2']) The value must be a list or a tuple """ if isinstance(val, str): val = [val] self.table[var] = val + self._get_list_value_for_modification(var) def append_unique(self, var, val): """ Appends a value to the specified item only if it's not already present:: def build(bld): bld.env.append_unique('CFLAGS', ['-O2', '-g']) The value must be a list or a tuple """ if isinstance(val, str): val = [val] current_value = self._get_list_value_for_modification(var) for x in val: if x not in current_value: current_value.append(x) def get_merged_dict(self): """ Computes the merged dictionary from the fusion of self and all its parent :rtype: a ConfigSet object """ table_list = [] env = self while 1: table_list.insert(0, env.table) try: env = env.parent except AttributeError: break merged_table = {} for table in table_list: merged_table.update(table) return merged_table def store(self, filename): """ Serializes the :py:class:`ConfigSet` data to a file. See :py:meth:`ConfigSet.load` for reading such files. :param filename: file to use :type filename: string """ try: os.makedirs(os.path.split(filename)[0]) except OSError: pass buf = [] merged_table = self.get_merged_dict() keys = list(merged_table.keys()) keys.sort() try: fun = ascii except NameError: fun = repr for k in keys: if k != 'undo_stack': buf.append('%s = %s\n' % (k, fun(merged_table[k]))) Utils.writef(filename, ''.join(buf)) def load(self, filename): """ Restores contents from a file (current values are not cleared). Files are written using :py:meth:`ConfigSet.store`. :param filename: file to use :type filename: string """ tbl = self.table code = Utils.readf(filename, m='r') for m in re_imp.finditer(code): g = m.group tbl[g(2)] = eval(g(3)) Logs.debug('env: %s', self.table) def update(self, d): """ Dictionary interface: replace values with the ones from another dict :param d: object to use the value from :type d: dict-like object """ self.table.update(d) def stash(self): """ Stores the object state to provide transactionality semantics:: env = ConfigSet() env.stash() try: env.append_value('CFLAGS', '-O3') call_some_method(env) finally: env.revert() The history is kept in a stack, and is lost during the serialization by :py:meth:`ConfigSet.store` """ orig = self.table tbl = self.table = self.table.copy() for x in tbl.keys(): tbl[x] = copy.deepcopy(tbl[x]) self.undo_stack = self.undo_stack + [orig] def commit(self): """ Commits transactional changes. See :py:meth:`ConfigSet.stash` """ self.undo_stack.pop(-1) def revert(self): """ Reverts the object to a previous state. See :py:meth:`ConfigSet.stash` """ self.table = self.undo_stack.pop(-1) kupfer-328/waflib/Configure.py000066400000000000000000000453751500175051100164340ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2018 (ita) """ Configuration system A :py:class:`waflib.Configure.ConfigurationContext` instance is created when ``waf configure`` is called, it is used to: * create data dictionaries (ConfigSet instances) * store the list of modules to import * hold configuration routines such as ``find_program``, etc """ import os, re, shlex, shutil, sys, time, traceback from waflib import ConfigSet, Utils, Options, Logs, Context, Build, Errors WAF_CONFIG_LOG = 'config.log' """Name of the configuration log file""" autoconfig = False """Execute the configuration automatically""" conf_template = '''# project %(app)s configured on %(now)s by # waf %(wafver)s (abi %(abi)s, python %(pyver)x on %(systype)s) # using %(args)s #''' class ConfigurationContext(Context.Context): '''configures the project''' cmd = 'configure' error_handlers = [] """ Additional functions to handle configuration errors """ def __init__(self, **kw): super(ConfigurationContext, self).__init__(**kw) self.environ = dict(os.environ) self.all_envs = {} self.top_dir = None self.out_dir = None self.tools = [] # tools loaded in the configuration, and that will be loaded when building self.hash = 0 self.files = [] self.tool_cache = [] self.setenv('') def setenv(self, name, env=None): """ Set a new config set for conf.env. If a config set of that name already exists, recall it without modification. The name is the filename prefix to save to ``c4che/NAME_cache.py``, and it is also used as *variants* by the build commands. Though related to variants, whatever kind of data may be stored in the config set:: def configure(cfg): cfg.env.ONE = 1 cfg.setenv('foo') cfg.env.ONE = 2 def build(bld): 2 == bld.env_of_name('foo').ONE :param name: name of the configuration set :type name: string :param env: ConfigSet to copy, or an empty ConfigSet is created :type env: :py:class:`waflib.ConfigSet.ConfigSet` """ if name not in self.all_envs or env: if not env: env = ConfigSet.ConfigSet() self.prepare_env(env) else: env = env.derive() self.all_envs[name] = env self.variant = name def get_env(self): """Getter for the env property""" return self.all_envs[self.variant] def set_env(self, val): """Setter for the env property""" self.all_envs[self.variant] = val env = property(get_env, set_env) def init_dirs(self): """ Initialize the project directory and the build directory """ top = self.top_dir if not top: top = Options.options.top if not top: top = getattr(Context.g_module, Context.TOP, None) if not top: top = self.path.abspath() top = os.path.abspath(top) self.srcnode = (os.path.isabs(top) and self.root or self.path).find_dir(top) assert(self.srcnode) out = self.out_dir if not out: out = Options.options.out if not out: out = getattr(Context.g_module, Context.OUT, None) if not out: out = Options.lockfile.replace('.lock-waf_%s_' % sys.platform, '').replace('.lock-waf', '') # someone can be messing with symlinks out = os.path.realpath(out) self.bldnode = (os.path.isabs(out) and self.root or self.path).make_node(out) self.bldnode.mkdir() if not os.path.isdir(self.bldnode.abspath()): self.fatal('Could not create the build directory %s' % self.bldnode.abspath()) def execute(self): """ See :py:func:`waflib.Context.Context.execute` """ self.init_dirs() self.cachedir = self.bldnode.make_node(Build.CACHE_DIR) self.cachedir.mkdir() path = os.path.join(self.bldnode.abspath(), WAF_CONFIG_LOG) self.logger = Logs.make_logger(path, 'cfg') app = getattr(Context.g_module, 'APPNAME', '') if app: ver = getattr(Context.g_module, 'VERSION', '') if ver: app = "%s (%s)" % (app, ver) params = {'now': time.ctime(), 'pyver': sys.hexversion, 'systype': sys.platform, 'args': " ".join(sys.argv), 'wafver': Context.WAFVERSION, 'abi': Context.ABI, 'app': app} self.to_log(conf_template % params) self.msg('Setting top to', self.srcnode.abspath()) self.msg('Setting out to', self.bldnode.abspath()) if id(self.srcnode) == id(self.bldnode): Logs.warn('Setting top == out') elif id(self.path) != id(self.srcnode): if self.srcnode.is_child_of(self.path): Logs.warn('Are you certain that you do not want to set top="." ?') super(ConfigurationContext, self).execute() self.store() Context.top_dir = self.srcnode.abspath() Context.out_dir = self.bldnode.abspath() # this will write a configure lock so that subsequent builds will # consider the current path as the root directory (see prepare_impl). # to remove: use 'waf distclean' env = ConfigSet.ConfigSet() env.argv = sys.argv env.options = Options.options.__dict__ env.config_cmd = self.cmd env.run_dir = Context.run_dir env.top_dir = Context.top_dir env.out_dir = Context.out_dir # conf.hash & conf.files hold wscript files paths and hash # (used only by Configure.autoconfig) env.hash = self.hash env.files = self.files env.environ = dict(self.environ) env.launch_dir = Context.launch_dir if not (self.env.NO_LOCK_IN_RUN or env.environ.get('NO_LOCK_IN_RUN') or getattr(Options.options, 'no_lock_in_run')): env.store(os.path.join(Context.run_dir, Options.lockfile)) if not (self.env.NO_LOCK_IN_TOP or env.environ.get('NO_LOCK_IN_TOP') or getattr(Options.options, 'no_lock_in_top')): env.store(os.path.join(Context.top_dir, Options.lockfile)) if not (self.env.NO_LOCK_IN_OUT or env.environ.get('NO_LOCK_IN_OUT') or getattr(Options.options, 'no_lock_in_out')): env.store(os.path.join(Context.out_dir, Options.lockfile)) def prepare_env(self, env): """ Insert *PREFIX*, *BINDIR* and *LIBDIR* values into ``env`` :type env: :py:class:`waflib.ConfigSet.ConfigSet` :param env: a ConfigSet, usually ``conf.env`` """ if not env.PREFIX: if Options.options.prefix or Utils.is_win32: env.PREFIX = Options.options.prefix else: env.PREFIX = '/' if not env.BINDIR: if Options.options.bindir: env.BINDIR = Options.options.bindir else: env.BINDIR = Utils.subst_vars('${PREFIX}/bin', env) if not env.LIBDIR: if Options.options.libdir: env.LIBDIR = Options.options.libdir else: env.LIBDIR = Utils.subst_vars('${PREFIX}/lib%s' % Utils.lib64(), env) def store(self): """Save the config results into the cache file""" n = self.cachedir.make_node('build.config.py') n.write('version = 0x%x\ntools = %r\n' % (Context.HEXVERSION, self.tools)) if not self.all_envs: self.fatal('nothing to store in the configuration context!') for key in self.all_envs: tmpenv = self.all_envs[key] tmpenv.store(os.path.join(self.cachedir.abspath(), key + Build.CACHE_SUFFIX)) def load(self, tool_list, tooldir=None, funs=None, with_sys_path=True, cache=False): """ Load Waf tools, which will be imported whenever a build is started. :param tool_list: waf tools to import :type tool_list: list of string :param tooldir: paths for the imports :type tooldir: list of string :param funs: functions to execute from the waf tools :type funs: list of string :param cache: whether to prevent the tool from running twice :type cache: bool """ tools = Utils.to_list(tool_list) if tooldir: tooldir = Utils.to_list(tooldir) for tool in tools: # avoid loading the same tool more than once with the same functions # used by composite projects if cache: mag = (tool, id(self.env), tooldir, funs) if mag in self.tool_cache: self.to_log('(tool %s is already loaded, skipping)' % tool) continue self.tool_cache.append(mag) module = None try: module = Context.load_tool(tool, tooldir, ctx=self, with_sys_path=with_sys_path) except ImportError as e: self.fatal('Could not load the Waf tool %r from %r\n%s' % (tool, getattr(e, 'waf_sys_path', sys.path), e)) except Exception as e: self.to_log('imp %r (%r & %r)' % (tool, tooldir, funs)) self.to_log(traceback.format_exc()) raise if funs is not None: self.eval_rules(funs) else: func = getattr(module, 'configure', None) if func: if type(func) is type(Utils.readf): func(self) else: self.eval_rules(func) self.tools.append({'tool':tool, 'tooldir':tooldir, 'funs':funs}) def post_recurse(self, node): """ Records the path and a hash of the scripts visited, see :py:meth:`waflib.Context.Context.post_recurse` :param node: script :type node: :py:class:`waflib.Node.Node` """ super(ConfigurationContext, self).post_recurse(node) self.hash = Utils.h_list((self.hash, node.read('rb'))) self.files.append(node.abspath()) def eval_rules(self, rules): """ Execute configuration tests provided as list of functions to run :param rules: list of configuration method names :type rules: list of string """ self.rules = Utils.to_list(rules) for x in self.rules: f = getattr(self, x) if not f: self.fatal('No such configuration function %r' % x) f() def conf(f): """ Decorator: attach new configuration functions to :py:class:`waflib.Build.BuildContext` and :py:class:`waflib.Configure.ConfigurationContext`. The methods bound will accept a parameter named 'mandatory' to disable the configuration errors:: def configure(conf): conf.find_program('abc', mandatory=False) :param f: method to bind :type f: function """ def fun(*k, **kw): mandatory = kw.pop('mandatory', True) try: return f(*k, **kw) except Errors.ConfigurationError: if mandatory: raise fun.__name__ = f.__name__ setattr(ConfigurationContext, f.__name__, fun) setattr(Build.BuildContext, f.__name__, fun) return f @conf def add_os_flags(self, var, dest=None, dup=False): """ Import operating system environment values into ``conf.env`` dict:: def configure(conf): conf.add_os_flags('CFLAGS') :param var: variable to use :type var: string :param dest: destination variable, by default the same as var :type dest: string :param dup: add the same set of flags again :type dup: bool """ try: flags = shlex.split(self.environ[var]) except KeyError: return if dup or ''.join(flags) not in ''.join(Utils.to_list(self.env[dest or var])): self.env.append_value(dest or var, flags) @conf def cmd_to_list(self, cmd): """ Detect if a command is written in pseudo shell like ``ccache g++`` and return a list. :param cmd: command :type cmd: a string or a list of string """ if isinstance(cmd, str): if os.path.isfile(cmd): # do not take any risk return [cmd] if os.sep == '/': return shlex.split(cmd) else: try: return shlex.split(cmd, posix=False) except TypeError: # Python 2.5 on windows? return shlex.split(cmd) return cmd @conf def check_waf_version(self, mini='1.9.99', maxi='2.1.0', **kw): """ Raise a Configuration error if the Waf version does not strictly match the given bounds:: conf.check_waf_version(mini='1.9.99', maxi='2.1.0') :type mini: number, tuple or string :param mini: Minimum required version :type maxi: number, tuple or string :param maxi: Maximum allowed version """ self.start_msg('Checking for waf version in %s-%s' % (str(mini), str(maxi)), **kw) ver = Context.HEXVERSION if Utils.num2ver(mini) > ver: self.fatal('waf version should be at least %r (%r found)' % (Utils.num2ver(mini), ver)) if Utils.num2ver(maxi) < ver: self.fatal('waf version should be at most %r (%r found)' % (Utils.num2ver(maxi), ver)) self.end_msg('ok', **kw) @conf def find_file(self, filename, path_list=[]): """ Find a file in a list of paths :param filename: name of the file to search for :param path_list: list of directories to search :return: the first matching filename; else a configuration exception is raised """ for n in Utils.to_list(filename): for d in Utils.to_list(path_list): p = os.path.expanduser(os.path.join(d, n)) if os.path.exists(p): return p self.fatal('Could not find %r' % filename) @conf def find_program(self, filename, **kw): """ Search for a program on the operating system When var is used, you may set os.environ[var] to help find a specific program version, for example:: $ CC='ccache gcc' waf configure :param path_list: paths to use for searching :type param_list: list of string :param var: store the result to conf.env[var] where var defaults to filename.upper() if not provided; the result is stored as a list of strings :type var: string :param value: obtain the program from the value passed exclusively :type value: list or string (list is preferred) :param exts: list of extensions for the binary (do not add an extension for portability) :type exts: list of string :param msg: name to display in the log, by default filename is used :type msg: string :param interpreter: interpreter for the program :type interpreter: ConfigSet variable key :raises: :py:class:`waflib.Errors.ConfigurationError` """ exts = kw.get('exts', Utils.is_win32 and '.exe,.com,.bat,.cmd' or ',.sh,.pl,.py') environ = kw.get('environ', getattr(self, 'environ', os.environ)) ret = '' filename = Utils.to_list(filename) msg = kw.get('msg', ', '.join(filename)) var = kw.get('var', '') if not var: var = re.sub(r'\W', '_', filename[0].upper()) path_list = kw.get('path_list', '') if path_list: path_list = Utils.to_list(path_list) else: path_list = environ.get('PATH', '').split(os.pathsep) if kw.get('value'): # user-provided in command-line options and passed to find_program ret = self.cmd_to_list(kw['value']) elif environ.get(var): # user-provided in the os environment ret = self.cmd_to_list(environ[var]) elif self.env[var]: # a default option in the wscript file ret = self.cmd_to_list(self.env[var]) else: if not ret: ret = self.find_binary(filename, exts.split(','), path_list) if not ret and Utils.winreg: ret = Utils.get_registry_app_path(Utils.winreg.HKEY_CURRENT_USER, filename) if not ret and Utils.winreg: ret = Utils.get_registry_app_path(Utils.winreg.HKEY_LOCAL_MACHINE, filename) ret = self.cmd_to_list(ret) if ret: if len(ret) == 1: retmsg = ret[0] else: retmsg = ret else: retmsg = False self.msg('Checking for program %r' % msg, retmsg, **kw) if not kw.get('quiet'): self.to_log('find program=%r paths=%r var=%r -> %r' % (filename, path_list, var, ret)) if not ret: self.fatal(kw.get('errmsg', '') or 'Could not find the program %r' % filename) interpreter = kw.get('interpreter') if interpreter is None: if not Utils.check_exe(ret[0], env=environ): self.fatal('Program %r is not executable' % ret) self.env[var] = ret else: self.env[var] = self.env[interpreter] + ret return ret @conf def find_binary(self, filenames, exts, paths): for f in filenames: for ext in exts: exe_name = f + ext if os.path.isabs(exe_name): if os.path.isfile(exe_name): return exe_name else: for path in paths: x = os.path.expanduser(os.path.join(path, exe_name)) if os.path.isfile(x): return x return None @conf def run_build(self, *k, **kw): """ Create a temporary build context to execute a build. A temporary reference to that build context is kept on self.test_bld for debugging purposes. The arguments to this function are passed to a single task generator for that build. Only three parameters are mandatory: :param features: features to pass to a task generator created in the build :type features: list of string :param compile_filename: file to create for the compilation (default: *test.c*) :type compile_filename: string :param code: input file contents :type code: string Though this function returns *0* by default, the build may bind attribute named *retval* on the build context object to return a particular value. See :py:func:`waflib.Tools.c_config.test_exec_fun` for example. The temporary builds creates a temporary folder; the name of that folder is calculated by hashing input arguments to this function, with the exception of :py:class:`waflib.ConfigSet.ConfigSet` objects which are used for both reading and writing values. This function also features a cache which is disabled by default; that cache relies on the hash value calculated as indicated above:: def options(opt): opt.add_option('--confcache', dest='confcache', default=0, action='count', help='Use a configuration cache') And execute the configuration with the following command-line:: $ waf configure --confcache """ buf = [] for key in sorted(kw.keys()): v = kw[key] if isinstance(v, ConfigSet.ConfigSet): # values are being written to, so they are excluded from contributing to the hash continue elif hasattr(v, '__call__'): buf.append(Utils.h_fun(v)) else: buf.append(str(v)) h = Utils.h_list(buf) dir = self.bldnode.abspath() + os.sep + (not Utils.is_win32 and '.' or '') + 'conf_check_' + Utils.to_hex(h) cachemode = kw.get('confcache', getattr(Options.options, 'confcache', None)) if not cachemode and os.path.exists(dir): shutil.rmtree(dir) try: os.makedirs(dir) except OSError: pass try: os.stat(dir) except OSError: self.fatal('cannot use the configuration test folder %r' % dir) if cachemode == 1: try: proj = ConfigSet.ConfigSet(os.path.join(dir, 'cache_run_build')) except EnvironmentError: pass else: ret = proj['cache_run_build'] if isinstance(ret, str) and ret.startswith('Test does not build'): self.fatal(ret) return ret bdir = os.path.join(dir, 'testbuild') if not os.path.exists(bdir): os.makedirs(bdir) cls_name = kw.get('run_build_cls') or getattr(self, 'run_build_cls', 'build') self.test_bld = bld = Context.create_context(cls_name, top_dir=dir, out_dir=bdir) bld.init_dirs() bld.progress_bar = 0 bld.targets = '*' bld.logger = self.logger bld.all_envs.update(self.all_envs) # not really necessary bld.env = kw['env'] bld.kw = kw bld.conf = self kw['build_fun'](bld) ret = -1 try: try: bld.compile() except Errors.WafError: ret = 'Test does not build: %s' % traceback.format_exc() self.fatal(ret) else: ret = getattr(bld, 'retval', 0) finally: if cachemode: # cache the results each time proj = ConfigSet.ConfigSet() proj['cache_run_build'] = ret proj.store(os.path.join(dir, 'cache_run_build')) else: shutil.rmtree(dir) return ret @conf def ret_msg(self, msg, args): if isinstance(msg, str): return msg return msg(args) @conf def test(self, *k, **kw): if not 'env' in kw: kw['env'] = self.env.derive() # validate_c for example if kw.get('validate'): kw['validate'](kw) self.start_msg(kw['msg'], **kw) ret = None try: ret = self.run_build(*k, **kw) except self.errors.ConfigurationError: self.end_msg(kw['errmsg'], 'YELLOW', **kw) if Logs.verbose > 1: raise else: self.fatal('The configuration failed') else: kw['success'] = ret if kw.get('post_check'): ret = kw['post_check'](kw) if ret: self.end_msg(kw['errmsg'], 'YELLOW', **kw) self.fatal('The configuration failed %r' % ret) else: self.end_msg(self.ret_msg(kw['okmsg'], kw), **kw) return ret kupfer-328/waflib/Context.py000077500000000000000000000514041500175051100161300ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010-2018 (ita) """ Classes and functions enabling the command system """ import os, re, sys from waflib import Utils, Errors, Logs import waflib.Node if sys.hexversion > 0x3040000: import types class imp(object): new_module = lambda x: types.ModuleType(x) else: import imp # the following 3 constants are updated on each new release (do not touch) HEXVERSION=0x2001900 """Constant updated on new releases""" WAFVERSION="2.0.25" """Constant updated on new releases""" WAFREVISION="2db0b41b2805cd5db3b55476c06b23c1e46d319f" """Git revision when the waf version is updated""" WAFNAME="waf" """Application name displayed on --help""" ABI = 20 """Version of the build data cache file format (used in :py:const:`waflib.Context.DBFILE`)""" DBFILE = '.wafpickle-%s-%d-%d' % (sys.platform, sys.hexversion, ABI) """Name of the pickle file for storing the build data""" APPNAME = 'APPNAME' """Default application name (used by ``waf dist``)""" VERSION = 'VERSION' """Default application version (used by ``waf dist``)""" TOP = 'top' """The variable name for the top-level directory in wscript files""" OUT = 'out' """The variable name for the output directory in wscript files""" WSCRIPT_FILE = 'wscript' """Name of the waf script files""" launch_dir = '' """Directory from which waf has been called""" run_dir = '' """Location of the wscript file to use as the entry point""" top_dir = '' """Location of the project directory (top), if the project was configured""" out_dir = '' """Location of the build directory (out), if the project was configured""" waf_dir = '' """Directory containing the waf modules""" default_encoding = Utils.console_encoding() """Encoding to use when reading outputs from other processes""" g_module = None """ Module representing the top-level wscript file (see :py:const:`waflib.Context.run_dir`) """ STDOUT = 1 STDERR = -1 BOTH = 0 classes = [] """ List of :py:class:`waflib.Context.Context` subclasses that can be used as waf commands. The classes are added automatically by a metaclass. """ def create_context(cmd_name, *k, **kw): """ Returns a new :py:class:`waflib.Context.Context` instance corresponding to the given command. Used in particular by :py:func:`waflib.Scripting.run_command` :param cmd_name: command name :type cmd_name: string :param k: arguments to give to the context class initializer :type k: list :param k: keyword arguments to give to the context class initializer :type k: dict :return: Context object :rtype: :py:class:`waflib.Context.Context` """ for x in classes: if x.cmd == cmd_name: return x(*k, **kw) ctx = Context(*k, **kw) ctx.fun = cmd_name return ctx class store_context(type): """ Metaclass that registers command classes into the list :py:const:`waflib.Context.classes` Context classes must provide an attribute 'cmd' representing the command name, and a function attribute 'fun' representing the function name that the command uses. """ def __init__(cls, name, bases, dct): super(store_context, cls).__init__(name, bases, dct) name = cls.__name__ if name in ('ctx', 'Context'): return try: cls.cmd except AttributeError: raise Errors.WafError('Missing command for the context class %r (cmd)' % name) if not getattr(cls, 'fun', None): cls.fun = cls.cmd classes.insert(0, cls) ctx = store_context('ctx', (object,), {}) """Base class for all :py:class:`waflib.Context.Context` classes""" class Context(ctx): """ Default context for waf commands, and base class for new command contexts. Context objects are passed to top-level functions:: def foo(ctx): print(ctx.__class__.__name__) # waflib.Context.Context Subclasses must define the class attributes 'cmd' and 'fun': :param cmd: command to execute as in ``waf cmd`` :type cmd: string :param fun: function name to execute when the command is called :type fun: string .. inheritance-diagram:: waflib.Context.Context waflib.Build.BuildContext waflib.Build.InstallContext waflib.Build.UninstallContext waflib.Build.StepContext waflib.Build.ListContext waflib.Configure.ConfigurationContext waflib.Scripting.Dist waflib.Scripting.DistCheck waflib.Build.CleanContext :top-classes: waflib.Context.Context """ errors = Errors """ Shortcut to :py:mod:`waflib.Errors` provided for convenience """ tools = {} """ A module cache for wscript files; see :py:meth:`Context.Context.load` """ def __init__(self, **kw): try: rd = kw['run_dir'] except KeyError: rd = run_dir # binds the context to the nodes in use to avoid a context singleton self.node_class = type('Nod3', (waflib.Node.Node,), {}) self.node_class.__module__ = 'waflib.Node' self.node_class.ctx = self self.root = self.node_class('', None) self.cur_script = None self.path = self.root.find_dir(rd) self.stack_path = [] self.exec_dict = {'ctx':self, 'conf':self, 'bld':self, 'opt':self} self.logger = None def finalize(self): """ Called to free resources such as logger files """ try: logger = self.logger except AttributeError: pass else: Logs.free_logger(logger) delattr(self, 'logger') def load(self, tool_list, *k, **kw): """ Loads a Waf tool as a module, and try calling the function named :py:const:`waflib.Context.Context.fun` from it. A ``tooldir`` argument may be provided as a list of module paths. :param tool_list: list of Waf tool names to load :type tool_list: list of string or space-separated string """ tools = Utils.to_list(tool_list) path = Utils.to_list(kw.get('tooldir', '')) with_sys_path = kw.get('with_sys_path', True) for t in tools: module = load_tool(t, path, with_sys_path=with_sys_path) fun = getattr(module, kw.get('name', self.fun), None) if fun: fun(self) def execute(self): """ Here, it calls the function name in the top-level wscript file. Most subclasses redefine this method to provide additional functionality. """ self.recurse([os.path.dirname(g_module.root_path)]) def pre_recurse(self, node): """ Method executed immediately before a folder is read by :py:meth:`waflib.Context.Context.recurse`. The current script is bound as a Node object on ``self.cur_script``, and the current path is bound to ``self.path`` :param node: script :type node: :py:class:`waflib.Node.Node` """ self.stack_path.append(self.cur_script) self.cur_script = node self.path = node.parent def post_recurse(self, node): """ Restores ``self.cur_script`` and ``self.path`` right after :py:meth:`waflib.Context.Context.recurse` terminates. :param node: script :type node: :py:class:`waflib.Node.Node` """ self.cur_script = self.stack_path.pop() if self.cur_script: self.path = self.cur_script.parent def recurse(self, dirs, name=None, mandatory=True, once=True, encoding=None): """ Runs user-provided functions from the supplied list of directories. The directories can be either absolute, or relative to the directory of the wscript file The methods :py:meth:`waflib.Context.Context.pre_recurse` and :py:meth:`waflib.Context.Context.post_recurse` are called immediately before and after a script has been executed. :param dirs: List of directories to visit :type dirs: list of string or space-separated string :param name: Name of function to invoke from the wscript :type name: string :param mandatory: whether sub wscript files are required to exist :type mandatory: bool :param once: read the script file once for a particular context :type once: bool """ try: cache = self.recurse_cache except AttributeError: cache = self.recurse_cache = {} for d in Utils.to_list(dirs): if not os.path.isabs(d): # absolute paths only d = os.path.join(self.path.abspath(), d) WSCRIPT = os.path.join(d, WSCRIPT_FILE) WSCRIPT_FUN = WSCRIPT + '_' + (name or self.fun) node = self.root.find_node(WSCRIPT_FUN) if node and (not once or node not in cache): cache[node] = True self.pre_recurse(node) try: function_code = node.read('r', encoding) exec(compile(function_code, node.abspath(), 'exec'), self.exec_dict) finally: self.post_recurse(node) elif not node: node = self.root.find_node(WSCRIPT) tup = (node, name or self.fun) if node and (not once or tup not in cache): cache[tup] = True self.pre_recurse(node) try: wscript_module = load_module(node.abspath(), encoding=encoding) user_function = getattr(wscript_module, (name or self.fun), None) if not user_function: if not mandatory: continue raise Errors.WafError('No function %r defined in %s' % (name or self.fun, node.abspath())) user_function(self) finally: self.post_recurse(node) elif not node: if not mandatory: continue try: os.listdir(d) except OSError: raise Errors.WafError('Cannot read the folder %r' % d) raise Errors.WafError('No wscript file in directory %s' % d) def log_command(self, cmd, kw): if Logs.verbose: fmt = os.environ.get('WAF_CMD_FORMAT') if fmt == 'string': if not isinstance(cmd, str): cmd = Utils.shell_escape(cmd) Logs.debug('runner: %r', cmd) Logs.debug('runner_env: kw=%s', kw) def exec_command(self, cmd, **kw): """ Runs an external process and returns the exit status:: def run(tsk): ret = tsk.generator.bld.exec_command('touch foo.txt') return ret If the context has the attribute 'log', then captures and logs the process stderr/stdout. Unlike :py:meth:`waflib.Context.Context.cmd_and_log`, this method does not return the stdout/stderr values captured. :param cmd: command argument for subprocess.Popen :type cmd: string or list :param kw: keyword arguments for subprocess.Popen. The parameters input/timeout will be passed to wait/communicate. :type kw: dict :returns: process exit status :rtype: integer :raises: :py:class:`waflib.Errors.WafError` if an invalid executable is specified for a non-shell process :raises: :py:class:`waflib.Errors.WafError` in case of execution failure """ subprocess = Utils.subprocess kw['shell'] = isinstance(cmd, str) self.log_command(cmd, kw) if self.logger: self.logger.info(cmd) if 'stdout' not in kw: kw['stdout'] = subprocess.PIPE if 'stderr' not in kw: kw['stderr'] = subprocess.PIPE if Logs.verbose and not kw['shell'] and not Utils.check_exe(cmd[0]): raise Errors.WafError('Program %s not found!' % cmd[0]) cargs = {} if 'timeout' in kw: if sys.hexversion >= 0x3030000: cargs['timeout'] = kw['timeout'] if not 'start_new_session' in kw: kw['start_new_session'] = True del kw['timeout'] if 'input' in kw: if kw['input']: cargs['input'] = kw['input'] kw['stdin'] = subprocess.PIPE del kw['input'] if 'cwd' in kw: if not isinstance(kw['cwd'], str): kw['cwd'] = kw['cwd'].abspath() encoding = kw.pop('decode_as', default_encoding) try: ret, out, err = Utils.run_process(cmd, kw, cargs) except Exception as e: raise Errors.WafError('Execution failure: %s' % str(e), ex=e) if out: if not isinstance(out, str): out = out.decode(encoding, errors='replace') if self.logger: self.logger.debug('out: %s', out) else: Logs.info(out, extra={'stream':sys.stdout, 'c1': ''}) if err: if not isinstance(err, str): err = err.decode(encoding, errors='replace') if self.logger: self.logger.error('err: %s' % err) else: Logs.info(err, extra={'stream':sys.stderr, 'c1': ''}) return ret def cmd_and_log(self, cmd, **kw): """ Executes a process and returns stdout/stderr if the execution is successful. An exception is thrown when the exit status is non-0. In that case, both stderr and stdout will be bound to the WafError object (configuration tests):: def configure(conf): out = conf.cmd_and_log(['echo', 'hello'], output=waflib.Context.STDOUT, quiet=waflib.Context.BOTH) (out, err) = conf.cmd_and_log(['echo', 'hello'], output=waflib.Context.BOTH) (out, err) = conf.cmd_and_log(cmd, input='\\n'.encode(), output=waflib.Context.STDOUT) try: conf.cmd_and_log(['which', 'someapp'], output=waflib.Context.BOTH) except Errors.WafError as e: print(e.stdout, e.stderr) :param cmd: args for subprocess.Popen :type cmd: list or string :param kw: keyword arguments for subprocess.Popen. The parameters input/timeout will be passed to wait/communicate. :type kw: dict :returns: a tuple containing the contents of stdout and stderr :rtype: string :raises: :py:class:`waflib.Errors.WafError` if an invalid executable is specified for a non-shell process :raises: :py:class:`waflib.Errors.WafError` in case of execution failure; stdout/stderr/returncode are bound to the exception object """ subprocess = Utils.subprocess kw['shell'] = isinstance(cmd, str) self.log_command(cmd, kw) quiet = kw.pop('quiet', None) to_ret = kw.pop('output', STDOUT) if Logs.verbose and not kw['shell'] and not Utils.check_exe(cmd[0]): raise Errors.WafError('Program %r not found!' % cmd[0]) kw['stdout'] = kw['stderr'] = subprocess.PIPE if quiet is None: self.to_log(cmd) cargs = {} if 'timeout' in kw: if sys.hexversion >= 0x3030000: cargs['timeout'] = kw['timeout'] if not 'start_new_session' in kw: kw['start_new_session'] = True del kw['timeout'] if 'input' in kw: if kw['input']: cargs['input'] = kw['input'] kw['stdin'] = subprocess.PIPE del kw['input'] if 'cwd' in kw: if not isinstance(kw['cwd'], str): kw['cwd'] = kw['cwd'].abspath() encoding = kw.pop('decode_as', default_encoding) try: ret, out, err = Utils.run_process(cmd, kw, cargs) except Exception as e: raise Errors.WafError('Execution failure: %s' % str(e), ex=e) if not isinstance(out, str): out = out.decode(encoding, errors='replace') if not isinstance(err, str): err = err.decode(encoding, errors='replace') if out and quiet != STDOUT and quiet != BOTH: self.to_log('out: %s' % out) if err and quiet != STDERR and quiet != BOTH: self.to_log('err: %s' % err) if ret: e = Errors.WafError('Command %r returned %r' % (cmd, ret)) e.returncode = ret e.stderr = err e.stdout = out raise e if to_ret == BOTH: return (out, err) elif to_ret == STDERR: return err return out def fatal(self, msg, ex=None): """ Prints an error message in red and stops command execution; this is usually used in the configuration section:: def configure(conf): conf.fatal('a requirement is missing') :param msg: message to display :type msg: string :param ex: optional exception object :type ex: exception :raises: :py:class:`waflib.Errors.ConfigurationError` """ if self.logger: self.logger.info('from %s: %s' % (self.path.abspath(), msg)) try: logfile = self.logger.handlers[0].baseFilename except AttributeError: pass else: if os.environ.get('WAF_PRINT_FAILURE_LOG'): # see #1930 msg = 'Log from (%s):\n%s\n' % (logfile, Utils.readf(logfile)) else: msg = '%s\n(complete log in %s)' % (msg, logfile) raise self.errors.ConfigurationError(msg, ex=ex) def to_log(self, msg): """ Logs information to the logger (if present), or to stderr. Empty messages are not printed:: def build(bld): bld.to_log('starting the build') Provide a logger on the context class or override this method if necessary. :param msg: message :type msg: string """ if not msg: return if self.logger: self.logger.info(msg) else: sys.stderr.write(str(msg)) sys.stderr.flush() def msg(self, *k, **kw): """ Prints a configuration message of the form ``msg: result``. The second part of the message will be in colors. The output can be disabled easily by setting ``in_msg`` to a positive value:: def configure(conf): self.in_msg = 1 conf.msg('Checking for library foo', 'ok') # no output :param msg: message to display to the user :type msg: string :param result: result to display :type result: string or boolean :param color: color to use, see :py:const:`waflib.Logs.colors_lst` :type color: string """ try: msg = kw['msg'] except KeyError: msg = k[0] self.start_msg(msg, **kw) try: result = kw['result'] except KeyError: result = k[1] color = kw.get('color') if not isinstance(color, str): color = result and 'GREEN' or 'YELLOW' self.end_msg(result, color, **kw) def start_msg(self, *k, **kw): """ Prints the beginning of a 'Checking for xxx' message. See :py:meth:`waflib.Context.Context.msg` """ if kw.get('quiet'): return msg = kw.get('msg') or k[0] try: if self.in_msg: self.in_msg += 1 return except AttributeError: self.in_msg = 0 self.in_msg += 1 try: self.line_just = max(self.line_just, len(msg)) except AttributeError: self.line_just = max(40, len(msg)) for x in (self.line_just * '-', msg): self.to_log(x) Logs.pprint('NORMAL', "%s :" % msg.ljust(self.line_just), sep='') def end_msg(self, *k, **kw): """Prints the end of a 'Checking for' message. See :py:meth:`waflib.Context.Context.msg`""" if kw.get('quiet'): return self.in_msg -= 1 if self.in_msg: return result = kw.get('result') or k[0] defcolor = 'GREEN' if result is True: msg = 'ok' elif not result: msg = 'not found' defcolor = 'YELLOW' else: msg = str(result) self.to_log(msg) try: color = kw['color'] except KeyError: if len(k) > 1 and k[1] in Logs.colors_lst: # compatibility waf 1.7 color = k[1] else: color = defcolor Logs.pprint(color, msg) def load_special_tools(self, var, ban=[]): """ Loads third-party extensions modules for certain programming languages by trying to list certain files in the extras/ directory. This method is typically called once for a programming language group, see for example :py:mod:`waflib.Tools.compiler_c` :param var: glob expression, for example 'cxx\\_\\*.py' :type var: string :param ban: list of exact file names to exclude :type ban: list of string """ if os.path.isdir(waf_dir): lst = self.root.find_node(waf_dir).find_node('waflib/extras').ant_glob(var) for x in lst: if not x.name in ban: load_tool(x.name.replace('.py', '')) else: from zipfile import PyZipFile waflibs = PyZipFile(waf_dir) lst = waflibs.namelist() for x in lst: if not re.match('waflib/extras/%s' % var.replace('*', '.*'), var): continue f = os.path.basename(x) doban = False for b in ban: r = b.replace('*', '.*') if re.match(r, f): doban = True if not doban: f = f.replace('.py', '') load_tool(f) cache_modules = {} """ Dictionary holding already loaded modules (wscript), indexed by their absolute path. The modules are added automatically by :py:func:`waflib.Context.load_module` """ def load_module(path, encoding=None): """ Loads a wscript file as a python module. This method caches results in :py:attr:`waflib.Context.cache_modules` :param path: file path :type path: string :return: Loaded Python module :rtype: module """ try: return cache_modules[path] except KeyError: pass module = imp.new_module(WSCRIPT_FILE) try: code = Utils.readf(path, m='r', encoding=encoding) except EnvironmentError: raise Errors.WafError('Could not read the file %r' % path) module_dir = os.path.dirname(path) sys.path.insert(0, module_dir) try: exec(compile(code, path, 'exec'), module.__dict__) finally: sys.path.remove(module_dir) cache_modules[path] = module return module def load_tool(tool, tooldir=None, ctx=None, with_sys_path=True): """ Imports a Waf tool as a python module, and stores it in the dict :py:const:`waflib.Context.Context.tools` :type tool: string :param tool: Name of the tool :type tooldir: list :param tooldir: List of directories to search for the tool module :type with_sys_path: boolean :param with_sys_path: whether or not to search the regular sys.path, besides waf_dir and potentially given tooldirs """ if tool == 'java': tool = 'javaw' # jython else: tool = tool.replace('++', 'xx') if not with_sys_path: back_path = sys.path sys.path = [] try: if tooldir: assert isinstance(tooldir, list) sys.path = tooldir + sys.path try: __import__(tool) except ImportError as e: e.waf_sys_path = list(sys.path) raise finally: for d in tooldir: sys.path.remove(d) ret = sys.modules[tool] Context.tools[tool] = ret return ret else: if not with_sys_path: sys.path.insert(0, waf_dir) try: for x in ('waflib.Tools.%s', 'waflib.extras.%s', 'waflib.%s', '%s'): try: __import__(x % tool) break except ImportError: x = None else: # raise an exception __import__(tool) except ImportError as e: e.waf_sys_path = list(sys.path) raise finally: if not with_sys_path: sys.path.remove(waf_dir) ret = sys.modules[x % tool] Context.tools[tool] = ret return ret finally: if not with_sys_path: sys.path += back_path kupfer-328/waflib/Errors.py000066400000000000000000000032611500175051100157530ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010-2018 (ita) """ Exceptions used in the Waf code """ import traceback, sys class WafError(Exception): """Base class for all Waf errors""" def __init__(self, msg='', ex=None): """ :param msg: error message :type msg: string :param ex: exception causing this error (optional) :type ex: exception """ Exception.__init__(self) self.msg = msg assert not isinstance(msg, Exception) self.stack = [] if ex: if not msg: self.msg = str(ex) if isinstance(ex, WafError): self.stack = ex.stack else: self.stack = traceback.extract_tb(sys.exc_info()[2]) self.stack += traceback.extract_stack()[:-1] self.verbose_msg = ''.join(traceback.format_list(self.stack)) def __str__(self): return str(self.msg) class BuildError(WafError): """Error raised during the build and install phases""" def __init__(self, error_tasks=[]): """ :param error_tasks: tasks that could not complete normally :type error_tasks: list of task objects """ self.tasks = error_tasks WafError.__init__(self, self.format_error()) def format_error(self): """Formats the error messages from the tasks that failed""" lst = ['Build failed'] for tsk in self.tasks: txt = tsk.format_error() if txt: lst.append(txt) return '\n'.join(lst) class ConfigurationError(WafError): """Configuration exception raised in particular by :py:meth:`waflib.Context.Context.fatal`""" pass class TaskRescan(WafError): """Task-specific exception type signalling required signature recalculations""" pass class TaskNotReady(WafError): """Task-specific exception type signalling that task signatures cannot be computed""" pass kupfer-328/waflib/Logs.py000066400000000000000000000230331500175051100154020ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2018 (ita) """ logging, colors, terminal width and pretty-print """ import os, re, traceback, sys from waflib import Utils, ansiterm if not os.environ.get('NOSYNC', False): # synchronized output is nearly mandatory to prevent garbled output if sys.stdout.isatty() and id(sys.stdout) == id(sys.__stdout__): sys.stdout = ansiterm.AnsiTerm(sys.stdout) if sys.stderr.isatty() and id(sys.stderr) == id(sys.__stderr__): sys.stderr = ansiterm.AnsiTerm(sys.stderr) # import the logging module after since it holds a reference on sys.stderr # in case someone uses the root logger import logging LOG_FORMAT = os.environ.get('WAF_LOG_FORMAT', '%(asctime)s %(c1)s%(zone)s%(c2)s %(message)s') HOUR_FORMAT = os.environ.get('WAF_HOUR_FORMAT', '%H:%M:%S') zones = [] """ See :py:class:`waflib.Logs.log_filter` """ verbose = 0 """ Global verbosity level, see :py:func:`waflib.Logs.debug` and :py:func:`waflib.Logs.error` """ colors_lst = { 'USE' : True, 'BOLD' :'\x1b[01;1m', 'RED' :'\x1b[01;31m', 'GREEN' :'\x1b[32m', 'YELLOW':'\x1b[33m', 'PINK' :'\x1b[35m', 'BLUE' :'\x1b[01;34m', 'CYAN' :'\x1b[36m', 'GREY' :'\x1b[37m', 'NORMAL':'\x1b[0m', 'cursor_on' :'\x1b[?25h', 'cursor_off' :'\x1b[?25l', } indicator = '\r\x1b[K%s%s%s' try: unicode except NameError: unicode = None def enable_colors(use): """ If *1* is given, then the system will perform a few verifications before enabling colors, such as checking whether the interpreter is running in a terminal. A value of zero will disable colors, and a value above *1* will force colors. :param use: whether to enable colors or not :type use: integer """ if use == 1: if not (sys.stderr.isatty() or sys.stdout.isatty()): use = 0 if Utils.is_win32 and os.name != 'java': term = os.environ.get('TERM', '') # has ansiterm else: term = os.environ.get('TERM', 'dumb') if term in ('dumb', 'emacs'): use = 0 if use >= 1: os.environ['TERM'] = 'vt100' colors_lst['USE'] = use # If console packages are available, replace the dummy function with a real # implementation try: get_term_cols = ansiterm.get_term_cols except AttributeError: def get_term_cols(): return 80 get_term_cols.__doc__ = """ Returns the console width in characters. :return: the number of characters per line :rtype: int """ def get_color(cl): """ Returns the ansi sequence corresponding to the given color name. An empty string is returned when coloring is globally disabled. :param cl: color name in capital letters :type cl: string """ if colors_lst['USE']: return colors_lst.get(cl, '') return '' class color_dict(object): """attribute-based color access, eg: colors.PINK""" def __getattr__(self, a): return get_color(a) def __call__(self, a): return get_color(a) colors = color_dict() re_log = re.compile(r'(\w+): (.*)', re.M) class log_filter(logging.Filter): """ Waf logs are of the form 'name: message', and can be filtered by 'waf --zones=name'. For example, the following:: from waflib import Logs Logs.debug('test: here is a message') Will be displayed only when executing:: $ waf --zones=test """ def __init__(self, name=''): logging.Filter.__init__(self, name) def filter(self, rec): """ Filters log records by zone and by logging level :param rec: log entry """ rec.zone = rec.module if rec.levelno >= logging.INFO: return True m = re_log.match(rec.msg) if m: rec.zone = m.group(1) rec.msg = m.group(2) if zones: return getattr(rec, 'zone', '') in zones or '*' in zones elif not verbose > 2: return False return True class log_handler(logging.StreamHandler): """Dispatches messages to stderr/stdout depending on the severity level""" def emit(self, record): """ Delegates the functionality to :py:meth:`waflib.Log.log_handler.emit_override` """ # default implementation try: try: self.stream = record.stream except AttributeError: if record.levelno >= logging.WARNING: record.stream = self.stream = sys.stderr else: record.stream = self.stream = sys.stdout self.emit_override(record) self.flush() except (KeyboardInterrupt, SystemExit): raise except: # from the python library -_- self.handleError(record) def emit_override(self, record, **kw): """ Writes the log record to the desired stream (stderr/stdout) """ self.terminator = getattr(record, 'terminator', '\n') stream = self.stream if unicode: # python2 msg = self.formatter.format(record) fs = '%s' + self.terminator try: if (isinstance(msg, unicode) and getattr(stream, 'encoding', None)): fs = fs.decode(stream.encoding) try: stream.write(fs % msg) except UnicodeEncodeError: stream.write((fs % msg).encode(stream.encoding)) else: stream.write(fs % msg) except UnicodeError: stream.write((fs % msg).encode('utf-8')) else: logging.StreamHandler.emit(self, record) class formatter(logging.Formatter): """Simple log formatter which handles colors""" def __init__(self): logging.Formatter.__init__(self, LOG_FORMAT, HOUR_FORMAT) def format(self, rec): """ Formats records and adds colors as needed. The records do not get a leading hour format if the logging level is above *INFO*. """ try: msg = rec.msg.decode('utf-8') except Exception: msg = rec.msg use = colors_lst['USE'] if (use == 1 and rec.stream.isatty()) or use == 2: c1 = getattr(rec, 'c1', None) if c1 is None: c1 = '' if rec.levelno >= logging.ERROR: c1 = colors.RED elif rec.levelno >= logging.WARNING: c1 = colors.YELLOW elif rec.levelno >= logging.INFO: c1 = colors.GREEN c2 = getattr(rec, 'c2', colors.NORMAL) msg = '%s%s%s' % (c1, msg, c2) else: # remove single \r that make long lines in text files # and other terminal commands msg = re.sub(r'\r(?!\n)|\x1B\[(K|.*?(m|h|l))', '', msg) if rec.levelno >= logging.INFO: # the goal of this is to format without the leading "Logs, hour" prefix if rec.args: try: return msg % rec.args except UnicodeDecodeError: return msg.encode('utf-8') % rec.args return msg rec.msg = msg rec.c1 = colors.PINK rec.c2 = colors.NORMAL return logging.Formatter.format(self, rec) log = None """global logger for Logs.debug, Logs.error, etc""" def debug(*k, **kw): """ Wraps logging.debug and discards messages if the verbosity level :py:attr:`waflib.Logs.verbose` ≤ 0 """ if verbose: k = list(k) k[0] = k[0].replace('\n', ' ') log.debug(*k, **kw) def error(*k, **kw): """ Wrap logging.errors, adds the stack trace when the verbosity level :py:attr:`waflib.Logs.verbose` ≥ 2 """ log.error(*k, **kw) if verbose > 2: st = traceback.extract_stack() if st: st = st[:-1] buf = [] for filename, lineno, name, line in st: buf.append(' File %r, line %d, in %s' % (filename, lineno, name)) if line: buf.append(' %s' % line.strip()) if buf: log.error('\n'.join(buf)) def warn(*k, **kw): """ Wraps logging.warning """ log.warning(*k, **kw) def info(*k, **kw): """ Wraps logging.info """ log.info(*k, **kw) def init_log(): """ Initializes the logger :py:attr:`waflib.Logs.log` """ global log log = logging.getLogger('waflib') log.handlers = [] log.filters = [] hdlr = log_handler() hdlr.setFormatter(formatter()) log.addHandler(hdlr) log.addFilter(log_filter()) log.setLevel(logging.DEBUG) def make_logger(path, name): """ Creates a simple logger, which is often used to redirect the context command output:: from waflib import Logs bld.logger = Logs.make_logger('test.log', 'build') bld.check(header_name='sadlib.h', features='cxx cprogram', mandatory=False) # have the file closed immediately Logs.free_logger(bld.logger) # stop logging bld.logger = None The method finalize() of the command will try to free the logger, if any :param path: file name to write the log output to :type path: string :param name: logger name (loggers are reused) :type name: string """ logger = logging.getLogger(name) if sys.hexversion > 0x3000000: encoding = sys.stdout.encoding else: encoding = None hdlr = logging.FileHandler(path, 'w', encoding=encoding) formatter = logging.Formatter('%(message)s') hdlr.setFormatter(formatter) logger.addHandler(hdlr) logger.setLevel(logging.DEBUG) return logger def make_mem_logger(name, to_log, size=8192): """ Creates a memory logger to avoid writing concurrently to the main logger """ from logging.handlers import MemoryHandler logger = logging.getLogger(name) hdlr = MemoryHandler(size, target=to_log) formatter = logging.Formatter('%(message)s') hdlr.setFormatter(formatter) logger.addHandler(hdlr) logger.memhandler = hdlr logger.setLevel(logging.DEBUG) return logger def free_logger(logger): """ Frees the resources held by the loggers created through make_logger or make_mem_logger. This is used for file cleanup and for handler removal (logger objects are re-used). """ try: for x in logger.handlers: x.close() logger.removeHandler(x) except Exception: pass def pprint(col, msg, label='', sep='\n'): """ Prints messages in color immediately on stderr:: from waflib import Logs Logs.pprint('RED', 'Something bad just happened') :param col: color name to use in :py:const:`Logs.colors_lst` :type col: string :param msg: message to display :type msg: string or a value that can be printed by %s :param label: a message to add after the colored output :type label: string :param sep: a string to append at the end (line separator) :type sep: string """ info('%s%s%s %s', colors(col), msg, colors.NORMAL, label, extra={'terminator':sep}) kupfer-328/waflib/Node.py000066400000000000000000000616251500175051100153740ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2018 (ita) """ Node: filesystem structure #. Each file/folder is represented by exactly one node. #. Some potential class properties are stored on :py:class:`waflib.Build.BuildContext` : nodes to depend on, etc. Unused class members can increase the `.wafpickle` file size sensibly. #. Node objects should never be created directly, use the methods :py:func:`Node.make_node` or :py:func:`Node.find_node` for the low-level operations #. The methods :py:func:`Node.find_resource`, :py:func:`Node.find_dir` :py:func:`Node.find_or_declare` must be used when a build context is present #. Each instance of :py:class:`waflib.Context.Context` has a unique :py:class:`Node` subclass required for serialization. (:py:class:`waflib.Node.Nod3`, see the :py:class:`waflib.Context.Context` initializer). A reference to the context owning a node is held as *self.ctx* """ import os, re, sys, shutil from waflib import Utils, Errors exclude_regs = ''' **/*~ **/#*# **/.#* **/%*% **/._* **/*.swp **/CVS **/CVS/** **/.cvsignore **/SCCS **/SCCS/** **/vssver.scc **/.svn **/.svn/** **/BitKeeper **/.git **/.git/** **/.gitignore **/.bzr **/.bzrignore **/.bzr/** **/.hg **/.hg/** **/_MTN **/_MTN/** **/.arch-ids **/{arch} **/_darcs **/_darcs/** **/.intlcache **/.DS_Store''' """ Ant patterns for files and folders to exclude while doing the recursive traversal in :py:meth:`waflib.Node.Node.ant_glob` """ def ant_matcher(s, ignorecase): reflags = re.I if ignorecase else 0 ret = [] for x in Utils.to_list(s): x = x.replace('\\', '/').replace('//', '/') if x.endswith('/'): x += '**' accu = [] for k in x.split('/'): if k == '**': accu.append(k) else: k = k.replace('.', '[.]').replace('*', '.*').replace('?', '.').replace('+', '\\+') k = '^%s$' % k try: exp = re.compile(k, flags=reflags) except Exception as e: raise Errors.WafError('Invalid pattern: %s' % k, e) else: accu.append(exp) ret.append(accu) return ret def ant_sub_filter(name, nn): ret = [] for lst in nn: if not lst: pass elif lst[0] == '**': ret.append(lst) if len(lst) > 1: if lst[1].match(name): ret.append(lst[2:]) else: ret.append([]) elif lst[0].match(name): ret.append(lst[1:]) return ret def ant_sub_matcher(name, pats): nacc = ant_sub_filter(name, pats[0]) nrej = ant_sub_filter(name, pats[1]) if [] in nrej: nacc = [] return [nacc, nrej] class Node(object): """ This class is organized in two parts: * The basic methods meant for filesystem access (compute paths, create folders, etc) * The methods bound to a :py:class:`waflib.Build.BuildContext` (require ``bld.srcnode`` and ``bld.bldnode``) """ dict_class = dict """ Subclasses can provide a dict class to enable case insensitivity for example. """ __slots__ = ('name', 'parent', 'children', 'cache_abspath', 'cache_isdir') def __init__(self, name, parent): """ .. note:: Use :py:func:`Node.make_node` or :py:func:`Node.find_node` instead of calling this constructor """ self.name = name self.parent = parent if parent: if name in parent.children: raise Errors.WafError('node %s exists in the parent files %r already' % (name, parent)) parent.children[name] = self def __setstate__(self, data): "Deserializes node information, used for persistence" self.name = data[0] self.parent = data[1] if data[2] is not None: # Issue 1480 self.children = self.dict_class(data[2]) def __getstate__(self): "Serializes node information, used for persistence" return (self.name, self.parent, getattr(self, 'children', None)) def __str__(self): """ String representation (abspath), for debugging purposes :rtype: string """ return self.abspath() def __repr__(self): """ String representation (abspath), for debugging purposes :rtype: string """ return self.abspath() def __copy__(self): """ Provided to prevent nodes from being copied :raises: :py:class:`waflib.Errors.WafError` """ raise Errors.WafError('nodes are not supposed to be copied') def read(self, flags='r', encoding='latin-1'): """ Reads and returns the contents of the file represented by this node, see :py:func:`waflib.Utils.readf`:: def build(bld): bld.path.find_node('wscript').read() :param flags: Open mode :type flags: string :param encoding: encoding value for Python3 :type encoding: string :rtype: string or bytes :return: File contents """ return Utils.readf(self.abspath(), flags, encoding) def write(self, data, flags='w', encoding='latin-1'): """ Writes data to the file represented by this node, see :py:func:`waflib.Utils.writef`:: def build(bld): bld.path.make_node('foo.txt').write('Hello, world!') :param data: data to write :type data: string :param flags: Write mode :type flags: string :param encoding: encoding value for Python3 :type encoding: string """ Utils.writef(self.abspath(), data, flags, encoding) def read_json(self, convert=True, encoding='utf-8'): """ Reads and parses the contents of this node as JSON (Python ≥ 2.6):: def build(bld): bld.path.find_node('abc.json').read_json() Note that this by default automatically decodes unicode strings on Python2, unlike what the Python JSON module does. :type convert: boolean :param convert: Prevents decoding of unicode strings on Python2 :type encoding: string :param encoding: The encoding of the file to read. This default to UTF8 as per the JSON standard :rtype: object :return: Parsed file contents """ import json # Python 2.6 and up object_pairs_hook = None if convert and sys.hexversion < 0x3000000: try: _type = unicode except NameError: _type = str def convert(value): if isinstance(value, list): return [convert(element) for element in value] elif isinstance(value, _type): return str(value) else: return value def object_pairs(pairs): return dict((str(pair[0]), convert(pair[1])) for pair in pairs) object_pairs_hook = object_pairs return json.loads(self.read(encoding=encoding), object_pairs_hook=object_pairs_hook) def write_json(self, data, pretty=True): """ Writes a python object as JSON to disk (Python ≥ 2.6) as UTF-8 data (JSON standard):: def build(bld): bld.path.find_node('xyz.json').write_json(199) :type data: object :param data: The data to write to disk :type pretty: boolean :param pretty: Determines if the JSON will be nicely space separated """ import json # Python 2.6 and up indent = 2 separators = (',', ': ') sort_keys = pretty newline = os.linesep if not pretty: indent = None separators = (',', ':') newline = '' output = json.dumps(data, indent=indent, separators=separators, sort_keys=sort_keys) + newline self.write(output, encoding='utf-8') def exists(self): """ Returns whether the Node is present on the filesystem :rtype: bool """ return os.path.exists(self.abspath()) def isdir(self): """ Returns whether the Node represents a folder :rtype: bool """ return os.path.isdir(self.abspath()) def chmod(self, val): """ Changes the file/dir permissions:: def build(bld): bld.path.chmod(493) # 0755 """ os.chmod(self.abspath(), val) def delete(self, evict=True): """ Removes the file/folder from the filesystem (equivalent to `rm -rf`), and remove this object from the Node tree. Do not use this object after calling this method. """ try: try: if os.path.isdir(self.abspath()): shutil.rmtree(self.abspath()) else: os.remove(self.abspath()) except OSError: if os.path.exists(self.abspath()): raise finally: if evict: self.evict() def evict(self): """ Removes this node from the Node tree """ del self.parent.children[self.name] def suffix(self): """ Returns the file rightmost extension, for example `a.b.c.d → .d` :rtype: string """ k = max(0, self.name.rfind('.')) return self.name[k:] def height(self): """ Returns the depth in the folder hierarchy from the filesystem root or from all the file drives :returns: filesystem depth :rtype: integer """ d = self val = -1 while d: d = d.parent val += 1 return val def listdir(self): """ Lists the folder contents :returns: list of file/folder names ordered alphabetically :rtype: list of string """ lst = Utils.listdir(self.abspath()) lst.sort() return lst def mkdir(self): """ Creates a folder represented by this node. Intermediate folders are created as needed. :raises: :py:class:`waflib.Errors.WafError` when the folder is missing """ if self.isdir(): return try: self.parent.mkdir() except OSError: pass if self.name: try: os.makedirs(self.abspath()) except OSError: pass if not self.isdir(): raise Errors.WafError('Could not create the directory %r' % self) try: self.children except AttributeError: self.children = self.dict_class() def find_node(self, lst): """ Finds a node on the file system (files or folders), and creates the corresponding Node objects if it exists :param lst: relative path :type lst: string or list of string :returns: The corresponding Node object or None if no entry was found on the filesystem :rtype: :py:class:´waflib.Node.Node´ """ if isinstance(lst, str): lst = [x for x in Utils.split_path(lst) if x and x != '.'] if lst and lst[0].startswith('\\\\') and not self.parent: node = self.ctx.root.make_node(lst[0]) node.cache_isdir = True return node.find_node(lst[1:]) cur = self for x in lst: if x == '..': cur = cur.parent or cur continue try: ch = cur.children except AttributeError: cur.children = self.dict_class() else: try: cur = ch[x] continue except KeyError: pass # optimistic: create the node first then look if it was correct to do so cur = self.__class__(x, cur) if not cur.exists(): cur.evict() return None if not cur.exists(): cur.evict() return None return cur def make_node(self, lst): """ Returns or creates a Node object corresponding to the input path without considering the filesystem. :param lst: relative path :type lst: string or list of string :rtype: :py:class:´waflib.Node.Node´ """ if isinstance(lst, str): lst = [x for x in Utils.split_path(lst) if x and x != '.'] cur = self for x in lst: if x == '..': cur = cur.parent or cur continue try: cur = cur.children[x] except AttributeError: cur.children = self.dict_class() except KeyError: pass else: continue cur = self.__class__(x, cur) return cur def search_node(self, lst): """ Returns a Node previously defined in the data structure. The filesystem is not considered. :param lst: relative path :type lst: string or list of string :rtype: :py:class:´waflib.Node.Node´ or None if there is no entry in the Node datastructure """ if isinstance(lst, str): lst = [x for x in Utils.split_path(lst) if x and x != '.'] cur = self for x in lst: if x == '..': cur = cur.parent or cur else: try: cur = cur.children[x] except (AttributeError, KeyError): return None return cur def path_from(self, node): """ Path of this node seen from the other:: def build(bld): n1 = bld.path.find_node('foo/bar/xyz.txt') n2 = bld.path.find_node('foo/stuff/') n1.path_from(n2) # '../bar/xyz.txt' :param node: path to use as a reference :type node: :py:class:`waflib.Node.Node` :returns: a relative path or an absolute one if that is better :rtype: string """ c1 = self c2 = node c1h = c1.height() c2h = c2.height() lst = [] up = 0 while c1h > c2h: lst.append(c1.name) c1 = c1.parent c1h -= 1 while c2h > c1h: up += 1 c2 = c2.parent c2h -= 1 while not c1 is c2: lst.append(c1.name) up += 1 c1 = c1.parent c2 = c2.parent if c1.parent: lst.extend(['..'] * up) lst.reverse() return os.sep.join(lst) or '.' else: return self.abspath() def abspath(self): """ Returns the absolute path. A cache is kept in the context as ``cache_node_abspath`` :rtype: string """ try: return self.cache_abspath except AttributeError: pass # think twice before touching this (performance + complexity + correctness) if not self.parent: val = os.sep elif not self.parent.name: val = os.sep + self.name else: val = self.parent.abspath() + os.sep + self.name self.cache_abspath = val return val if Utils.is_win32: def abspath(self): try: return self.cache_abspath except AttributeError: pass if not self.parent: val = '' elif not self.parent.name: val = self.name + os.sep else: val = self.parent.abspath().rstrip(os.sep) + os.sep + self.name self.cache_abspath = val return val def is_child_of(self, node): """ Returns whether the object belongs to a subtree of the input node:: def build(bld): node = bld.path.find_node('wscript') node.is_child_of(bld.path) # True :param node: path to use as a reference :type node: :py:class:`waflib.Node.Node` :rtype: bool """ p = self diff = self.height() - node.height() while diff > 0: diff -= 1 p = p.parent return p is node def ant_iter(self, accept=None, maxdepth=25, pats=[], dir=False, src=True, remove=True, quiet=False): """ Recursive method used by :py:meth:`waflib.Node.ant_glob`. :param accept: function used for accepting/rejecting a node, returns the patterns that can be still accepted in recursion :type accept: function :param maxdepth: maximum depth in the filesystem (25) :type maxdepth: int :param pats: list of patterns to accept and list of patterns to exclude :type pats: tuple :param dir: return folders too (False by default) :type dir: bool :param src: return files (True by default) :type src: bool :param remove: remove files/folders that do not exist (True by default) :type remove: bool :param quiet: disable build directory traversal warnings (verbose mode) :type quiet: bool :returns: A generator object to iterate from :rtype: iterator """ dircont = self.listdir() try: lst = set(self.children.keys()) except AttributeError: self.children = self.dict_class() else: if remove: for x in lst - set(dircont): self.children[x].evict() for name in dircont: npats = accept(name, pats) if npats and npats[0]: accepted = [] in npats[0] node = self.make_node([name]) isdir = node.isdir() if accepted: if isdir: if dir: yield node elif src: yield node if isdir: node.cache_isdir = True if maxdepth: for k in node.ant_iter(accept=accept, maxdepth=maxdepth - 1, pats=npats, dir=dir, src=src, remove=remove, quiet=quiet): yield k def ant_glob(self, *k, **kw): """ Finds files across folders and returns Node objects: * ``**/*`` find all files recursively * ``**/*.class`` find all files ending by .class * ``..`` find files having two dot characters For example:: def configure(cfg): # find all .cpp files cfg.path.ant_glob('**/*.cpp') # find particular files from the root filesystem (can be slow) cfg.root.ant_glob('etc/*.txt') # simple exclusion rule example cfg.path.ant_glob('*.c*', excl=['*.c'], src=True, dir=False) For more information about the patterns, consult http://ant.apache.org/manual/dirtasks.html Please remember that the '..' sequence does not represent the parent directory:: def configure(cfg): cfg.path.ant_glob('../*.h') # incorrect cfg.path.parent.ant_glob('*.h') # correct The Node structure is itself a filesystem cache, so certain precautions must be taken while matching files in the build or installation phases. Nodes objects that do have a corresponding file or folder are garbage-collected by default. This garbage collection is usually required to prevent returning files that do not exist anymore. Yet, this may also remove Node objects of files that are yet-to-be built. This typically happens when trying to match files in the build directory, but there are also cases when files are created in the source directory. Run ``waf -v`` to display any warnings, and try consider passing ``remove=False`` when matching files in the build directory. Since ant_glob can traverse both source and build folders, it is a best practice to call this method only from the most specific build node:: def build(bld): # traverses the build directory, may need ``remove=False``: bld.path.ant_glob('project/dir/**/*.h') # better, no accidental build directory traversal: bld.path.find_node('project/dir').ant_glob('**/*.h') # best In addition, files and folders are listed immediately. When matching files in the build folders, consider passing ``generator=True`` so that the generator object returned can defer computation to a later stage. For example:: def build(bld): bld(rule='tar xvf ${SRC}', source='arch.tar') bld.add_group() gen = bld.bldnode.ant_glob("*.h", generator=True, remove=True) # files will be listed only after the arch.tar is unpacked bld(rule='ls ${SRC}', source=gen, name='XYZ') :param incl: ant patterns or list of patterns to include :type incl: string or list of strings :param excl: ant patterns or list of patterns to exclude :type excl: string or list of strings :param dir: return folders too (False by default) :type dir: bool :param src: return files (True by default) :type src: bool :param maxdepth: maximum depth of recursion :type maxdepth: int :param ignorecase: ignore case while matching (False by default) :type ignorecase: bool :param generator: Whether to evaluate the Nodes lazily :type generator: bool :param remove: remove files/folders that do not exist (True by default) :type remove: bool :param quiet: disable build directory traversal warnings (verbose mode) :type quiet: bool :returns: The corresponding Node objects as a list or as a generator object (generator=True) :rtype: by default, list of :py:class:`waflib.Node.Node` instances """ src = kw.get('src', True) dir = kw.get('dir') excl = kw.get('excl', exclude_regs) incl = k and k[0] or kw.get('incl', '**') remove = kw.get('remove', True) maxdepth = kw.get('maxdepth', 25) ignorecase = kw.get('ignorecase', False) quiet = kw.get('quiet', False) pats = (ant_matcher(incl, ignorecase), ant_matcher(excl, ignorecase)) if kw.get('generator'): return Utils.lazy_generator(self.ant_iter, (ant_sub_matcher, maxdepth, pats, dir, src, remove, quiet)) it = self.ant_iter(ant_sub_matcher, maxdepth, pats, dir, src, remove, quiet) if kw.get('flat'): # returns relative paths as a space-delimited string # prefer Node objects whenever possible return ' '.join(x.path_from(self) for x in it) return list(it) # ---------------------------------------------------------------------------- # the methods below require the source/build folders (bld.srcnode/bld.bldnode) def is_src(self): """ Returns True if the node is below the source directory. Note that ``!is_src() ≠ is_bld()`` :rtype: bool """ cur = self x = self.ctx.srcnode y = self.ctx.bldnode while cur.parent: if cur is y: return False if cur is x: return True cur = cur.parent return False def is_bld(self): """ Returns True if the node is below the build directory. Note that ``!is_bld() ≠ is_src()`` :rtype: bool """ cur = self y = self.ctx.bldnode while cur.parent: if cur is y: return True cur = cur.parent return False def get_src(self): """ Returns the corresponding Node object in the source directory (or self if already under the source directory). Use this method only if the purpose is to create a Node object (this is common with folders but not with files, see ticket 1937) :rtype: :py:class:`waflib.Node.Node` """ cur = self x = self.ctx.srcnode y = self.ctx.bldnode lst = [] while cur.parent: if cur is y: lst.reverse() return x.make_node(lst) if cur is x: return self lst.append(cur.name) cur = cur.parent return self def get_bld(self): """ Return the corresponding Node object in the build directory (or self if already under the build directory). Use this method only if the purpose is to create a Node object (this is common with folders but not with files, see ticket 1937) :rtype: :py:class:`waflib.Node.Node` """ cur = self x = self.ctx.srcnode y = self.ctx.bldnode lst = [] while cur.parent: if cur is y: return self if cur is x: lst.reverse() return self.ctx.bldnode.make_node(lst) lst.append(cur.name) cur = cur.parent # the file is external to the current project, make a fake root in the current build directory lst.reverse() if lst and Utils.is_win32 and len(lst[0]) == 2 and lst[0].endswith(':'): lst[0] = lst[0][0] return self.ctx.bldnode.make_node(['__root__'] + lst) def find_resource(self, lst): """ Use this method in the build phase to find source files corresponding to the relative path given. First it looks up the Node data structure to find any declared Node object in the build directory. If None is found, it then considers the filesystem in the source directory. :param lst: relative path :type lst: string or list of string :returns: the corresponding Node object or None :rtype: :py:class:`waflib.Node.Node` """ if isinstance(lst, str): lst = [x for x in Utils.split_path(lst) if x and x != '.'] node = self.get_bld().search_node(lst) if not node: node = self.get_src().find_node(lst) if node and node.isdir(): return None return node def find_or_declare(self, lst): """ Use this method in the build phase to declare output files which are meant to be written in the build directory. This method creates the Node object and its parent folder as needed. :param lst: relative path :type lst: string or list of string """ if isinstance(lst, str) and os.path.isabs(lst): node = self.ctx.root.make_node(lst) else: node = self.get_bld().make_node(lst) node.parent.mkdir() return node def find_dir(self, lst): """ Searches for a folder on the filesystem (see :py:meth:`waflib.Node.Node.find_node`) :param lst: relative path :type lst: string or list of string :returns: The corresponding Node object or None if there is no such folder :rtype: :py:class:`waflib.Node.Node` """ if isinstance(lst, str): lst = [x for x in Utils.split_path(lst) if x and x != '.'] node = self.find_node(lst) if node and not node.isdir(): return None return node # helpers for building things def change_ext(self, ext, ext_in=None): """ Declares a build node with a distinct extension; this is uses :py:meth:`waflib.Node.Node.find_or_declare` :return: A build node of the same path, but with a different extension :rtype: :py:class:`waflib.Node.Node` """ name = self.name if ext_in is None: k = name.rfind('.') if k >= 0: name = name[:k] + ext else: name = name + ext else: name = name[:- len(ext_in)] + ext return self.parent.find_or_declare([name]) def bldpath(self): """ Returns the relative path seen from the build directory ``src/foo.cpp`` :rtype: string """ return self.path_from(self.ctx.bldnode) def srcpath(self): """ Returns the relative path seen from the source directory ``../src/foo.cpp`` :rtype: string """ return self.path_from(self.ctx.srcnode) def relpath(self): """ If a file in the build directory, returns :py:meth:`waflib.Node.Node.bldpath`, else returns :py:meth:`waflib.Node.Node.srcpath` :rtype: string """ cur = self x = self.ctx.bldnode while cur.parent: if cur is x: return self.bldpath() cur = cur.parent return self.srcpath() def bld_dir(self): """ Equivalent to self.parent.bldpath() :rtype: string """ return self.parent.bldpath() def h_file(self): """ See :py:func:`waflib.Utils.h_file` :return: a hash representing the file contents :rtype: string or bytes """ return Utils.h_file(self.abspath()) def get_bld_sig(self): """ Returns a signature (see :py:meth:`waflib.Node.Node.h_file`) for the purpose of build dependency calculation. This method uses a per-context cache. :return: a hash representing the object contents :rtype: string or bytes """ # previous behaviour can be set by returning self.ctx.node_sigs[self] when a build node try: cache = self.ctx.cache_sig except AttributeError: cache = self.ctx.cache_sig = {} try: ret = cache[self] except KeyError: p = self.abspath() try: ret = cache[self] = self.h_file() except EnvironmentError: if self.isdir(): # allow folders as build nodes, do not use the creation time st = os.stat(p) ret = cache[self] = Utils.h_list([p, st.st_ino, st.st_mode]) return ret raise return ret pickle_lock = Utils.threading.Lock() """Lock mandatory for thread-safe node serialization""" class Nod3(Node): """Mandatory subclass for thread-safe node serialization""" pass # do not remove kupfer-328/waflib/Options.py000066400000000000000000000272661500175051100161450ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Scott Newton, 2005 (scottn) # Thomas Nagy, 2006-2018 (ita) """ Support for waf command-line options Provides default and command-line options, as well the command that reads the ``options`` wscript function. """ import os, tempfile, optparse, sys, re from waflib import Logs, Utils, Context, Errors options = optparse.Values() """ A global dictionary representing user-provided command-line options:: $ waf --foo=bar """ commands = [] """ List of commands to execute extracted from the command-line. This list is consumed during the execution by :py:func:`waflib.Scripting.run_commands`. """ envvars = [] """ List of environment variable declarations placed after the Waf executable name. These are detected by searching for "=" in the remaining arguments. You probably do not want to use this. """ lockfile = os.environ.get('WAFLOCK', '.lock-waf_%s_build' % sys.platform) """ Name of the lock file that marks a project as configured """ class opt_parser(optparse.OptionParser): """ Command-line options parser. """ def __init__(self, ctx, allow_unknown=False): optparse.OptionParser.__init__(self, conflict_handler='resolve', add_help_option=False, version='%s %s (%s)' % (Context.WAFNAME, Context.WAFVERSION, Context.WAFREVISION)) self.formatter.width = Logs.get_term_cols() self.ctx = ctx self.allow_unknown = allow_unknown def _process_args(self, largs, rargs, values): """ Custom _process_args to allow unknown options according to the allow_unknown status """ while rargs: try: optparse.OptionParser._process_args(self,largs,rargs,values) except (optparse.BadOptionError, optparse.AmbiguousOptionError) as e: if self.allow_unknown: largs.append(e.opt_str) else: self.error(str(e)) def _process_long_opt(self, rargs, values): # --custom-option=-ftxyz is interpreted as -f -t... see #2280 if self.allow_unknown: back = [] + rargs try: optparse.OptionParser._process_long_opt(self, rargs, values) except optparse.BadOptionError: while rargs: rargs.pop() rargs.extend(back) rargs.pop(0) raise else: optparse.OptionParser._process_long_opt(self, rargs, values) def print_usage(self, file=None): return self.print_help(file) def get_usage(self): """ Builds the message to print on ``waf --help`` :rtype: string """ cmds_str = {} for cls in Context.classes: if not cls.cmd or cls.cmd == 'options' or cls.cmd.startswith( '_' ): continue s = cls.__doc__ or '' cmds_str[cls.cmd] = s if Context.g_module: for (k, v) in Context.g_module.__dict__.items(): if k in ('options', 'init', 'shutdown'): continue if type(v) is type(Context.create_context): if v.__doc__ and not k.startswith('_'): cmds_str[k] = v.__doc__ just = 0 for k in cmds_str: just = max(just, len(k)) lst = [' %s: %s' % (k.ljust(just), v) for (k, v) in cmds_str.items()] lst.sort() ret = '\n'.join(lst) return '''%s [commands] [options] Main commands (example: ./%s build -j4) %s ''' % (Context.WAFNAME, Context.WAFNAME, ret) class OptionsContext(Context.Context): """ Collects custom options from wscript files and parses the command line. Sets the global :py:const:`waflib.Options.commands` and :py:const:`waflib.Options.options` values. """ cmd = 'options' fun = 'options' def __init__(self, **kw): super(OptionsContext, self).__init__(**kw) self.parser = opt_parser(self) """Instance of :py:class:`waflib.Options.opt_parser`""" self.option_groups = {} jobs = self.jobs() p = self.add_option color = os.environ.get('NOCOLOR', '') and 'no' or 'auto' if os.environ.get('CLICOLOR', '') == '0': color = 'no' elif os.environ.get('CLICOLOR_FORCE', '') == '1': color = 'yes' p('-c', '--color', dest='colors', default=color, action='store', help='whether to use colors (yes/no/auto) [default: auto]', choices=('yes', 'no', 'auto')) p('-j', '--jobs', dest='jobs', default=jobs, type='int', help='amount of parallel jobs (%r)' % jobs) p('-k', '--keep', dest='keep', default=0, action='count', help='continue despite errors (-kk to try harder)') p('-v', '--verbose', dest='verbose', default=0, action='count', help='verbosity level -v -vv or -vvv [default: 0]') p('--zones', dest='zones', default='', action='store', help='debugging zones (task_gen, deps, tasks, etc)') p('--profile', dest='profile', default=0, action='store_true', help=optparse.SUPPRESS_HELP) p('--pdb', dest='pdb', default=0, action='store_true', help=optparse.SUPPRESS_HELP) p('-h', '--help', dest='whelp', default=0, action='store_true', help="show this help message and exit") gr = self.add_option_group('Configuration options') self.option_groups['configure options'] = gr gr.add_option('-o', '--out', action='store', default='', help='build dir for the project', dest='out') gr.add_option('-t', '--top', action='store', default='', help='src dir for the project', dest='top') gr.add_option('--no-lock-in-run', action='store_true', default=os.environ.get('NO_LOCK_IN_RUN', ''), help=optparse.SUPPRESS_HELP, dest='no_lock_in_run') gr.add_option('--no-lock-in-out', action='store_true', default=os.environ.get('NO_LOCK_IN_OUT', ''), help=optparse.SUPPRESS_HELP, dest='no_lock_in_out') gr.add_option('--no-lock-in-top', action='store_true', default=os.environ.get('NO_LOCK_IN_TOP', ''), help=optparse.SUPPRESS_HELP, dest='no_lock_in_top') default_prefix = getattr(Context.g_module, 'default_prefix', os.environ.get('PREFIX')) if not default_prefix: if Utils.unversioned_sys_platform() == 'win32': d = tempfile.gettempdir() default_prefix = d[0].upper() + d[1:] # win32 preserves the case, but gettempdir does not else: default_prefix = '/usr/local/' gr.add_option('--prefix', dest='prefix', default=default_prefix, help='installation prefix [default: %r]' % default_prefix) gr.add_option('--bindir', dest='bindir', help='bindir') gr.add_option('--libdir', dest='libdir', help='libdir') gr = self.add_option_group('Build and installation options') self.option_groups['build and install options'] = gr gr.add_option('-p', '--progress', dest='progress_bar', default=0, action='count', help= '-p: progress bar; -pp: ide output') gr.add_option('--targets', dest='targets', default='', action='store', help='task generators, e.g. "target1,target2"') gr = self.add_option_group('Step options') self.option_groups['step options'] = gr gr.add_option('--files', dest='files', default='', action='store', help='files to process, by regexp, e.g. "*/main.c,*/test/main.o"') default_destdir = os.environ.get('DESTDIR', '') gr = self.add_option_group('Installation and uninstallation options') self.option_groups['install/uninstall options'] = gr gr.add_option('--destdir', help='installation root [default: %r]' % default_destdir, default=default_destdir, dest='destdir') gr.add_option('-f', '--force', dest='force', default=False, action='store_true', help='force file installation') gr.add_option('--distcheck-args', metavar='ARGS', help='arguments to pass to distcheck', default=None, action='store') def jobs(self): """ Finds the optimal amount of cpu cores to use for parallel jobs. At runtime the options can be obtained from :py:const:`waflib.Options.options` :: from waflib.Options import options njobs = options.jobs :return: the amount of cpu cores :rtype: int """ count = int(os.environ.get('JOBS', 0)) if count < 1: if 'NUMBER_OF_PROCESSORS' in os.environ: # on Windows, use the NUMBER_OF_PROCESSORS environment variable count = int(os.environ.get('NUMBER_OF_PROCESSORS', 1)) else: # on everything else, first try the POSIX sysconf values if hasattr(os, 'sysconf_names'): if 'SC_NPROCESSORS_ONLN' in os.sysconf_names: count = int(os.sysconf('SC_NPROCESSORS_ONLN')) elif 'SC_NPROCESSORS_CONF' in os.sysconf_names: count = int(os.sysconf('SC_NPROCESSORS_CONF')) if not count and os.name not in ('nt', 'java'): try: tmp = self.cmd_and_log(['sysctl', '-n', 'hw.ncpu'], quiet=0) except Errors.WafError: pass else: if re.match('^[0-9]+$', tmp): count = int(tmp) if count < 1: count = 1 elif count > 1024: count = 1024 return count def add_option(self, *k, **kw): """ Wraps ``optparse.add_option``:: def options(ctx): ctx.add_option('-u', '--use', dest='use', default=False, action='store_true', help='a boolean option') :rtype: optparse option object """ return self.parser.add_option(*k, **kw) def add_option_group(self, *k, **kw): """ Wraps ``optparse.add_option_group``:: def options(ctx): gr = ctx.add_option_group('some options') gr.add_option('-u', '--use', dest='use', default=False, action='store_true') :rtype: optparse option group object """ try: gr = self.option_groups[k[0]] except KeyError: gr = self.parser.add_option_group(*k, **kw) self.option_groups[k[0]] = gr return gr def get_option_group(self, opt_str): """ Wraps ``optparse.get_option_group``:: def options(ctx): gr = ctx.get_option_group('configure options') gr.add_option('-o', '--out', action='store', default='', help='build dir for the project', dest='out') :rtype: optparse option group object """ try: return self.option_groups[opt_str] except KeyError: for group in self.parser.option_groups: if group.title == opt_str: return group return None def sanitize_path(self, path, cwd=None): if not cwd: cwd = Context.launch_dir p = os.path.expanduser(path) p = os.path.join(cwd, p) p = os.path.normpath(p) p = os.path.abspath(p) return p def parse_cmd_args(self, _args=None, cwd=None, allow_unknown=False): """ Just parse the arguments """ self.parser.allow_unknown = allow_unknown (options, leftover_args) = self.parser.parse_args(args=_args) envvars = [] commands = [] for arg in leftover_args: if '=' in arg: envvars.append(arg) elif arg != 'options': commands.append(arg) if options.jobs < 1: options.jobs = 1 for name in 'top out destdir prefix bindir libdir'.split(): # those paths are usually expanded from Context.launch_dir if getattr(options, name, None): path = self.sanitize_path(getattr(options, name), cwd) setattr(options, name, path) return options, commands, envvars def init_module_vars(self, arg_options, arg_commands, arg_envvars): options.__dict__.clear() del commands[:] del envvars[:] options.__dict__.update(arg_options.__dict__) commands.extend(arg_commands) envvars.extend(arg_envvars) for var in envvars: (name, value) = var.split('=', 1) os.environ[name.strip()] = value def init_logs(self, options, commands, envvars): Logs.verbose = options.verbose if options.verbose >= 1: self.load('errcheck') colors = {'yes' : 2, 'auto' : 1, 'no' : 0}[options.colors] Logs.enable_colors(colors) if options.zones: Logs.zones = options.zones.split(',') if not Logs.verbose: Logs.verbose = 1 elif Logs.verbose > 0: Logs.zones = ['runner'] if Logs.verbose > 2: Logs.zones = ['*'] def parse_args(self, _args=None): """ Parses arguments from a list which is not necessarily the command-line. Initializes the module variables options, commands and envvars If help is requested, prints it and exit the application :param _args: arguments :type _args: list of strings """ options, commands, envvars = self.parse_cmd_args() self.init_logs(options, commands, envvars) self.init_module_vars(options, commands, envvars) def execute(self): """ See :py:func:`waflib.Context.Context.execute` """ super(OptionsContext, self).execute() self.parse_args() Utils.alloc_process_pool(options.jobs) kupfer-328/waflib/Runner.py000066400000000000000000000400121500175051100157430ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2018 (ita) """ Runner.py: Task scheduling and execution """ import heapq, traceback try: from queue import Queue, PriorityQueue except ImportError: from Queue import Queue try: from Queue import PriorityQueue except ImportError: class PriorityQueue(Queue): def _init(self, maxsize): self.maxsize = maxsize self.queue = [] def _put(self, item): heapq.heappush(self.queue, item) def _get(self): return heapq.heappop(self.queue) from waflib import Utils, Task, Errors, Logs GAP = 5 """ Wait for at least ``GAP * njobs`` before trying to enqueue more tasks to run """ class PriorityTasks(object): def __init__(self): self.lst = [] def __len__(self): return len(self.lst) def __iter__(self): return iter(self.lst) def __str__(self): return 'PriorityTasks: [%s]' % '\n '.join(str(x) for x in self.lst) def clear(self): self.lst = [] def append(self, task): heapq.heappush(self.lst, task) def appendleft(self, task): "Deprecated, do not use" heapq.heappush(self.lst, task) def pop(self): return heapq.heappop(self.lst) def extend(self, lst): if self.lst: for x in lst: self.append(x) else: if isinstance(lst, list): self.lst = lst heapq.heapify(lst) else: self.lst = lst.lst class Consumer(Utils.threading.Thread): """ Daemon thread object that executes a task. It shares a semaphore with the coordinator :py:class:`waflib.Runner.Spawner`. There is one instance per task to consume. """ def __init__(self, spawner, task): Utils.threading.Thread.__init__(self) self.task = task """Task to execute""" self.spawner = spawner """Coordinator object""" self.daemon = True self.start() def run(self): """ Processes a single task """ try: if not self.spawner.master.stop: self.spawner.master.process_task(self.task) finally: self.spawner.sem.release() self.spawner.master.out.put(self.task) self.task = None self.spawner = None class Spawner(Utils.threading.Thread): """ Daemon thread that consumes tasks from :py:class:`waflib.Runner.Parallel` producer and spawns a consuming thread :py:class:`waflib.Runner.Consumer` for each :py:class:`waflib.Task.Task` instance. """ def __init__(self, master): Utils.threading.Thread.__init__(self) self.master = master """:py:class:`waflib.Runner.Parallel` producer instance""" self.sem = Utils.threading.Semaphore(master.numjobs) """Bounded semaphore that prevents spawning more than *n* concurrent consumers""" self.daemon = True self.start() def run(self): """ Spawns new consumers to execute tasks by delegating to :py:meth:`waflib.Runner.Spawner.loop` """ try: self.loop() except Exception: # Python 2 prints unnecessary messages when shutting down # we also want to stop the thread properly pass def loop(self): """ Consumes task objects from the producer; ends when the producer has no more task to provide. """ master = self.master while 1: task = master.ready.get() self.sem.acquire() if not master.stop: task.log_display(task.generator.bld) Consumer(self, task) class Parallel(object): """ Schedule the tasks obtained from the build context for execution. """ def __init__(self, bld, j=2): """ The initialization requires a build context reference for computing the total number of jobs. """ self.numjobs = j """ Amount of parallel consumers to use """ self.bld = bld """ Instance of :py:class:`waflib.Build.BuildContext` """ self.outstanding = PriorityTasks() """Heap of :py:class:`waflib.Task.Task` that may be ready to be executed""" self.postponed = PriorityTasks() """Heap of :py:class:`waflib.Task.Task` which are not ready to run for non-DAG reasons""" self.incomplete = set() """List of :py:class:`waflib.Task.Task` waiting for dependent tasks to complete (DAG)""" self.ready = PriorityQueue(0) """List of :py:class:`waflib.Task.Task` ready to be executed by consumers""" self.out = Queue(0) """List of :py:class:`waflib.Task.Task` returned by the task consumers""" self.count = 0 """Amount of tasks that may be processed by :py:class:`waflib.Runner.TaskConsumer`""" self.processed = 0 """Amount of tasks processed""" self.stop = False """Error flag to stop the build""" self.error = [] """Tasks that could not be executed""" self.biter = None """Task iterator which must give groups of parallelizable tasks when calling ``next()``""" self.dirty = False """ Flag that indicates that the build cache must be saved when a task was executed (calls :py:meth:`waflib.Build.BuildContext.store`)""" self.revdeps = Utils.defaultdict(set) """ The reverse dependency graph of dependencies obtained from Task.run_after """ self.spawner = None """ Coordinating daemon thread that spawns thread consumers """ if self.numjobs > 1: self.spawner = Spawner(self) def get_next_task(self): """ Obtains the next Task instance to run :rtype: :py:class:`waflib.Task.Task` """ if not self.outstanding: return None return self.outstanding.pop() def postpone(self, tsk): """ Adds the task to the list :py:attr:`waflib.Runner.Parallel.postponed`. The order is scrambled so as to consume as many tasks in parallel as possible. :param tsk: task instance :type tsk: :py:class:`waflib.Task.Task` """ self.postponed.append(tsk) def refill_task_list(self): """ Pulls a next group of tasks to execute in :py:attr:`waflib.Runner.Parallel.outstanding`. Ensures that all tasks in the current build group are complete before processing the next one. """ while self.count > self.numjobs * GAP: self.get_out() while not self.outstanding: if self.count: self.get_out() if self.outstanding: break elif self.postponed: try: cond = self.deadlock == self.processed except AttributeError: pass else: if cond: # The most common reason is conflicting build order declaration # for example: "X run_after Y" and "Y run_after X" # Another can be changing "run_after" dependencies while the build is running # for example: updating "tsk.run_after" in the "runnable_status" method lst = [] for tsk in self.postponed: deps = [id(x) for x in tsk.run_after if not x.hasrun] lst.append('%s\t-> %r' % (repr(tsk), deps)) if not deps: lst.append('\n task %r dependencies are done, check its *runnable_status*?' % id(tsk)) raise Errors.WafError('Deadlock detected: check the task build order%s' % ''.join(lst)) self.deadlock = self.processed if self.postponed: self.outstanding.extend(self.postponed) self.postponed.clear() elif not self.count: if self.incomplete: for x in self.incomplete: for k in x.run_after: if not k.hasrun: break else: # dependency added after the build started without updating revdeps self.incomplete.remove(x) self.outstanding.append(x) break else: if self.stop or self.error: break raise Errors.WafError('Broken revdeps detected on %r' % self.incomplete) else: tasks = next(self.biter) ready, waiting = self.prio_and_split(tasks) self.outstanding.extend(ready) self.incomplete.update(waiting) self.total = self.bld.total() break def add_more_tasks(self, tsk): """ If a task provides :py:attr:`waflib.Task.Task.more_tasks`, then the tasks contained in that list are added to the current build and will be processed before the next build group. The priorities for dependent tasks are not re-calculated globally :param tsk: task instance :type tsk: :py:attr:`waflib.Task.Task` """ if getattr(tsk, 'more_tasks', None): more = set(tsk.more_tasks) groups_done = set() def iteri(a, b): for x in a: yield x for x in b: yield x # Update the dependency tree # this assumes that task.run_after values were updated for x in iteri(self.outstanding, self.incomplete): for k in x.run_after: if isinstance(k, Task.TaskGroup): if k not in groups_done: groups_done.add(k) for j in k.prev & more: self.revdeps[j].add(k) elif k in more: self.revdeps[k].add(x) ready, waiting = self.prio_and_split(tsk.more_tasks) self.outstanding.extend(ready) self.incomplete.update(waiting) self.total += len(tsk.more_tasks) def mark_finished(self, tsk): def try_unfreeze(x): # DAG ancestors are likely to be in the incomplete set # This assumes that the run_after contents have not changed # after the build starts, else a deadlock may occur if x in self.incomplete: # TODO remove dependencies to free some memory? # x.run_after.remove(tsk) for k in x.run_after: if not k.hasrun: break else: self.incomplete.remove(x) self.outstanding.append(x) if tsk in self.revdeps: for x in self.revdeps[tsk]: if isinstance(x, Task.TaskGroup): x.prev.remove(tsk) if not x.prev: for k in x.next: # TODO necessary optimization? k.run_after.remove(x) try_unfreeze(k) # TODO necessary optimization? x.next = [] else: try_unfreeze(x) del self.revdeps[tsk] if hasattr(tsk, 'semaphore'): sem = tsk.semaphore try: sem.release(tsk) except KeyError: # TODO pass else: while sem.waiting and not sem.is_locked(): # take a frozen task, make it ready to run x = sem.waiting.pop() self._add_task(x) def get_out(self): """ Waits for a Task that task consumers add to :py:attr:`waflib.Runner.Parallel.out` after execution. Adds more Tasks if necessary through :py:attr:`waflib.Runner.Parallel.add_more_tasks`. :rtype: :py:attr:`waflib.Task.Task` """ tsk = self.out.get() if not self.stop: self.add_more_tasks(tsk) self.mark_finished(tsk) self.count -= 1 self.dirty = True return tsk def add_task(self, tsk): """ Enqueue a Task to :py:attr:`waflib.Runner.Parallel.ready` so that consumers can run them. :param tsk: task instance :type tsk: :py:attr:`waflib.Task.Task` """ # TODO change in waf 2.1 self.ready.put(tsk) def _add_task(self, tsk): if hasattr(tsk, 'semaphore'): sem = tsk.semaphore try: sem.acquire(tsk) except IndexError: sem.waiting.add(tsk) return self.count += 1 self.processed += 1 if self.numjobs == 1: tsk.log_display(tsk.generator.bld) try: self.process_task(tsk) finally: self.out.put(tsk) else: self.add_task(tsk) def process_task(self, tsk): """ Processes a task and attempts to stop the build in case of errors """ tsk.process() if tsk.hasrun != Task.SUCCESS: self.error_handler(tsk) def skip(self, tsk): """ Mark a task as skipped/up-to-date """ tsk.hasrun = Task.SKIPPED self.mark_finished(tsk) def cancel(self, tsk): """ Mark a task as failed because of unsatisfiable dependencies """ tsk.hasrun = Task.CANCELED self.mark_finished(tsk) def error_handler(self, tsk): """ Called when a task cannot be executed. The flag :py:attr:`waflib.Runner.Parallel.stop` is set, unless the build is executed with:: $ waf build -k :param tsk: task instance :type tsk: :py:attr:`waflib.Task.Task` """ if not self.bld.keep: self.stop = True self.error.append(tsk) def task_status(self, tsk): """ Obtains the task status to decide whether to run it immediately or not. :return: the exit status, for example :py:attr:`waflib.Task.ASK_LATER` :rtype: integer """ try: return tsk.runnable_status() except Exception: self.processed += 1 tsk.err_msg = traceback.format_exc() if not self.stop and self.bld.keep: self.skip(tsk) if self.bld.keep == 1: # if -k stop on the first exception, if -kk try to go as far as possible if Logs.verbose > 1 or not self.error: self.error.append(tsk) self.stop = True else: if Logs.verbose > 1: self.error.append(tsk) return Task.EXCEPTION tsk.hasrun = Task.EXCEPTION self.error_handler(tsk) return Task.EXCEPTION def start(self): """ Obtains Task instances from the BuildContext instance and adds the ones that need to be executed to :py:class:`waflib.Runner.Parallel.ready` so that the :py:class:`waflib.Runner.Spawner` consumer thread has them executed. Obtains the executed Tasks back from :py:class:`waflib.Runner.Parallel.out` and marks the build as failed by setting the ``stop`` flag. If only one job is used, then executes the tasks one by one, without consumers. """ self.total = self.bld.total() while not self.stop: self.refill_task_list() # consider the next task tsk = self.get_next_task() if not tsk: if self.count: # tasks may add new ones after they are run continue else: # no tasks to run, no tasks running, time to exit break if tsk.hasrun: # if the task is marked as "run", just skip it self.processed += 1 continue if self.stop: # stop immediately after a failure is detected break st = self.task_status(tsk) if st == Task.RUN_ME: self._add_task(tsk) elif st == Task.ASK_LATER: self.postpone(tsk) elif st == Task.SKIP_ME: self.processed += 1 self.skip(tsk) self.add_more_tasks(tsk) elif st == Task.CANCEL_ME: # A dependency problem has occurred, and the # build is most likely run with `waf -k` if Logs.verbose > 1: self.error.append(tsk) self.processed += 1 self.cancel(tsk) # self.count represents the tasks that have been made available to the consumer threads # collect all the tasks after an error else the message may be incomplete while self.error and self.count: self.get_out() self.ready.put(None) if not self.stop: assert not self.count assert not self.postponed assert not self.incomplete def prio_and_split(self, tasks): """ Label input tasks with priority values, and return a pair containing the tasks that are ready to run and the tasks that are necessarily waiting for other tasks to complete. The priority system is really meant as an optional layer for optimization: dependency cycles are found quickly, and builds should be more efficient. A high priority number means that a task is processed first. This method can be overridden to disable the priority system:: def prio_and_split(self, tasks): return tasks, [] :return: A pair of task lists :rtype: tuple """ # to disable: #return tasks, [] for x in tasks: x.visited = 0 reverse = self.revdeps groups_done = set() for x in tasks: for k in x.run_after: if isinstance(k, Task.TaskGroup): if k not in groups_done: groups_done.add(k) for j in k.prev: reverse[j].add(k) else: reverse[k].add(x) # the priority number is not the tree depth def visit(n): if isinstance(n, Task.TaskGroup): return sum(visit(k) for k in n.next) if n.visited == 0: n.visited = 1 if n in reverse: rev = reverse[n] n.prio_order = n.tree_weight + len(rev) + sum(visit(k) for k in rev) else: n.prio_order = n.tree_weight n.visited = 2 elif n.visited == 1: raise Errors.WafError('Dependency cycle found!') return n.prio_order for x in tasks: if x.visited != 0: # must visit all to detect cycles continue try: visit(x) except Errors.WafError: self.debug_cycles(tasks, reverse) ready = [] waiting = [] for x in tasks: for k in x.run_after: if not k.hasrun: waiting.append(x) break else: ready.append(x) return (ready, waiting) def debug_cycles(self, tasks, reverse): tmp = {} for x in tasks: tmp[x] = 0 def visit(n, acc): if isinstance(n, Task.TaskGroup): for k in n.next: visit(k, acc) return if tmp[n] == 0: tmp[n] = 1 for k in reverse.get(n, []): visit(k, [n] + acc) tmp[n] = 2 elif tmp[n] == 1: lst = [] for tsk in acc: lst.append(repr(tsk)) if tsk is n: # exclude prior nodes, we want the minimum cycle break raise Errors.WafError('Task dependency cycle in "run_after" constraints: %s' % ''.join(lst)) for x in tasks: visit(x, []) kupfer-328/waflib/Scripting.py000066400000000000000000000403741500175051100164470ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2018 (ita) "Module called for configuring, compiling and installing targets" from __future__ import with_statement import os, shlex, shutil, traceback, errno, sys, stat from waflib import Utils, Configure, Logs, Options, ConfigSet, Context, Errors, Build, Node build_dir_override = None no_climb_commands = ['configure'] default_cmd = "build" def waf_entry_point(current_directory, version, wafdir): """ This is the main entry point, all Waf execution starts here. :param current_directory: absolute path representing the current directory :type current_directory: string :param version: version number :type version: string :param wafdir: absolute path representing the directory of the waf library :type wafdir: string """ Logs.init_log() if Context.WAFVERSION != version: Logs.error('Waf script %r and library %r do not match (directory %r)', version, Context.WAFVERSION, wafdir) sys.exit(1) # Store current directory before any chdir Context.waf_dir = wafdir Context.run_dir = Context.launch_dir = current_directory start_dir = current_directory no_climb = os.environ.get('NOCLIMB') if len(sys.argv) > 1: # os.path.join handles absolute paths # if sys.argv[1] is not an absolute path, then it is relative to the current working directory potential_wscript = os.path.join(current_directory, sys.argv[1]) if os.path.basename(potential_wscript) == Context.WSCRIPT_FILE and os.path.isfile(potential_wscript): # need to explicitly normalize the path, as it may contain extra '/.' path = os.path.normpath(os.path.dirname(potential_wscript)) start_dir = os.path.abspath(path) no_climb = True sys.argv.pop(1) ctx = Context.create_context('options') (options, commands, env) = ctx.parse_cmd_args(allow_unknown=True) if options.top: start_dir = Context.run_dir = Context.top_dir = options.top no_climb = True if options.out: Context.out_dir = options.out # if 'configure' is in the commands, do not search any further if not no_climb: for k in no_climb_commands: for y in commands: if y.startswith(k): no_climb = True break # try to find a lock file (if the project was configured) # at the same time, store the first wscript file seen cur = start_dir while cur: try: lst = os.listdir(cur) except OSError: lst = [] Logs.error('Directory %r is unreadable!', cur) if Options.lockfile in lst: env = ConfigSet.ConfigSet() try: env.load(os.path.join(cur, Options.lockfile)) ino = os.stat(cur)[stat.ST_INO] except EnvironmentError: pass else: # check if the folder was not moved for x in (env.run_dir, env.top_dir, env.out_dir): if not x: continue if Utils.is_win32: if cur == x: load = True break else: # if the filesystem features symlinks, compare the inode numbers try: ino2 = os.stat(x)[stat.ST_INO] except OSError: pass else: if ino == ino2: load = True break else: Logs.warn('invalid lock file in %s', cur) load = False if load: Context.run_dir = env.run_dir Context.top_dir = env.top_dir Context.out_dir = env.out_dir break if not Context.run_dir: if Context.WSCRIPT_FILE in lst: Context.run_dir = cur next = os.path.dirname(cur) if next == cur: break cur = next if no_climb: break wscript = os.path.normpath(os.path.join(Context.run_dir, Context.WSCRIPT_FILE)) if not os.path.exists(wscript): if options.whelp: Logs.warn('These are the generic options (no wscript/project found)') ctx.parser.print_help() sys.exit(0) Logs.error('Waf: Run from a folder containing a %r file (or try -h for the generic options)', Context.WSCRIPT_FILE) sys.exit(1) try: os.chdir(Context.run_dir) except OSError: Logs.error('Waf: The folder %r is unreadable', Context.run_dir) sys.exit(1) try: set_main_module(wscript) except Errors.WafError as e: Logs.pprint('RED', e.verbose_msg) Logs.error(str(e)) sys.exit(1) except Exception as e: Logs.error('Waf: The wscript in %r is unreadable', Context.run_dir) traceback.print_exc(file=sys.stdout) sys.exit(2) if options.profile: import cProfile, pstats cProfile.runctx('from waflib import Scripting; Scripting.run_commands()', {}, {}, 'profi.txt') p = pstats.Stats('profi.txt') p.sort_stats('time').print_stats(75) # or 'cumulative' else: try: try: run_commands() except: if options.pdb: import pdb type, value, tb = sys.exc_info() traceback.print_exc() pdb.post_mortem(tb) else: raise except Errors.WafError as e: if Logs.verbose > 1: Logs.pprint('RED', e.verbose_msg) Logs.error(e.msg) sys.exit(1) except SystemExit: raise except Exception as e: traceback.print_exc(file=sys.stdout) sys.exit(2) except KeyboardInterrupt: Logs.pprint('RED', 'Interrupted') sys.exit(68) def set_main_module(file_path): """ Read the main wscript file into :py:const:`waflib.Context.Context.g_module` and bind default functions such as ``init``, ``dist``, ``distclean`` if not defined. Called by :py:func:`waflib.Scripting.waf_entry_point` during the initialization. :param file_path: absolute path representing the top-level wscript file :type file_path: string """ Context.g_module = Context.load_module(file_path) Context.g_module.root_path = file_path # note: to register the module globally, use the following: # sys.modules['wscript_main'] = g_module def set_def(obj): name = obj.__name__ if not name in Context.g_module.__dict__: setattr(Context.g_module, name, obj) for k in (dist, distclean, distcheck): set_def(k) # add dummy init and shutdown functions if they're not defined if not 'init' in Context.g_module.__dict__: Context.g_module.init = Utils.nada if not 'shutdown' in Context.g_module.__dict__: Context.g_module.shutdown = Utils.nada if not 'options' in Context.g_module.__dict__: Context.g_module.options = Utils.nada def parse_options(): """ Parses the command-line options and initialize the logging system. Called by :py:func:`waflib.Scripting.waf_entry_point` during the initialization. """ ctx = Context.create_context('options') ctx.execute() if not Options.commands: if isinstance(default_cmd, list): Options.commands.extend(default_cmd) else: Options.commands.append(default_cmd) if Options.options.whelp: ctx.parser.print_help() sys.exit(0) def run_command(cmd_name): """ Executes a single Waf command. Called by :py:func:`waflib.Scripting.run_commands`. :param cmd_name: command to execute, like ``build`` :type cmd_name: string """ ctx = Context.create_context(cmd_name) ctx.log_timer = Utils.Timer() ctx.options = Options.options # provided for convenience ctx.cmd = cmd_name try: ctx.execute() finally: # Issue 1374 ctx.finalize() return ctx def run_commands(): """ Execute the Waf commands that were given on the command-line, and the other options Called by :py:func:`waflib.Scripting.waf_entry_point` during the initialization, and executed after :py:func:`waflib.Scripting.parse_options`. """ parse_options() run_command('init') while Options.commands: cmd_name = Options.commands.pop(0) ctx = run_command(cmd_name) Logs.info('%r finished successfully (%s)', cmd_name, ctx.log_timer) run_command('shutdown') ########################################################################################### def distclean_dir(dirname): """ Distclean function called in the particular case when:: top == out :param dirname: absolute path of the folder to clean :type dirname: string """ for (root, dirs, files) in os.walk(dirname): for f in files: if f.endswith(('.o', '.moc', '.exe')): fname = os.path.join(root, f) try: os.remove(fname) except OSError: Logs.warn('Could not remove %r', fname) for x in (Context.DBFILE, 'config.log'): try: os.remove(x) except OSError: pass try: shutil.rmtree(Build.CACHE_DIR) except OSError: pass def distclean(ctx): '''removes build folders and data''' def remove_and_log(k, fun): try: fun(k) except EnvironmentError as e: if e.errno != errno.ENOENT: Logs.warn('Could not remove %r', k) # remove waf cache folders on the top-level if not Options.commands: for k in os.listdir('.'): for x in '.waf-2 waf-2 .waf3-2 waf3-2'.split(): if k.startswith(x): remove_and_log(k, shutil.rmtree) # remove a build folder, if any cur = '.' if os.environ.get('NO_LOCK_IN_TOP') or ctx.options.no_lock_in_top: cur = ctx.options.out try: lst = os.listdir(cur) except OSError: Logs.warn('Could not read %r', cur) return if Options.lockfile in lst: f = os.path.join(cur, Options.lockfile) try: env = ConfigSet.ConfigSet(f) except EnvironmentError: Logs.warn('Could not read %r', f) return if not env.out_dir or not env.top_dir: Logs.warn('Invalid lock file %r', f) return if env.out_dir == env.top_dir: distclean_dir(env.out_dir) else: remove_and_log(env.out_dir, shutil.rmtree) env_dirs = [env.out_dir] if not (os.environ.get('NO_LOCK_IN_TOP') or ctx.options.no_lock_in_top): env_dirs.append(env.top_dir) if not (os.environ.get('NO_LOCK_IN_RUN') or ctx.options.no_lock_in_run): env_dirs.append(env.run_dir) for k in env_dirs: p = os.path.join(k, Options.lockfile) remove_and_log(p, os.remove) class Dist(Context.Context): '''creates an archive containing the project source code''' cmd = 'dist' fun = 'dist' algo = 'tar.bz2' ext_algo = {} def execute(self): """ See :py:func:`waflib.Context.Context.execute` """ self.recurse([os.path.dirname(Context.g_module.root_path)]) self.archive() def archive(self): """ Creates the source archive. """ import tarfile arch_name = self.get_arch_name() try: self.base_path except AttributeError: self.base_path = self.path node = self.base_path.make_node(arch_name) try: node.delete() except OSError: pass files = self.get_files() if self.algo.startswith('tar.'): tar = tarfile.open(node.abspath(), 'w:' + self.algo.replace('tar.', '')) for x in files: self.add_tar_file(x, tar) tar.close() elif self.algo == 'zip': import zipfile zip = zipfile.ZipFile(node.abspath(), 'w', compression=zipfile.ZIP_DEFLATED) for x in files: archive_name = self.get_base_name() + '/' + x.path_from(self.base_path) zip.write(x.abspath(), archive_name, zipfile.ZIP_DEFLATED) zip.close() else: self.fatal('Valid algo types are tar.bz2, tar.gz, tar.xz or zip') try: from hashlib import sha256 except ImportError: digest = '' else: digest = ' (sha256=%r)' % sha256(node.read(flags='rb')).hexdigest() Logs.info('New archive created: %s%s', self.arch_name, digest) def get_tar_path(self, node): """ Return the path to use for a node in the tar archive, the purpose of this is to let subclases resolve symbolic links or to change file names :return: absolute path :rtype: string """ return node.abspath() def add_tar_file(self, x, tar): """ Adds a file to the tar archive. Symlinks are not verified. :param x: file path :param tar: tar file object """ p = self.get_tar_path(x) tinfo = tar.gettarinfo(name=p, arcname=self.get_tar_prefix() + '/' + x.path_from(self.base_path)) tinfo.uid = 0 tinfo.gid = 0 tinfo.uname = 'root' tinfo.gname = 'root' if os.path.isfile(p): with open(p, 'rb') as f: tar.addfile(tinfo, fileobj=f) else: tar.addfile(tinfo) def get_tar_prefix(self): """ Returns the base path for files added into the archive tar file :rtype: string """ try: return self.tar_prefix except AttributeError: return self.get_base_name() def get_arch_name(self): """ Returns the archive file name. Set the attribute *arch_name* to change the default value:: def dist(ctx): ctx.arch_name = 'ctx.tar.bz2' :rtype: string """ try: self.arch_name except AttributeError: self.arch_name = self.get_base_name() + '.' + self.ext_algo.get(self.algo, self.algo) return self.arch_name def get_base_name(self): """ Returns the default name of the main directory in the archive, which is set to *appname-version*. Set the attribute *base_name* to change the default value:: def dist(ctx): ctx.base_name = 'files' :rtype: string """ try: self.base_name except AttributeError: appname = getattr(Context.g_module, Context.APPNAME, 'noname') version = getattr(Context.g_module, Context.VERSION, '1.0') self.base_name = appname + '-' + version return self.base_name def get_excl(self): """ Returns the patterns to exclude for finding the files in the top-level directory. Set the attribute *excl* to change the default value:: def dist(ctx): ctx.excl = 'build **/*.o **/*.class' :rtype: string """ try: return self.excl except AttributeError: self.excl = Node.exclude_regs + ' **/waf-2.* **/.waf-2.* **/waf3-2.* **/.waf3-2.* **/*~ **/*.rej **/*.orig **/*.pyc **/*.pyo **/*.bak **/*.swp **/.lock-w*' if Context.out_dir: nd = self.root.find_node(Context.out_dir) if nd: self.excl += ' ' + nd.path_from(self.base_path) return self.excl def get_files(self): """ Files to package are searched automatically by :py:func:`waflib.Node.Node.ant_glob`. Set *files* to prevent this behaviour:: def dist(ctx): ctx.files = ctx.path.find_node('wscript') Files are also searched from the directory 'base_path', to change it, set:: def dist(ctx): ctx.base_path = path :rtype: list of :py:class:`waflib.Node.Node` """ try: files = self.files except AttributeError: files = self.base_path.ant_glob('**/*', excl=self.get_excl()) return files def dist(ctx): '''makes a tarball for redistributing the sources''' pass class DistCheck(Dist): """creates an archive with dist, then tries to build it""" fun = 'distcheck' cmd = 'distcheck' def execute(self): """ See :py:func:`waflib.Context.Context.execute` """ self.recurse([os.path.dirname(Context.g_module.root_path)]) self.archive() self.check() def make_distcheck_cmd(self, tmpdir): cfg = [] if Options.options.distcheck_args: cfg = shlex.split(Options.options.distcheck_args) else: cfg = [x for x in sys.argv if x.startswith('-')] cmd = [sys.executable, sys.argv[0], 'configure', 'build', 'install', 'uninstall', '--destdir=' + tmpdir] + cfg return cmd def check(self): """ Creates the archive, uncompresses it and tries to build the project """ import tempfile, tarfile with tarfile.open(self.get_arch_name()) as t: for x in t: t.extract(x) instdir = tempfile.mkdtemp('.inst', self.get_base_name()) cmd = self.make_distcheck_cmd(instdir) ret = Utils.subprocess.Popen(cmd, cwd=self.get_base_name()).wait() if ret: raise Errors.WafError('distcheck failed with code %r' % ret) if os.path.exists(instdir): raise Errors.WafError('distcheck succeeded, but files were left in %s' % instdir) shutil.rmtree(self.get_base_name()) def distcheck(ctx): '''checks if the project compiles (tarball from 'dist')''' pass def autoconfigure(execute_method): """ Decorator that enables context commands to run *configure* as needed. """ def execute(self): """ Wraps :py:func:`waflib.Context.Context.execute` on the context class """ if not Configure.autoconfig: return execute_method(self) env = ConfigSet.ConfigSet() do_config = False try: env.load(os.path.join(Context.top_dir, Options.lockfile)) except EnvironmentError: Logs.warn('Configuring the project') do_config = True else: if env.run_dir != Context.run_dir: do_config = True else: h = 0 for f in env.files: try: h = Utils.h_list((h, Utils.readf(f, 'rb'))) except EnvironmentError: do_config = True break else: do_config = h != env.hash if do_config: cmd = env.config_cmd or 'configure' if Configure.autoconfig == 'clobber': tmp = Options.options.__dict__ launch_dir_tmp = Context.launch_dir if env.options: Options.options.__dict__ = env.options Context.launch_dir = env.launch_dir try: run_command(cmd) finally: Options.options.__dict__ = tmp Context.launch_dir = launch_dir_tmp else: run_command(cmd) run_command(self.cmd) else: return execute_method(self) return execute Build.BuildContext.execute = autoconfigure(Build.BuildContext.execute) kupfer-328/waflib/Task.py000066400000000000000000001150761500175051100154110ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2018 (ita) """ Tasks represent atomic operations such as processes. """ import os, re, sys, tempfile, traceback from waflib import Utils, Logs, Errors # task states NOT_RUN = 0 """The task was not executed yet""" MISSING = 1 """The task has been executed but the files have not been created""" CRASHED = 2 """The task execution returned a non-zero exit status""" EXCEPTION = 3 """An exception occurred in the task execution""" CANCELED = 4 """A dependency for the task is missing so it was cancelled""" SKIPPED = 8 """The task did not have to be executed""" SUCCESS = 9 """The task was successfully executed""" ASK_LATER = -1 """The task is not ready to be executed""" SKIP_ME = -2 """The task does not need to be executed""" RUN_ME = -3 """The task must be executed""" CANCEL_ME = -4 """The task cannot be executed because of a dependency problem""" COMPILE_TEMPLATE_SHELL = ''' def f(tsk): env = tsk.env gen = tsk.generator bld = gen.bld cwdx = tsk.get_cwd() p = env.get_flat def to_list(xx): if isinstance(xx, str): return [xx] return xx tsk.last_cmd = cmd = \'\'\' %s \'\'\' % s return tsk.exec_command(cmd, cwd=cwdx, env=env.env or None) ''' COMPILE_TEMPLATE_NOSHELL = ''' def f(tsk): env = tsk.env gen = tsk.generator bld = gen.bld cwdx = tsk.get_cwd() def to_list(xx): if isinstance(xx, str): return [xx] return xx def merge(lst1, lst2): if lst1 and lst2: return lst1[:-1] + [lst1[-1] + lst2[0]] + lst2[1:] return lst1 + lst2 lst = [] %s if '' in lst: lst = [x for x in lst if x] tsk.last_cmd = lst return tsk.exec_command(lst, cwd=cwdx, env=env.env or None) ''' COMPILE_TEMPLATE_SIG_VARS = ''' def f(tsk): sig = tsk.generator.bld.hash_env_vars(tsk.env, tsk.vars) tsk.m.update(sig) env = tsk.env gen = tsk.generator bld = gen.bld cwdx = tsk.get_cwd() p = env.get_flat buf = [] %s tsk.m.update(repr(buf).encode()) ''' classes = {} """ The metaclass :py:class:`waflib.Task.store_task_type` stores all class tasks created by user scripts or Waf tools to this dict. It maps class names to class objects. """ class store_task_type(type): """ Metaclass: store the task classes into the dict pointed by the class attribute 'register' which defaults to :py:const:`waflib.Task.classes`, The attribute 'run_str' is compiled into a method 'run' bound to the task class. """ def __init__(cls, name, bases, dict): super(store_task_type, cls).__init__(name, bases, dict) name = cls.__name__ if name != 'evil' and name != 'Task': if getattr(cls, 'run_str', None): # if a string is provided, convert it to a method (f, dvars) = compile_fun(cls.run_str, cls.shell) cls.hcode = Utils.h_cmd(cls.run_str) cls.orig_run_str = cls.run_str # change the name of run_str or it is impossible to subclass with a function cls.run_str = None cls.run = f # process variables cls.vars = list(set(cls.vars + dvars)) cls.vars.sort() if cls.vars: fun = compile_sig_vars(cls.vars) if fun: cls.sig_vars = fun elif getattr(cls, 'run', None) and not 'hcode' in cls.__dict__: # getattr(cls, 'hcode') would look in the upper classes cls.hcode = Utils.h_cmd(cls.run) # be creative getattr(cls, 'register', classes)[name] = cls evil = store_task_type('evil', (object,), {}) "Base class provided to avoid writing a metaclass, so the code can run in python 2.6 and 3.x unmodified" class Task(evil): """ Task objects represents actions to perform such as commands to execute by calling the `run` method. Detecting when to execute a task occurs in the method :py:meth:`waflib.Task.Task.runnable_status`. Detecting which tasks to execute is performed through a hash value returned by :py:meth:`waflib.Task.Task.signature`. The task signature is persistent from build to build. """ vars = [] """ConfigSet variables that should trigger a rebuild (class attribute used for :py:meth:`waflib.Task.Task.sig_vars`)""" always_run = False """Specify whether task instances must always be executed or not (class attribute)""" shell = False """Execute the command with the shell (class attribute)""" color = 'GREEN' """Color for the console display, see :py:const:`waflib.Logs.colors_lst`""" ext_in = [] """File extensions that objects of this task class may use""" ext_out = [] """File extensions that objects of this task class may create""" before = [] """The instances of this class are executed before the instances of classes whose names are in this list""" after = [] """The instances of this class are executed after the instances of classes whose names are in this list""" hcode = Utils.SIG_NIL """String representing an additional hash for the class representation""" keep_last_cmd = False """Whether to keep the last command executed on the instance after execution. This may be useful for certain extensions but it can a lot of memory. """ weight = 0 """Optional weight to tune the priority for task instances. The higher, the earlier. The weight only applies to single task objects.""" tree_weight = 0 """Optional weight to tune the priority of task instances and whole subtrees. The higher, the earlier.""" prio_order = 0 """Priority order set by the scheduler on instances during the build phase. You most likely do not need to set it. """ __slots__ = ('hasrun', 'generator', 'env', 'inputs', 'outputs', 'dep_nodes', 'run_after') def __init__(self, *k, **kw): self.hasrun = NOT_RUN try: self.generator = kw['generator'] except KeyError: self.generator = self self.env = kw['env'] """:py:class:`waflib.ConfigSet.ConfigSet` object (make sure to provide one)""" self.inputs = [] """List of input nodes, which represent the files used by the task instance""" self.outputs = [] """List of output nodes, which represent the files created by the task instance""" self.dep_nodes = [] """List of additional nodes to depend on""" self.run_after = set() """Set of tasks that must be executed before this one""" def __lt__(self, other): return self.priority() > other.priority() def __le__(self, other): return self.priority() >= other.priority() def __gt__(self, other): return self.priority() < other.priority() def __ge__(self, other): return self.priority() <= other.priority() def get_cwd(self): """ :return: current working directory :rtype: :py:class:`waflib.Node.Node` """ bld = self.generator.bld ret = getattr(self, 'cwd', None) or getattr(bld, 'cwd', bld.bldnode) if isinstance(ret, str): if os.path.isabs(ret): ret = bld.root.make_node(ret) else: ret = self.generator.path.make_node(ret) return ret def quote_flag(self, x): """ Surround a process argument by quotes so that a list of arguments can be written to a file :param x: flag :type x: string :return: quoted flag :rtype: string """ old = x if '\\' in x: x = x.replace('\\', '\\\\') if '"' in x: x = x.replace('"', '\\"') if old != x or ' ' in x or '\t' in x or "'" in x: x = '"%s"' % x return x def priority(self): """ Priority of execution; the higher, the earlier :return: the priority value :rtype: a tuple of numeric values """ return (self.weight + self.prio_order, - getattr(self.generator, 'tg_idx_count', 0)) def split_argfile(self, cmd): """ Splits a list of process commands into the executable part and its list of arguments :return: a tuple containing the executable first and then the rest of arguments :rtype: tuple """ return ([cmd[0]], [self.quote_flag(x) for x in cmd[1:]]) def exec_command(self, cmd, **kw): """ Wrapper for :py:meth:`waflib.Context.Context.exec_command`. This version set the current working directory (``build.variant_dir``), applies PATH settings (if self.env.PATH is provided), and can run long commands through a temporary ``@argfile``. :param cmd: process command to execute :type cmd: list of string (best) or string (process will use a shell) :return: the return code :rtype: int Optional parameters: #. cwd: current working directory (Node or string) #. stdout: set to None to prevent waf from capturing the process standard output #. stderr: set to None to prevent waf from capturing the process standard error #. timeout: timeout value (Python 3) """ if not 'cwd' in kw: kw['cwd'] = self.get_cwd() if hasattr(self, 'timeout'): kw['timeout'] = self.timeout if self.env.PATH: env = kw['env'] = dict(kw.get('env') or self.env.env or os.environ) env['PATH'] = self.env.PATH if isinstance(self.env.PATH, str) else os.pathsep.join(self.env.PATH) if hasattr(self, 'stdout'): kw['stdout'] = self.stdout if hasattr(self, 'stderr'): kw['stderr'] = self.stderr if not isinstance(cmd, str): if Utils.is_win32: # win32 compares the resulting length http://support.microsoft.com/kb/830473 too_long = sum([len(arg) for arg in cmd]) + len(cmd) > 8192 else: # non-win32 counts the amount of arguments (200k) too_long = len(cmd) > 200000 if too_long and getattr(self, 'allow_argsfile', True): # Shunt arguments to a temporary file if the command is too long. cmd, args = self.split_argfile(cmd) try: (fd, tmp) = tempfile.mkstemp() os.write(fd, '\r\n'.join(args).encode()) os.close(fd) if Logs.verbose: Logs.debug('argfile: @%r -> %r', tmp, args) return self.generator.bld.exec_command(cmd + ['@' + tmp], **kw) finally: try: os.remove(tmp) except OSError: # anti-virus and indexers can keep files open -_- pass return self.generator.bld.exec_command(cmd, **kw) def process(self): """ Runs the task and handles errors :return: 0 or None if everything is fine :rtype: integer """ # remove the task signature immediately before it is executed # so that the task will be executed again in case of failure try: del self.generator.bld.task_sigs[self.uid()] except KeyError: pass try: ret = self.run() except Exception: self.err_msg = traceback.format_exc() self.hasrun = EXCEPTION else: if ret: self.err_code = ret self.hasrun = CRASHED else: try: self.post_run() except Errors.WafError: pass except Exception: self.err_msg = traceback.format_exc() self.hasrun = EXCEPTION else: self.hasrun = SUCCESS if self.hasrun != SUCCESS and self.scan: # rescan dependencies on next run try: del self.generator.bld.imp_sigs[self.uid()] except KeyError: pass def log_display(self, bld): "Writes the execution status on the context logger" if self.generator.bld.progress_bar == 3: return s = self.display() if s: if bld.logger: logger = bld.logger else: logger = Logs if self.generator.bld.progress_bar == 1: c1 = Logs.colors.cursor_off c2 = Logs.colors.cursor_on logger.info(s, extra={'stream': sys.stderr, 'terminator':'', 'c1': c1, 'c2' : c2}) else: logger.info(s, extra={'terminator':'', 'c1': '', 'c2' : ''}) def display(self): """ Returns an execution status for the console, the progress bar, or the IDE output. :rtype: string """ col1 = Logs.colors(self.color) col2 = Logs.colors.NORMAL master = self.generator.bld.producer def cur(): # the current task position, computed as late as possible return master.processed - master.ready.qsize() if self.generator.bld.progress_bar == 1: return self.generator.bld.progress_line(cur(), master.total, col1, col2) if self.generator.bld.progress_bar == 2: ela = str(self.generator.bld.timer) try: ins = ','.join([n.name for n in self.inputs]) except AttributeError: ins = '' try: outs = ','.join([n.name for n in self.outputs]) except AttributeError: outs = '' return '|Total %s|Current %s|Inputs %s|Outputs %s|Time %s|\n' % (master.total, cur(), ins, outs, ela) s = str(self) if not s: return None total = master.total n = len(str(total)) fs = '[%%%dd/%%%dd] %%s%%s%%s%%s\n' % (n, n) kw = self.keyword() if kw: kw += ' ' return fs % (cur(), total, kw, col1, s, col2) def hash_constraints(self): """ Identifies a task type for all the constraints relevant for the scheduler: precedence, file production :return: a hash value :rtype: string """ return (tuple(self.before), tuple(self.after), tuple(self.ext_in), tuple(self.ext_out), self.__class__.__name__, self.hcode) def format_error(self): """ Returns an error message to display the build failure reasons :rtype: string """ if Logs.verbose: msg = ': %r\n%r' % (self, getattr(self, 'last_cmd', '')) else: msg = ' (run with -v to display more information)' name = getattr(self.generator, 'name', '') if getattr(self, "err_msg", None): return self.err_msg elif not self.hasrun: return 'task in %r was not executed for some reason: %r' % (name, self) elif self.hasrun == CRASHED: try: return ' -> task in %r failed with exit status %r%s' % (name, self.err_code, msg) except AttributeError: return ' -> task in %r failed%s' % (name, msg) elif self.hasrun == MISSING: return ' -> missing files in %r%s' % (name, msg) elif self.hasrun == CANCELED: return ' -> %r canceled because of missing dependencies' % name else: return 'invalid status for task in %r: %r' % (name, self.hasrun) def colon(self, var1, var2): """ Enable scriptlet expressions of the form ${FOO_ST:FOO} If the first variable (FOO_ST) is empty, then an empty list is returned The results will be slightly different if FOO_ST is a list, for example:: env.FOO = ['p1', 'p2'] env.FOO_ST = '-I%s' # ${FOO_ST:FOO} returns ['-Ip1', '-Ip2'] env.FOO_ST = ['-a', '-b'] # ${FOO_ST:FOO} returns ['-a', '-b', 'p1', '-a', '-b', 'p2'] """ tmp = self.env[var1] if not tmp: return [] if isinstance(var2, str): it = self.env[var2] else: it = var2 if isinstance(tmp, str): return [tmp % x for x in it] else: lst = [] for y in it: lst.extend(tmp) lst.append(y) return lst def __str__(self): "string to display to the user" name = self.__class__.__name__ if self.outputs: if name.endswith(('lib', 'program')) or not self.inputs: node = self.outputs[0] return node.path_from(node.ctx.launch_node()) if not (self.inputs or self.outputs): return self.__class__.__name__ if len(self.inputs) == 1: node = self.inputs[0] return node.path_from(node.ctx.launch_node()) src_str = ' '.join([a.path_from(a.ctx.launch_node()) for a in self.inputs]) tgt_str = ' '.join([a.path_from(a.ctx.launch_node()) for a in self.outputs]) if self.outputs: sep = ' -> ' else: sep = '' return '%s: %s%s%s' % (self.__class__.__name__, src_str, sep, tgt_str) def keyword(self): "Display keyword used to prettify the console outputs" name = self.__class__.__name__ if name.endswith(('lib', 'program')): return 'Linking' if len(self.inputs) == 1 and len(self.outputs) == 1: return 'Compiling' if not self.inputs: if self.outputs: return 'Creating' else: return 'Running' return 'Processing' def __repr__(self): "for debugging purposes" try: ins = ",".join([x.name for x in self.inputs]) outs = ",".join([x.name for x in self.outputs]) except AttributeError: ins = ",".join([str(x) for x in self.inputs]) outs = ",".join([str(x) for x in self.outputs]) return "".join(['\n\t{task %r: ' % id(self), self.__class__.__name__, " ", ins, " -> ", outs, '}']) def uid(self): """ Returns an identifier used to determine if tasks are up-to-date. Since the identifier will be stored between executions, it must be: - unique for a task: no two tasks return the same value (for a given build context) - the same for a given task instance By default, the node paths, the class name, and the function are used as inputs to compute a hash. The pointer to the object (python built-in 'id') will change between build executions, and must be avoided in such hashes. :return: hash value :rtype: string """ try: return self.uid_ except AttributeError: m = Utils.md5(self.__class__.__name__) up = m.update for x in self.inputs + self.outputs: up(x.abspath()) self.uid_ = m.digest() return self.uid_ def set_inputs(self, inp): """ Appends the nodes to the *inputs* list :param inp: input nodes :type inp: node or list of nodes """ if isinstance(inp, list): self.inputs += inp else: self.inputs.append(inp) def set_outputs(self, out): """ Appends the nodes to the *outputs* list :param out: output nodes :type out: node or list of nodes """ if isinstance(out, list): self.outputs += out else: self.outputs.append(out) def set_run_after(self, task): """ Run this task only after the given *task*. Calling this method from :py:meth:`waflib.Task.Task.runnable_status` may cause build deadlocks; see :py:meth:`waflib.Tools.fc.fc.runnable_status` for details. :param task: task :type task: :py:class:`waflib.Task.Task` """ assert isinstance(task, Task) self.run_after.add(task) def signature(self): """ Task signatures are stored between build executions, they are use to track the changes made to the input nodes (not to the outputs!). The signature hashes data from various sources: * explicit dependencies: files listed in the inputs (list of node objects) :py:meth:`waflib.Task.Task.sig_explicit_deps` * implicit dependencies: list of nodes returned by scanner methods (when present) :py:meth:`waflib.Task.Task.sig_implicit_deps` * hashed data: variables/values read from task.vars/task.env :py:meth:`waflib.Task.Task.sig_vars` If the signature is expected to give a different result, clear the cache kept in ``self.cache_sig``:: from waflib import Task class cls(Task.Task): def signature(self): sig = super(Task.Task, self).signature() delattr(self, 'cache_sig') return super(Task.Task, self).signature() :return: the signature value :rtype: string or bytes """ try: return self.cache_sig except AttributeError: pass self.m = Utils.md5(self.hcode) # explicit deps self.sig_explicit_deps() # env vars self.sig_vars() # implicit deps / scanner results if self.scan: try: self.sig_implicit_deps() except Errors.TaskRescan: return self.signature() ret = self.cache_sig = self.m.digest() return ret def runnable_status(self): """ Returns the Task status :return: a task state in :py:const:`waflib.Task.RUN_ME`, :py:const:`waflib.Task.SKIP_ME`, :py:const:`waflib.Task.CANCEL_ME` or :py:const:`waflib.Task.ASK_LATER`. :rtype: int """ bld = self.generator.bld if bld.is_install < 0: return SKIP_ME for t in self.run_after: if not t.hasrun: return ASK_LATER elif t.hasrun < SKIPPED: # a dependency has an error return CANCEL_ME # first compute the signature try: new_sig = self.signature() except Errors.TaskNotReady: return ASK_LATER # compare the signature to a signature computed previously key = self.uid() try: prev_sig = bld.task_sigs[key] except KeyError: Logs.debug('task: task %r must run: it was never run before or the task code changed', self) return RUN_ME if new_sig != prev_sig: Logs.debug('task: task %r must run: the task signature changed', self) return RUN_ME # compare the signatures of the outputs for node in self.outputs: sig = bld.node_sigs.get(node) if not sig: Logs.debug('task: task %r must run: an output node has no signature', self) return RUN_ME if sig != key: Logs.debug('task: task %r must run: an output node was produced by another task', self) return RUN_ME if not node.exists(): Logs.debug('task: task %r must run: an output node does not exist', self) return RUN_ME return (self.always_run and RUN_ME) or SKIP_ME def post_run(self): """ Called after successful execution to record that the task has run by updating the entry in :py:attr:`waflib.Build.BuildContext.task_sigs`. """ bld = self.generator.bld for node in self.outputs: if not node.exists(): self.hasrun = MISSING self.err_msg = '-> missing file: %r' % node.abspath() raise Errors.WafError(self.err_msg) bld.node_sigs[node] = self.uid() # make sure this task produced the files in question bld.task_sigs[self.uid()] = self.signature() if not self.keep_last_cmd: try: del self.last_cmd except AttributeError: pass def sig_explicit_deps(self): """ Used by :py:meth:`waflib.Task.Task.signature`; it hashes :py:attr:`waflib.Task.Task.inputs` and :py:attr:`waflib.Task.Task.dep_nodes` signatures. """ bld = self.generator.bld upd = self.m.update # the inputs for x in self.inputs + self.dep_nodes: upd(x.get_bld_sig()) # manual dependencies, they can slow down the builds if bld.deps_man: additional_deps = bld.deps_man for x in self.inputs + self.outputs: try: d = additional_deps[x] except KeyError: continue for v in d: try: v = v.get_bld_sig() except AttributeError: if hasattr(v, '__call__'): v = v() # dependency is a function, call it upd(v) def sig_deep_inputs(self): """ Enable rebuilds on input files task signatures. Not used by default. Example: hashes of output programs can be unchanged after being re-linked, despite the libraries being different. This method can thus prevent stale unit test results (waf_unit_test.py). Hashing input file timestamps is another possibility for the implementation. This may cause unnecessary rebuilds when input tasks are frequently executed. Here is an implementation example:: lst = [] for node in self.inputs + self.dep_nodes: st = os.stat(node.abspath()) lst.append(st.st_mtime) lst.append(st.st_size) self.m.update(Utils.h_list(lst)) The downside of the implementation is that it absolutely requires all build directory files to be declared within the current build. """ bld = self.generator.bld lst = [bld.task_sigs[bld.node_sigs[node]] for node in (self.inputs + self.dep_nodes) if node.is_bld()] self.m.update(Utils.h_list(lst)) def sig_vars(self): """ Used by :py:meth:`waflib.Task.Task.signature`; it hashes :py:attr:`waflib.Task.Task.env` variables/values When overriding this method, and if scriptlet expressions are used, make sure to follow the code in :py:meth:`waflib.Task.Task.compile_sig_vars` to enable dependencies on scriptlet results. This method may be replaced on subclasses by the metaclass to force dependencies on scriptlet code. """ sig = self.generator.bld.hash_env_vars(self.env, self.vars) self.m.update(sig) scan = None """ This method, when provided, returns a tuple containing: * a list of nodes corresponding to real files * a list of names for files not found in path_lst For example:: from waflib.Task import Task class mytask(Task): def scan(self, node): return ([], []) The first and second lists in the tuple are stored in :py:attr:`waflib.Build.BuildContext.node_deps` and :py:attr:`waflib.Build.BuildContext.raw_deps` respectively. """ def sig_implicit_deps(self): """ Used by :py:meth:`waflib.Task.Task.signature`; it hashes node signatures obtained by scanning for dependencies (:py:meth:`waflib.Task.Task.scan`). The exception :py:class:`waflib.Errors.TaskRescan` is thrown when a file has changed. In this case, the method :py:meth:`waflib.Task.Task.signature` is called once again, and return here to call :py:meth:`waflib.Task.Task.scan` and searching for dependencies. """ bld = self.generator.bld # get the task signatures from previous runs key = self.uid() prev = bld.imp_sigs.get(key, []) # for issue #379 if prev: try: if prev == self.compute_sig_implicit_deps(): return prev except Errors.TaskNotReady: raise except EnvironmentError: # when a file was renamed, remove the stale nodes (headers in folders without source files) # this will break the order calculation for headers created during the build in the source directory (should be uncommon) # the behaviour will differ when top != out for x in bld.node_deps.get(self.uid(), []): if not x.is_bld() and not x.exists(): try: del x.parent.children[x.name] except KeyError: pass del bld.imp_sigs[key] raise Errors.TaskRescan('rescan') # no previous run or the signature of the dependencies has changed, rescan the dependencies (bld.node_deps[key], bld.raw_deps[key]) = self.scan() if Logs.verbose: Logs.debug('deps: scanner for %s: %r; unresolved: %r', self, bld.node_deps[key], bld.raw_deps[key]) # recompute the signature and return it try: bld.imp_sigs[key] = self.compute_sig_implicit_deps() except EnvironmentError: for k in bld.node_deps.get(self.uid(), []): if not k.exists(): Logs.warn('Dependency %r for %r is missing: check the task declaration and the build order!', k, self) raise def compute_sig_implicit_deps(self): """ Used by :py:meth:`waflib.Task.Task.sig_implicit_deps` for computing the actual hash of the :py:class:`waflib.Node.Node` returned by the scanner. :return: a hash value for the implicit dependencies :rtype: string or bytes """ upd = self.m.update self.are_implicit_nodes_ready() # scanner returns a node that does not have a signature # just *ignore* the error and let them figure out from the compiler output # waf -k behaviour for k in self.generator.bld.node_deps.get(self.uid(), []): upd(k.get_bld_sig()) return self.m.digest() def are_implicit_nodes_ready(self): """ For each node returned by the scanner, see if there is a task that creates it, and infer the build order This has a low performance impact on null builds (1.86s->1.66s) thanks to caching (28s->1.86s) """ bld = self.generator.bld try: cache = bld.dct_implicit_nodes except AttributeError: bld.dct_implicit_nodes = cache = {} # one cache per build group try: dct = cache[bld.current_group] except KeyError: dct = cache[bld.current_group] = {} for tsk in bld.cur_tasks: for x in tsk.outputs: dct[x] = tsk modified = False for x in bld.node_deps.get(self.uid(), []): if x in dct: self.run_after.add(dct[x]) modified = True if modified: for tsk in self.run_after: if not tsk.hasrun: #print "task is not ready..." raise Errors.TaskNotReady('not ready') if sys.hexversion > 0x3000000: def uid(self): try: return self.uid_ except AttributeError: m = Utils.md5(self.__class__.__name__.encode('latin-1', 'xmlcharrefreplace')) up = m.update for x in self.inputs + self.outputs: up(x.abspath().encode('latin-1', 'xmlcharrefreplace')) self.uid_ = m.digest() return self.uid_ uid.__doc__ = Task.uid.__doc__ Task.uid = uid def is_before(t1, t2): """ Returns a non-zero value if task t1 is to be executed before task t2:: t1.ext_out = '.h' t2.ext_in = '.h' t2.after = ['t1'] t1.before = ['t2'] waflib.Task.is_before(t1, t2) # True :param t1: Task object :type t1: :py:class:`waflib.Task.Task` :param t2: Task object :type t2: :py:class:`waflib.Task.Task` """ to_list = Utils.to_list for k in to_list(t2.ext_in): if k in to_list(t1.ext_out): return 1 if t1.__class__.__name__ in to_list(t2.after): return 1 if t2.__class__.__name__ in to_list(t1.before): return 1 return 0 def set_file_constraints(tasks): """ Updates the ``run_after`` attribute of all tasks based on the task inputs and outputs :param tasks: tasks :type tasks: list of :py:class:`waflib.Task.Task` """ ins = Utils.defaultdict(set) outs = Utils.defaultdict(set) for x in tasks: for a in x.inputs: ins[a].add(x) for a in x.dep_nodes: ins[a].add(x) for a in x.outputs: outs[a].add(x) links = set(ins.keys()).intersection(outs.keys()) for k in links: for a in ins[k]: a.run_after.update(outs[k]) class TaskGroup(object): """ Wrap nxm task order constraints into a single object to prevent the creation of large list/set objects This is an optimization """ def __init__(self, prev, next): self.prev = prev self.next = next self.done = False def get_hasrun(self): for k in self.prev: if not k.hasrun: return NOT_RUN return SUCCESS hasrun = property(get_hasrun, None) def set_precedence_constraints(tasks): """ Updates the ``run_after`` attribute of all tasks based on the after/before/ext_out/ext_in attributes :param tasks: tasks :type tasks: list of :py:class:`waflib.Task.Task` """ cstr_groups = Utils.defaultdict(list) for x in tasks: h = x.hash_constraints() cstr_groups[h].append(x) keys = list(cstr_groups.keys()) maxi = len(keys) # this list should be short for i in range(maxi): t1 = cstr_groups[keys[i]][0] for j in range(i + 1, maxi): t2 = cstr_groups[keys[j]][0] # add the constraints based on the comparisons if is_before(t1, t2): a = i b = j elif is_before(t2, t1): a = j b = i else: continue a = cstr_groups[keys[a]] b = cstr_groups[keys[b]] if len(a) < 2 or len(b) < 2: for x in b: x.run_after.update(a) else: group = TaskGroup(set(a), set(b)) for x in b: x.run_after.add(group) def funex(c): """ Compiles a scriptlet expression into a Python function :param c: function to compile :type c: string :return: the function 'f' declared in the input string :rtype: function """ dc = {} exec(c, dc) return dc['f'] re_cond = re.compile(r'(?P\w+)|(?P\|)|(?P&)') re_novar = re.compile(r'^(SRC|TGT)\W+.*?$') reg_act = re.compile(r'(?P\\)|(?P\$\$)|(?P\$\{(?P\w+)(?P.*?)\})', re.M) def compile_fun_shell(line): """ Creates a compiled function to execute a process through a sub-shell """ extr = [] def repl(match): g = match.group if g('dollar'): return "$" elif g('backslash'): return '\\\\' elif g('subst'): extr.append((g('var'), g('code'))) return "%s" return None line = reg_act.sub(repl, line) or line dvars = [] def add_dvar(x): if x not in dvars: dvars.append(x) def replc(m): # performs substitutions and populates dvars if m.group('and'): return ' and ' elif m.group('or'): return ' or ' else: x = m.group('var') add_dvar(x) return 'env[%r]' % x parm = [] app = parm.append for (var, meth) in extr: if var == 'SRC': if meth: app('tsk.inputs%s' % meth) else: app('" ".join([a.path_from(cwdx) for a in tsk.inputs])') elif var == 'TGT': if meth: app('tsk.outputs%s' % meth) else: app('" ".join([a.path_from(cwdx) for a in tsk.outputs])') elif meth: if meth.startswith(':'): add_dvar(var) m = meth[1:] if m == 'SRC': m = '[a.path_from(cwdx) for a in tsk.inputs]' elif m == 'TGT': m = '[a.path_from(cwdx) for a in tsk.outputs]' elif re_novar.match(m): m = '[tsk.inputs%s]' % m[3:] elif re_novar.match(m): m = '[tsk.outputs%s]' % m[3:] else: add_dvar(m) if m[:3] not in ('tsk', 'gen', 'bld'): m = '%r' % m app('" ".join(tsk.colon(%r, %s))' % (var, m)) elif meth.startswith('?'): # In A?B|C output env.A if one of env.B or env.C is non-empty expr = re_cond.sub(replc, meth[1:]) app('p(%r) if (%s) else ""' % (var, expr)) else: call = '%s%s' % (var, meth) add_dvar(call) app(call) else: add_dvar(var) app("p('%s')" % var) if parm: parm = "%% (%s) " % (',\n\t\t'.join(parm)) else: parm = '' c = COMPILE_TEMPLATE_SHELL % (line, parm) Logs.debug('action: %s', c.strip().splitlines()) return (funex(c), dvars) reg_act_noshell = re.compile(r"(?P\s+)|(?P\$\{(?P\w+)(?P.*?)\})|(?P([^$ \t\n\r\f\v]|\$\$)+)", re.M) def compile_fun_noshell(line): """ Creates a compiled function to execute a process without a sub-shell """ buf = [] dvars = [] merge = False app = buf.append def add_dvar(x): if x not in dvars: dvars.append(x) def replc(m): # performs substitutions and populates dvars if m.group('and'): return ' and ' elif m.group('or'): return ' or ' else: x = m.group('var') add_dvar(x) return 'env[%r]' % x for m in reg_act_noshell.finditer(line): if m.group('space'): merge = False continue elif m.group('text'): app('[%r]' % m.group('text').replace('$$', '$')) elif m.group('subst'): var = m.group('var') code = m.group('code') if var == 'SRC': if code: app('[tsk.inputs%s]' % code) else: app('[a.path_from(cwdx) for a in tsk.inputs]') elif var == 'TGT': if code: app('[tsk.outputs%s]' % code) else: app('[a.path_from(cwdx) for a in tsk.outputs]') elif code: if code.startswith(':'): # a composed variable ${FOO:OUT} add_dvar(var) m = code[1:] if m == 'SRC': m = '[a.path_from(cwdx) for a in tsk.inputs]' elif m == 'TGT': m = '[a.path_from(cwdx) for a in tsk.outputs]' elif re_novar.match(m): m = '[tsk.inputs%s]' % m[3:] elif re_novar.match(m): m = '[tsk.outputs%s]' % m[3:] else: add_dvar(m) if m[:3] not in ('tsk', 'gen', 'bld'): m = '%r' % m app('tsk.colon(%r, %s)' % (var, m)) elif code.startswith('?'): # In A?B|C output env.A if one of env.B or env.C is non-empty expr = re_cond.sub(replc, code[1:]) app('to_list(env[%r] if (%s) else [])' % (var, expr)) else: # plain code such as ${tsk.inputs[0].abspath()} call = '%s%s' % (var, code) add_dvar(call) app('to_list(%s)' % call) else: # a plain variable such as # a plain variable like ${AR} app('to_list(env[%r])' % var) add_dvar(var) if merge: tmp = 'merge(%s, %s)' % (buf[-2], buf[-1]) del buf[-1] buf[-1] = tmp merge = True # next turn buf = ['lst.extend(%s)' % x for x in buf] fun = COMPILE_TEMPLATE_NOSHELL % "\n\t".join(buf) Logs.debug('action: %s', fun.strip().splitlines()) return (funex(fun), dvars) def compile_fun(line, shell=False): """ Parses a string expression such as '${CC} ${SRC} -o ${TGT}' and returns a pair containing: * The function created (compiled) for use as :py:meth:`waflib.Task.Task.run` * The list of variables that must cause rebuilds when *env* data is modified for example:: from waflib.Task import compile_fun compile_fun('cxx', '${CXX} -o ${TGT[0]} ${SRC} -I ${SRC[0].parent.bldpath()}') def build(bld): bld(source='wscript', rule='echo "foo\\${SRC[0].name}\\bar"') The env variables (CXX, ..) on the task must not hold dicts so as to preserve a consistent order. The reserved keywords ``TGT`` and ``SRC`` represent the task input and output nodes """ if isinstance(line, str): if line.find('<') > 0 or line.find('>') > 0 or line.find('&&') > 0: shell = True else: dvars_lst = [] funs_lst = [] for x in line: if isinstance(x, str): fun, dvars = compile_fun(x, shell) dvars_lst += dvars funs_lst.append(fun) else: # assume a function to let through funs_lst.append(x) def composed_fun(task): for x in funs_lst: ret = x(task) if ret: return ret return None return composed_fun, dvars_lst if shell: return compile_fun_shell(line) else: return compile_fun_noshell(line) def compile_sig_vars(vars): """ This method produces a sig_vars method suitable for subclasses that provide scriptlet code in their run_str code. If no such method can be created, this method returns None. The purpose of the sig_vars method returned is to ensures that rebuilds occur whenever the contents of the expression changes. This is the case B below:: import time # case A: regular variables tg = bld(rule='echo ${FOO}') tg.env.FOO = '%s' % time.time() # case B bld(rule='echo ${gen.foo}', foo='%s' % time.time()) :param vars: env variables such as CXXFLAGS or gen.foo :type vars: list of string :return: A sig_vars method relevant for dependencies if adequate, else None :rtype: A function, or None in most cases """ buf = [] for x in sorted(vars): if x[:3] in ('tsk', 'gen', 'bld'): buf.append('buf.append(%s)' % x) if buf: return funex(COMPILE_TEMPLATE_SIG_VARS % '\n\t'.join(buf)) return None def task_factory(name, func=None, vars=None, color='GREEN', ext_in=[], ext_out=[], before=[], after=[], shell=False, scan=None): """ Returns a new task subclass with the function ``run`` compiled from the line given. :param func: method run :type func: string or function :param vars: list of variables to hash :type vars: list of string :param color: color to use :type color: string :param shell: when *func* is a string, enable/disable the use of the shell :type shell: bool :param scan: method scan :type scan: function :rtype: :py:class:`waflib.Task.Task` """ params = { 'vars': vars or [], # function arguments are static, and this one may be modified by the class 'color': color, 'name': name, 'shell': shell, 'scan': scan, } if isinstance(func, str) or isinstance(func, tuple): params['run_str'] = func else: params['run'] = func cls = type(Task)(name, (Task,), params) classes[name] = cls if ext_in: cls.ext_in = Utils.to_list(ext_in) if ext_out: cls.ext_out = Utils.to_list(ext_out) if before: cls.before = Utils.to_list(before) if after: cls.after = Utils.to_list(after) return cls def deep_inputs(cls): """ Task class decorator to enable rebuilds on input files task signatures """ def sig_explicit_deps(self): Task.sig_explicit_deps(self) Task.sig_deep_inputs(self) cls.sig_explicit_deps = sig_explicit_deps return cls TaskBase = Task "Provided for compatibility reasons, TaskBase should not be used" class TaskSemaphore(object): """ Task semaphores provide a simple and efficient way of throttling the amount of a particular task to run concurrently. The throttling value is capped by the amount of maximum jobs, so for example, a `TaskSemaphore(10)` has no effect in a `-j2` build. Task semaphores are typically specified on the task class level:: class compile(waflib.Task.Task): semaphore = waflib.Task.TaskSemaphore(2) run_str = 'touch ${TGT}' Task semaphores are meant to be used by the build scheduler in the main thread, so there are no guarantees of thread safety. """ def __init__(self, num): """ :param num: maximum value of concurrent tasks :type num: int """ self.num = num self.locking = set() self.waiting = set() def is_locked(self): """Returns True if this semaphore cannot be acquired by more tasks""" return len(self.locking) >= self.num def acquire(self, tsk): """ Mark the semaphore as used by the given task (not re-entrant). :param tsk: task object :type tsk: :py:class:`waflib.Task.Task` :raises: :py:class:`IndexError` in case the resource is already acquired """ if self.is_locked(): raise IndexError('Cannot lock more %r' % self.locking) self.locking.add(tsk) def release(self, tsk): """ Mark the semaphore as unused by the given task. :param tsk: task object :type tsk: :py:class:`waflib.Task.Task` :raises: :py:class:`KeyError` in case the resource is not acquired by the task """ self.locking.remove(tsk) kupfer-328/waflib/TaskGen.py000066400000000000000000000636351500175051100160460ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2018 (ita) """ Task generators The class :py:class:`waflib.TaskGen.task_gen` encapsulates the creation of task objects (low-level code) The instances can have various parameters, but the creation of task nodes (Task.py) is deferred. To achieve this, various methods are called from the method "apply" """ import copy, re, os, functools from waflib import Task, Utils, Logs, Errors, ConfigSet, Node feats = Utils.defaultdict(set) """remember the methods declaring features""" HEADER_EXTS = ['.h', '.hpp', '.hxx', '.hh'] class task_gen(object): """ Instances of this class create :py:class:`waflib.Task.Task` when calling the method :py:meth:`waflib.TaskGen.task_gen.post` from the main thread. A few notes: * The methods to call (*self.meths*) can be specified dynamically (removing, adding, ..) * The 'features' are used to add methods to self.meths and then execute them * The attribute 'path' is a node representing the location of the task generator * The tasks created are added to the attribute *tasks* * The attribute 'idx' is a counter of task generators in the same path """ mappings = Utils.ordered_iter_dict() """Mappings are global file extension mappings that are retrieved in the order of definition""" prec = Utils.defaultdict(set) """Dict that holds the precedence execution rules for task generator methods""" def __init__(self, *k, **kw): """ Task generator objects predefine various attributes (source, target) for possible processing by process_rule (make-like rules) or process_source (extensions, misc methods) Tasks are stored on the attribute 'tasks'. They are created by calling methods listed in ``self.meths`` or referenced in the attribute ``features`` A topological sort is performed to execute the methods in correct order. The extra key/value elements passed in ``kw`` are set as attributes """ self.source = [] self.target = '' self.meths = [] """ List of method names to execute (internal) """ self.features = [] """ List of feature names for bringing new methods in """ self.tasks = [] """ Tasks created are added to this list """ if not 'bld' in kw: # task generators without a build context :-/ self.env = ConfigSet.ConfigSet() self.idx = 0 self.path = None else: self.bld = kw['bld'] self.env = self.bld.env.derive() self.path = kw.get('path', self.bld.path) # by default, emulate chdir when reading scripts # Provide a unique index per folder # This is part of a measure to prevent output file name collisions path = self.path.abspath() try: self.idx = self.bld.idx[path] = self.bld.idx.get(path, 0) + 1 except AttributeError: self.bld.idx = {} self.idx = self.bld.idx[path] = 1 # Record the global task generator count try: self.tg_idx_count = self.bld.tg_idx_count = self.bld.tg_idx_count + 1 except AttributeError: self.tg_idx_count = self.bld.tg_idx_count = 1 for key, val in kw.items(): setattr(self, key, val) def __str__(self): """Debugging helper""" return "" % (self.name, self.path.abspath()) def __repr__(self): """Debugging helper""" lst = [] for x in self.__dict__: if x not in ('env', 'bld', 'compiled_tasks', 'tasks'): lst.append("%s=%s" % (x, repr(getattr(self, x)))) return "bld(%s) in %s" % (", ".join(lst), self.path.abspath()) def get_cwd(self): """ Current working directory for the task generator, defaults to the build directory. This is still used in a few places but it should disappear at some point as the classes define their own working directory. :rtype: :py:class:`waflib.Node.Node` """ return self.bld.bldnode def get_name(self): """ If the attribute ``name`` is not set on the instance, the name is computed from the target name:: def build(bld): x = bld(name='foo') x.get_name() # foo y = bld(target='bar') y.get_name() # bar :rtype: string :return: name of this task generator """ try: return self._name except AttributeError: if isinstance(self.target, list): lst = [str(x) for x in self.target] name = self._name = ','.join(lst) else: name = self._name = str(self.target) return name def set_name(self, name): self._name = name name = property(get_name, set_name) def to_list(self, val): """ Ensures that a parameter is a list, see :py:func:`waflib.Utils.to_list` :type val: string or list of string :param val: input to return as a list :rtype: list """ if isinstance(val, str): return val.split() else: return val def post(self): """ Creates tasks for this task generators. The following operations are performed: #. The body of this method is called only once and sets the attribute ``posted`` #. The attribute ``features`` is used to add more methods in ``self.meths`` #. The methods are sorted by the precedence table ``self.prec`` or `:waflib:attr:waflib.TaskGen.task_gen.prec` #. The methods are then executed in order #. The tasks created are added to :py:attr:`waflib.TaskGen.task_gen.tasks` """ if getattr(self, 'posted', None): return False self.posted = True keys = set(self.meths) keys.update(feats['*']) # add the methods listed in the features self.features = Utils.to_list(self.features) for x in self.features: st = feats[x] if st: keys.update(st) elif not x in Task.classes: Logs.warn('feature %r does not exist - bind at least one method to it?', x) # copy the precedence table prec = {} prec_tbl = self.prec for x in prec_tbl: if x in keys: prec[x] = prec_tbl[x] # elements disconnected tmp = [] for a in keys: for x in prec.values(): if a in x: break else: tmp.append(a) tmp.sort(reverse=True) # topological sort out = [] while tmp: e = tmp.pop() if e in keys: out.append(e) try: nlst = prec[e] except KeyError: pass else: del prec[e] for x in nlst: for y in prec: if x in prec[y]: break else: tmp.append(x) tmp.sort(reverse=True) if prec: buf = ['Cycle detected in the method execution:'] for k, v in prec.items(): buf.append('- %s after %s' % (k, [x for x in v if x in prec])) raise Errors.WafError('\n'.join(buf)) self.meths = out # then we run the methods in order Logs.debug('task_gen: posting %s %d', self, id(self)) for x in out: try: v = getattr(self, x) except AttributeError: raise Errors.WafError('%r is not a valid task generator method' % x) Logs.debug('task_gen: -> %s (%d)', x, id(self)) v() Logs.debug('task_gen: posted %s', self.name) return True def get_hook(self, node): """ Returns the ``@extension`` method to call for a Node of a particular extension. :param node: Input file to process :type node: :py:class:`waflib.Tools.Node.Node` :return: A method able to process the input node by looking at the extension :rtype: function """ name = node.name for k in self.mappings: try: if name.endswith(k): return self.mappings[k] except TypeError: # regexps objects if k.match(name): return self.mappings[k] keys = list(self.mappings.keys()) raise Errors.WafError("File %r has no mapping in %r (load a waf tool?)" % (node, keys)) def create_task(self, name, src=None, tgt=None, **kw): """ Creates task instances. :param name: task class name :type name: string :param src: input nodes :type src: list of :py:class:`waflib.Tools.Node.Node` :param tgt: output nodes :type tgt: list of :py:class:`waflib.Tools.Node.Node` :return: A task object :rtype: :py:class:`waflib.Task.Task` """ task = Task.classes[name](env=self.env.derive(), generator=self) if src: task.set_inputs(src) if tgt: task.set_outputs(tgt) task.__dict__.update(kw) self.tasks.append(task) return task def clone(self, env): """ Makes a copy of a task generator. Once the copy is made, it is necessary to ensure that the it does not create the same output files as the original, or the same files may be compiled several times. :param env: A configuration set :type env: :py:class:`waflib.ConfigSet.ConfigSet` :return: A copy :rtype: :py:class:`waflib.TaskGen.task_gen` """ newobj = self.bld() for x in self.__dict__: if x in ('env', 'bld'): continue elif x in ('path', 'features'): setattr(newobj, x, getattr(self, x)) else: setattr(newobj, x, copy.copy(getattr(self, x))) newobj.posted = False if isinstance(env, str): newobj.env = self.bld.all_envs[env].derive() else: newobj.env = env.derive() return newobj def declare_chain(name='', rule=None, reentrant=None, color='BLUE', ext_in=[], ext_out=[], before=[], after=[], decider=None, scan=None, install_path=None, shell=False): """ Creates a new mapping and a task class for processing files by extension. See Tools/flex.py for an example. :param name: name for the task class :type name: string :param rule: function to execute or string to be compiled in a function :type rule: string or function :param reentrant: re-inject the output file in the process (done automatically, set to 0 to disable) :type reentrant: int :param color: color for the task output :type color: string :param ext_in: execute the task only after the files of such extensions are created :type ext_in: list of string :param ext_out: execute the task only before files of such extensions are processed :type ext_out: list of string :param before: execute instances of this task before classes of the given names :type before: list of string :param after: execute instances of this task after classes of the given names :type after: list of string :param decider: if present, function that returns a list of output file extensions (overrides ext_out for output files, but not for the build order) :type decider: function :param scan: scanner function for the task :type scan: function :param install_path: installation path for the output nodes :type install_path: string """ ext_in = Utils.to_list(ext_in) ext_out = Utils.to_list(ext_out) if not name: name = rule cls = Task.task_factory(name, rule, color=color, ext_in=ext_in, ext_out=ext_out, before=before, after=after, scan=scan, shell=shell) def x_file(self, node): if ext_in: _ext_in = ext_in[0] tsk = self.create_task(name, node) cnt = 0 ext = decider(self, node) if decider else cls.ext_out for x in ext: k = node.change_ext(x, ext_in=_ext_in) tsk.outputs.append(k) if reentrant != None: if cnt < int(reentrant): self.source.append(k) else: # reinject downstream files into the build for y in self.mappings: # ~ nfile * nextensions :-/ if k.name.endswith(y): self.source.append(k) break cnt += 1 if install_path: self.install_task = self.add_install_files(install_to=install_path, install_from=tsk.outputs) return tsk for x in cls.ext_in: task_gen.mappings[x] = x_file return x_file def taskgen_method(func): """ Decorator that registers method as a task generator method. The function must accept a task generator as first parameter:: from waflib.TaskGen import taskgen_method @taskgen_method def mymethod(self): pass :param func: task generator method to add :type func: function :rtype: function """ setattr(task_gen, func.__name__, func) return func def feature(*k): """ Decorator that registers a task generator method that will be executed when the object attribute ``feature`` contains the corresponding key(s):: from waflib.TaskGen import feature @feature('myfeature') def myfunction(self): print('that is my feature!') def build(bld): bld(features='myfeature') :param k: feature names :type k: list of string """ def deco(func): setattr(task_gen, func.__name__, func) for name in k: feats[name].update([func.__name__]) return func return deco def before_method(*k): """ Decorator that registera task generator method which will be executed before the functions of given name(s):: from waflib.TaskGen import feature, before @feature('myfeature') @before_method('fun2') def fun1(self): print('feature 1!') @feature('myfeature') def fun2(self): print('feature 2!') def build(bld): bld(features='myfeature') :param k: method names :type k: list of string """ def deco(func): setattr(task_gen, func.__name__, func) for fun_name in k: task_gen.prec[func.__name__].add(fun_name) return func return deco before = before_method def after_method(*k): """ Decorator that registers a task generator method which will be executed after the functions of given name(s):: from waflib.TaskGen import feature, after @feature('myfeature') @after_method('fun2') def fun1(self): print('feature 1!') @feature('myfeature') def fun2(self): print('feature 2!') def build(bld): bld(features='myfeature') :param k: method names :type k: list of string """ def deco(func): setattr(task_gen, func.__name__, func) for fun_name in k: task_gen.prec[fun_name].add(func.__name__) return func return deco after = after_method def extension(*k): """ Decorator that registers a task generator method which will be invoked during the processing of source files for the extension given:: from waflib import Task class mytask(Task): run_str = 'cp ${SRC} ${TGT}' @extension('.moo') def create_maa_file(self, node): self.create_task('mytask', node, node.change_ext('.maa')) def build(bld): bld(source='foo.moo') """ def deco(func): setattr(task_gen, func.__name__, func) for x in k: task_gen.mappings[x] = func return func return deco @taskgen_method def to_nodes(self, lst, path=None): """ Flatten the input list of string/nodes/lists into a list of nodes. It is used by :py:func:`waflib.TaskGen.process_source` and :py:func:`waflib.TaskGen.process_rule`. It is designed for source files, for folders, see :py:func:`waflib.Tools.ccroot.to_incnodes`: :param lst: input list :type lst: list of string and nodes :param path: path from which to search the nodes (by default, :py:attr:`waflib.TaskGen.task_gen.path`) :type path: :py:class:`waflib.Tools.Node.Node` :rtype: list of :py:class:`waflib.Tools.Node.Node` """ tmp = [] path = path or self.path find = path.find_resource if isinstance(lst, Node.Node): lst = [lst] for x in Utils.to_list(lst): if isinstance(x, str): node = find(x) elif hasattr(x, 'name'): node = x else: tmp.extend(self.to_nodes(x)) continue if not node: raise Errors.WafError('source not found: %r in %r' % (x, self)) tmp.append(node) return tmp @feature('*') def process_source(self): """ Processes each element in the attribute ``source`` by extension. #. The *source* list is converted through :py:meth:`waflib.TaskGen.to_nodes` to a list of :py:class:`waflib.Node.Node` first. #. File extensions are mapped to methods having the signature: ``def meth(self, node)`` by :py:meth:`waflib.TaskGen.extension` #. The method is retrieved through :py:meth:`waflib.TaskGen.task_gen.get_hook` #. When called, the methods may modify self.source to append more source to process #. The mappings can map an extension or a filename (see the code below) """ self.source = self.to_nodes(getattr(self, 'source', [])) for node in self.source: self.get_hook(node)(self, node) @feature('*') @before_method('process_source') def process_rule(self): """ Processes the attribute ``rule``. When present, :py:meth:`waflib.TaskGen.process_source` is disabled:: def build(bld): bld(rule='cp ${SRC} ${TGT}', source='wscript', target='bar.txt') Main attributes processed: * rule: command to execute, it can be a tuple of strings for multiple commands * chmod: permissions for the resulting files (integer value such as Utils.O755) * shell: set to False to execute the command directly (default is True to use a shell) * scan: scanner function * vars: list of variables to trigger rebuilds, such as CFLAGS * cls_str: string to display when executing the task * cls_keyword: label to display when executing the task * cache_rule: by default, try to re-use similar classes, set to False to disable * source: list of Node or string objects representing the source files required by this task * target: list of Node or string objects representing the files that this task creates * cwd: current working directory (Node or string) * stdout: standard output, set to None to prevent waf from capturing the text * stderr: standard error, set to None to prevent waf from capturing the text * timeout: timeout for command execution (Python 3) * always: whether to always run the command (False by default) * deep_inputs: whether the task must depend on the input file tasks too (False by default) """ if not getattr(self, 'rule', None): return # create the task class name = str(getattr(self, 'name', None) or self.target or getattr(self.rule, '__name__', self.rule)) # or we can put the class in a cache for performance reasons try: cache = self.bld.cache_rule_attr except AttributeError: cache = self.bld.cache_rule_attr = {} chmod = getattr(self, 'chmod', None) shell = getattr(self, 'shell', True) color = getattr(self, 'color', 'BLUE') scan = getattr(self, 'scan', None) _vars = getattr(self, 'vars', []) cls_str = getattr(self, 'cls_str', None) cls_keyword = getattr(self, 'cls_keyword', None) use_cache = getattr(self, 'cache_rule', 'True') deep_inputs = getattr(self, 'deep_inputs', False) scan_val = has_deps = hasattr(self, 'deps') if scan: scan_val = id(scan) key = Utils.h_list((name, self.rule, chmod, shell, color, cls_str, cls_keyword, scan_val, _vars, deep_inputs)) cls = None if use_cache: try: cls = cache[key] except KeyError: pass if not cls: rule = self.rule if chmod is not None: def chmod_fun(tsk): for x in tsk.outputs: os.chmod(x.abspath(), tsk.generator.chmod) if isinstance(rule, tuple): rule = list(rule) rule.append(chmod_fun) rule = tuple(rule) else: rule = (rule, chmod_fun) cls = Task.task_factory(name, rule, _vars, shell=shell, color=color) if cls_str: setattr(cls, '__str__', self.cls_str) if cls_keyword: setattr(cls, 'keyword', self.cls_keyword) if deep_inputs: Task.deep_inputs(cls) if scan: cls.scan = self.scan elif has_deps: def scan(self): deps = getattr(self.generator, 'deps', None) nodes = self.generator.to_nodes(deps) return [nodes, []] cls.scan = scan if use_cache: cache[key] = cls # now create one instance tsk = self.create_task(name) for x in ('after', 'before', 'ext_in', 'ext_out'): setattr(tsk, x, getattr(self, x, [])) if hasattr(self, 'stdout'): tsk.stdout = self.stdout if hasattr(self, 'stderr'): tsk.stderr = self.stderr if getattr(self, 'timeout', None): tsk.timeout = self.timeout if getattr(self, 'always', None): tsk.always_run = True if getattr(self, 'target', None): if isinstance(self.target, str): self.target = self.target.split() if not isinstance(self.target, list): self.target = [self.target] for x in self.target: if isinstance(x, str): tsk.outputs.append(self.path.find_or_declare(x)) else: x.parent.mkdir() # if a node was given, create the required folders tsk.outputs.append(x) if getattr(self, 'install_path', None): self.install_task = self.add_install_files(install_to=self.install_path, install_from=tsk.outputs, chmod=getattr(self, 'chmod', Utils.O644)) if getattr(self, 'source', None): tsk.inputs = self.to_nodes(self.source) # bypass the execution of process_source by setting the source to an empty list self.source = [] if getattr(self, 'cwd', None): tsk.cwd = self.cwd if isinstance(tsk.run, functools.partial): # Python documentation says: "partial objects defined in classes # behave like static methods and do not transform into bound # methods during instance attribute look-up." tsk.run = functools.partial(tsk.run, tsk) @feature('seq') def sequence_order(self): """ Adds a strict sequential constraint between the tasks generated by task generators. It works because task generators are posted in order. It will not post objects which belong to other folders. Example:: bld(features='javac seq') bld(features='jar seq') To start a new sequence, set the attribute seq_start, for example:: obj = bld(features='seq') obj.seq_start = True Note that the method is executed in last position. This is more an example than a widely-used solution. """ if self.meths and self.meths[-1] != 'sequence_order': self.meths.append('sequence_order') return if getattr(self, 'seq_start', None): return # all the tasks previously declared must be run before these if getattr(self.bld, 'prev', None): self.bld.prev.post() for x in self.bld.prev.tasks: for y in self.tasks: y.set_run_after(x) self.bld.prev = self re_m4 = re.compile(r'@(\w+)@', re.M) class subst_pc(Task.Task): """ Creates *.pc* files from *.pc.in*. The task is executed whenever an input variable used in the substitution changes. """ def force_permissions(self): "Private for the time being, we will probably refactor this into run_str=[run1,chmod]" if getattr(self.generator, 'chmod', None): for x in self.outputs: os.chmod(x.abspath(), self.generator.chmod) def run(self): "Substitutes variables in a .in file" if getattr(self.generator, 'is_copy', None): for i, x in enumerate(self.outputs): x.write(self.inputs[i].read('rb'), 'wb') stat = os.stat(self.inputs[i].abspath()) # Preserve mtime of the copy os.utime(self.outputs[i].abspath(), (stat.st_atime, stat.st_mtime)) self.force_permissions() return None if getattr(self.generator, 'fun', None): ret = self.generator.fun(self) if not ret: self.force_permissions() return ret code = self.inputs[0].read(encoding=getattr(self.generator, 'encoding', 'latin-1')) if getattr(self.generator, 'subst_fun', None): code = self.generator.subst_fun(self, code) if code is not None: self.outputs[0].write(code, encoding=getattr(self.generator, 'encoding', 'latin-1')) self.force_permissions() return None # replace all % by %% to prevent errors by % signs code = code.replace('%', '%%') # extract the vars foo into lst and replace @foo@ by %(foo)s lst = [] def repl(match): g = match.group if g(1): lst.append(g(1)) return "%%(%s)s" % g(1) return '' code = getattr(self.generator, 're_m4', re_m4).sub(repl, code) try: d = self.generator.dct except AttributeError: d = {} for x in lst: tmp = getattr(self.generator, x, '') or self.env[x] or self.env[x.upper()] try: tmp = ''.join(tmp) except TypeError: tmp = str(tmp) d[x] = tmp code = code % d self.outputs[0].write(code, encoding=getattr(self.generator, 'encoding', 'latin-1')) self.generator.bld.raw_deps[self.uid()] = lst # make sure the signature is updated try: delattr(self, 'cache_sig') except AttributeError: pass self.force_permissions() def sig_vars(self): """ Compute a hash (signature) of the variables used in the substitution """ bld = self.generator.bld env = self.env upd = self.m.update if getattr(self.generator, 'fun', None): upd(Utils.h_fun(self.generator.fun).encode()) if getattr(self.generator, 'subst_fun', None): upd(Utils.h_fun(self.generator.subst_fun).encode()) # raw_deps: persistent custom values returned by the scanner vars = self.generator.bld.raw_deps.get(self.uid(), []) # hash both env vars and task generator attributes act_sig = bld.hash_env_vars(env, vars) upd(act_sig) lst = [getattr(self.generator, x, '') for x in vars] upd(Utils.h_list(lst)) return self.m.digest() @extension('.pc.in') def add_pcfile(self, node): """ Processes *.pc.in* files to *.pc*. Installs the results to ``${PREFIX}/lib/pkgconfig/`` by default def build(bld): bld(source='foo.pc.in', install_path='${LIBDIR}/pkgconfig/') """ tsk = self.create_task('subst_pc', node, node.change_ext('.pc', '.pc.in')) self.install_task = self.add_install_files( install_to=getattr(self, 'install_path', '${LIBDIR}/pkgconfig/'), install_from=tsk.outputs) class subst(subst_pc): pass @feature('subst') @before_method('process_source', 'process_rule') def process_subst(self): """ Defines a transformation that substitutes the contents of *source* files to *target* files:: def build(bld): bld( features='subst', source='foo.c.in', target='foo.c', install_path='${LIBDIR}/pkgconfig', VAR = 'val' ) The input files are supposed to contain macros of the form *@VAR@*, where *VAR* is an argument of the task generator object. This method overrides the processing by :py:meth:`waflib.TaskGen.process_source`. """ src = Utils.to_list(getattr(self, 'source', [])) if isinstance(src, Node.Node): src = [src] tgt = Utils.to_list(getattr(self, 'target', [])) if isinstance(tgt, Node.Node): tgt = [tgt] if len(src) != len(tgt): raise Errors.WafError('invalid number of source/target for %r' % self) for x, y in zip(src, tgt): if not x or not y: raise Errors.WafError('null source or target for %r' % self) a, b = None, None if isinstance(x, str) and isinstance(y, str) and x == y: a = self.path.find_node(x) b = self.path.get_bld().make_node(y) if not os.path.isfile(b.abspath()): b.parent.mkdir() else: if isinstance(x, str): a = self.path.find_resource(x) elif isinstance(x, Node.Node): a = x if isinstance(y, str): b = self.path.find_or_declare(y) elif isinstance(y, Node.Node): b = y if not a: raise Errors.WafError('could not find %r for %r' % (x, self)) tsk = self.create_task('subst', a, b) for k in ('after', 'before', 'ext_in', 'ext_out'): val = getattr(self, k, None) if val: setattr(tsk, k, val) # paranoid safety measure for the general case foo.in->foo.h with ambiguous dependencies for xt in HEADER_EXTS: if b.name.endswith(xt): tsk.ext_out = tsk.ext_out + ['.h'] break inst_to = getattr(self, 'install_path', None) if inst_to: self.install_task = self.add_install_files(install_to=inst_to, install_from=b, chmod=getattr(self, 'chmod', Utils.O644)) self.source = [] kupfer-328/waflib/Tools/000077500000000000000000000000001500175051100152235ustar00rootroot00000000000000kupfer-328/waflib/Tools/__init__.py000066400000000000000000000001071500175051100173320ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2018 (ita) kupfer-328/waflib/Tools/c_aliases.py000066400000000000000000000067741500175051100175360ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2015 (ita) "base for all c/c++ programs and libraries" from waflib import Utils, Errors from waflib.Configure import conf def get_extensions(lst): """ Returns the file extensions for the list of files given as input :param lst: files to process :list lst: list of string or :py:class:`waflib.Node.Node` :return: list of file extensions :rtype: list of string """ ret = [] for x in Utils.to_list(lst): if not isinstance(x, str): x = x.name ret.append(x[x.rfind('.') + 1:]) return ret def sniff_features(**kw): """ Computes and returns the features required for a task generator by looking at the file extensions. This aimed for C/C++ mainly:: snif_features(source=['foo.c', 'foo.cxx'], type='shlib') # returns ['cxx', 'c', 'cxxshlib', 'cshlib'] :param source: source files to process :type source: list of string or :py:class:`waflib.Node.Node` :param type: object type in *program*, *shlib* or *stlib* :type type: string :return: the list of features for a task generator processing the source files :rtype: list of string """ exts = get_extensions(kw.get('source', [])) typ = kw['typ'] feats = [] # watch the order, cxx will have the precedence for x in 'cxx cpp c++ cc C'.split(): if x in exts: feats.append('cxx') break if 'c' in exts or 'vala' in exts or 'gs' in exts: feats.append('c') if 's' in exts or 'S' in exts: feats.append('asm') for x in 'f f90 F F90 for FOR'.split(): if x in exts: feats.append('fc') break if 'd' in exts: feats.append('d') if 'java' in exts: feats.append('java') return 'java' if typ in ('program', 'shlib', 'stlib'): will_link = False for x in feats: if x in ('cxx', 'd', 'fc', 'c', 'asm'): feats.append(x + typ) will_link = True if not will_link and not kw.get('features', []): raise Errors.WafError('Unable to determine how to link %r, try adding eg: features="c cshlib"?' % kw) return feats def set_features(kw, typ): """ Inserts data in the input dict *kw* based on existing data and on the type of target required (typ). :param kw: task generator parameters :type kw: dict :param typ: type of target :type typ: string """ kw['typ'] = typ kw['features'] = Utils.to_list(kw.get('features', [])) + Utils.to_list(sniff_features(**kw)) @conf def program(bld, *k, **kw): """ Alias for creating programs by looking at the file extensions:: def build(bld): bld.program(source='foo.c', target='app') # equivalent to: # bld(features='c cprogram', source='foo.c', target='app') """ set_features(kw, 'program') return bld(*k, **kw) @conf def shlib(bld, *k, **kw): """ Alias for creating shared libraries by looking at the file extensions:: def build(bld): bld.shlib(source='foo.c', target='app') # equivalent to: # bld(features='c cshlib', source='foo.c', target='app') """ set_features(kw, 'shlib') return bld(*k, **kw) @conf def stlib(bld, *k, **kw): """ Alias for creating static libraries by looking at the file extensions:: def build(bld): bld.stlib(source='foo.cpp', target='app') # equivalent to: # bld(features='cxx cxxstlib', source='foo.cpp', target='app') """ set_features(kw, 'stlib') return bld(*k, **kw) @conf def objects(bld, *k, **kw): """ Alias for creating object files by looking at the file extensions:: def build(bld): bld.objects(source='foo.c', target='app') # equivalent to: # bld(features='c', source='foo.c', target='app') """ set_features(kw, 'objects') return bld(*k, **kw) kupfer-328/waflib/Tools/c_config.py000066400000000000000000001220121500175051100173420ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2018 (ita) """ C/C++/D configuration helpers """ from __future__ import with_statement import os, re, shlex from waflib import Build, Utils, Task, Options, Logs, Errors, Runner from waflib.TaskGen import after_method, feature from waflib.Configure import conf WAF_CONFIG_H = 'config.h' """default name for the config.h file""" DEFKEYS = 'define_key' INCKEYS = 'include_key' SNIP_EMPTY_PROGRAM = ''' int main(int argc, char **argv) { (void)argc; (void)argv; return 0; } ''' MACRO_TO_DESTOS = { '__linux__' : 'linux', '__GNU__' : 'gnu', # hurd '__FreeBSD__' : 'freebsd', '__NetBSD__' : 'netbsd', '__OpenBSD__' : 'openbsd', '__sun' : 'sunos', '__hpux' : 'hpux', '__sgi' : 'irix', '_AIX' : 'aix', '__CYGWIN__' : 'cygwin', '__MSYS__' : 'cygwin', '_UWIN' : 'uwin', '_WIN64' : 'win32', '_WIN32' : 'win32', # Note about darwin: this is also tested with 'defined __APPLE__ && defined __MACH__' somewhere below in this file. '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' : 'darwin', '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' : 'darwin', # iphone '__QNX__' : 'qnx', '__native_client__' : 'nacl' # google native client platform } MACRO_TO_DEST_CPU = { '__x86_64__' : 'x86_64', '__amd64__' : 'x86_64', '__i386__' : 'x86', '__ia64__' : 'ia', '__mips__' : 'mips', '__sparc__' : 'sparc', '__alpha__' : 'alpha', '__aarch64__' : 'aarch64', '__thumb__' : 'thumb', '__arm__' : 'arm', '__hppa__' : 'hppa', '__powerpc__' : 'powerpc', '__ppc__' : 'powerpc', '__convex__' : 'convex', '__m68k__' : 'm68k', '__s390x__' : 's390x', '__s390__' : 's390', '__sh__' : 'sh', '__xtensa__' : 'xtensa', '__e2k__' : 'e2k', '__riscv' : 'riscv', } @conf def parse_flags(self, line, uselib_store, env=None, force_static=False, posix=None): """ Parses flags from the input lines, and adds them to the relevant use variables:: def configure(conf): conf.parse_flags('-O3', 'FOO') # conf.env.CXXFLAGS_FOO = ['-O3'] # conf.env.CFLAGS_FOO = ['-O3'] :param line: flags :type line: string :param uselib_store: where to add the flags :type uselib_store: string :param env: config set or conf.env by default :type env: :py:class:`waflib.ConfigSet.ConfigSet` :param force_static: force usage of static libraries :type force_static: bool default False :param posix: usage of POSIX mode for shlex lexical analiysis library :type posix: bool default True """ assert(isinstance(line, str)) env = env or self.env # Issue 811 and 1371 if posix is None: posix = True if '\\' in line: posix = ('\\ ' in line) or ('\\\\' in line) lex = shlex.shlex(line, posix=posix) lex.whitespace_split = True lex.commenters = '' lst = list(lex) so_re = re.compile(r"\.so(?:\.[0-9]+)*$") # append_unique is not always possible # for example, apple flags may require both -arch i386 and -arch ppc uselib = uselib_store def app(var, val): env.append_value('%s_%s' % (var, uselib), val) def appu(var, val): env.append_unique('%s_%s' % (var, uselib), val) static = False while lst: x = lst.pop(0) st = x[:2] ot = x[2:] if st == '-I' or st == '/I': if not ot: ot = lst.pop(0) appu('INCLUDES', ot) elif st == '-i': tmp = [x, lst.pop(0)] app('CFLAGS', tmp) app('CXXFLAGS', tmp) elif st == '-D' or (env.CXX_NAME == 'msvc' and st == '/D'): # not perfect but.. if not ot: ot = lst.pop(0) app('DEFINES', ot) elif st == '-l': if not ot: ot = lst.pop(0) prefix = 'STLIB' if (force_static or static) else 'LIB' app(prefix, ot) elif st == '-L': if not ot: ot = lst.pop(0) prefix = 'STLIBPATH' if (force_static or static) else 'LIBPATH' appu(prefix, ot) elif x.startswith('/LIBPATH:'): prefix = 'STLIBPATH' if (force_static or static) else 'LIBPATH' appu(prefix, x.replace('/LIBPATH:', '')) elif x.startswith('-std='): prefix = 'CXXFLAGS' if '++' in x else 'CFLAGS' app(prefix, x) elif x.startswith('+') or x in ('-pthread', '-fPIC', '-fpic', '-fPIE', '-fpie', '-flto', '-fno-lto'): app('CFLAGS', x) app('CXXFLAGS', x) app('LINKFLAGS', x) elif x == '-framework': appu('FRAMEWORK', lst.pop(0)) elif x.startswith('-F'): appu('FRAMEWORKPATH', x[2:]) elif x == '-Wl,-rpath' or x == '-Wl,-R': app('RPATH', lst.pop(0).lstrip('-Wl,')) elif x.startswith('-Wl,-R,'): app('RPATH', x[7:]) elif x.startswith('-Wl,-R'): app('RPATH', x[6:]) elif x.startswith('-Wl,-rpath,'): app('RPATH', x[11:]) elif x == '-Wl,-Bstatic' or x == '-Bstatic': static = True elif x == '-Wl,-Bdynamic' or x == '-Bdynamic': static = False elif x.startswith('-Wl') or x in ('-rdynamic', '-pie'): app('LINKFLAGS', x) elif x.startswith(('-m', '-f', '-dynamic', '-O', '-g')): # Adding the -W option breaks python builds on Openindiana app('CFLAGS', x) app('CXXFLAGS', x) elif x.startswith('-bundle'): app('LINKFLAGS', x) elif x.startswith(('-undefined', '-Xlinker')): arg = lst.pop(0) app('LINKFLAGS', [x, arg]) elif x.startswith(('-arch', '-isysroot')): tmp = [x, lst.pop(0)] app('CFLAGS', tmp) app('CXXFLAGS', tmp) app('LINKFLAGS', tmp) elif x.endswith(('.a', '.dylib', '.lib')) or so_re.search(x): appu('LINKFLAGS', x) # not cool, #762 else: self.to_log('Unhandled flag %r' % x) @conf def validate_cfg(self, kw): """ Searches for the program *pkg-config* if missing, and validates the parameters to pass to :py:func:`waflib.Tools.c_config.exec_cfg`. :param path: the **-config program to use** (default is *pkg-config*) :type path: list of string :param msg: message to display to describe the test executed :type msg: string :param okmsg: message to display when the test is successful :type okmsg: string :param errmsg: message to display in case of error :type errmsg: string """ if not 'path' in kw: if not self.env.PKGCONFIG: self.find_program('pkg-config', var='PKGCONFIG') kw['path'] = self.env.PKGCONFIG # verify that exactly one action is requested s = ('atleast_pkgconfig_version' in kw) + ('modversion' in kw) + ('package' in kw) if s != 1: raise ValueError('exactly one of atleast_pkgconfig_version, modversion and package must be set') if not 'msg' in kw: if 'atleast_pkgconfig_version' in kw: kw['msg'] = 'Checking for pkg-config version >= %r' % kw['atleast_pkgconfig_version'] elif 'modversion' in kw: kw['msg'] = 'Checking for %r version' % kw['modversion'] else: kw['msg'] = 'Checking for %r' %(kw['package']) # let the modversion check set the okmsg to the detected version if not 'okmsg' in kw and not 'modversion' in kw: kw['okmsg'] = 'yes' if not 'errmsg' in kw: kw['errmsg'] = 'not found' # pkg-config version if 'atleast_pkgconfig_version' in kw: pass elif 'modversion' in kw: if not 'uselib_store' in kw: kw['uselib_store'] = kw['modversion'] if not 'define_name' in kw: kw['define_name'] = '%s_VERSION' % Utils.quote_define_name(kw['uselib_store']) else: if not 'uselib_store' in kw: kw['uselib_store'] = Utils.to_list(kw['package'])[0].upper() if not 'define_name' in kw: kw['define_name'] = self.have_define(kw['uselib_store']) @conf def exec_cfg(self, kw): """ Executes ``pkg-config`` or other ``-config`` applications to collect configuration flags: * if atleast_pkgconfig_version is given, check that pkg-config has the version n and return * if modversion is given, then return the module version * else, execute the *-config* program with the *args* and *variables* given, and set the flags on the *conf.env.FLAGS_name* variable :param path: the **-config program to use** :type path: list of string :param atleast_pkgconfig_version: minimum pkg-config version to use (disable other tests) :type atleast_pkgconfig_version: string :param package: package name, for example *gtk+-2.0* :type package: string :param uselib_store: if the test is successful, define HAVE\\_*name*. It is also used to define *conf.env.FLAGS_name* variables. :type uselib_store: string :param modversion: if provided, return the version of the given module and define *name*\\_VERSION :type modversion: string :param args: arguments to give to *package* when retrieving flags :type args: list of string :param variables: return the values of particular variables :type variables: list of string :param define_variable: additional variables to define (also in conf.env.PKG_CONFIG_DEFINES) :type define_variable: dict(string: string) :param pkg_config_path: paths where pkg-config should search for .pc config files (overrides env.PKG_CONFIG_PATH if exists) :type pkg_config_path: string, list of directories separated by colon :param force_static: force usage of static libraries :type force_static: bool default False :param posix: usage of POSIX mode for shlex lexical analiysis library :type posix: bool default True """ path = Utils.to_list(kw['path']) env = self.env.env or None if kw.get('pkg_config_path'): if not env: env = dict(self.environ) env['PKG_CONFIG_PATH'] = kw['pkg_config_path'] def define_it(): define_name = kw['define_name'] # by default, add HAVE_X to the config.h, else provide DEFINES_X for use=X if kw.get('global_define', 1): self.define(define_name, 1, False) else: self.env.append_unique('DEFINES_%s' % kw['uselib_store'], "%s=1" % define_name) if kw.get('add_have_to_env', 1): self.env[define_name] = 1 # pkg-config version if 'atleast_pkgconfig_version' in kw: cmd = path + ['--atleast-pkgconfig-version=%s' % kw['atleast_pkgconfig_version']] self.cmd_and_log(cmd, env=env) return # single version for a module if 'modversion' in kw: version = self.cmd_and_log(path + ['--modversion', kw['modversion']], env=env).strip() if not 'okmsg' in kw: kw['okmsg'] = version self.define(kw['define_name'], version) return version lst = [] + path defi = kw.get('define_variable') if not defi: defi = self.env.PKG_CONFIG_DEFINES or {} for key, val in defi.items(): lst.append('--define-variable=%s=%s' % (key, val)) static = kw.get('force_static', False) if 'args' in kw: args = Utils.to_list(kw['args']) if '--static' in args or '--static-libs' in args: static = True lst += args # tools like pkgconf expect the package argument after the -- ones -_- lst.extend(Utils.to_list(kw['package'])) # retrieving variables of a module if 'variables' in kw: v_env = kw.get('env', self.env) vars = Utils.to_list(kw['variables']) for v in vars: val = self.cmd_and_log(lst + ['--variable=' + v], env=env).strip() var = '%s_%s' % (kw['uselib_store'], v) v_env[var] = val return # so we assume the command-line will output flags to be parsed afterwards ret = self.cmd_and_log(lst, env=env) define_it() self.parse_flags(ret, kw['uselib_store'], kw.get('env', self.env), force_static=static, posix=kw.get('posix')) return ret @conf def check_cfg(self, *k, **kw): """ Checks for configuration flags using a **-config**-like program (pkg-config, sdl-config, etc). This wraps internal calls to :py:func:`waflib.Tools.c_config.validate_cfg` and :py:func:`waflib.Tools.c_config.exec_cfg` so check exec_cfg parameters descriptions for more details on kw passed A few examples:: def configure(conf): conf.load('compiler_c') conf.check_cfg(package='glib-2.0', args='--libs --cflags') conf.check_cfg(package='pango') conf.check_cfg(package='pango', uselib_store='MYPANGO', args=['--cflags', '--libs']) conf.check_cfg(package='pango', args=['pango >= 0.1.0', 'pango < 9.9.9', '--cflags', '--libs'], msg="Checking for 'pango 0.1.0'") conf.check_cfg(path='sdl-config', args='--cflags --libs', package='', uselib_store='SDL') conf.check_cfg(path='mpicc', args='--showme:compile --showme:link', package='', uselib_store='OPEN_MPI', mandatory=False) # variables conf.check_cfg(package='gtk+-2.0', variables=['includedir', 'prefix'], uselib_store='FOO') print(conf.env.FOO_includedir) """ self.validate_cfg(kw) if 'msg' in kw: self.start_msg(kw['msg'], **kw) ret = None try: ret = self.exec_cfg(kw) except self.errors.WafError as e: if 'errmsg' in kw: self.end_msg(kw['errmsg'], 'YELLOW', **kw) if Logs.verbose > 1: self.to_log('Command failure: %s' % e) self.fatal('The configuration failed') else: if not ret: ret = True kw['success'] = ret if 'okmsg' in kw: self.end_msg(self.ret_msg(kw['okmsg'], kw), **kw) return ret def build_fun(bld): """ Build function that is used for running configuration tests with ``conf.check()`` """ if bld.kw['compile_filename']: node = bld.srcnode.make_node(bld.kw['compile_filename']) node.write(bld.kw['code']) o = bld(features=bld.kw['features'], source=bld.kw['compile_filename'], target='testprog') for k, v in bld.kw.items(): setattr(o, k, v) if not bld.kw.get('quiet'): bld.conf.to_log("==>\n%s\n<==" % bld.kw['code']) @conf def validate_c(self, kw): """ Pre-checks the parameters that will be given to :py:func:`waflib.Configure.run_build` :param compiler: c or cxx (tries to guess what is best) :type compiler: string :param type: cprogram, cshlib, cstlib - not required if *features are given directly* :type type: binary to create :param feature: desired features for the task generator that will execute the test, for example ``cxx cxxstlib`` :type feature: list of string :param fragment: provide a piece of code for the test (default is to let the system create one) :type fragment: string :param uselib_store: define variables after the test is executed (IMPORTANT!) :type uselib_store: string :param use: parameters to use for building (just like the normal *use* keyword) :type use: list of string :param define_name: define to set when the check is over :type define_name: string :param execute: execute the resulting binary :type execute: bool :param define_ret: if execute is set to True, use the execution output in both the define and the return value :type define_ret: bool :param header_name: check for a particular header :type header_name: string :param auto_add_header_name: if header_name was set, add the headers in env.INCKEYS so the next tests will include these headers :type auto_add_header_name: bool """ for x in ('type_name', 'field_name', 'function_name'): if x in kw: Logs.warn('Invalid argument %r in test' % x) if not 'build_fun' in kw: kw['build_fun'] = build_fun if not 'env' in kw: kw['env'] = self.env.derive() env = kw['env'] if not 'compiler' in kw and not 'features' in kw: kw['compiler'] = 'c' if env.CXX_NAME and Task.classes.get('cxx'): kw['compiler'] = 'cxx' if not self.env.CXX: self.fatal('a c++ compiler is required') else: if not self.env.CC: self.fatal('a c compiler is required') if not 'compile_mode' in kw: kw['compile_mode'] = 'c' if 'cxx' in Utils.to_list(kw.get('features', [])) or kw.get('compiler') == 'cxx': kw['compile_mode'] = 'cxx' if not 'type' in kw: kw['type'] = 'cprogram' if not 'features' in kw: if not 'header_name' in kw or kw.get('link_header_test', True): kw['features'] = [kw['compile_mode'], kw['type']] # "c ccprogram" else: kw['features'] = [kw['compile_mode']] else: kw['features'] = Utils.to_list(kw['features']) if not 'compile_filename' in kw: kw['compile_filename'] = 'test.c' + ((kw['compile_mode'] == 'cxx') and 'pp' or '') def to_header(dct): if 'header_name' in dct: dct = Utils.to_list(dct['header_name']) return ''.join(['#include <%s>\n' % x for x in dct]) return '' if 'framework_name' in kw: # OSX, not sure this is used anywhere fwkname = kw['framework_name'] if not 'uselib_store' in kw: kw['uselib_store'] = fwkname.upper() if not kw.get('no_header'): fwk = '%s/%s.h' % (fwkname, fwkname) if kw.get('remove_dot_h'): fwk = fwk[:-2] val = kw.get('header_name', []) kw['header_name'] = Utils.to_list(val) + [fwk] kw['msg'] = 'Checking for framework %s' % fwkname kw['framework'] = fwkname elif 'header_name' in kw: if not 'msg' in kw: kw['msg'] = 'Checking for header %s' % kw['header_name'] l = Utils.to_list(kw['header_name']) assert len(l), 'list of headers in header_name is empty' kw['code'] = to_header(kw) + SNIP_EMPTY_PROGRAM if not 'uselib_store' in kw: kw['uselib_store'] = l[0].upper() if not 'define_name' in kw: kw['define_name'] = self.have_define(l[0]) if 'lib' in kw: if not 'msg' in kw: kw['msg'] = 'Checking for library %s' % kw['lib'] if not 'uselib_store' in kw: kw['uselib_store'] = kw['lib'].upper() if 'stlib' in kw: if not 'msg' in kw: kw['msg'] = 'Checking for static library %s' % kw['stlib'] if not 'uselib_store' in kw: kw['uselib_store'] = kw['stlib'].upper() if 'fragment' in kw: # an additional code fragment may be provided to replace the predefined code # in custom headers kw['code'] = kw['fragment'] if not 'msg' in kw: kw['msg'] = 'Checking for code snippet' if not 'errmsg' in kw: kw['errmsg'] = 'no' for (flagsname,flagstype) in (('cxxflags','compiler'), ('cflags','compiler'), ('linkflags','linker')): if flagsname in kw: if not 'msg' in kw: kw['msg'] = 'Checking for %s flags %s' % (flagstype, kw[flagsname]) if not 'errmsg' in kw: kw['errmsg'] = 'no' if not 'execute' in kw: kw['execute'] = False if kw['execute']: kw['features'].append('test_exec') kw['chmod'] = Utils.O755 if not 'errmsg' in kw: kw['errmsg'] = 'not found' if not 'okmsg' in kw: kw['okmsg'] = 'yes' if not 'code' in kw: kw['code'] = SNIP_EMPTY_PROGRAM # if there are headers to append automatically to the next tests if self.env[INCKEYS]: kw['code'] = '\n'.join(['#include <%s>' % x for x in self.env[INCKEYS]]) + '\n' + kw['code'] # in case defines lead to very long command-lines if kw.get('merge_config_header') or env.merge_config_header: kw['code'] = '%s\n\n%s' % (self.get_config_header(), kw['code']) env.DEFINES = [] # modify the copy if not kw.get('success'): kw['success'] = None if 'define_name' in kw: self.undefine(kw['define_name']) if not 'msg' in kw: self.fatal('missing "msg" in conf.check(...)') @conf def post_check(self, *k, **kw): """ Sets the variables after a test executed in :py:func:`waflib.Tools.c_config.check` was run successfully """ is_success = 0 if kw['execute']: if kw['success'] is not None: if kw.get('define_ret'): is_success = kw['success'] else: is_success = (kw['success'] == 0) else: is_success = (kw['success'] == 0) if kw.get('define_name'): comment = kw.get('comment', '') define_name = kw['define_name'] if kw['execute'] and kw.get('define_ret') and isinstance(is_success, str): if kw.get('global_define', 1): self.define(define_name, is_success, quote=kw.get('quote', 1), comment=comment) else: if kw.get('quote', 1): succ = '"%s"' % is_success else: succ = int(is_success) val = '%s=%s' % (define_name, succ) var = 'DEFINES_%s' % kw['uselib_store'] self.env.append_value(var, val) else: if kw.get('global_define', 1): self.define_cond(define_name, is_success, comment=comment) else: var = 'DEFINES_%s' % kw['uselib_store'] self.env.append_value(var, '%s=%s' % (define_name, int(is_success))) # define conf.env.HAVE_X to 1 if kw.get('add_have_to_env', 1): if kw.get('uselib_store'): self.env[self.have_define(kw['uselib_store'])] = 1 elif kw['execute'] and kw.get('define_ret'): self.env[define_name] = is_success else: self.env[define_name] = int(is_success) if 'header_name' in kw: if kw.get('auto_add_header_name'): self.env.append_value(INCKEYS, Utils.to_list(kw['header_name'])) if is_success and 'uselib_store' in kw: from waflib.Tools import ccroot # See get_uselib_vars in ccroot.py _vars = set() for x in kw['features']: if x in ccroot.USELIB_VARS: _vars |= ccroot.USELIB_VARS[x] for k in _vars: x = k.lower() if x in kw: self.env.append_value(k + '_' + kw['uselib_store'], kw[x]) return is_success @conf def check(self, *k, **kw): """ Performs a configuration test by calling :py:func:`waflib.Configure.run_build`. For the complete list of parameters, see :py:func:`waflib.Tools.c_config.validate_c`. To force a specific compiler, pass ``compiler='c'`` or ``compiler='cxx'`` to the list of arguments Besides build targets, complete builds can be given through a build function. All files will be written to a temporary directory:: def build(bld): lib_node = bld.srcnode.make_node('libdir/liblc1.c') lib_node.parent.mkdir() lib_node.write('#include \\nint lib_func(void) { FILE *f = fopen("foo", "r");}\\n', 'w') bld(features='c cshlib', source=[lib_node], linkflags=conf.env.EXTRA_LDFLAGS, target='liblc') conf.check(build_fun=build, msg=msg) """ self.validate_c(kw) self.start_msg(kw['msg'], **kw) ret = None try: ret = self.run_build(*k, **kw) except self.errors.ConfigurationError: self.end_msg(kw['errmsg'], 'YELLOW', **kw) if Logs.verbose > 1: raise else: self.fatal('The configuration failed') else: kw['success'] = ret ret = self.post_check(*k, **kw) if not ret: self.end_msg(kw['errmsg'], 'YELLOW', **kw) self.fatal('The configuration failed %r' % ret) else: self.end_msg(self.ret_msg(kw['okmsg'], kw), **kw) return ret class test_exec(Task.Task): """ A task that runs programs after they are built. See :py:func:`waflib.Tools.c_config.test_exec_fun`. """ color = 'PINK' def run(self): cmd = [self.inputs[0].abspath()] + getattr(self.generator, 'test_args', []) if getattr(self.generator, 'rpath', None): if getattr(self.generator, 'define_ret', False): self.generator.bld.retval = self.generator.bld.cmd_and_log(cmd) else: self.generator.bld.retval = self.generator.bld.exec_command(cmd) else: env = self.env.env or {} env.update(dict(os.environ)) for var in ('LD_LIBRARY_PATH', 'DYLD_LIBRARY_PATH', 'PATH'): env[var] = self.inputs[0].parent.abspath() + os.path.pathsep + env.get(var, '') if getattr(self.generator, 'define_ret', False): self.generator.bld.retval = self.generator.bld.cmd_and_log(cmd, env=env) else: self.generator.bld.retval = self.generator.bld.exec_command(cmd, env=env) @feature('test_exec') @after_method('apply_link') def test_exec_fun(self): """ The feature **test_exec** is used to create a task that will to execute the binary created (link task output) during the build. The exit status will be set on the build context, so only one program may have the feature *test_exec*. This is used by configuration tests:: def configure(conf): conf.check(execute=True) """ self.create_task('test_exec', self.link_task.outputs[0]) @conf def check_cxx(self, *k, **kw): """ Runs a test with a task generator of the form:: conf.check(features='cxx cxxprogram', ...) """ kw['compiler'] = 'cxx' return self.check(*k, **kw) @conf def check_cc(self, *k, **kw): """ Runs a test with a task generator of the form:: conf.check(features='c cprogram', ...) """ kw['compiler'] = 'c' return self.check(*k, **kw) @conf def set_define_comment(self, key, comment): """ Sets a comment that will appear in the configuration header :type key: string :type comment: string """ coms = self.env.DEFINE_COMMENTS if not coms: coms = self.env.DEFINE_COMMENTS = {} coms[key] = comment or '' @conf def get_define_comment(self, key): """ Returns the comment associated to a define :type key: string """ coms = self.env.DEFINE_COMMENTS or {} return coms.get(key, '') @conf def define(self, key, val, quote=True, comment=''): """ Stores a single define and its state into ``conf.env.DEFINES``. The value is cast to an integer (0/1). :param key: define name :type key: string :param val: value :type val: int or string :param quote: enclose strings in quotes (yes by default) :type quote: bool """ assert isinstance(key, str) if not key: return if val is True: val = 1 elif val in (False, None): val = 0 if isinstance(val, int) or isinstance(val, float): s = '%s=%s' else: s = quote and '%s="%s"' or '%s=%s' app = s % (key, str(val)) ban = key + '=' lst = self.env.DEFINES for x in lst: if x.startswith(ban): lst[lst.index(x)] = app break else: self.env.append_value('DEFINES', app) self.env.append_unique(DEFKEYS, key) self.set_define_comment(key, comment) @conf def undefine(self, key, comment=''): """ Removes a global define from ``conf.env.DEFINES`` :param key: define name :type key: string """ assert isinstance(key, str) if not key: return ban = key + '=' lst = [x for x in self.env.DEFINES if not x.startswith(ban)] self.env.DEFINES = lst self.env.append_unique(DEFKEYS, key) self.set_define_comment(key, comment) @conf def define_cond(self, key, val, comment=''): """ Conditionally defines a name:: def configure(conf): conf.define_cond('A', True) # equivalent to: # if val: conf.define('A', 1) # else: conf.undefine('A') :param key: define name :type key: string :param val: value :type val: int or string """ assert isinstance(key, str) if not key: return if val: self.define(key, 1, comment=comment) else: self.undefine(key, comment=comment) @conf def is_defined(self, key): """ Indicates whether a particular define is globally set in ``conf.env.DEFINES``. :param key: define name :type key: string :return: True if the define is set :rtype: bool """ assert key and isinstance(key, str) ban = key + '=' for x in self.env.DEFINES: if x.startswith(ban): return True return False @conf def get_define(self, key): """ Returns the value of an existing define, or None if not found :param key: define name :type key: string :rtype: string """ assert key and isinstance(key, str) ban = key + '=' for x in self.env.DEFINES: if x.startswith(ban): return x[len(ban):] return None @conf def have_define(self, key): """ Returns a variable suitable for command-line or header use by removing invalid characters and prefixing it with ``HAVE_`` :param key: define name :type key: string :return: the input key prefixed by *HAVE_* and substitute any invalid characters. :rtype: string """ return (self.env.HAVE_PAT or 'HAVE_%s') % Utils.quote_define_name(key) @conf def write_config_header(self, configfile='', guard='', top=False, defines=True, headers=False, remove=True, define_prefix=''): """ Writes a configuration header containing defines and includes:: def configure(cnf): cnf.define('A', 1) cnf.write_config_header('config.h') This function only adds include guards (if necessary), consult :py:func:`waflib.Tools.c_config.get_config_header` for details on the body. :param configfile: path to the file to create (relative or absolute) :type configfile: string :param guard: include guard name to add, by default it is computed from the file name :type guard: string :param top: write the configuration header from the build directory (default is from the current path) :type top: bool :param defines: add the defines (yes by default) :type defines: bool :param headers: add #include in the file :type headers: bool :param remove: remove the defines after they are added (yes by default, works like in autoconf) :type remove: bool :type define_prefix: string :param define_prefix: prefix all the defines in the file with a particular prefix """ if not configfile: configfile = WAF_CONFIG_H waf_guard = guard or 'W_%s_WAF' % Utils.quote_define_name(configfile) node = top and self.bldnode or self.path.get_bld() node = node.make_node(configfile) node.parent.mkdir() lst = ['/* WARNING! All changes made to this file will be lost! */\n'] lst.append('#ifndef %s\n#define %s\n' % (waf_guard, waf_guard)) lst.append(self.get_config_header(defines, headers, define_prefix=define_prefix)) lst.append('\n#endif /* %s */\n' % waf_guard) node.write('\n'.join(lst)) # config files must not be removed on "waf clean" self.env.append_unique(Build.CFG_FILES, [node.abspath()]) if remove: for key in self.env[DEFKEYS]: self.undefine(key) self.env[DEFKEYS] = [] @conf def get_config_header(self, defines=True, headers=False, define_prefix=''): """ Creates the contents of a ``config.h`` file from the defines and includes set in conf.env.define_key / conf.env.include_key. No include guards are added. A prelude will be added from the variable env.WAF_CONFIG_H_PRELUDE if provided. This can be used to insert complex macros or include guards:: def configure(conf): conf.env.WAF_CONFIG_H_PRELUDE = '#include \\n' conf.write_config_header('config.h') :param defines: write the defines values :type defines: bool :param headers: write include entries for each element in self.env.INCKEYS :type headers: bool :type define_prefix: string :param define_prefix: prefix all the defines with a particular prefix :return: the contents of a ``config.h`` file :rtype: string """ lst = [] if self.env.WAF_CONFIG_H_PRELUDE: lst.append(self.env.WAF_CONFIG_H_PRELUDE) if headers: for x in self.env[INCKEYS]: lst.append('#include <%s>' % x) if defines: tbl = {} for k in self.env.DEFINES: a, _, b = k.partition('=') tbl[a] = b for k in self.env[DEFKEYS]: caption = self.get_define_comment(k) if caption: caption = ' /* %s */' % caption try: txt = '#define %s%s %s%s' % (define_prefix, k, tbl[k], caption) except KeyError: txt = '/* #undef %s%s */%s' % (define_prefix, k, caption) lst.append(txt) return "\n".join(lst) @conf def cc_add_flags(conf): """ Adds CFLAGS / CPPFLAGS from os.environ to conf.env """ conf.add_os_flags('CPPFLAGS', dup=False) conf.add_os_flags('CFLAGS', dup=False) @conf def cxx_add_flags(conf): """ Adds CXXFLAGS / CPPFLAGS from os.environ to conf.env """ conf.add_os_flags('CPPFLAGS', dup=False) conf.add_os_flags('CXXFLAGS', dup=False) @conf def link_add_flags(conf): """ Adds LINKFLAGS / LDFLAGS from os.environ to conf.env """ conf.add_os_flags('LINKFLAGS', dup=False) conf.add_os_flags('LDFLAGS', dup=False) @conf def cc_load_tools(conf): """ Loads the Waf c extensions """ if not conf.env.DEST_OS: conf.env.DEST_OS = Utils.unversioned_sys_platform() conf.load('c') @conf def cxx_load_tools(conf): """ Loads the Waf c++ extensions """ if not conf.env.DEST_OS: conf.env.DEST_OS = Utils.unversioned_sys_platform() conf.load('cxx') @conf def get_cc_version(conf, cc, gcc=False, icc=False, clang=False): """ Runs the preprocessor to determine the gcc/icc/clang version The variables CC_VERSION, DEST_OS, DEST_BINFMT and DEST_CPU will be set in *conf.env* :raise: :py:class:`waflib.Errors.ConfigurationError` """ cmd = cc + ['-dM', '-E', '-'] env = conf.env.env or None try: out, err = conf.cmd_and_log(cmd, output=0, input='\n'.encode(), env=env) except Errors.WafError: conf.fatal('Could not determine the compiler version %r' % cmd) if gcc: if out.find('__INTEL_COMPILER') >= 0: conf.fatal('The intel compiler pretends to be gcc') if out.find('__GNUC__') < 0 and out.find('__clang__') < 0: conf.fatal('Could not determine the compiler type') if icc and out.find('__INTEL_COMPILER') < 0: conf.fatal('Not icc/icpc') if clang and out.find('__clang__') < 0: conf.fatal('Not clang/clang++') if not clang and out.find('__clang__') >= 0: conf.fatal('Could not find gcc/g++ (only Clang), if renamed try eg: CC=gcc48 CXX=g++48 waf configure') k = {} if icc or gcc or clang: out = out.splitlines() for line in out: lst = shlex.split(line) if len(lst)>2: key = lst[1] val = lst[2] k[key] = val def isD(var): return var in k # Some documentation is available at http://predef.sourceforge.net # The names given to DEST_OS must match what Utils.unversioned_sys_platform() returns. if not conf.env.DEST_OS: conf.env.DEST_OS = '' for i in MACRO_TO_DESTOS: if isD(i): conf.env.DEST_OS = MACRO_TO_DESTOS[i] break else: if isD('__APPLE__') and isD('__MACH__'): conf.env.DEST_OS = 'darwin' elif isD('__unix__'): # unix must be tested last as it's a generic fallback conf.env.DEST_OS = 'generic' if isD('__ELF__'): conf.env.DEST_BINFMT = 'elf' elif isD('__WINNT__') or isD('__CYGWIN__') or isD('_WIN32'): conf.env.DEST_BINFMT = 'pe' if not conf.env.IMPLIBDIR: conf.env.IMPLIBDIR = conf.env.LIBDIR # for .lib or .dll.a files conf.env.LIBDIR = conf.env.BINDIR elif isD('__APPLE__'): conf.env.DEST_BINFMT = 'mac-o' if not conf.env.DEST_BINFMT: # Infer the binary format from the os name. conf.env.DEST_BINFMT = Utils.destos_to_binfmt(conf.env.DEST_OS) for i in MACRO_TO_DEST_CPU: if isD(i): conf.env.DEST_CPU = MACRO_TO_DEST_CPU[i] break Logs.debug('ccroot: dest platform: ' + ' '.join([conf.env[x] or '?' for x in ('DEST_OS', 'DEST_BINFMT', 'DEST_CPU')])) if icc: ver = k['__INTEL_COMPILER'] conf.env.CC_VERSION = (ver[:-2], ver[-2], ver[-1]) else: if isD('__clang__') and isD('__clang_major__'): conf.env.CC_VERSION = (k['__clang_major__'], k['__clang_minor__'], k['__clang_patchlevel__']) else: # older clang versions and gcc conf.env.CC_VERSION = (k['__GNUC__'], k['__GNUC_MINOR__'], k.get('__GNUC_PATCHLEVEL__', '0')) return k @conf def get_xlc_version(conf, cc): """ Returns the Aix compiler version :raise: :py:class:`waflib.Errors.ConfigurationError` """ cmd = cc + ['-qversion'] try: out, err = conf.cmd_and_log(cmd, output=0) except Errors.WafError: conf.fatal('Could not find xlc %r' % cmd) # the intention is to catch the 8.0 in "IBM XL C/C++ Enterprise Edition V8.0 for AIX..." for v in (r"IBM XL C/C\+\+.* V(?P\d*)\.(?P\d*)",): version_re = re.compile(v, re.I).search match = version_re(out or err) if match: k = match.groupdict() conf.env.CC_VERSION = (k['major'], k['minor']) break else: conf.fatal('Could not determine the XLC version.') @conf def get_suncc_version(conf, cc): """ Returns the Sun compiler version :raise: :py:class:`waflib.Errors.ConfigurationError` """ cmd = cc + ['-V'] try: out, err = conf.cmd_and_log(cmd, output=0) except Errors.WafError as e: # Older versions of the compiler exit with non-zero status when reporting their version if not (hasattr(e, 'returncode') and hasattr(e, 'stdout') and hasattr(e, 'stderr')): conf.fatal('Could not find suncc %r' % cmd) out = e.stdout err = e.stderr version = (out or err) version = version.splitlines()[0] # cc: Sun C 5.10 SunOS_i386 2009/06/03 # cc: Studio 12.5 Sun C++ 5.14 SunOS_sparc Beta 2015/11/17 # cc: WorkShop Compilers 5.0 98/12/15 C 5.0 version_re = re.compile(r'cc: (studio.*?|\s+)?(sun\s+(c\+\+|c)|(WorkShop\s+Compilers))?\s+(?P\d*)\.(?P\d*)', re.I).search match = version_re(version) if match: k = match.groupdict() conf.env.CC_VERSION = (k['major'], k['minor']) else: conf.fatal('Could not determine the suncc version.') # ============ the --as-needed flag should added during the configuration, not at runtime ========= @conf def add_as_needed(self): """ Adds ``--as-needed`` to the *LINKFLAGS* On some platforms, it is a default flag. In some cases (e.g., in NS-3) it is necessary to explicitly disable this feature with `-Wl,--no-as-needed` flag. """ if self.env.DEST_BINFMT == 'elf' and 'gcc' in (self.env.CXX_NAME, self.env.CC_NAME): self.env.append_unique('LINKFLAGS', '-Wl,--as-needed') # ============ parallel configuration class cfgtask(Task.Task): """ A task that executes build configuration tests (calls conf.check) Make sure to use locks if concurrent access to the same conf.env data is necessary. """ def __init__(self, *k, **kw): Task.Task.__init__(self, *k, **kw) self.run_after = set() def display(self): return '' def runnable_status(self): for x in self.run_after: if not x.hasrun: return Task.ASK_LATER return Task.RUN_ME def uid(self): return Utils.SIG_NIL def signature(self): return Utils.SIG_NIL def run(self): conf = self.conf bld = Build.BuildContext(top_dir=conf.srcnode.abspath(), out_dir=conf.bldnode.abspath()) bld.env = conf.env bld.init_dirs() bld.in_msg = 1 # suppress top-level start_msg bld.logger = self.logger bld.multicheck_task = self args = self.args try: if 'func' in args: bld.test(build_fun=args['func'], msg=args.get('msg', ''), okmsg=args.get('okmsg', ''), errmsg=args.get('errmsg', ''), ) else: args['multicheck_mandatory'] = args.get('mandatory', True) args['mandatory'] = True try: bld.check(**args) finally: args['mandatory'] = args['multicheck_mandatory'] except Exception: return 1 def process(self): Task.Task.process(self) if 'msg' in self.args: with self.generator.bld.multicheck_lock: self.conf.start_msg(self.args['msg']) if self.hasrun == Task.NOT_RUN: self.conf.end_msg('test cancelled', 'YELLOW') elif self.hasrun != Task.SUCCESS: self.conf.end_msg(self.args.get('errmsg', 'no'), 'YELLOW') else: self.conf.end_msg(self.args.get('okmsg', 'yes'), 'GREEN') @conf def multicheck(self, *k, **kw): """ Runs configuration tests in parallel; results are printed sequentially at the end of the build but each test must provide its own msg value to display a line:: def test_build(ctx): ctx.in_msg = True # suppress console outputs ctx.check_large_file(mandatory=False) conf.multicheck( {'header_name':'stdio.h', 'msg':'... stdio', 'uselib_store':'STDIO', 'global_define':False}, {'header_name':'xyztabcd.h', 'msg':'... optional xyztabcd.h', 'mandatory': False}, {'header_name':'stdlib.h', 'msg':'... stdlib', 'okmsg': 'aye', 'errmsg': 'nope'}, {'func': test_build, 'msg':'... testing an arbitrary build function', 'okmsg':'ok'}, msg = 'Checking for headers in parallel', mandatory = True, # mandatory tests raise an error at the end run_all_tests = True, # try running all tests ) The configuration tests may modify the values in conf.env in any order, and the define values can affect configuration tests being executed. It is hence recommended to provide `uselib_store` values with `global_define=False` to prevent such issues. """ self.start_msg(kw.get('msg', 'Executing %d configuration tests' % len(k)), **kw) # Force a copy so that threads append to the same list at least # no order is guaranteed, but the values should not disappear at least for var in ('DEFINES', DEFKEYS): self.env.append_value(var, []) self.env.DEFINE_COMMENTS = self.env.DEFINE_COMMENTS or {} # define a task object that will execute our tests class par(object): def __init__(self): self.keep = False self.task_sigs = {} self.progress_bar = 0 def total(self): return len(tasks) def to_log(self, *k, **kw): return bld = par() bld.keep = kw.get('run_all_tests', True) bld.imp_sigs = {} tasks = [] id_to_task = {} for counter, dct in enumerate(k): x = Task.classes['cfgtask'](bld=bld, env=None) tasks.append(x) x.args = dct x.args['multicheck_counter'] = counter x.bld = bld x.conf = self x.args = dct # bind a logger that will keep the info in memory x.logger = Logs.make_mem_logger(str(id(x)), self.logger) if 'id' in dct: id_to_task[dct['id']] = x # second pass to set dependencies with after_test/before_test for x in tasks: for key in Utils.to_list(x.args.get('before_tests', [])): tsk = id_to_task[key] if not tsk: raise ValueError('No test named %r' % key) tsk.run_after.add(x) for key in Utils.to_list(x.args.get('after_tests', [])): tsk = id_to_task[key] if not tsk: raise ValueError('No test named %r' % key) x.run_after.add(tsk) def it(): yield tasks while 1: yield [] bld.producer = p = Runner.Parallel(bld, Options.options.jobs) bld.multicheck_lock = Utils.threading.Lock() p.biter = it() self.end_msg('started') p.start() # flush the logs in order into the config.log for x in tasks: x.logger.memhandler.flush() self.start_msg('-> processing test results') if p.error: for x in p.error: if getattr(x, 'err_msg', None): self.to_log(x.err_msg) self.end_msg('fail', color='RED') raise Errors.WafError('There is an error in the library, read config.log for more information') failure_count = 0 for x in tasks: if x.hasrun not in (Task.SUCCESS, Task.NOT_RUN): failure_count += 1 if failure_count: self.end_msg(kw.get('errmsg', '%s test failed' % failure_count), color='YELLOW', **kw) else: self.end_msg('all ok', **kw) for x in tasks: if x.hasrun != Task.SUCCESS: if x.args.get('mandatory', True): self.fatal(kw.get('fatalmsg') or 'One of the tests has failed, read config.log for more information') @conf def check_gcc_o_space(self, mode='c'): if int(self.env.CC_VERSION[0]) > 4: # this is for old compilers return self.env.stash() if mode == 'c': self.env.CCLNK_TGT_F = ['-o', ''] elif mode == 'cxx': self.env.CXXLNK_TGT_F = ['-o', ''] features = '%s %sshlib' % (mode, mode) try: self.check(msg='Checking if the -o link must be split from arguments', fragment=SNIP_EMPTY_PROGRAM, features=features) except self.errors.ConfigurationError: self.env.revert() else: self.env.commit() kupfer-328/waflib/Tools/c_osx.py000066400000000000000000000133261500175051100167150ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy 2008-2018 (ita) """ MacOSX related tools """ import os, shutil, platform from waflib import Task, Utils from waflib.TaskGen import taskgen_method, feature, after_method, before_method app_info = ''' CFBundlePackageType APPL CFBundleGetInfoString Created by Waf CFBundleSignature ???? NOTE THIS IS A GENERATED FILE, DO NOT MODIFY CFBundleExecutable {app_name} ''' """ plist template """ @feature('c', 'cxx') def set_macosx_deployment_target(self): """ see WAF issue 285 and also and also http://trac.macports.org/ticket/17059 """ if self.env.MACOSX_DEPLOYMENT_TARGET: os.environ['MACOSX_DEPLOYMENT_TARGET'] = self.env.MACOSX_DEPLOYMENT_TARGET elif 'MACOSX_DEPLOYMENT_TARGET' not in os.environ: if Utils.unversioned_sys_platform() == 'darwin': os.environ['MACOSX_DEPLOYMENT_TARGET'] = '.'.join(platform.mac_ver()[0].split('.')[:2]) @taskgen_method def create_bundle_dirs(self, name, out): """ Creates bundle folders, used by :py:func:`create_task_macplist` and :py:func:`create_task_macapp` """ dir = out.parent.find_or_declare(name) dir.mkdir() macos = dir.find_or_declare(['Contents', 'MacOS']) macos.mkdir() return dir def bundle_name_for_output(out): name = out.name k = name.rfind('.') if k >= 0: name = name[:k] + '.app' else: name = name + '.app' return name @feature('cprogram', 'cxxprogram') @after_method('apply_link') def create_task_macapp(self): """ To compile an executable into a Mac application (a .app), set its *mac_app* attribute:: def build(bld): bld.shlib(source='a.c', target='foo', mac_app=True) To force *all* executables to be transformed into Mac applications:: def build(bld): bld.env.MACAPP = True bld.shlib(source='a.c', target='foo') """ if self.env.MACAPP or getattr(self, 'mac_app', False): out = self.link_task.outputs[0] name = bundle_name_for_output(out) dir = self.create_bundle_dirs(name, out) n1 = dir.find_or_declare(['Contents', 'MacOS', out.name]) self.apptask = self.create_task('macapp', self.link_task.outputs, n1) inst_to = getattr(self, 'install_path', '/Applications') + '/%s/Contents/MacOS/' % name self.add_install_files(install_to=inst_to, install_from=n1, chmod=Utils.O755) if getattr(self, 'mac_files', None): # this only accepts files; they will be installed as seen from mac_files_root mac_files_root = getattr(self, 'mac_files_root', None) if isinstance(mac_files_root, str): mac_files_root = self.path.find_node(mac_files_root) if not mac_files_root: self.bld.fatal('Invalid mac_files_root %r' % self.mac_files_root) res_dir = n1.parent.parent.make_node('Resources') inst_to = getattr(self, 'install_path', '/Applications') + '/%s/Resources' % name for node in self.to_nodes(self.mac_files): relpath = node.path_from(mac_files_root or node.parent) self.create_task('macapp', node, res_dir.make_node(relpath)) self.add_install_as(install_to=os.path.join(inst_to, relpath), install_from=node) if getattr(self.bld, 'is_install', None): # disable regular binary installation self.install_task.hasrun = Task.SKIP_ME @feature('cprogram', 'cxxprogram') @after_method('apply_link') def create_task_macplist(self): """ Creates a :py:class:`waflib.Tools.c_osx.macplist` instance. """ if self.env.MACAPP or getattr(self, 'mac_app', False): out = self.link_task.outputs[0] name = bundle_name_for_output(out) dir = self.create_bundle_dirs(name, out) n1 = dir.find_or_declare(['Contents', 'Info.plist']) self.plisttask = plisttask = self.create_task('macplist', [], n1) plisttask.context = { 'app_name': self.link_task.outputs[0].name, 'env': self.env } plist_ctx = getattr(self, 'plist_context', None) if (plist_ctx): plisttask.context.update(plist_ctx) if getattr(self, 'mac_plist', False): node = self.path.find_resource(self.mac_plist) if node: plisttask.inputs.append(node) else: plisttask.code = self.mac_plist else: plisttask.code = app_info inst_to = getattr(self, 'install_path', '/Applications') + '/%s/Contents/' % name self.add_install_files(install_to=inst_to, install_from=n1) @feature('cshlib', 'cxxshlib') @before_method('apply_link', 'propagate_uselib_vars') def apply_bundle(self): """ To make a bundled shared library (a ``.bundle``), set the *mac_bundle* attribute:: def build(bld): bld.shlib(source='a.c', target='foo', mac_bundle = True) To force *all* executables to be transformed into bundles:: def build(bld): bld.env.MACBUNDLE = True bld.shlib(source='a.c', target='foo') """ if self.env.MACBUNDLE or getattr(self, 'mac_bundle', False): self.env.LINKFLAGS_cshlib = self.env.LINKFLAGS_cxxshlib = [] # disable the '-dynamiclib' flag self.env.cshlib_PATTERN = self.env.cxxshlib_PATTERN = self.env.macbundle_PATTERN use = self.use = self.to_list(getattr(self, 'use', [])) if not 'MACBUNDLE' in use: use.append('MACBUNDLE') app_dirs = ['Contents', 'Contents/MacOS', 'Contents/Resources'] class macapp(Task.Task): """ Creates mac applications """ color = 'PINK' def run(self): self.outputs[0].parent.mkdir() shutil.copy2(self.inputs[0].srcpath(), self.outputs[0].abspath()) class macplist(Task.Task): """ Creates plist files """ color = 'PINK' ext_in = ['.bin'] def run(self): if getattr(self, 'code', None): txt = self.code else: txt = self.inputs[0].read() context = getattr(self, 'context', {}) txt = txt.format(**context) self.outputs[0].write(txt) kupfer-328/waflib/Tools/c_preproc.py000066400000000000000000000660651500175051100175660ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2018 (ita) """ C/C++ preprocessor for finding dependencies Reasons for using the Waf preprocessor by default #. Some c/c++ extensions (Qt) require a custom preprocessor for obtaining the dependencies (.moc files) #. Not all compilers provide .d files for obtaining the dependencies (portability) #. A naive file scanner will not catch the constructs such as "#include foo()" #. A naive file scanner will catch unnecessary dependencies (change an unused header -> recompile everything) Regarding the speed concerns: * the preprocessing is performed only when files must be compiled * the macros are evaluated only for #if/#elif/#include * system headers are not scanned by default Now if you do not want the Waf preprocessor, the tool +gccdeps* uses the .d files produced during the compilation to track the dependencies (useful when used with the boost libraries). It only works with gcc >= 4.4 though. A dumb preprocessor is also available in the tool *c_dumbpreproc* """ # TODO: more varargs, pragma once import re, string, traceback from waflib import Logs, Utils, Errors class PreprocError(Errors.WafError): pass FILE_CACHE_SIZE = 100000 LINE_CACHE_SIZE = 100000 POPFILE = '-' "Constant representing a special token used in :py:meth:`waflib.Tools.c_preproc.c_parser.start` iteration to switch to a header read previously" recursion_limit = 150 "Limit on the amount of files to read in the dependency scanner" go_absolute = False "Set to True to track headers on files in /usr/include, else absolute paths are ignored (but it becomes very slow)" standard_includes = ['/usr/local/include', '/usr/include'] if Utils.is_win32: standard_includes = [] use_trigraphs = 0 """Apply trigraph rules (False by default)""" # obsolete, do not use strict_quotes = 0 g_optrans = { 'not':'!', 'not_eq':'!', 'and':'&&', 'and_eq':'&=', 'or':'||', 'or_eq':'|=', 'xor':'^', 'xor_eq':'^=', 'bitand':'&', 'bitor':'|', 'compl':'~', } """Operators such as and/or/xor for c++. Set an empty dict to disable.""" # ignore #warning and #error re_lines = re.compile( '^[ \t]*(?:#|%:)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef|pragma)[ \t]*(.*)\r*$', re.IGNORECASE | re.MULTILINE) """Match #include lines""" re_mac = re.compile(r"^[a-zA-Z_]\w*") """Match macro definitions""" re_fun = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*[(]') """Match macro functions""" re_pragma_once = re.compile(r'^\s*once\s*', re.IGNORECASE) """Match #pragma once statements""" re_nl = re.compile('\\\\\r*\n', re.MULTILINE) """Match newlines""" re_cpp = re.compile(r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', re.DOTALL | re.MULTILINE ) """Filter C/C++ comments""" trig_def = [('??'+a, b) for a, b in zip("=-/!'()<>", r'#~\|^[]{}')] """Trigraph definitions""" chr_esc = {'0':0, 'a':7, 'b':8, 't':9, 'n':10, 'f':11, 'v':12, 'r':13, '\\':92, "'":39} """Escape characters""" NUM = 'i' """Number token""" OP = 'O' """Operator token""" IDENT = 'T' """Identifier token""" STR = 's' """String token""" CHAR = 'c' """Character token""" tok_types = [NUM, STR, IDENT, OP] """Token types""" exp_types = [ r"""0[xX](?P[a-fA-F0-9]+)(?P[uUlL]*)|L*?'(?P(\\.|[^\\'])+)'|(?P\d+)[Ee](?P[+-]*?\d+)(?P[fFlL]*)|(?P\d*\.\d+)([Ee](?P[+-]*?\d+))?(?P[fFlL]*)|(?P\d+\.\d*)([Ee](?P[+-]*?\d+))?(?P[fFlL]*)|(?P0*)(?P\d+)(?P[uUlL]*)""", r'L?"([^"\\]|\\.)*"', r'[a-zA-Z_]\w*', r'%:%:|<<=|>>=|\.\.\.|<<|<%|<:|<=|>>|>=|\+\+|\+=|--|->|-=|\*=|/=|%:|%=|%>|==|&&|&=|\|\||\|=|\^=|:>|!=|##|[\(\)\{\}\[\]<>\?\|\^\*\+&=:!#;,%/\-\?\~\.]', ] """Expression types""" re_clexer = re.compile('|'.join(["(?P<%s>%s)" % (name, part) for name, part in zip(tok_types, exp_types)]), re.M) """Match expressions into tokens""" accepted = 'a' """Parser state is *accepted*""" ignored = 'i' """Parser state is *ignored*, for example preprocessor lines in an #if 0 block""" undefined = 'u' """Parser state is *undefined* at the moment""" skipped = 's' """Parser state is *skipped*, for example preprocessor lines in a #elif 0 block""" def repl(m): """Replace function used with :py:attr:`waflib.Tools.c_preproc.re_cpp`""" s = m.group() if s[0] == '/': return ' ' return s prec = {} """ Operator precedence rules required for parsing expressions of the form:: #if 1 && 2 != 0 """ ops = ['* / %', '+ -', '<< >>', '< <= >= >', '== !=', '& | ^', '&& ||', ','] for x, syms in enumerate(ops): for u in syms.split(): prec[u] = x def reduce_nums(val_1, val_2, val_op): """ Apply arithmetic rules to compute a result :param val1: input parameter :type val1: int or string :param val2: input parameter :type val2: int or string :param val_op: C operator in *+*, */*, *-*, etc :type val_op: string :rtype: int """ #print val_1, val_2, val_op # now perform the operation, make certain a and b are numeric try: a = 0 + val_1 except TypeError: a = int(val_1) try: b = 0 + val_2 except TypeError: b = int(val_2) d = val_op if d == '%': c = a % b elif d=='+': c = a + b elif d=='-': c = a - b elif d=='*': c = a * b elif d=='/': c = a / b elif d=='^': c = a ^ b elif d=='==': c = int(a == b) elif d=='|' or d == 'bitor': c = a | b elif d=='||' or d == 'or' : c = int(a or b) elif d=='&' or d == 'bitand': c = a & b elif d=='&&' or d == 'and': c = int(a and b) elif d=='!=' or d == 'not_eq': c = int(a != b) elif d=='^' or d == 'xor': c = int(a^b) elif d=='<=': c = int(a <= b) elif d=='<': c = int(a < b) elif d=='>': c = int(a > b) elif d=='>=': c = int(a >= b) elif d=='<<': c = a << b elif d=='>>': c = a >> b else: c = 0 return c def get_num(lst): """ Try to obtain a number from a list of tokens. The token types are defined in :py:attr:`waflib.Tools.ccroot.tok_types`. :param lst: list of preprocessor tokens :type lst: list of tuple (tokentype, value) :return: a pair containing the number and the rest of the list :rtype: tuple(value, list) """ if not lst: raise PreprocError('empty list for get_num') (p, v) = lst[0] if p == OP: if v == '(': count_par = 1 i = 1 while i < len(lst): (p, v) = lst[i] if p == OP: if v == ')': count_par -= 1 if count_par == 0: break elif v == '(': count_par += 1 i += 1 else: raise PreprocError('rparen expected %r' % lst) (num, _) = get_term(lst[1:i]) return (num, lst[i+1:]) elif v == '+': return get_num(lst[1:]) elif v == '-': num, lst = get_num(lst[1:]) return (reduce_nums('-1', num, '*'), lst) elif v == '!': num, lst = get_num(lst[1:]) return (int(not int(num)), lst) elif v == '~': num, lst = get_num(lst[1:]) return (~ int(num), lst) else: raise PreprocError('Invalid op token %r for get_num' % lst) elif p == NUM: return v, lst[1:] elif p == IDENT: # all macros should have been replaced, remaining identifiers eval to 0 return 0, lst[1:] else: raise PreprocError('Invalid token %r for get_num' % lst) def get_term(lst): """ Evaluate an expression recursively, for example:: 1+1+1 -> 2+1 -> 3 :param lst: list of tokens :type lst: list of tuple(token, value) :return: the value and the remaining tokens :rtype: value, list """ if not lst: raise PreprocError('empty list for get_term') num, lst = get_num(lst) if not lst: return (num, []) (p, v) = lst[0] if p == OP: if v == ',': # skip return get_term(lst[1:]) elif v == '?': count_par = 0 i = 1 while i < len(lst): (p, v) = lst[i] if p == OP: if v == ')': count_par -= 1 elif v == '(': count_par += 1 elif v == ':': if count_par == 0: break i += 1 else: raise PreprocError('rparen expected %r' % lst) if int(num): return get_term(lst[1:i]) else: return get_term(lst[i+1:]) else: num2, lst = get_num(lst[1:]) if not lst: # no more tokens to process num2 = reduce_nums(num, num2, v) return get_term([(NUM, num2)] + lst) # operator precedence p2, v2 = lst[0] if p2 != OP: raise PreprocError('op expected %r' % lst) if prec[v2] >= prec[v]: num2 = reduce_nums(num, num2, v) return get_term([(NUM, num2)] + lst) else: num3, lst = get_num(lst[1:]) num3 = reduce_nums(num2, num3, v2) return get_term([(NUM, num), (p, v), (NUM, num3)] + lst) raise PreprocError('cannot reduce %r' % lst) def reduce_eval(lst): """ Take a list of tokens and output true or false for #if/#elif conditions. :param lst: a list of tokens :type lst: list of tuple(token, value) :return: a token :rtype: tuple(NUM, int) """ num, lst = get_term(lst) return (NUM, num) def stringize(lst): """ Merge a list of tokens into a string :param lst: a list of tokens :type lst: list of tuple(token, value) :rtype: string """ lst = [str(v2) for (p2, v2) in lst] return "".join(lst) def paste_tokens(t1, t2): """ Token pasting works between identifiers, particular operators, and identifiers and numbers:: a ## b -> ab > ## = -> >= a ## 2 -> a2 :param t1: token :type t1: tuple(type, value) :param t2: token :type t2: tuple(type, value) """ p1 = None if t1[0] == OP and t2[0] == OP: p1 = OP elif t1[0] == IDENT and (t2[0] == IDENT or t2[0] == NUM): p1 = IDENT elif t1[0] == NUM and t2[0] == NUM: p1 = NUM if not p1: raise PreprocError('tokens do not make a valid paste %r and %r' % (t1, t2)) return (p1, t1[1] + t2[1]) def reduce_tokens(lst, defs, ban=[]): """ Replace the tokens in lst, using the macros provided in defs, and a list of macros that cannot be re-applied :param lst: list of tokens :type lst: list of tuple(token, value) :param defs: macro definitions :type defs: dict :param ban: macros that cannot be substituted (recursion is not allowed) :type ban: list of string :return: the new list of tokens :rtype: value, list """ i = 0 while i < len(lst): (p, v) = lst[i] if p == IDENT and v == "defined": del lst[i] if i < len(lst): (p2, v2) = lst[i] if p2 == IDENT: if v2 in defs: lst[i] = (NUM, 1) else: lst[i] = (NUM, 0) elif p2 == OP and v2 == '(': del lst[i] (p2, v2) = lst[i] del lst[i] # remove the ident, and change the ) for the value if v2 in defs: lst[i] = (NUM, 1) else: lst[i] = (NUM, 0) else: raise PreprocError('Invalid define expression %r' % lst) elif p == IDENT and v in defs: if isinstance(defs[v], str): a, b = extract_macro(defs[v]) defs[v] = b macro_def = defs[v] to_add = macro_def[1] if isinstance(macro_def[0], list): # macro without arguments del lst[i] accu = to_add[:] reduce_tokens(accu, defs, ban+[v]) for tmp in accu: lst.insert(i, tmp) i += 1 else: # collect the arguments for the funcall args = [] del lst[i] if i >= len(lst): raise PreprocError('expected ( after %r (got nothing)' % v) (p2, v2) = lst[i] if p2 != OP or v2 != '(': raise PreprocError('expected ( after %r' % v) del lst[i] one_param = [] count_paren = 0 while i < len(lst): p2, v2 = lst[i] del lst[i] if p2 == OP and count_paren == 0: if v2 == '(': one_param.append((p2, v2)) count_paren += 1 elif v2 == ')': if one_param: args.append(one_param) break elif v2 == ',': if not one_param: raise PreprocError('empty param in funcall %r' % v) args.append(one_param) one_param = [] else: one_param.append((p2, v2)) else: one_param.append((p2, v2)) if v2 == '(': count_paren += 1 elif v2 == ')': count_paren -= 1 else: raise PreprocError('malformed macro') # substitute the arguments within the define expression accu = [] arg_table = macro_def[0] j = 0 while j < len(to_add): (p2, v2) = to_add[j] if p2 == OP and v2 == '#': # stringize is for arguments only if j+1 < len(to_add) and to_add[j+1][0] == IDENT and to_add[j+1][1] in arg_table: toks = args[arg_table[to_add[j+1][1]]] accu.append((STR, stringize(toks))) j += 1 else: accu.append((p2, v2)) elif p2 == OP and v2 == '##': # token pasting, how can man invent such a complicated system? if accu and j+1 < len(to_add): # we have at least two tokens t1 = accu[-1] if to_add[j+1][0] == IDENT and to_add[j+1][1] in arg_table: toks = args[arg_table[to_add[j+1][1]]] if toks: accu[-1] = paste_tokens(t1, toks[0]) #(IDENT, accu[-1][1] + toks[0][1]) accu.extend(toks[1:]) else: # error, case "a##" accu.append((p2, v2)) accu.extend(toks) elif to_add[j+1][0] == IDENT and to_add[j+1][1] == '__VA_ARGS__': # first collect the tokens va_toks = [] st = len(macro_def[0]) pt = len(args) for x in args[pt-st+1:]: va_toks.extend(x) va_toks.append((OP, ',')) if va_toks: va_toks.pop() # extra comma if len(accu)>1: (p3, v3) = accu[-1] (p4, v4) = accu[-2] if v3 == '##': # remove the token paste accu.pop() if v4 == ',' and pt < st: # remove the comma accu.pop() accu += va_toks else: accu[-1] = paste_tokens(t1, to_add[j+1]) j += 1 else: # Invalid paste, case "##a" or "b##" accu.append((p2, v2)) elif p2 == IDENT and v2 in arg_table: toks = args[arg_table[v2]] reduce_tokens(toks, defs, ban+[v]) accu.extend(toks) else: accu.append((p2, v2)) j += 1 reduce_tokens(accu, defs, ban+[v]) for x in range(len(accu)-1, -1, -1): lst.insert(i, accu[x]) i += 1 def eval_macro(lst, defs): """ Reduce the tokens by :py:func:`waflib.Tools.c_preproc.reduce_tokens` and try to return a 0/1 result by :py:func:`waflib.Tools.c_preproc.reduce_eval`. :param lst: list of tokens :type lst: list of tuple(token, value) :param defs: macro definitions :type defs: dict :rtype: int """ reduce_tokens(lst, defs, []) if not lst: raise PreprocError('missing tokens to evaluate') if lst: p, v = lst[0] if p == IDENT and v not in defs: raise PreprocError('missing macro %r' % lst) p, v = reduce_eval(lst) return int(v) != 0 def extract_macro(txt): """ Process a macro definition of the form:: #define f(x, y) x * y into a function or a simple macro without arguments :param txt: expression to exact a macro definition from :type txt: string :return: a tuple containing the name, the list of arguments and the replacement :rtype: tuple(string, [list, list]) """ t = tokenize(txt) if re_fun.search(txt): p, name = t[0] p, v = t[1] if p != OP: raise PreprocError('expected (') i = 1 pindex = 0 params = {} prev = '(' while 1: i += 1 p, v = t[i] if prev == '(': if p == IDENT: params[v] = pindex pindex += 1 prev = p elif p == OP and v == ')': break else: raise PreprocError('unexpected token (3)') elif prev == IDENT: if p == OP and v == ',': prev = v elif p == OP and v == ')': break else: raise PreprocError('comma or ... expected') elif prev == ',': if p == IDENT: params[v] = pindex pindex += 1 prev = p elif p == OP and v == '...': raise PreprocError('not implemented (1)') else: raise PreprocError('comma or ... expected (2)') elif prev == '...': raise PreprocError('not implemented (2)') else: raise PreprocError('unexpected else') #~ print (name, [params, t[i+1:]]) return (name, [params, t[i+1:]]) else: (p, v) = t[0] if len(t) > 1: return (v, [[], t[1:]]) else: # empty define, assign an empty token return (v, [[], [('T','')]]) re_include = re.compile(r'^\s*(<(?:.*)>|"(?:.*)")') def extract_include(txt, defs): """ Process a line in the form:: #include foo :param txt: include line to process :type txt: string :param defs: macro definitions :type defs: dict :return: the file name :rtype: string """ m = re_include.search(txt) if m: txt = m.group(1) return txt[0], txt[1:-1] # perform preprocessing and look at the result, it must match an include toks = tokenize(txt) reduce_tokens(toks, defs, ['waf_include']) if not toks: raise PreprocError('could not parse include %r' % txt) if len(toks) == 1: if toks[0][0] == STR: return '"', toks[0][1] else: if toks[0][1] == '<' and toks[-1][1] == '>': ret = '<', stringize(toks).lstrip('<').rstrip('>') return ret raise PreprocError('could not parse include %r' % txt) def parse_char(txt): """ Parse a c character :param txt: character to parse :type txt: string :return: a character literal :rtype: string """ if not txt: raise PreprocError('attempted to parse a null char') if txt[0] != '\\': return ord(txt) c = txt[1] if c == 'x': if len(txt) == 4 and txt[3] in string.hexdigits: return int(txt[2:], 16) return int(txt[2:], 16) elif c.isdigit(): if c == '0' and len(txt)==2: return 0 for i in 3, 2, 1: if len(txt) > i and txt[1:1+i].isdigit(): return (1+i, int(txt[1:1+i], 8)) else: try: return chr_esc[c] except KeyError: raise PreprocError('could not parse char literal %r' % txt) def tokenize(s): """ Convert a string into a list of tokens (shlex.split does not apply to c/c++/d) :param s: input to tokenize :type s: string :return: a list of tokens :rtype: list of tuple(token, value) """ return tokenize_private(s)[:] # force a copy of the results def tokenize_private(s): ret = [] for match in re_clexer.finditer(s): m = match.group for name in tok_types: v = m(name) if v: if name == IDENT: if v in g_optrans: name = OP elif v.lower() == "true": v = 1 name = NUM elif v.lower() == "false": v = 0 name = NUM elif name == NUM: if m('oct'): v = int(v, 8) elif m('hex'): v = int(m('hex'), 16) elif m('n0'): v = m('n0') else: v = m('char') if v: v = parse_char(v) else: v = m('n2') or m('n4') elif name == OP: if v == '%:': v = '#' elif v == '%:%:': v = '##' elif name == STR: # remove the quotes around the string v = v[1:-1] ret.append((name, v)) break return ret def format_defines(lst): ret = [] for y in lst: if y: pos = y.find('=') if pos == -1: # "-DFOO" should give "#define FOO 1" ret.append(y) elif pos > 0: # all others are assumed to be -DX=Y ret.append('%s %s' % (y[:pos], y[pos+1:])) else: raise ValueError('Invalid define expression %r' % y) return ret class c_parser(object): """ Used by :py:func:`waflib.Tools.c_preproc.scan` to parse c/h files. Note that by default, only project headers are parsed. """ def __init__(self, nodepaths=None, defines=None): self.lines = [] """list of lines read""" if defines is None: self.defs = {} else: self.defs = dict(defines) # make a copy self.state = [] self.count_files = 0 self.currentnode_stack = [] self.nodepaths = nodepaths or [] """Include paths""" self.nodes = [] """List of :py:class:`waflib.Node.Node` found so far""" self.names = [] """List of file names that could not be matched by any file""" self.curfile = '' """Current file""" self.ban_includes = set() """Includes that must not be read (#pragma once)""" self.listed = set() """Include nodes/names already listed to avoid duplicates in self.nodes/self.names""" def cached_find_resource(self, node, filename): """ Find a file from the input directory :param node: directory :type node: :py:class:`waflib.Node.Node` :param filename: header to find :type filename: string :return: the node if found, or None :rtype: :py:class:`waflib.Node.Node` """ try: cache = node.ctx.preproc_cache_node except AttributeError: cache = node.ctx.preproc_cache_node = Utils.lru_cache(FILE_CACHE_SIZE) key = (node, filename) try: return cache[key] except KeyError: ret = node.find_resource(filename) if ret: if getattr(ret, 'children', None): ret = None elif ret.is_child_of(node.ctx.bldnode): tmp = node.ctx.srcnode.search_node(ret.path_from(node.ctx.bldnode)) if tmp and getattr(tmp, 'children', None): ret = None cache[key] = ret return ret def tryfind(self, filename, kind='"', env=None): """ Try to obtain a node from the filename based from the include paths. Will add the node found to :py:attr:`waflib.Tools.c_preproc.c_parser.nodes` or the file name to :py:attr:`waflib.Tools.c_preproc.c_parser.names` if no corresponding file is found. Called by :py:attr:`waflib.Tools.c_preproc.c_parser.start`. :param filename: header to find :type filename: string :return: the node if found :rtype: :py:class:`waflib.Node.Node` """ if filename.endswith('.moc'): # we could let the qt4 module use a subclass, but then the function "scan" below must be duplicated # in the qt4 and in the qt5 classes. So we have two lines here and it is sufficient. self.names.append(filename) return None self.curfile = filename found = None if kind == '"': if env.MSVC_VERSION: for n in reversed(self.currentnode_stack): found = self.cached_find_resource(n, filename) if found: break else: found = self.cached_find_resource(self.currentnode_stack[-1], filename) if not found: for n in self.nodepaths: found = self.cached_find_resource(n, filename) if found: break listed = self.listed if found and not found in self.ban_includes: if found not in listed: listed.add(found) self.nodes.append(found) self.addlines(found) else: if filename not in listed: listed.add(filename) self.names.append(filename) return found def filter_comments(self, node): """ Filter the comments from a c/h file, and return the preprocessor lines. The regexps :py:attr:`waflib.Tools.c_preproc.re_cpp`, :py:attr:`waflib.Tools.c_preproc.re_nl` and :py:attr:`waflib.Tools.c_preproc.re_lines` are used internally. :return: the preprocessor directives as a list of (keyword, line) :rtype: a list of string pairs """ # return a list of tuples : keyword, line code = node.read() if use_trigraphs: for (a, b) in trig_def: code = code.split(a).join(b) code = re_nl.sub('', code) code = re_cpp.sub(repl, code) return re_lines.findall(code) def parse_lines(self, node): try: cache = node.ctx.preproc_cache_lines except AttributeError: cache = node.ctx.preproc_cache_lines = Utils.lru_cache(LINE_CACHE_SIZE) try: return cache[node] except KeyError: cache[node] = lines = self.filter_comments(node) lines.append((POPFILE, '')) lines.reverse() return lines def addlines(self, node): """ Add the lines from a header in the list of preprocessor lines to parse :param node: header :type node: :py:class:`waflib.Node.Node` """ self.currentnode_stack.append(node.parent) self.count_files += 1 if self.count_files > recursion_limit: # issue #812 raise PreprocError('recursion limit exceeded') if Logs.verbose: Logs.debug('preproc: reading file %r', node) try: lines = self.parse_lines(node) except EnvironmentError: raise PreprocError('could not read the file %r' % node) except Exception: if Logs.verbose > 0: Logs.error('parsing %r failed %s', node, traceback.format_exc()) else: self.lines.extend(lines) def start(self, node, env): """ Preprocess a source file to obtain the dependencies, which are accumulated to :py:attr:`waflib.Tools.c_preproc.c_parser.nodes` and :py:attr:`waflib.Tools.c_preproc.c_parser.names`. :param node: source file :type node: :py:class:`waflib.Node.Node` :param env: config set containing additional defines to take into account :type env: :py:class:`waflib.ConfigSet.ConfigSet` """ Logs.debug('preproc: scanning %s (in %s)', node.name, node.parent.name) self.current_file = node self.addlines(node) # macros may be defined on the command-line, so they must be parsed as if they were part of the file if env.DEFINES: lst = format_defines(env.DEFINES) lst.reverse() self.lines.extend([('define', x) for x in lst]) while self.lines: (token, line) = self.lines.pop() if token == POPFILE: self.count_files -= 1 self.currentnode_stack.pop() continue try: state = self.state # make certain we define the state if we are about to enter in an if block if token[:2] == 'if': state.append(undefined) elif token == 'endif': state.pop() # skip lines when in a dead 'if' branch, wait for the endif if token[0] != 'e': if skipped in self.state or ignored in self.state: continue if token == 'if': ret = eval_macro(tokenize(line), self.defs) if ret: state[-1] = accepted else: state[-1] = ignored elif token == 'ifdef': m = re_mac.match(line) if m and m.group() in self.defs: state[-1] = accepted else: state[-1] = ignored elif token == 'ifndef': m = re_mac.match(line) if m and m.group() in self.defs: state[-1] = ignored else: state[-1] = accepted elif token == 'include' or token == 'import': (kind, inc) = extract_include(line, self.defs) self.current_file = self.tryfind(inc, kind, env) if token == 'import': self.ban_includes.add(self.current_file) elif token == 'elif': if state[-1] == accepted: state[-1] = skipped elif state[-1] == ignored: if eval_macro(tokenize(line), self.defs): state[-1] = accepted elif token == 'else': if state[-1] == accepted: state[-1] = skipped elif state[-1] == ignored: state[-1] = accepted elif token == 'define': try: self.defs[self.define_name(line)] = line except AttributeError: raise PreprocError('Invalid define line %r' % line) elif token == 'undef': m = re_mac.match(line) if m and m.group() in self.defs: self.defs.__delitem__(m.group()) #print "undef %s" % name elif token == 'pragma': if re_pragma_once.match(line.lower()): self.ban_includes.add(self.current_file) except Exception as e: if Logs.verbose: Logs.debug('preproc: line parsing failed (%s): %s %s', e, line, traceback.format_exc()) def define_name(self, line): """ :param line: define line :type line: string :rtype: string :return: the define name """ return re_mac.match(line).group() def scan(task): """ Get the dependencies using a c/c++ preprocessor, this is required for finding dependencies of the kind:: #include some_macro() This function is bound as a task method on :py:class:`waflib.Tools.c.c` and :py:class:`waflib.Tools.cxx.cxx` for example """ try: incn = task.generator.includes_nodes except AttributeError: raise Errors.WafError('%r is missing a feature such as "c", "cxx" or "includes": ' % task.generator) if go_absolute: nodepaths = incn + [task.generator.bld.root.find_dir(x) for x in standard_includes] else: nodepaths = [x for x in incn if x.is_child_of(x.ctx.srcnode) or x.is_child_of(x.ctx.bldnode)] tmp = c_parser(nodepaths) tmp.start(task.inputs[0], task.env) return (tmp.nodes, tmp.names) kupfer-328/waflib/Tools/c_tests.py000066400000000000000000000137531500175051100172520ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2016-2018 (ita) """ Various configuration tests. """ from waflib import Task from waflib.Configure import conf from waflib.TaskGen import feature, before_method, after_method LIB_CODE = ''' #ifdef _MSC_VER #define testEXPORT __declspec(dllexport) #else #define testEXPORT #endif testEXPORT int lib_func(void) { return 9; } ''' MAIN_CODE = ''' #ifdef _MSC_VER #define testEXPORT __declspec(dllimport) #else #define testEXPORT #endif testEXPORT int lib_func(void); int main(int argc, char **argv) { (void)argc; (void)argv; return !(lib_func() == 9); } ''' @feature('link_lib_test') @before_method('process_source') def link_lib_test_fun(self): """ The configuration test :py:func:`waflib.Configure.run_build` declares a unique task generator, so we need to create other task generators from here to check if the linker is able to link libraries. """ def write_test_file(task): task.outputs[0].write(task.generator.code) rpath = [] if getattr(self, 'add_rpath', False): rpath = [self.bld.path.get_bld().abspath()] mode = self.mode m = '%s %s' % (mode, mode) ex = self.test_exec and 'test_exec' or '' bld = self.bld bld(rule=write_test_file, target='test.' + mode, code=LIB_CODE) bld(rule=write_test_file, target='main.' + mode, code=MAIN_CODE) bld(features='%sshlib' % m, source='test.' + mode, target='test') bld(features='%sprogram %s' % (m, ex), source='main.' + mode, target='app', use='test', rpath=rpath) @conf def check_library(self, mode=None, test_exec=True): """ Checks if libraries can be linked with the current linker. Uses :py:func:`waflib.Tools.c_tests.link_lib_test_fun`. :param mode: c or cxx or d :type mode: string """ if not mode: mode = 'c' if self.env.CXX: mode = 'cxx' self.check( compile_filename = [], features = 'link_lib_test', msg = 'Checking for libraries', mode = mode, test_exec = test_exec) ######################################################################################## INLINE_CODE = ''' typedef int foo_t; static %s foo_t static_foo () {return 0; } %s foo_t foo () { return 0; } ''' INLINE_VALUES = ['inline', '__inline__', '__inline'] @conf def check_inline(self, **kw): """ Checks for the right value for inline macro. Define INLINE_MACRO to 1 if the define is found. If the inline macro is not 'inline', add a define to the ``config.h`` (#define inline __inline__) :param define_name: define INLINE_MACRO by default to 1 if the macro is defined :type define_name: string :param features: by default *c* or *cxx* depending on the compiler present :type features: list of string """ self.start_msg('Checking for inline') if not 'define_name' in kw: kw['define_name'] = 'INLINE_MACRO' if not 'features' in kw: if self.env.CXX: kw['features'] = ['cxx'] else: kw['features'] = ['c'] for x in INLINE_VALUES: kw['fragment'] = INLINE_CODE % (x, x) try: self.check(**kw) except self.errors.ConfigurationError: continue else: self.end_msg(x) if x != 'inline': self.define('inline', x, quote=False) return x self.fatal('could not use inline functions') ######################################################################################## LARGE_FRAGMENT = '''#include int main(int argc, char **argv) { (void)argc; (void)argv; return !(sizeof(off_t) >= 8); } ''' @conf def check_large_file(self, **kw): """ Checks for large file support and define the macro HAVE_LARGEFILE The test is skipped on win32 systems (DEST_BINFMT == pe). :param define_name: define to set, by default *HAVE_LARGEFILE* :type define_name: string :param execute: execute the test (yes by default) :type execute: bool """ if not 'define_name' in kw: kw['define_name'] = 'HAVE_LARGEFILE' if not 'execute' in kw: kw['execute'] = True if not 'features' in kw: if self.env.CXX: kw['features'] = ['cxx', 'cxxprogram'] else: kw['features'] = ['c', 'cprogram'] kw['fragment'] = LARGE_FRAGMENT kw['msg'] = 'Checking for large file support' ret = True try: if self.env.DEST_BINFMT != 'pe': ret = self.check(**kw) except self.errors.ConfigurationError: pass else: if ret: return True kw['msg'] = 'Checking for -D_FILE_OFFSET_BITS=64' kw['defines'] = ['_FILE_OFFSET_BITS=64'] try: ret = self.check(**kw) except self.errors.ConfigurationError: pass else: self.define('_FILE_OFFSET_BITS', 64) return ret self.fatal('There is no support for large files') ######################################################################################## ENDIAN_FRAGMENT = ''' #ifdef _MSC_VER #define testshlib_EXPORT __declspec(dllexport) #else #define testshlib_EXPORT #endif short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int testshlib_EXPORT use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; ''' class grep_for_endianness(Task.Task): """ Task that reads a binary and tries to determine the endianness """ color = 'PINK' def run(self): txt = self.inputs[0].read(flags='rb').decode('latin-1') if txt.find('LiTTleEnDian') > -1: self.generator.tmp.append('little') elif txt.find('BIGenDianSyS') > -1: self.generator.tmp.append('big') else: return -1 @feature('grep_for_endianness') @after_method('apply_link') def grep_for_endianness_fun(self): """ Used by the endianness configuration test """ self.create_task('grep_for_endianness', self.link_task.outputs[0]) @conf def check_endianness(self): """ Executes a configuration test to determine the endianness """ tmp = [] def check_msg(self): return tmp[0] self.check(fragment=ENDIAN_FRAGMENT, features='c cshlib grep_for_endianness', msg='Checking for endianness', define='ENDIANNESS', tmp=tmp, okmsg=check_msg, confcache=None) return tmp[0] kupfer-328/waflib/Tools/ccroot.py000066400000000000000000000633031500175051100170730ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2018 (ita) """ Classes and methods shared by tools providing support for C-like language such as C/C++/D/Assembly/Go (this support module is almost never used alone). """ import os, re from waflib import Task, Utils, Node, Errors, Logs from waflib.TaskGen import after_method, before_method, feature, taskgen_method, extension from waflib.Tools import c_aliases, c_preproc, c_config, c_osx, c_tests from waflib.Configure import conf SYSTEM_LIB_PATHS = ['/usr/lib64', '/usr/lib', '/usr/local/lib64', '/usr/local/lib'] USELIB_VARS = Utils.defaultdict(set) """ Mapping for features to :py:class:`waflib.ConfigSet.ConfigSet` variables. See :py:func:`waflib.Tools.ccroot.propagate_uselib_vars`. """ USELIB_VARS['c'] = set(['INCLUDES', 'FRAMEWORKPATH', 'DEFINES', 'CPPFLAGS', 'CCDEPS', 'CFLAGS', 'ARCH']) USELIB_VARS['cxx'] = set(['INCLUDES', 'FRAMEWORKPATH', 'DEFINES', 'CPPFLAGS', 'CXXDEPS', 'CXXFLAGS', 'ARCH']) USELIB_VARS['d'] = set(['INCLUDES', 'DFLAGS']) USELIB_VARS['includes'] = set(['INCLUDES', 'FRAMEWORKPATH', 'ARCH']) USELIB_VARS['cprogram'] = USELIB_VARS['cxxprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS', 'FRAMEWORK', 'FRAMEWORKPATH', 'ARCH', 'LDFLAGS']) USELIB_VARS['cshlib'] = USELIB_VARS['cxxshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS', 'FRAMEWORK', 'FRAMEWORKPATH', 'ARCH', 'LDFLAGS']) USELIB_VARS['cstlib'] = USELIB_VARS['cxxstlib'] = set(['ARFLAGS', 'LINKDEPS']) USELIB_VARS['dprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) USELIB_VARS['dshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) USELIB_VARS['dstlib'] = set(['ARFLAGS', 'LINKDEPS']) USELIB_VARS['asm'] = set(['ASFLAGS']) # ================================================================================================= @taskgen_method def create_compiled_task(self, name, node): """ Create the compilation task: c, cxx, asm, etc. The output node is created automatically (object file with a typical **.o** extension). The task is appended to the list *compiled_tasks* which is then used by :py:func:`waflib.Tools.ccroot.apply_link` :param name: name of the task class :type name: string :param node: the file to compile :type node: :py:class:`waflib.Node.Node` :return: The task created :rtype: :py:class:`waflib.Task.Task` """ out = '%s.%d.o' % (node.name, self.idx) task = self.create_task(name, node, node.parent.find_or_declare(out)) try: self.compiled_tasks.append(task) except AttributeError: self.compiled_tasks = [task] return task @taskgen_method def to_incnodes(self, inlst): """ Task generator method provided to convert a list of string/nodes into a list of includes folders. The paths are assumed to be relative to the task generator path, except if they begin by **#** in which case they are searched from the top-level directory (``bld.srcnode``). The folders are simply assumed to be existing. The node objects in the list are returned in the output list. The strings are converted into node objects if possible. The node is searched from the source directory, and if a match is found, the equivalent build directory is created and added to the returned list too. When a folder cannot be found, it is ignored. :param inlst: list of folders :type inlst: space-delimited string or a list of string/nodes :rtype: list of :py:class:`waflib.Node.Node` :return: list of include folders as nodes """ lst = [] seen = set() for x in self.to_list(inlst): if x in seen or not x: continue seen.add(x) # with a real lot of targets, it is sometimes interesting to cache the results below if isinstance(x, Node.Node): lst.append(x) else: if os.path.isabs(x): lst.append(self.bld.root.make_node(x) or x) else: if x[0] == '#': p = self.bld.bldnode.make_node(x[1:]) v = self.bld.srcnode.make_node(x[1:]) else: p = self.path.get_bld().make_node(x) v = self.path.make_node(x) if p.is_child_of(self.bld.bldnode): p.mkdir() lst.append(p) lst.append(v) return lst @feature('c', 'cxx', 'd', 'asm', 'fc', 'includes') @after_method('propagate_uselib_vars', 'process_source') def apply_incpaths(self): """ Task generator method that processes the attribute *includes*:: tg = bld(features='includes', includes='.') The folders only need to be relative to the current directory, the equivalent build directory is added automatically (for headers created in the build directory). This enables using a build directory or not (``top == out``). This method will add a list of nodes read by :py:func:`waflib.Tools.ccroot.to_incnodes` in ``tg.env.INCPATHS``, and the list of include paths in ``tg.env.INCLUDES``. """ lst = self.to_incnodes(self.to_list(getattr(self, 'includes', [])) + self.env.INCLUDES) self.includes_nodes = lst cwd = self.get_cwd() self.env.INCPATHS = [x.path_from(cwd) for x in lst] class link_task(Task.Task): """ Base class for all link tasks. A task generator is supposed to have at most one link task bound in the attribute *link_task*. See :py:func:`waflib.Tools.ccroot.apply_link`. .. inheritance-diagram:: waflib.Tools.ccroot.stlink_task waflib.Tools.c.cprogram waflib.Tools.c.cshlib waflib.Tools.cxx.cxxstlib waflib.Tools.cxx.cxxprogram waflib.Tools.cxx.cxxshlib waflib.Tools.d.dprogram waflib.Tools.d.dshlib waflib.Tools.d.dstlib waflib.Tools.ccroot.fake_shlib waflib.Tools.ccroot.fake_stlib waflib.Tools.asm.asmprogram waflib.Tools.asm.asmshlib waflib.Tools.asm.asmstlib :top-classes: waflib.Tools.ccroot.link_task """ color = 'YELLOW' weight = 3 """Try to process link tasks as early as possible""" inst_to = None """Default installation path for the link task outputs, or None to disable""" chmod = Utils.O755 """Default installation mode for the link task outputs""" def add_target(self, target): """ Process the *target* attribute to add the platform-specific prefix/suffix such as *.so* or *.exe*. The settings are retrieved from ``env.clsname_PATTERN`` """ if isinstance(target, str): base = self.generator.path if target.startswith('#'): # for those who like flat structures target = target[1:] base = self.generator.bld.bldnode pattern = self.env[self.__class__.__name__ + '_PATTERN'] if not pattern: pattern = '%s' folder, name = os.path.split(target) if self.__class__.__name__.find('shlib') > 0 and getattr(self.generator, 'vnum', None): nums = self.generator.vnum.split('.') if self.env.DEST_BINFMT == 'pe': # include the version in the dll file name, # the import lib file name stays unversioned. name = name + '-' + nums[0] elif self.env.DEST_OS == 'openbsd': pattern = '%s.%s' % (pattern, nums[0]) if len(nums) >= 2: pattern += '.%s' % nums[1] if folder: tmp = folder + os.sep + pattern % name else: tmp = pattern % name target = base.find_or_declare(tmp) self.set_outputs(target) def exec_command(self, *k, **kw): ret = super(link_task, self).exec_command(*k, **kw) if not ret and self.env.DO_MANIFEST: ret = self.exec_mf() return ret def exec_mf(self): """ Create manifest files for VS-like compilers (msvc, ifort, ...) """ if not self.env.MT: return 0 manifest = None for out_node in self.outputs: if out_node.name.endswith('.manifest'): manifest = out_node.abspath() break else: # Should never get here. If we do, it means the manifest file was # never added to the outputs list, thus we don't have a manifest file # to embed, so we just return. return 0 # embedding mode. Different for EXE's and DLL's. # see: http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx mode = '' for x in Utils.to_list(self.generator.features): if x in ('cprogram', 'cxxprogram', 'fcprogram', 'fcprogram_test'): mode = 1 elif x in ('cshlib', 'cxxshlib', 'fcshlib'): mode = 2 Logs.debug('msvc: embedding manifest in mode %r', mode) lst = [] + self.env.MT lst.extend(Utils.to_list(self.env.MTFLAGS)) lst.extend(['-manifest', manifest]) lst.append('-outputresource:%s;%s' % (self.outputs[0].abspath(), mode)) return super(link_task, self).exec_command(lst) class stlink_task(link_task): """ Base for static link tasks, which use *ar* most of the time. The target is always removed before being written. """ run_str = '${AR} ${ARFLAGS} ${AR_TGT_F}${TGT} ${AR_SRC_F}${SRC}' chmod = Utils.O644 """Default installation mode for the static libraries""" def rm_tgt(cls): old = cls.run def wrap(self): try: os.remove(self.outputs[0].abspath()) except OSError: pass return old(self) setattr(cls, 'run', wrap) rm_tgt(stlink_task) @feature('skip_stlib_link_deps') @before_method('process_use') def apply_skip_stlib_link_deps(self): """ This enables an optimization in the :py:func:wafilb.Tools.ccroot.processes_use: method that skips dependency and link flag optimizations for targets that generate static libraries (via the :py:class:Tools.ccroot.stlink_task task). The actual behavior is implemented in :py:func:wafilb.Tools.ccroot.processes_use: method so this feature only tells waf to enable the new behavior. """ self.env.SKIP_STLIB_LINK_DEPS = True @feature('c', 'cxx', 'd', 'fc', 'asm') @after_method('process_source') def apply_link(self): """ Collect the tasks stored in ``compiled_tasks`` (created by :py:func:`waflib.Tools.ccroot.create_compiled_task`), and use the outputs for a new instance of :py:class:`waflib.Tools.ccroot.link_task`. The class to use is the first link task matching a name from the attribute *features*, for example:: def build(bld): tg = bld(features='cxx cxxprogram cprogram', source='main.c', target='app') will create the task ``tg.link_task`` as a new instance of :py:class:`waflib.Tools.cxx.cxxprogram` """ for x in self.features: if x == 'cprogram' and 'cxx' in self.features: # limited compat x = 'cxxprogram' elif x == 'cshlib' and 'cxx' in self.features: x = 'cxxshlib' if x in Task.classes: if issubclass(Task.classes[x], link_task): link = x break else: return objs = [t.outputs[0] for t in getattr(self, 'compiled_tasks', [])] self.link_task = self.create_task(link, objs) self.link_task.add_target(self.target) # remember that the install paths are given by the task generators try: inst_to = self.install_path except AttributeError: inst_to = self.link_task.inst_to if inst_to: # install a copy of the node list we have at this moment (implib not added) self.install_task = self.add_install_files( install_to=inst_to, install_from=self.link_task.outputs[:], chmod=self.link_task.chmod, task=self.link_task) @taskgen_method def use_rec(self, name, **kw): """ Processes the ``use`` keyword recursively. This method is kind of private and only meant to be used from ``process_use`` """ if name in self.tmp_use_not or name in self.tmp_use_seen: return try: y = self.bld.get_tgen_by_name(name) except Errors.WafError: self.uselib.append(name) self.tmp_use_not.add(name) return self.tmp_use_seen.append(name) y.post() # bind temporary attributes on the task generator y.tmp_use_objects = objects = kw.get('objects', True) y.tmp_use_stlib = stlib = kw.get('stlib', True) try: link_task = y.link_task except AttributeError: y.tmp_use_var = '' else: objects = False if not isinstance(link_task, stlink_task): stlib = False y.tmp_use_var = 'LIB' else: y.tmp_use_var = 'STLIB' p = self.tmp_use_prec for x in self.to_list(getattr(y, 'use', [])): if self.env["STLIB_" + x]: continue try: p[x].append(name) except KeyError: p[x] = [name] self.use_rec(x, objects=objects, stlib=stlib) @feature('c', 'cxx', 'd', 'use', 'fc') @before_method('apply_incpaths', 'propagate_uselib_vars') @after_method('apply_link', 'process_source') def process_use(self): """ Process the ``use`` attribute which contains a list of task generator names:: def build(bld): bld.shlib(source='a.c', target='lib1') bld.program(source='main.c', target='app', use='lib1') See :py:func:`waflib.Tools.ccroot.use_rec`. """ use_not = self.tmp_use_not = set() self.tmp_use_seen = [] # we would like an ordered set use_prec = self.tmp_use_prec = {} self.uselib = self.to_list(getattr(self, 'uselib', [])) self.includes = self.to_list(getattr(self, 'includes', [])) names = self.to_list(getattr(self, 'use', [])) for x in names: self.use_rec(x) for x in use_not: if x in use_prec: del use_prec[x] # topological sort out = self.tmp_use_sorted = [] tmp = [] for x in self.tmp_use_seen: for k in use_prec.values(): if x in k: break else: tmp.append(x) while tmp: e = tmp.pop() out.append(e) try: nlst = use_prec[e] except KeyError: pass else: del use_prec[e] for x in nlst: for y in use_prec: if x in use_prec[y]: break else: tmp.append(x) if use_prec: raise Errors.WafError('Cycle detected in the use processing %r' % use_prec) out.reverse() link_task = getattr(self, 'link_task', None) for x in out: y = self.bld.get_tgen_by_name(x) var = y.tmp_use_var if var and link_task: if self.env.SKIP_STLIB_LINK_DEPS and isinstance(link_task, stlink_task): # If the skip_stlib_link_deps feature is enabled then we should # avoid adding lib deps to the stlink_task instance. pass elif var == 'LIB' or y.tmp_use_stlib or x in names: self.env.append_value(var, [y.target[y.target.rfind(os.sep) + 1:]]) self.link_task.dep_nodes.extend(y.link_task.outputs) tmp_path = y.link_task.outputs[0].parent.path_from(self.get_cwd()) self.env.append_unique(var + 'PATH', [tmp_path]) else: if y.tmp_use_objects: self.add_objects_from_tgen(y) if getattr(y, 'export_includes', None): # self.includes may come from a global variable #2035 self.includes = self.includes + y.to_incnodes(y.export_includes) if getattr(y, 'export_defines', None): self.env.append_value('DEFINES', self.to_list(y.export_defines)) # and finally, add the use variables (no recursion needed) for x in names: try: y = self.bld.get_tgen_by_name(x) except Errors.WafError: if not self.env['STLIB_' + x] and not x in self.uselib: self.uselib.append(x) else: for k in self.to_list(getattr(y, 'use', [])): if not self.env['STLIB_' + k] and not k in self.uselib: self.uselib.append(k) @taskgen_method def accept_node_to_link(self, node): """ PRIVATE INTERNAL USE ONLY """ return not node.name.endswith('.pdb') @taskgen_method def add_objects_from_tgen(self, tg): """ Add the objects from the depending compiled tasks as link task inputs. Some objects are filtered: for instance, .pdb files are added to the compiled tasks but not to the link tasks (to avoid errors) PRIVATE INTERNAL USE ONLY """ try: link_task = self.link_task except AttributeError: pass else: for tsk in getattr(tg, 'compiled_tasks', []): for x in tsk.outputs: if self.accept_node_to_link(x): link_task.inputs.append(x) @taskgen_method def get_uselib_vars(self): """ :return: the *uselib* variables associated to the *features* attribute (see :py:attr:`waflib.Tools.ccroot.USELIB_VARS`) :rtype: list of string """ _vars = set() for x in self.features: if x in USELIB_VARS: _vars |= USELIB_VARS[x] return _vars @feature('c', 'cxx', 'd', 'fc', 'javac', 'cs', 'uselib', 'asm') @after_method('process_use') def propagate_uselib_vars(self): """ Process uselib variables for adding flags. For example, the following target:: def build(bld): bld.env.AFLAGS_aaa = ['bar'] from waflib.Tools.ccroot import USELIB_VARS USELIB_VARS['aaa'] = ['AFLAGS'] tg = bld(features='aaa', aflags='test') The *aflags* attribute will be processed and this method will set:: tg.env.AFLAGS = ['bar', 'test'] """ _vars = self.get_uselib_vars() env = self.env app = env.append_value feature_uselib = self.features + self.to_list(getattr(self, 'uselib', [])) for var in _vars: y = var.lower() val = getattr(self, y, []) if val: app(var, self.to_list(val)) for x in feature_uselib: val = env['%s_%s' % (var, x)] if val: app(var, val) # ============ the code above must not know anything about import libs ========== @feature('cshlib', 'cxxshlib', 'fcshlib') @after_method('apply_link') def apply_implib(self): """ Handle dlls and their import libs on Windows-like systems. A ``.dll.a`` file called *import library* is generated. It must be installed as it is required for linking the library. """ if not self.env.DEST_BINFMT == 'pe': return dll = self.link_task.outputs[0] if isinstance(self.target, Node.Node): name = self.target.name else: name = os.path.split(self.target)[1] implib = self.env.implib_PATTERN % name implib = dll.parent.find_or_declare(implib) self.env.append_value('LINKFLAGS', self.env.IMPLIB_ST % implib.bldpath()) self.link_task.outputs.append(implib) if getattr(self, 'defs', None) and self.env.DEST_BINFMT == 'pe': node = self.path.find_resource(self.defs) if not node: raise Errors.WafError('invalid def file %r' % self.defs) if self.env.def_PATTERN: self.env.append_value('LINKFLAGS', self.env.def_PATTERN % node.path_from(self.get_cwd())) self.link_task.dep_nodes.append(node) else: # gcc for windows takes *.def file as input without any special flag self.link_task.inputs.append(node) # where to put the import library if getattr(self, 'install_task', None): try: # user has given a specific installation path for the import library inst_to = self.install_path_implib except AttributeError: try: # user has given an installation path for the main library, put the import library in it inst_to = self.install_path except AttributeError: # else, put the library in BINDIR and the import library in LIBDIR inst_to = '${IMPLIBDIR}' self.install_task.install_to = '${BINDIR}' if not self.env.IMPLIBDIR: self.env.IMPLIBDIR = self.env.LIBDIR self.implib_install_task = self.add_install_files(install_to=inst_to, install_from=implib, chmod=self.link_task.chmod, task=self.link_task) # ============ the code above must not know anything about vnum processing on unix platforms ========= re_vnum = re.compile('^([1-9]\\d*|0)([.]([1-9]\\d*|0)){0,2}?$') @feature('cshlib', 'cxxshlib', 'dshlib', 'fcshlib', 'vnum') @after_method('apply_link', 'propagate_uselib_vars') def apply_vnum(self): """ Enforce version numbering on shared libraries. The valid version numbers must have either zero or two dots:: def build(bld): bld.shlib(source='a.c', target='foo', vnum='14.15.16') In this example on Linux platform, ``libfoo.so`` is installed as ``libfoo.so.14.15.16``, and the following symbolic links are created: * ``libfoo.so → libfoo.so.14.15.16`` * ``libfoo.so.14 → libfoo.so.14.15.16`` By default, the library will be assigned SONAME ``libfoo.so.14``, effectively declaring ABI compatibility between all minor and patch releases for the major version of the library. When necessary, the compatibility can be explicitly defined using `cnum` parameter: def build(bld): bld.shlib(source='a.c', target='foo', vnum='14.15.16', cnum='14.15') In this case, the assigned SONAME will be ``libfoo.so.14.15`` with ABI compatibility only between path releases for a specific major and minor version of the library. On OS X platform, install-name parameter will follow the above logic for SONAME with exception that it also specifies an absolute path (based on install_path) of the library. """ if not getattr(self, 'vnum', '') or os.name != 'posix' or self.env.DEST_BINFMT not in ('elf', 'mac-o'): return link = self.link_task if not re_vnum.match(self.vnum): raise Errors.WafError('Invalid vnum %r for target %r' % (self.vnum, getattr(self, 'name', self))) nums = self.vnum.split('.') node = link.outputs[0] cnum = getattr(self, 'cnum', str(nums[0])) cnums = cnum.split('.') if len(cnums)>len(nums) or nums[0:len(cnums)] != cnums: raise Errors.WafError('invalid compatibility version %s' % cnum) libname = node.name if libname.endswith('.dylib'): name3 = libname.replace('.dylib', '.%s.dylib' % self.vnum) name2 = libname.replace('.dylib', '.%s.dylib' % cnum) else: name3 = libname + '.' + self.vnum name2 = libname + '.' + cnum # add the so name for the ld linker - to disable, just unset env.SONAME_ST if self.env.SONAME_ST: v = self.env.SONAME_ST % name2 self.env.append_value('LINKFLAGS', v.split()) # the following task is just to enable execution from the build dir :-/ if self.env.DEST_OS != 'openbsd': outs = [node.parent.make_node(name3)] if name2 != name3: outs.append(node.parent.make_node(name2)) self.create_task('vnum', node, outs) if getattr(self, 'install_task', None): self.install_task.hasrun = Task.SKIPPED self.install_task.no_errcheck_out = True path = self.install_task.install_to if self.env.DEST_OS == 'openbsd': libname = self.link_task.outputs[0].name t1 = self.add_install_as(install_to='%s/%s' % (path, libname), install_from=node, chmod=self.link_task.chmod) self.vnum_install_task = (t1,) else: t1 = self.add_install_as(install_to=path + os.sep + name3, install_from=node, chmod=self.link_task.chmod) t3 = self.add_symlink_as(install_to=path + os.sep + libname, install_from=name3) if name2 != name3: t2 = self.add_symlink_as(install_to=path + os.sep + name2, install_from=name3) self.vnum_install_task = (t1, t2, t3) else: self.vnum_install_task = (t1, t3) if '-dynamiclib' in self.env.LINKFLAGS: # this requires after(propagate_uselib_vars) try: inst_to = self.install_path except AttributeError: inst_to = self.link_task.inst_to if inst_to: p = Utils.subst_vars(inst_to, self.env) path = os.path.join(p, name2) self.env.append_value('LINKFLAGS', ['-install_name', path]) self.env.append_value('LINKFLAGS', '-Wl,-compatibility_version,%s' % cnum) self.env.append_value('LINKFLAGS', '-Wl,-current_version,%s' % self.vnum) class vnum(Task.Task): """ Create the symbolic links for a versioned shared library. Instances are created by :py:func:`waflib.Tools.ccroot.apply_vnum` """ color = 'CYAN' ext_in = ['.bin'] def keyword(self): return 'Symlinking' def run(self): for x in self.outputs: path = x.abspath() try: os.remove(path) except OSError: pass try: os.symlink(self.inputs[0].name, path) except OSError: return 1 class fake_shlib(link_task): """ Task used for reading a system library and adding the dependency on it """ def runnable_status(self): for t in self.run_after: if not t.hasrun: return Task.ASK_LATER return Task.SKIP_ME class fake_stlib(stlink_task): """ Task used for reading a system library and adding the dependency on it """ def runnable_status(self): for t in self.run_after: if not t.hasrun: return Task.ASK_LATER return Task.SKIP_ME @conf def read_shlib(self, name, paths=[], export_includes=[], export_defines=[]): """ Read a system shared library, enabling its use as a local library. Will trigger a rebuild if the file changes:: def build(bld): bld.read_shlib('m') bld.program(source='main.c', use='m') """ return self(name=name, features='fake_lib', lib_paths=paths, lib_type='shlib', export_includes=export_includes, export_defines=export_defines) @conf def read_stlib(self, name, paths=[], export_includes=[], export_defines=[]): """ Read a system static library, enabling a use as a local library. Will trigger a rebuild if the file changes. """ return self(name=name, features='fake_lib', lib_paths=paths, lib_type='stlib', export_includes=export_includes, export_defines=export_defines) lib_patterns = { 'shlib' : ['lib%s.so', '%s.so', 'lib%s.dylib', 'lib%s.dll', '%s.dll'], 'stlib' : ['lib%s.a', '%s.a', 'lib%s.dll', '%s.dll', 'lib%s.lib', '%s.lib'], } @feature('fake_lib') def process_lib(self): """ Find the location of a foreign library. Used by :py:class:`waflib.Tools.ccroot.read_shlib` and :py:class:`waflib.Tools.ccroot.read_stlib`. """ node = None names = [x % self.name for x in lib_patterns[self.lib_type]] for x in self.lib_paths + [self.path] + SYSTEM_LIB_PATHS: if not isinstance(x, Node.Node): x = self.bld.root.find_node(x) or self.path.find_node(x) if not x: continue for y in names: node = x.find_node(y) if node: try: Utils.h_file(node.abspath()) except EnvironmentError: raise ValueError('Could not read %r' % y) break else: continue break else: raise Errors.WafError('could not find library %r' % self.name) self.link_task = self.create_task('fake_%s' % self.lib_type, [], [node]) self.target = self.name class fake_o(Task.Task): def runnable_status(self): return Task.SKIP_ME @extension('.o', '.obj') def add_those_o_files(self, node): tsk = self.create_task('fake_o', [], node) try: self.compiled_tasks.append(tsk) except AttributeError: self.compiled_tasks = [tsk] @feature('fake_obj') @before_method('process_source') def process_objs(self): """ Puts object files in the task generator outputs """ for node in self.to_nodes(self.source): self.add_those_o_files(node) self.source = [] @conf def read_object(self, obj): """ Read an object file, enabling injection in libs/programs. Will trigger a rebuild if the file changes. :param obj: object file path, as string or Node """ if not isinstance(obj, self.path.__class__): obj = self.path.find_resource(obj) return self(features='fake_obj', source=obj, name=obj.name) @feature('cxxprogram', 'cprogram') @after_method('apply_link', 'process_use') def set_full_paths_hpux(self): """ On hp-ux, extend the libpaths and static library paths to absolute paths """ if self.env.DEST_OS != 'hp-ux': return base = self.bld.bldnode.abspath() for var in ['LIBPATH', 'STLIBPATH']: lst = [] for x in self.env[var]: if x.startswith('/'): lst.append(x) else: lst.append(os.path.normpath(os.path.join(base, x))) self.env[var] = lst kupfer-328/waflib/Tools/errcheck.py000066400000000000000000000172221500175051100173670ustar00rootroot00000000000000#! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 (ita) """ Common mistakes highlighting. There is a performance impact, so this tool is only loaded when running ``waf -v`` """ typos = { 'feature':'features', 'sources':'source', 'targets':'target', 'include':'includes', 'export_include':'export_includes', 'define':'defines', 'importpath':'includes', 'installpath':'install_path', 'iscopy':'is_copy', 'uses':'use', } meths_typos = ['__call__', 'program', 'shlib', 'stlib', 'objects'] import sys from waflib import Logs, Build, Node, Task, TaskGen, ConfigSet, Errors, Utils from waflib.Tools import ccroot def check_same_targets(self): mp = Utils.defaultdict(list) uids = {} def check_task(tsk): if not isinstance(tsk, Task.Task): return if hasattr(tsk, 'no_errcheck_out'): return for node in tsk.outputs: mp[node].append(tsk) try: uids[tsk.uid()].append(tsk) except KeyError: uids[tsk.uid()] = [tsk] for g in self.groups: for tg in g: try: for tsk in tg.tasks: check_task(tsk) except AttributeError: # raised if not a task generator, which should be uncommon check_task(tg) dupe = False for (k, v) in mp.items(): if len(v) > 1: dupe = True msg = '* Node %r is created more than once%s. The task generators are:' % (k, Logs.verbose == 1 and " (full message on 'waf -v -v')" or "") Logs.error(msg) for x in v: if Logs.verbose > 1: Logs.error(' %d. %r', 1 + v.index(x), x.generator) else: Logs.error(' %d. %r in %r', 1 + v.index(x), x.generator.name, getattr(x.generator, 'path', None)) Logs.error('If you think that this is an error, set no_errcheck_out on the task instance') if not dupe: for (k, v) in uids.items(): if len(v) > 1: Logs.error('* Several tasks use the same identifier. Please check the information on\n https://waf.io/apidocs/Task.html?highlight=uid#waflib.Task.Task.uid') tg_details = tsk.generator.name if Logs.verbose > 2: tg_details = tsk.generator for tsk in v: Logs.error(' - object %r (%r) defined in %r', tsk.__class__.__name__, tsk, tg_details) def check_invalid_constraints(self): feat = set() for x in list(TaskGen.feats.values()): feat.union(set(x)) for (x, y) in TaskGen.task_gen.prec.items(): feat.add(x) feat.union(set(y)) ext = set() for x in TaskGen.task_gen.mappings.values(): ext.add(x.__name__) invalid = ext & feat if invalid: Logs.error('The methods %r have invalid annotations: @extension <-> @feature/@before_method/@after_method', list(invalid)) # the build scripts have been read, so we can check for invalid after/before attributes on task classes for cls in list(Task.classes.values()): if sys.hexversion > 0x3000000 and issubclass(cls, Task.Task) and isinstance(cls.hcode, str): raise Errors.WafError('Class %r has hcode value %r of type , expecting (use Utils.h_cmd() ?)' % (cls, cls.hcode)) for x in ('before', 'after'): for y in Utils.to_list(getattr(cls, x, [])): if not Task.classes.get(y): Logs.error('Erroneous order constraint %r=%r on task class %r', x, y, cls.__name__) if getattr(cls, 'rule', None): Logs.error('Erroneous attribute "rule" on task class %r (rename to "run_str")', cls.__name__) def replace(m): """ Replaces existing BuildContext methods to verify parameter names, for example ``bld(source=)`` has no ending *s* """ oldcall = getattr(Build.BuildContext, m) def call(self, *k, **kw): ret = oldcall(self, *k, **kw) for x in typos: if x in kw: if x == 'iscopy' and 'subst' in getattr(self, 'features', ''): continue Logs.error('Fix the typo %r -> %r on %r', x, typos[x], ret) return ret setattr(Build.BuildContext, m, call) def enhance_lib(): """ Modifies existing classes and methods to enable error verification """ for m in meths_typos: replace(m) # catch '..' in ant_glob patterns def ant_glob(self, *k, **kw): if k: lst = Utils.to_list(k[0]) for pat in lst: sp = pat.split('/') if '..' in sp: Logs.error("In ant_glob pattern %r: '..' means 'two dots', not 'parent directory'", k[0]) if '.' in sp: Logs.error("In ant_glob pattern %r: '.' means 'one dot', not 'current directory'", k[0]) return self.old_ant_glob(*k, **kw) Node.Node.old_ant_glob = Node.Node.ant_glob Node.Node.ant_glob = ant_glob # catch ant_glob on build folders def ant_iter(self, accept=None, maxdepth=25, pats=[], dir=False, src=True, remove=True, quiet=False): if remove: try: if self.is_child_of(self.ctx.bldnode) and not quiet: quiet = True Logs.error('Calling ant_glob on build folders (%r) is dangerous: add quiet=True / remove=False', self) except AttributeError: pass return self.old_ant_iter(accept, maxdepth, pats, dir, src, remove, quiet) Node.Node.old_ant_iter = Node.Node.ant_iter Node.Node.ant_iter = ant_iter # catch conflicting ext_in/ext_out/before/after declarations old = Task.is_before def is_before(t1, t2): ret = old(t1, t2) if ret and old(t2, t1): Logs.error('Contradictory order constraints in classes %r %r', t1, t2) return ret Task.is_before = is_before # check for bld(feature='cshlib') where no 'c' is given - this can be either a mistake or on purpose # so we only issue a warning def check_err_features(self): lst = self.to_list(self.features) if 'shlib' in lst: Logs.error('feature shlib -> cshlib, dshlib or cxxshlib') for x in ('c', 'cxx', 'd', 'fc'): if not x in lst and lst and lst[0] in [x+y for y in ('program', 'shlib', 'stlib')]: Logs.error('%r features is probably missing %r', self, x) TaskGen.feature('*')(check_err_features) # check for erroneous order constraints def check_err_order(self): if not hasattr(self, 'rule') and not 'subst' in Utils.to_list(self.features): for x in ('before', 'after', 'ext_in', 'ext_out'): if hasattr(self, x): Logs.warn('Erroneous order constraint %r on non-rule based task generator %r', x, self) else: for x in ('before', 'after'): for y in self.to_list(getattr(self, x, [])): if not Task.classes.get(y): Logs.error('Erroneous order constraint %s=%r on %r (no such class)', x, y, self) TaskGen.feature('*')(check_err_order) # check for @extension used with @feature/@before_method/@after_method def check_compile(self): check_invalid_constraints(self) try: ret = self.orig_compile() finally: check_same_targets(self) return ret Build.BuildContext.orig_compile = Build.BuildContext.compile Build.BuildContext.compile = check_compile # check for invalid build groups #914 def use_rec(self, name, **kw): try: y = self.bld.get_tgen_by_name(name) except Errors.WafError: pass else: idx = self.bld.get_group_idx(self) odx = self.bld.get_group_idx(y) if odx > idx: msg = "Invalid 'use' across build groups:" if Logs.verbose > 1: msg += '\n target %r\n uses:\n %r' % (self, y) else: msg += " %r uses %r (try 'waf -v -v' for the full error)" % (self.name, name) raise Errors.WafError(msg) self.orig_use_rec(name, **kw) TaskGen.task_gen.orig_use_rec = TaskGen.task_gen.use_rec TaskGen.task_gen.use_rec = use_rec # check for env.append def _getattr(self, name, default=None): if name == 'append' or name == 'add': raise Errors.WafError('env.append and env.add do not exist: use env.append_value/env.append_unique') elif name == 'prepend': raise Errors.WafError('env.prepend does not exist: use env.prepend_value') if name in self.__slots__: return super(ConfigSet.ConfigSet, self).__getattr__(name, default) else: return self[name] ConfigSet.ConfigSet.__getattr__ = _getattr def options(opt): """ Error verification can be enabled by default (not just on ``waf -v``) by adding to the user script options """ enhance_lib() kupfer-328/waflib/Tools/gnu_dirs.py000066400000000000000000000120761500175051100174150ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Ali Sabil, 2007 """ Sets various standard variables such as INCLUDEDIR. SBINDIR and others. To use this module just call:: opt.load('gnu_dirs') and:: conf.load('gnu_dirs') Add options for the standard GNU directories, this tool will add the options found in autotools, and will update the environment with the following installation variables: ============== ========================================= ======================= Variable Description Default Value ============== ========================================= ======================= PREFIX installation prefix /usr/local EXEC_PREFIX installation prefix for binaries PREFIX BINDIR user commands EXEC_PREFIX/bin SBINDIR system binaries EXEC_PREFIX/sbin LIBEXECDIR program-specific binaries EXEC_PREFIX/libexec SYSCONFDIR host-specific configuration PREFIX/etc SHAREDSTATEDIR architecture-independent variable data PREFIX/com LOCALSTATEDIR variable data PREFIX/var LIBDIR object code libraries EXEC_PREFIX/lib INCLUDEDIR header files PREFIX/include OLDINCLUDEDIR header files for non-GCC compilers /usr/include DATAROOTDIR architecture-independent data root PREFIX/share DATADIR architecture-independent data DATAROOTDIR INFODIR GNU "info" documentation DATAROOTDIR/info LOCALEDIR locale-dependent data DATAROOTDIR/locale MANDIR manual pages DATAROOTDIR/man DOCDIR documentation root DATAROOTDIR/doc/APPNAME HTMLDIR HTML documentation DOCDIR DVIDIR DVI documentation DOCDIR PDFDIR PDF documentation DOCDIR PSDIR PostScript documentation DOCDIR ============== ========================================= ======================= """ import os, re from waflib import Utils, Options, Context gnuopts = ''' bindir, user commands, ${EXEC_PREFIX}/bin sbindir, system binaries, ${EXEC_PREFIX}/sbin libexecdir, program-specific binaries, ${EXEC_PREFIX}/libexec sysconfdir, host-specific configuration, ${PREFIX}/etc sharedstatedir, architecture-independent variable data, ${PREFIX}/com localstatedir, variable data, ${PREFIX}/var libdir, object code libraries, ${EXEC_PREFIX}/lib%s includedir, header files, ${PREFIX}/include oldincludedir, header files for non-GCC compilers, /usr/include datarootdir, architecture-independent data root, ${PREFIX}/share datadir, architecture-independent data, ${DATAROOTDIR} infodir, GNU "info" documentation, ${DATAROOTDIR}/info localedir, locale-dependent data, ${DATAROOTDIR}/locale mandir, manual pages, ${DATAROOTDIR}/man docdir, documentation root, ${DATAROOTDIR}/doc/${PACKAGE} htmldir, HTML documentation, ${DOCDIR} dvidir, DVI documentation, ${DOCDIR} pdfdir, PDF documentation, ${DOCDIR} psdir, PostScript documentation, ${DOCDIR} ''' % Utils.lib64() _options = [x.split(', ') for x in gnuopts.splitlines() if x] def configure(conf): """ Reads the command-line options to set lots of variables in *conf.env*. The variables BINDIR and LIBDIR will be overwritten. """ def get_param(varname, default): return getattr(Options.options, varname, '') or default env = conf.env env.LIBDIR = env.BINDIR = [] env.EXEC_PREFIX = get_param('EXEC_PREFIX', env.PREFIX) env.PACKAGE = getattr(Context.g_module, 'APPNAME', None) or env.PACKAGE complete = False iter = 0 while not complete and iter < len(_options) + 1: iter += 1 complete = True for name, help, default in _options: name = name.upper() if not env[name]: try: env[name] = Utils.subst_vars(get_param(name, default).replace('/', os.sep), env) except TypeError: complete = False if not complete: lst = [x for x, _, _ in _options if not env[x.upper()]] raise conf.errors.WafError('Variable substitution failure %r' % lst) def options(opt): """ Adds lots of command-line options, for example:: --exec-prefix: EXEC_PREFIX """ inst_dir = opt.add_option_group('Installation prefix', 'By default, "waf install" will put the files in\ "/usr/local/bin", "/usr/local/lib" etc. An installation prefix other\ than "/usr/local" can be given using "--prefix", for example "--prefix=$HOME"') for k in ('--prefix', '--destdir'): option = opt.parser.get_option(k) if option: opt.parser.remove_option(k) inst_dir.add_option(option) inst_dir.add_option('--exec-prefix', help = 'installation prefix for binaries [PREFIX]', default = '', dest = 'EXEC_PREFIX') dirs_options = opt.add_option_group('Installation directories') for name, help, default in _options: option_name = '--' + name str_default = default str_help = '%s [%s]' % (help, re.sub(r'\$\{([^}]+)\}', r'\1', str_default)) dirs_options.add_option(option_name, help=str_help, default='', dest=name.upper()) kupfer-328/waflib/Tools/intltool.py000066400000000000000000000152001500175051100174370ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2018 (ita) """ Support for translation tools such as msgfmt and intltool Usage:: def configure(conf): conf.load('gnu_dirs intltool') def build(bld): # process the .po files into .gmo files, and install them in LOCALEDIR bld(features='intltool_po', appname='myapp', podir='po', install_path="${LOCALEDIR}") # process an input file, substituting the translations from the po dir bld( features = "intltool_in", podir = "../po", style = "desktop", flags = ["-u"], source = 'kupfer.desktop.in', install_path = "${DATADIR}/applications", ) Usage of the :py:mod:`waflib.Tools.gnu_dirs` is recommended, but not obligatory. """ from __future__ import with_statement import os, re from waflib import Context, Task, Utils, Logs import waflib.Tools.ccroot from waflib.TaskGen import feature, before_method, taskgen_method from waflib.Logs import error from waflib.Configure import conf _style_flags = { 'ba': '-b', 'desktop': '-d', 'keys': '-k', 'quoted': '--quoted-style', 'quotedxml': '--quotedxml-style', 'rfc822deb': '-r', 'schemas': '-s', 'xml': '-x', } @taskgen_method def ensure_localedir(self): """ Expands LOCALEDIR from DATAROOTDIR/locale if possible, or falls back to PREFIX/share/locale """ # use the tool gnu_dirs to provide options to define this if not self.env.LOCALEDIR: if self.env.DATAROOTDIR: self.env.LOCALEDIR = os.path.join(self.env.DATAROOTDIR, 'locale') else: self.env.LOCALEDIR = os.path.join(self.env.PREFIX, 'share', 'locale') @before_method('process_source') @feature('intltool_in') def apply_intltool_in_f(self): """ Creates tasks to translate files by intltool-merge:: def build(bld): bld( features = "intltool_in", podir = "../po", style = "desktop", flags = ["-u"], source = 'kupfer.desktop.in', install_path = "${DATADIR}/applications", ) :param podir: location of the .po files :type podir: string :param source: source files to process :type source: list of string :param style: the intltool-merge mode of operation, can be one of the following values: ``ba``, ``desktop``, ``keys``, ``quoted``, ``quotedxml``, ``rfc822deb``, ``schemas`` and ``xml``. See the ``intltool-merge`` man page for more information about supported modes of operation. :type style: string :param flags: compilation flags ("-quc" by default) :type flags: list of string :param install_path: installation path :type install_path: string """ try: self.meths.remove('process_source') except ValueError: pass self.ensure_localedir() podir = getattr(self, 'podir', '.') podirnode = self.path.find_dir(podir) if not podirnode: error("could not find the podir %r" % podir) return cache = getattr(self, 'intlcache', '.intlcache') self.env.INTLCACHE = [os.path.join(str(self.path.get_bld()), podir, cache)] self.env.INTLPODIR = podirnode.bldpath() self.env.append_value('INTLFLAGS', getattr(self, 'flags', self.env.INTLFLAGS_DEFAULT)) if '-c' in self.env.INTLFLAGS: self.bld.fatal('Redundant -c flag in intltool task %r' % self) style = getattr(self, 'style', None) if style: try: style_flag = _style_flags[style] except KeyError: self.bld.fatal('intltool_in style "%s" is not valid' % style) self.env.append_unique('INTLFLAGS', [style_flag]) for i in self.to_list(self.source): node = self.path.find_resource(i) task = self.create_task('intltool', node, node.change_ext('')) inst = getattr(self, 'install_path', None) if inst: self.add_install_files(install_to=inst, install_from=task.outputs) @feature('intltool_po') def apply_intltool_po(self): """ Creates tasks to process po files:: def build(bld): bld(features='intltool_po', appname='myapp', podir='po', install_path="${LOCALEDIR}") The relevant task generator arguments are: :param podir: directory of the .po files :type podir: string :param appname: name of the application :type appname: string :param install_path: installation directory :type install_path: string The file LINGUAS must be present in the directory pointed by *podir* and list the translation files to process. """ try: self.meths.remove('process_source') except ValueError: pass self.ensure_localedir() appname = getattr(self, 'appname', getattr(Context.g_module, Context.APPNAME, 'set_your_app_name')) podir = getattr(self, 'podir', '.') inst = getattr(self, 'install_path', '${LOCALEDIR}') linguas = self.path.find_node(os.path.join(podir, 'LINGUAS')) if linguas: # scan LINGUAS file for locales to process with open(linguas.abspath()) as f: langs = [] for line in f.readlines(): # ignore lines containing comments if not line.startswith('#'): langs += line.split() re_linguas = re.compile('[-a-zA-Z_@.]+') for lang in langs: # Make sure that we only process lines which contain locales if re_linguas.match(lang): node = self.path.find_resource(os.path.join(podir, re_linguas.match(lang).group() + '.po')) task = self.create_task('po', node, node.change_ext('.mo')) if inst: filename = task.outputs[0].name (langname, ext) = os.path.splitext(filename) inst_file = inst + os.sep + langname + os.sep + 'LC_MESSAGES' + os.sep + appname + '.mo' self.add_install_as(install_to=inst_file, install_from=task.outputs[0], chmod=getattr(self, 'chmod', Utils.O644)) else: Logs.pprint('RED', "Error no LINGUAS file found in po directory") class po(Task.Task): """ Compiles .po files into .gmo files """ run_str = '${MSGFMT} -o ${TGT} ${SRC}' color = 'BLUE' class intltool(Task.Task): """ Calls intltool-merge to update translation files """ run_str = '${INTLTOOL} ${INTLFLAGS} ${INTLCACHE_ST:INTLCACHE} ${INTLPODIR} ${SRC} ${TGT}' color = 'BLUE' @conf def find_msgfmt(conf): """ Detects msgfmt and sets the ``MSGFMT`` variable """ conf.find_program('msgfmt', var='MSGFMT') @conf def find_intltool_merge(conf): """ Detects intltool-merge """ if not conf.env.PERL: conf.find_program('perl', var='PERL') conf.env.INTLCACHE_ST = '--cache=%s' conf.env.INTLFLAGS_DEFAULT = ['-q', '-u'] conf.find_program('intltool-merge', interpreter='PERL', var='INTLTOOL') def configure(conf): """ Detects the program *msgfmt* and set *conf.env.MSGFMT*. Detects the program *intltool-merge* and set *conf.env.INTLTOOL*. It is possible to set INTLTOOL in the environment, but it must not have spaces in it:: $ INTLTOOL="/path/to/the program/intltool" waf configure If a C/C++ compiler is present, execute a compilation test to find the header *locale.h*. """ conf.find_msgfmt() conf.find_intltool_merge() if conf.env.CC or conf.env.CXX: conf.check(header_name='locale.h') kupfer-328/waflib/Tools/python.py000066400000000000000000000553401500175051100171250ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2007-2015 (ita) # Gustavo Carneiro (gjc), 2007 """ Support for Python, detect the headers and libraries and provide *use* variables to link C/C++ programs against them:: def options(opt): opt.load('compiler_c python') def configure(conf): conf.load('compiler_c python') conf.check_python_version((2,4,2)) conf.check_python_headers() def build(bld): bld.program(features='pyembed', source='a.c', target='myprog') bld.shlib(features='pyext', source='b.c', target='mylib') """ import os, sys from waflib import Errors, Logs, Node, Options, Task, Utils from waflib.TaskGen import extension, before_method, after_method, feature from waflib.Configure import conf FRAG = ''' #include #ifdef __cplusplus extern "C" { #endif void Py_Initialize(void); void Py_Finalize(void); #ifdef __cplusplus } #endif int main(int argc, char **argv) { (void)argc; (void)argv; Py_Initialize(); Py_Finalize(); return 0; } ''' """ Piece of C/C++ code used in :py:func:`waflib.Tools.python.check_python_headers` """ INST = ''' import sys, py_compile py_compile.compile(sys.argv[1], sys.argv[2], sys.argv[3], True) ''' """ Piece of Python code used in :py:class:`waflib.Tools.python.pyo` and :py:class:`waflib.Tools.python.pyc` for byte-compiling python files """ DISTUTILS_IMP = """ try: from distutils.sysconfig import get_config_var, get_python_lib except ImportError: from sysconfig import get_config_var, get_path def get_python_lib(*k, **kw): keyword='platlib' if kw.get('plat_specific') else 'purelib' if 'prefix' in kw: return get_path(keyword, vars={'installed_base': kw['prefix'], 'platbase': kw['prefix']}) return get_path(keyword) """.splitlines() @before_method('process_source') @feature('py') def feature_py(self): """ Create tasks to byte-compile .py files and install them, if requested """ self.install_path = getattr(self, 'install_path', '${PYTHONDIR}') install_from = getattr(self, 'install_from', None) if install_from and not isinstance(install_from, Node.Node): install_from = self.path.find_dir(install_from) self.install_from = install_from ver = self.env.PYTHON_VERSION if not ver: self.bld.fatal('Installing python files requires PYTHON_VERSION, try conf.check_python_version') if int(ver.replace('.', '')) > 31: self.install_32 = True @extension('.py') def process_py(self, node): """ Add signature of .py file, so it will be byte-compiled when necessary """ assert(hasattr(self, 'install_path')), 'add features="py" for target "%s" in "%s/wscript".' % (self.target, self.path.nice_path()) self.install_from = getattr(self, 'install_from', None) relative_trick = getattr(self, 'relative_trick', True) if self.install_from: assert isinstance(self.install_from, Node.Node), \ 'add features="py" for target "%s" in "%s/wscript" (%s).' % (self.target, self.path.nice_path(), type(self.install_from)) # where to install the python file if self.install_path: if self.install_from: self.add_install_files(install_to=self.install_path, install_from=node, cwd=self.install_from, relative_trick=relative_trick) else: self.add_install_files(install_to=self.install_path, install_from=node, relative_trick=relative_trick) lst = [] if self.env.PYC: lst.append('pyc') if self.env.PYO: lst.append('pyo') if self.install_path: if self.install_from: target_dir = node.path_from(self.install_from) if relative_trick else node.name pyd = Utils.subst_vars("%s/%s" % (self.install_path, target_dir), self.env) else: target_dir = node.path_from(self.path) if relative_trick else node.name pyd = Utils.subst_vars("%s/%s" % (self.install_path, target_dir), self.env) else: pyd = node.abspath() for ext in lst: if self.env.PYTAG and not self.env.NOPYCACHE: # __pycache__ installation for python 3.2 - PEP 3147 name = node.name[:-3] pyobj = node.parent.get_bld().make_node('__pycache__').make_node("%s.%s.%s" % (name, self.env.PYTAG, ext)) pyobj.parent.mkdir() else: pyobj = node.change_ext(".%s" % ext) tsk = self.create_task(ext, node, pyobj) tsk.pyd = pyd if self.install_path: self.add_install_files(install_to=os.path.dirname(pyd), install_from=pyobj, cwd=node.parent.get_bld(), relative_trick=relative_trick) class pyc(Task.Task): """ Byte-compiling python files """ color = 'PINK' def __str__(self): node = self.outputs[0] return node.path_from(node.ctx.launch_node()) def run(self): cmd = [Utils.subst_vars('${PYTHON}', self.env), '-c', INST, self.inputs[0].abspath(), self.outputs[0].abspath(), self.pyd] ret = self.generator.bld.exec_command(cmd) return ret class pyo(Task.Task): """ Byte-compiling python files """ color = 'PINK' def __str__(self): node = self.outputs[0] return node.path_from(node.ctx.launch_node()) def run(self): cmd = [Utils.subst_vars('${PYTHON}', self.env), Utils.subst_vars('${PYFLAGS_OPT}', self.env), '-c', INST, self.inputs[0].abspath(), self.outputs[0].abspath(), self.pyd] ret = self.generator.bld.exec_command(cmd) return ret @feature('pyext') @before_method('propagate_uselib_vars', 'apply_link') @after_method('apply_bundle') def init_pyext(self): """ Change the values of *cshlib_PATTERN* and *cxxshlib_PATTERN* to remove the *lib* prefix from library names. """ self.uselib = self.to_list(getattr(self, 'uselib', [])) if not 'PYEXT' in self.uselib: self.uselib.append('PYEXT') # override shlib_PATTERN set by the osx module self.env.cshlib_PATTERN = self.env.cxxshlib_PATTERN = self.env.macbundle_PATTERN = self.env.pyext_PATTERN self.env.fcshlib_PATTERN = self.env.dshlib_PATTERN = self.env.pyext_PATTERN try: if not self.install_path: return except AttributeError: self.install_path = '${PYTHONARCHDIR}' @feature('pyext') @before_method('apply_link', 'apply_bundle') def set_bundle(self): """Mac-specific pyext extension that enables bundles from c_osx.py""" if Utils.unversioned_sys_platform() == 'darwin': self.mac_bundle = True @before_method('propagate_uselib_vars') @feature('pyembed') def init_pyembed(self): """ Add the PYEMBED variable. """ self.uselib = self.to_list(getattr(self, 'uselib', [])) if not 'PYEMBED' in self.uselib: self.uselib.append('PYEMBED') @conf def get_python_variables(self, variables, imports=None): """ Spawn a new python process to dump configuration variables :param variables: variables to print :type variables: list of string :param imports: one import by element :type imports: list of string :return: the variable values :rtype: list of string """ if not imports: try: imports = self.python_imports except AttributeError: imports = DISTUTILS_IMP program = list(imports) # copy program.append('') for v in variables: program.append("print(repr(%s))" % v) os_env = dict(os.environ) try: del os_env['MACOSX_DEPLOYMENT_TARGET'] # see comments in the OSX tool except KeyError: pass try: out = self.cmd_and_log(self.env.PYTHON + ['-c', '\n'.join(program)], env=os_env) except Errors.WafError: self.fatal('Could not run %r' % self.env.PYTHON) self.to_log(out) return_values = [] for s in out.splitlines(): s = s.strip() if not s: continue if s == 'None': return_values.append(None) elif (s[0] == "'" and s[-1] == "'") or (s[0] == '"' and s[-1] == '"'): return_values.append(eval(s)) elif s[0].isdigit(): return_values.append(int(s)) else: break return return_values @conf def test_pyembed(self, mode, msg='Testing pyembed configuration'): self.check(header_name='Python.h', define_name='HAVE_PYEMBED', msg=msg, fragment=FRAG, errmsg='Could not build a python embedded interpreter', features='%s %sprogram pyembed' % (mode, mode)) @conf def test_pyext(self, mode, msg='Testing pyext configuration'): self.check(header_name='Python.h', define_name='HAVE_PYEXT', msg=msg, fragment=FRAG, errmsg='Could not build python extensions', features='%s %sshlib pyext' % (mode, mode)) @conf def python_cross_compile(self, features='pyembed pyext'): """ For cross-compilation purposes, it is possible to bypass the normal detection and set the flags that you want: PYTHON_VERSION='3.4' PYTAG='cpython34' pyext_PATTERN="%s.so" PYTHON_LDFLAGS='-lpthread -ldl' waf configure The following variables are used: PYTHON_VERSION required PYTAG required PYTHON_LDFLAGS required pyext_PATTERN required PYTHON_PYEXT_LDFLAGS PYTHON_PYEMBED_LDFLAGS """ features = Utils.to_list(features) if not ('PYTHON_LDFLAGS' in self.environ or 'PYTHON_PYEXT_LDFLAGS' in self.environ or 'PYTHON_PYEMBED_LDFLAGS' in self.environ): return False for x in 'PYTHON_VERSION PYTAG pyext_PATTERN'.split(): if not x in self.environ: self.fatal('Please set %s in the os environment' % x) else: self.env[x] = self.environ[x] xx = self.env.CXX_NAME and 'cxx' or 'c' if 'pyext' in features: flags = self.environ.get('PYTHON_PYEXT_LDFLAGS', self.environ.get('PYTHON_LDFLAGS')) if flags is None: self.fatal('No flags provided through PYTHON_PYEXT_LDFLAGS as required') else: self.parse_flags(flags, 'PYEXT') self.test_pyext(xx) if 'pyembed' in features: flags = self.environ.get('PYTHON_PYEMBED_LDFLAGS', self.environ.get('PYTHON_LDFLAGS')) if flags is None: self.fatal('No flags provided through PYTHON_PYEMBED_LDFLAGS as required') else: self.parse_flags(flags, 'PYEMBED') self.test_pyembed(xx) return True @conf def check_python_headers(conf, features='pyembed pyext'): """ Check for headers and libraries necessary to extend or embed python. It may use the module *distutils* or sysconfig in newer Python versions. On success the environment variables xxx_PYEXT and xxx_PYEMBED are added: * PYEXT: for compiling python extensions * PYEMBED: for embedding a python interpreter """ features = Utils.to_list(features) assert ('pyembed' in features) or ('pyext' in features), "check_python_headers features must include 'pyembed' and/or 'pyext'" env = conf.env if not env.CC_NAME and not env.CXX_NAME: conf.fatal('load a compiler first (gcc, g++, ..)') # bypass all the code below for cross-compilation if conf.python_cross_compile(features): return if not env.PYTHON_VERSION: conf.check_python_version() pybin = env.PYTHON if not pybin: conf.fatal('Could not find the python executable') # so we actually do all this for compatibility reasons and for obtaining pyext_PATTERN below v = 'prefix SO EXT_SUFFIX LDFLAGS LIBDIR LIBPL INCLUDEPY Py_ENABLE_SHARED MACOSX_DEPLOYMENT_TARGET LDSHARED CFLAGS LDVERSION'.split() try: lst = conf.get_python_variables(["get_config_var('%s') or ''" % x for x in v]) except RuntimeError: conf.fatal("Python development headers not found (-v for details).") vals = ['%s = %r' % (x, y) for (x, y) in zip(v, lst)] conf.to_log("Configuration returned from %r:\n%s\n" % (pybin, '\n'.join(vals))) dct = dict(zip(v, lst)) x = 'MACOSX_DEPLOYMENT_TARGET' if dct[x]: env[x] = conf.environ[x] = str(dct[x]) env.pyext_PATTERN = '%s' + (dct['EXT_SUFFIX'] or dct['SO']) # SO is deprecated in 3.5 and removed in 3.11 # Try to get pythonX.Y-config num = '.'.join(env.PYTHON_VERSION.split('.')[:2]) conf.find_program([''.join(pybin) + '-config', 'python%s-config' % num, 'python-config-%s' % num, 'python%sm-config' % num], var='PYTHON_CONFIG', msg="python-config", mandatory=False) if env.PYTHON_CONFIG: # check python-config output only once if conf.env.HAVE_PYTHON_H: return # python2.6-config requires 3 runs all_flags = [['--cflags', '--libs', '--ldflags']] if sys.hexversion < 0x2070000: all_flags = [[k] for k in all_flags[0]] xx = env.CXX_NAME and 'cxx' or 'c' if 'pyembed' in features: for flags in all_flags: # Python 3.8 has different flags for pyembed, needs --embed embedflags = flags + ['--embed'] try: conf.check_cfg(msg='Asking python-config for pyembed %r flags' % ' '.join(embedflags), path=env.PYTHON_CONFIG, package='', uselib_store='PYEMBED', args=embedflags) except conf.errors.ConfigurationError: # However Python < 3.8 doesn't accept --embed, so we need a fallback conf.check_cfg(msg='Asking python-config for pyembed %r flags' % ' '.join(flags), path=env.PYTHON_CONFIG, package='', uselib_store='PYEMBED', args=flags) try: conf.test_pyembed(xx) except conf.errors.ConfigurationError: # python bug 7352 if dct['Py_ENABLE_SHARED'] and dct['LIBDIR']: env.append_unique('LIBPATH_PYEMBED', [dct['LIBDIR']]) conf.test_pyembed(xx) else: raise if 'pyext' in features: for flags in all_flags: conf.check_cfg(msg='Asking python-config for pyext %r flags' % ' '.join(flags), path=env.PYTHON_CONFIG, package='', uselib_store='PYEXT', args=flags) try: conf.test_pyext(xx) except conf.errors.ConfigurationError: # python bug 7352 if dct['Py_ENABLE_SHARED'] and dct['LIBDIR']: env.append_unique('LIBPATH_PYEXT', [dct['LIBDIR']]) conf.test_pyext(xx) else: raise conf.define('HAVE_PYTHON_H', 1) return # No python-config, do something else on windows systems all_flags = dct['LDFLAGS'] + ' ' + dct['CFLAGS'] conf.parse_flags(all_flags, 'PYEMBED') all_flags = dct['LDFLAGS'] + ' ' + dct['LDSHARED'] + ' ' + dct['CFLAGS'] conf.parse_flags(all_flags, 'PYEXT') result = None if not dct["LDVERSION"]: dct["LDVERSION"] = env.PYTHON_VERSION # further simplification will be complicated for name in ('python' + dct['LDVERSION'], 'python' + env.PYTHON_VERSION + 'm', 'python' + env.PYTHON_VERSION.replace('.', '')): # LIBPATH_PYEMBED is already set; see if it works. if not result and env.LIBPATH_PYEMBED: path = env.LIBPATH_PYEMBED conf.to_log("\n\n# Trying default LIBPATH_PYEMBED: %r\n" % path) result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in LIBPATH_PYEMBED' % name) if not result and dct['LIBDIR']: path = [dct['LIBDIR']] conf.to_log("\n\n# try again with -L$python_LIBDIR: %r\n" % path) result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in LIBDIR' % name) if not result and dct['LIBPL']: path = [dct['LIBPL']] conf.to_log("\n\n# try again with -L$python_LIBPL (some systems don't install the python library in $prefix/lib)\n") result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in python_LIBPL' % name) if not result: path = [os.path.join(dct['prefix'], "libs")] conf.to_log("\n\n# try again with -L$prefix/libs, and pythonXY rather than pythonX.Y (win32)\n") result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in $prefix/libs' % name) if not result: path = [os.path.normpath(os.path.join(dct['INCLUDEPY'], '..', 'libs'))] conf.to_log("\n\n# try again with -L$INCLUDEPY/../libs, and pythonXY rather than pythonX.Y (win32)\n") result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in $INCLUDEPY/../libs' % name) if result: break # do not forget to set LIBPATH_PYEMBED if result: env.LIBPATH_PYEMBED = path env.append_value('LIB_PYEMBED', [name]) else: conf.to_log("\n\n### LIB NOT FOUND\n") # under certain conditions, python extensions must link to # python libraries, not just python embedding programs. if Utils.is_win32 or dct['Py_ENABLE_SHARED']: env.LIBPATH_PYEXT = env.LIBPATH_PYEMBED env.LIB_PYEXT = env.LIB_PYEMBED conf.to_log("Found an include path for Python extensions: %r\n" % (dct['INCLUDEPY'],)) env.INCLUDES_PYEXT = [dct['INCLUDEPY']] env.INCLUDES_PYEMBED = [dct['INCLUDEPY']] # Code using the Python API needs to be compiled with -fno-strict-aliasing if env.CC_NAME == 'gcc': env.append_unique('CFLAGS_PYEMBED', ['-fno-strict-aliasing']) env.append_unique('CFLAGS_PYEXT', ['-fno-strict-aliasing']) if env.CXX_NAME == 'gcc': env.append_unique('CXXFLAGS_PYEMBED', ['-fno-strict-aliasing']) env.append_unique('CXXFLAGS_PYEXT', ['-fno-strict-aliasing']) if env.CC_NAME == "msvc": try: from distutils.msvccompiler import MSVCCompiler except ImportError: # From https://github.com/python/cpython/blob/main/Lib/distutils/msvccompiler.py env.append_value('CFLAGS_PYEXT', [ '/nologo', '/Ox', '/MD', '/W3', '/GX', '/DNDEBUG']) env.append_value('CXXFLAGS_PYEXT', [ '/nologo', '/Ox', '/MD', '/W3', '/GX', '/DNDEBUG']) env.append_value('LINKFLAGS_PYEXT', ['/DLL', '/nologo', '/INCREMENTAL:NO']) else: dist_compiler = MSVCCompiler() dist_compiler.initialize() env.append_value('CFLAGS_PYEXT', dist_compiler.compile_options) env.append_value('CXXFLAGS_PYEXT', dist_compiler.compile_options) env.append_value('LINKFLAGS_PYEXT', dist_compiler.ldflags_shared) conf.check(header_name='Python.h', define_name='HAVE_PYTHON_H', uselib='PYEMBED', fragment=FRAG, errmsg='Could not build a Python embedded interpreter') @conf def check_python_version(conf, minver=None): """ Check if the python interpreter is found matching a given minimum version. minver should be a tuple, eg. to check for python >= 2.4.2 pass (2,4,2) as minver. If successful, PYTHON_VERSION is defined as 'MAJOR.MINOR' (eg. '2.4') of the actual python version found, and PYTHONDIR and PYTHONARCHDIR are defined, pointing to the site-packages directories appropriate for this python version, where modules/packages/extensions should be installed. :param minver: minimum version :type minver: tuple of int """ assert minver is None or isinstance(minver, tuple) pybin = conf.env.PYTHON if not pybin: conf.fatal('could not find the python executable') # Get python version string cmd = pybin + ['-c', 'import sys\nfor x in sys.version_info: print(str(x))'] Logs.debug('python: Running python command %r', cmd) lines = conf.cmd_and_log(cmd).split() assert len(lines) == 5, "found %r lines, expected 5: %r" % (len(lines), lines) pyver_tuple = (int(lines[0]), int(lines[1]), int(lines[2]), lines[3], int(lines[4])) # Compare python version with the minimum required result = (minver is None) or (pyver_tuple >= minver) if result: # define useful environment variables pyver = '.'.join([str(x) for x in pyver_tuple[:2]]) conf.env.PYTHON_VERSION = pyver if 'PYTHONDIR' in conf.env: # Check if --pythondir was specified pydir = conf.env.PYTHONDIR elif 'PYTHONDIR' in conf.environ: # Check environment for PYTHONDIR pydir = conf.environ['PYTHONDIR'] else: # Finally, try to guess if Utils.is_win32: (pydir,) = conf.get_python_variables(["get_python_lib(standard_lib=0) or ''"]) else: (pydir,) = conf.get_python_variables(["get_python_lib(standard_lib=0, prefix=%r) or ''" % conf.env.PREFIX]) if 'PYTHONARCHDIR' in conf.env: # Check if --pythonarchdir was specified pyarchdir = conf.env.PYTHONARCHDIR elif 'PYTHONARCHDIR' in conf.environ: # Check environment for PYTHONDIR pyarchdir = conf.environ['PYTHONARCHDIR'] else: # Finally, try to guess (pyarchdir, ) = conf.get_python_variables(["get_python_lib(plat_specific=1, standard_lib=0, prefix=%r) or ''" % conf.env.PREFIX]) if not pyarchdir: pyarchdir = pydir if hasattr(conf, 'define'): # conf.define is added by the C tool, so may not exist conf.define('PYTHONDIR', pydir) conf.define('PYTHONARCHDIR', pyarchdir) conf.env.PYTHONDIR = pydir conf.env.PYTHONARCHDIR = pyarchdir # Feedback pyver_full = '.'.join(map(str, pyver_tuple[:3])) if minver is None: conf.msg('Checking for python version', pyver_full) else: minver_str = '.'.join(map(str, minver)) conf.msg('Checking for python version >= %s' % (minver_str,), pyver_full, color=result and 'GREEN' or 'YELLOW') if not result: conf.fatal('The python version is too old, expecting %r' % (minver,)) PYTHON_MODULE_TEMPLATE = ''' import %s as current_module version = getattr(current_module, '__version__', None) if version is not None: print(str(version)) else: print('unknown version') ''' @conf def check_python_module(conf, module_name, condition=''): """ Check if the selected python interpreter can import the given python module:: def configure(conf): conf.check_python_module('pygccxml') conf.check_python_module('re', condition="ver > num(2, 0, 4) and ver <= num(3, 0, 0)") :param module_name: module :type module_name: string """ msg = "Checking for python module %r" % module_name if condition: msg = '%s (%s)' % (msg, condition) conf.start_msg(msg) try: ret = conf.cmd_and_log(conf.env.PYTHON + ['-c', PYTHON_MODULE_TEMPLATE % module_name]) except Errors.WafError: conf.end_msg(False) conf.fatal('Could not find the python module %r' % module_name) ret = ret.strip() if condition: conf.end_msg(ret) if ret == 'unknown version': conf.fatal('Could not check the %s version' % module_name) def num(*k): if isinstance(k[0], int): return Utils.loose_version('.'.join([str(x) for x in k])) else: return Utils.loose_version(k[0]) d = {'num': num, 'ver': Utils.loose_version(ret)} ev = eval(condition, {}, d) if not ev: conf.fatal('The %s version does not satisfy the requirements' % module_name) else: if ret == 'unknown version': conf.end_msg(True) else: conf.end_msg(ret) def configure(conf): """ Detect the python interpreter """ v = conf.env if getattr(Options.options, 'pythondir', None): v.PYTHONDIR = Options.options.pythondir if getattr(Options.options, 'pythonarchdir', None): v.PYTHONARCHDIR = Options.options.pythonarchdir if getattr(Options.options, 'nopycache', None): v.NOPYCACHE=Options.options.nopycache if not v.PYTHON: v.PYTHON = [getattr(Options.options, 'python', None) or sys.executable] v.PYTHON = Utils.to_list(v.PYTHON) conf.find_program('python', var='PYTHON') v.PYFLAGS = '' v.PYFLAGS_OPT = '-O' v.PYC = getattr(Options.options, 'pyc', 1) v.PYO = getattr(Options.options, 'pyo', 1) try: v.PYTAG = conf.cmd_and_log(conf.env.PYTHON + ['-c', "import sys\ntry:\n print(sys.implementation.cache_tag)\nexcept AttributeError:\n import imp\n print(imp.get_tag())\n"]).strip() except Errors.WafError: pass def options(opt): """ Add python-specific options """ pyopt=opt.add_option_group("Python Options") pyopt.add_option('--nopyc', dest = 'pyc', action='store_false', default=1, help = 'Do not install bytecode compiled .pyc files (configuration) [Default:install]') pyopt.add_option('--nopyo', dest='pyo', action='store_false', default=1, help='Do not install optimised compiled .pyo files (configuration) [Default:install]') pyopt.add_option('--nopycache',dest='nopycache', action='store_true', help='Do not use __pycache__ directory to install objects [Default:auto]') pyopt.add_option('--python', dest="python", help='python binary to be used [Default: %s]' % sys.executable) pyopt.add_option('--pythondir', dest='pythondir', help='Installation path for python modules (py, platform-independent .py and .pyc files)') pyopt.add_option('--pythonarchdir', dest='pythonarchdir', help='Installation path for python extension (pyext, platform-dependent .so or .dylib files)') kupfer-328/waflib/Utils.py000066400000000000000000000623121500175051100156010ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2018 (ita) """ Utilities and platform-specific fixes The portability fixes try to provide a consistent behavior of the Waf API through Python versions 2.5 to 3.X and across different platforms (win32, linux, etc) """ from __future__ import with_statement import atexit, os, sys, errno, inspect, re, datetime, platform, base64, signal, functools, time, shlex try: import cPickle except ImportError: import pickle as cPickle # leave this if os.name == 'posix' and sys.version_info[0] < 3: try: import subprocess32 as subprocess except ImportError: import subprocess else: import subprocess try: TimeoutExpired = subprocess.TimeoutExpired except AttributeError: class TimeoutExpired(Exception): pass from collections import deque, defaultdict try: import _winreg as winreg except ImportError: try: import winreg except ImportError: winreg = None from waflib import Errors try: from hashlib import md5 except ImportError: try: from hashlib import sha1 as md5 except ImportError: # never fail to enable potential fixes from another module pass else: try: md5().digest() except ValueError: # Fips? #2213 from hashlib import sha1 as md5 try: import threading except ImportError: if not 'JOBS' in os.environ: # no threading :-( os.environ['JOBS'] = '1' class threading(object): """ A fake threading class for platforms lacking the threading module. Use ``waf -j1`` on those platforms """ pass class Lock(object): """Fake Lock class""" def acquire(self): pass def release(self): pass threading.Lock = threading.Thread = Lock SIG_NIL = 'SIG_NIL_SIG_NIL_'.encode() """Arbitrary null value for hashes. Modify this value according to the hash function in use""" O644 = 420 """Constant representing the permissions for regular files (0644 raises a syntax error on python 3)""" O755 = 493 """Constant representing the permissions for executable files (0755 raises a syntax error on python 3)""" rot_chr = ['\\', '|', '/', '-'] "List of characters to use when displaying the throbber (progress bar)" rot_idx = 0 "Index of the current throbber character (progress bar)" class ordered_iter_dict(dict): """Ordered dictionary that provides iteration from the most recently inserted keys first""" def __init__(self, *k, **kw): self.lst = deque() dict.__init__(self, *k, **kw) def clear(self): dict.clear(self) self.lst = deque() def __setitem__(self, key, value): if key in dict.keys(self): self.lst.remove(key) dict.__setitem__(self, key, value) self.lst.append(key) def __delitem__(self, key): dict.__delitem__(self, key) try: self.lst.remove(key) except ValueError: pass def __iter__(self): return reversed(self.lst) def keys(self): return reversed(self.lst) class lru_node(object): """ Used by :py:class:`waflib.Utils.lru_cache` """ __slots__ = ('next', 'prev', 'key', 'val') def __init__(self): self.next = self self.prev = self self.key = None self.val = None class lru_cache(object): """ A simple least-recently used cache with lazy allocation """ __slots__ = ('maxlen', 'table', 'head') def __init__(self, maxlen=100): self.maxlen = maxlen """ Maximum amount of elements in the cache """ self.table = {} """ Mapping key-value """ self.head = lru_node() self.head.next = self.head self.head.prev = self.head def __getitem__(self, key): node = self.table[key] # assert(key==node.key) if node is self.head: return node.val # detach the node found node.prev.next = node.next node.next.prev = node.prev # replace the head node.next = self.head.next node.prev = self.head self.head = node.next.prev = node.prev.next = node return node.val def __setitem__(self, key, val): if key in self.table: # update the value for an existing key node = self.table[key] node.val = val self.__getitem__(key) else: if len(self.table) < self.maxlen: # the very first item is unused until the maximum is reached node = lru_node() node.prev = self.head node.next = self.head.next node.prev.next = node.next.prev = node else: node = self.head = self.head.next try: # that's another key del self.table[node.key] except KeyError: pass node.key = key node.val = val self.table[key] = node class lazy_generator(object): def __init__(self, fun, params): self.fun = fun self.params = params def __iter__(self): return self def __next__(self): try: it = self.it except AttributeError: it = self.it = self.fun(*self.params) return next(it) next = __next__ is_win32 = os.sep == '\\' or sys.platform == 'win32' or os.name == 'nt' # msys2 """ Whether this system is a Windows series """ def readf(fname, m='r', encoding='latin-1'): """ Reads an entire file into a string. See also :py:meth:`waflib.Node.Node.readf`:: def build(ctx): from waflib import Utils txt = Utils.readf(self.path.find_node('wscript').abspath()) txt = ctx.path.find_node('wscript').read() :type fname: string :param fname: Path to file :type m: string :param m: Open mode :type encoding: string :param encoding: encoding value, only used for python 3 :rtype: string :return: Content of the file """ if sys.hexversion > 0x3000000 and not 'b' in m: m += 'b' with open(fname, m) as f: txt = f.read() if encoding: txt = txt.decode(encoding) else: txt = txt.decode() else: with open(fname, m) as f: txt = f.read() return txt def writef(fname, data, m='w', encoding='latin-1'): """ Writes an entire file from a string. See also :py:meth:`waflib.Node.Node.writef`:: def build(ctx): from waflib import Utils txt = Utils.writef(self.path.make_node('i_like_kittens').abspath(), 'some data') self.path.make_node('i_like_kittens').write('some data') :type fname: string :param fname: Path to file :type data: string :param data: The contents to write to the file :type m: string :param m: Open mode :type encoding: string :param encoding: encoding value, only used for python 3 """ if sys.hexversion > 0x3000000 and not 'b' in m: data = data.encode(encoding) m += 'b' with open(fname, m) as f: f.write(data) def h_file(fname): """ Computes a hash value for a file by using md5. Use the md5_tstamp extension to get faster build hashes if necessary. :type fname: string :param fname: path to the file to hash :return: hash of the file contents :rtype: string or bytes """ m = md5() with open(fname, 'rb') as f: while fname: fname = f.read(200000) m.update(fname) return m.digest() def readf_win32(f, m='r', encoding='latin-1'): flags = os.O_NOINHERIT | os.O_RDONLY if 'b' in m: flags |= os.O_BINARY if '+' in m: flags |= os.O_RDWR try: fd = os.open(f, flags) except OSError: raise IOError('Cannot read from %r' % f) if sys.hexversion > 0x3000000 and not 'b' in m: m += 'b' with os.fdopen(fd, m) as f: txt = f.read() if encoding: txt = txt.decode(encoding) else: txt = txt.decode() else: with os.fdopen(fd, m) as f: txt = f.read() return txt def writef_win32(f, data, m='w', encoding='latin-1'): if sys.hexversion > 0x3000000 and not 'b' in m: data = data.encode(encoding) m += 'b' flags = os.O_CREAT | os.O_TRUNC | os.O_WRONLY | os.O_NOINHERIT if 'b' in m: flags |= os.O_BINARY if '+' in m: flags |= os.O_RDWR try: fd = os.open(f, flags) except OSError: raise OSError('Cannot write to %r' % f) with os.fdopen(fd, m) as f: f.write(data) def h_file_win32(fname): try: fd = os.open(fname, os.O_BINARY | os.O_RDONLY | os.O_NOINHERIT) except OSError: raise OSError('Cannot read from %r' % fname) m = md5() with os.fdopen(fd, 'rb') as f: while fname: fname = f.read(200000) m.update(fname) return m.digest() # always save these readf_unix = readf writef_unix = writef h_file_unix = h_file if hasattr(os, 'O_NOINHERIT') and sys.hexversion < 0x3040000: # replace the default functions readf = readf_win32 writef = writef_win32 h_file = h_file_win32 try: x = ''.encode('hex') except LookupError: import binascii def to_hex(s): ret = binascii.hexlify(s) if not isinstance(ret, str): ret = ret.decode('utf-8') return ret else: def to_hex(s): return s.encode('hex') to_hex.__doc__ = """ Return the hexadecimal representation of a string :param s: string to convert :type s: string """ def listdir_win32(s): """ Lists the contents of a folder in a portable manner. On Win32, returns the list of drive letters: ['C:', 'X:', 'Z:'] when an empty string is given. :type s: string :param s: a string, which can be empty on Windows """ if not s: try: import ctypes except ImportError: # there is nothing much we can do return [x + ':\\' for x in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'] else: dlen = 4 # length of "?:\\x00" maxdrives = 26 buf = ctypes.create_string_buffer(maxdrives * dlen) ndrives = ctypes.windll.kernel32.GetLogicalDriveStringsA(maxdrives*dlen, ctypes.byref(buf)) return [ str(buf.raw[4*i:4*i+2].decode('ascii')) for i in range(int(ndrives/dlen)) ] if len(s) == 2 and s[1] == ":": s += os.sep if not os.path.isdir(s): e = OSError('%s is not a directory' % s) e.errno = errno.ENOENT raise e return os.listdir(s) listdir = os.listdir if is_win32: listdir = listdir_win32 def num2ver(ver): """ Converts a string, tuple or version number into an integer. The number is supposed to have at most 4 digits:: from waflib.Utils import num2ver num2ver('1.3.2') == num2ver((1,3,2)) == num2ver((1,3,2,0)) :type ver: string or tuple of numbers :param ver: a version number """ if isinstance(ver, str): ver = tuple(ver.split('.')) if isinstance(ver, tuple): ret = 0 for i in range(4): if i < len(ver): ret += 256**(3 - i) * int(ver[i]) return ret return ver def to_list(val): """ Converts a string argument to a list by splitting it by spaces. Returns the object if not a string:: from waflib.Utils import to_list lst = to_list('a b c d') :param val: list of string or space-separated string :rtype: list :return: Argument converted to list """ if isinstance(val, str): return val.split() else: return val def console_encoding(): try: import ctypes except ImportError: pass else: try: codepage = ctypes.windll.kernel32.GetConsoleCP() except AttributeError: pass else: if codepage: if 65001 == codepage and sys.version_info < (3, 3): return 'utf-8' return 'cp%d' % codepage return sys.stdout.encoding or ('cp1252' if is_win32 else 'latin-1') def split_path_unix(path): return path.split('/') def split_path_cygwin(path): if path.startswith('//'): ret = path.split('/')[2:] ret[0] = '/' + ret[0] return ret return path.split('/') re_sp = re.compile('[/\\\\]+') def split_path_win32(path): if path.startswith('\\\\'): ret = re_sp.split(path)[1:] ret[0] = '\\\\' + ret[0] if ret[0] == '\\\\?': return ret[1:] return ret return re_sp.split(path) msysroot = None def split_path_msys(path): if path.startswith(('/', '\\')) and not path.startswith(('//', '\\\\')): # msys paths can be in the form /usr/bin global msysroot if not msysroot: # msys has python 2.7 or 3, so we can use this msysroot = subprocess.check_output(['cygpath', '-w', '/']).decode(sys.stdout.encoding or 'latin-1') msysroot = msysroot.strip() path = os.path.normpath(msysroot + os.sep + path) return split_path_win32(path) if sys.platform == 'cygwin': split_path = split_path_cygwin elif is_win32: # Consider this an MSYSTEM environment if $MSYSTEM is set and python # reports is executable from a unix like path on a windows host. if os.environ.get('MSYSTEM') and sys.executable.startswith('/'): split_path = split_path_msys else: split_path = split_path_win32 else: split_path = split_path_unix split_path.__doc__ = """ Splits a path by / or \\; do not confuse this function with with ``os.path.split`` :type path: string :param path: path to split :return: list of string """ def check_dir(path): """ Ensures that a directory exists (similar to ``mkdir -p``). :type path: string :param path: Path to directory :raises: :py:class:`waflib.Errors.WafError` if the folder cannot be added. """ if not os.path.isdir(path): try: os.makedirs(path) except OSError as e: if not os.path.isdir(path): raise Errors.WafError('Cannot create the folder %r' % path, ex=e) def check_exe(name, env=None): """ Ensures that a program exists :type name: string :param name: path to the program :param env: configuration object :type env: :py:class:`waflib.ConfigSet.ConfigSet` :return: path of the program or None :raises: :py:class:`waflib.Errors.WafError` if the folder cannot be added. """ if not name: raise ValueError('Cannot execute an empty string!') def is_exe(fpath): return os.path.isfile(fpath) and os.access(fpath, os.X_OK) fpath, fname = os.path.split(name) if fpath and is_exe(name): return os.path.abspath(name) else: env = env or os.environ for path in env['PATH'].split(os.pathsep): path = path.strip('"') exe_file = os.path.join(path, name) if is_exe(exe_file): return os.path.abspath(exe_file) return None def def_attrs(cls, **kw): """ Sets default attributes on a class instance :type cls: class :param cls: the class to update the given attributes in. :type kw: dict :param kw: dictionary of attributes names and values. """ for k, v in kw.items(): if not hasattr(cls, k): setattr(cls, k, v) def quote_define_name(s): """ Converts a string into an identifier suitable for C defines. :type s: string :param s: String to convert :rtype: string :return: Identifier suitable for C defines """ fu = re.sub('[^a-zA-Z0-9]', '_', s) fu = re.sub('_+', '_', fu) fu = fu.upper() return fu # shlex.quote didn't exist until python 3.3. Prior to that it was a non-documented # function in pipes. try: shell_quote = shlex.quote except AttributeError: import pipes shell_quote = pipes.quote def shell_escape(cmd): """ Escapes a command: ['ls', '-l', 'arg space'] -> ls -l 'arg space' """ if isinstance(cmd, str): return cmd return ' '.join(shell_quote(x) for x in cmd) def h_list(lst): """ Hashes lists of ordered data. Using hash(tup) for tuples would be much more efficient, but Python now enforces hash randomization :param lst: list to hash :type lst: list of strings :return: hash of the list """ return md5(repr(lst).encode()).digest() if sys.hexversion < 0x3000000: def h_list_python2(lst): return md5(repr(lst)).digest() h_list_python2.__doc__ = h_list.__doc__ h_list = h_list_python2 def h_fun(fun): """ Hash functions :param fun: function to hash :type fun: function :return: hash of the function :rtype: string or bytes """ try: return fun.code except AttributeError: if isinstance(fun, functools.partial): code = list(fun.args) # The method items() provides a sequence of tuples where the first element # represents an optional argument of the partial function application # # The sorting result outcome will be consistent because: # 1. tuples are compared in order of their elements # 2. optional argument namess are unique code.extend(sorted(fun.keywords.items())) code.append(h_fun(fun.func)) fun.code = h_list(code) return fun.code try: h = inspect.getsource(fun) except EnvironmentError: h = 'nocode' try: fun.code = h except AttributeError: pass return h def h_cmd(ins): """ Hashes objects recursively :param ins: input object :type ins: string or list or tuple or function :rtype: string or bytes """ # this function is not meant to be particularly fast if isinstance(ins, str): # a command is either a string ret = ins elif isinstance(ins, list) or isinstance(ins, tuple): # or a list of functions/strings ret = str([h_cmd(x) for x in ins]) else: # or just a python function ret = str(h_fun(ins)) if sys.hexversion > 0x3000000: ret = ret.encode('latin-1', 'xmlcharrefreplace') return ret reg_subst = re.compile(r"(\\\\)|(\$\$)|\$\{([^}]+)\}") def subst_vars(expr, params): """ Replaces ${VAR} with the value of VAR taken from a dict or a config set:: from waflib import Utils s = Utils.subst_vars('${PREFIX}/bin', env) :type expr: string :param expr: String to perform substitution on :param params: Dictionary or config set to look up variable values. """ def repl_var(m): if m.group(1): return '\\' if m.group(2): return '$' try: # ConfigSet instances may contain lists return params.get_flat(m.group(3)) except AttributeError: return params[m.group(3)] # if you get a TypeError, it means that 'expr' is not a string... # Utils.subst_vars(None, env) will not work return reg_subst.sub(repl_var, expr) def destos_to_binfmt(key): """ Returns the binary format based on the unversioned platform name, and defaults to ``elf`` if nothing is found. :param key: platform name :type key: string :return: string representing the binary format """ if key == 'darwin': return 'mac-o' elif key in ('win32', 'cygwin', 'uwin', 'msys'): return 'pe' return 'elf' def unversioned_sys_platform(): """ Returns the unversioned platform name. Some Python platform names contain versions, that depend on the build environment, e.g. linux2, freebsd6, etc. This returns the name without the version number. Exceptions are os2 and win32, which are returned verbatim. :rtype: string :return: Unversioned platform name """ s = sys.platform if s.startswith('java'): # The real OS is hidden under the JVM. from java.lang import System s = System.getProperty('os.name') # see http://lopica.sourceforge.net/os.html for a list of possible values if s == 'Mac OS X': return 'darwin' elif s.startswith('Windows '): return 'win32' elif s == 'OS/2': return 'os2' elif s == 'HP-UX': return 'hp-ux' elif s in ('SunOS', 'Solaris'): return 'sunos' else: s = s.lower() # powerpc == darwin for our purposes if s == 'powerpc': return 'darwin' if s == 'win32' or s == 'os2': return s if s == 'cli' and os.name == 'nt': # ironpython is only on windows as far as we know return 'win32' return re.split(r'\d+$', s)[0] def nada(*k, **kw): """ Does nothing :return: None """ pass class Timer(object): """ Simple object for timing the execution of commands. Its string representation is the duration:: from waflib.Utils import Timer timer = Timer() a_few_operations() s = str(timer) """ def __init__(self): self.start_time = self.now() def __str__(self): delta = self.now() - self.start_time if not isinstance(delta, datetime.timedelta): delta = datetime.timedelta(seconds=delta) days = delta.days hours, rem = divmod(delta.seconds, 3600) minutes, seconds = divmod(rem, 60) seconds += delta.microseconds * 1e-6 result = '' if days: result += '%dd' % days if days or hours: result += '%dh' % hours if days or hours or minutes: result += '%dm' % minutes return '%s%.3fs' % (result, seconds) def now(self): return datetime.datetime.utcnow() if hasattr(time, 'perf_counter'): def now(self): return time.perf_counter() def read_la_file(path): """ Reads property files, used by msvc.py :param path: file to read :type path: string """ sp = re.compile(r'^([^=]+)=\'(.*)\'$') dc = {} for line in readf(path).splitlines(): try: _, left, right, _ = sp.split(line.strip()) dc[left] = right except ValueError: pass return dc def run_once(fun): """ Decorator: let a function cache its results, use like this:: @run_once def foo(k): return 345*2343 .. note:: in practice this can cause memory leaks, prefer a :py:class:`waflib.Utils.lru_cache` :param fun: function to execute :type fun: function :return: the return value of the function executed """ cache = {} def wrap(*k): try: return cache[k] except KeyError: ret = fun(*k) cache[k] = ret return ret wrap.__cache__ = cache wrap.__name__ = fun.__name__ return wrap def get_registry_app_path(key, filename): """ Returns the value of a registry key for an executable :type key: string :type filename: list of string """ if not winreg: return None try: result = winreg.QueryValue(key, "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s.exe" % filename[0]) except OSError: pass else: if os.path.isfile(result): return result def lib64(): """ Guess the default ``/usr/lib`` extension for 64-bit applications :return: '64' or '' :rtype: string """ # default settings for /usr/lib if os.sep == '/': if platform.architecture()[0] == '64bit': if os.path.exists('/usr/lib64') and not os.path.exists('/usr/lib32'): return '64' return '' def loose_version(ver_str): # private for the time being! # see #2402 lst = re.split(r'([.]|\\d+|[a-zA-Z])', ver_str) ver = [] for i, val in enumerate(lst): try: ver.append(int(val)) except ValueError: if val != '.': ver.append(val) return ver def sane_path(p): # private function for the time being! return os.path.abspath(os.path.expanduser(p)) process_pool = [] """ List of processes started to execute sub-process commands """ def get_process(): """ Returns a process object that can execute commands as sub-processes :rtype: subprocess.Popen """ try: return process_pool.pop() except IndexError: filepath = os.path.dirname(os.path.abspath(__file__)) + os.sep + 'processor.py' cmd = [sys.executable, '-c', readf(filepath)] return subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, bufsize=0, close_fds=not is_win32) def run_prefork_process(cmd, kwargs, cargs): """ Delegates process execution to a pre-forked process instance. """ if not kwargs.get('env'): kwargs['env'] = dict(os.environ) try: obj = base64.b64encode(cPickle.dumps([cmd, kwargs, cargs])) except (TypeError, AttributeError): return run_regular_process(cmd, kwargs, cargs) proc = get_process() if not proc: return run_regular_process(cmd, kwargs, cargs) proc.stdin.write(obj) proc.stdin.write('\n'.encode()) proc.stdin.flush() obj = proc.stdout.readline() if not obj: raise OSError('Preforked sub-process %r died' % proc.pid) process_pool.append(proc) lst = cPickle.loads(base64.b64decode(obj)) # Jython wrapper failures (bash/execvp) assert len(lst) == 5 ret, out, err, ex, trace = lst if ex: if ex == 'OSError': raise OSError(trace) elif ex == 'ValueError': raise ValueError(trace) elif ex == 'TimeoutExpired': exc = TimeoutExpired(cmd, timeout=cargs['timeout'], output=out) exc.stderr = err raise exc else: raise Exception(trace) return ret, out, err def lchown(path, user=-1, group=-1): """ Change the owner/group of a path, raises an OSError if the ownership change fails. :param user: user to change :type user: int or str :param group: group to change :type group: int or str """ if isinstance(user, str): import pwd entry = pwd.getpwnam(user) if not entry: raise OSError('Unknown user %r' % user) user = entry[2] if isinstance(group, str): import grp entry = grp.getgrnam(group) if not entry: raise OSError('Unknown group %r' % group) group = entry[2] return os.lchown(path, user, group) def run_regular_process(cmd, kwargs, cargs={}): """ Executes a subprocess command by using subprocess.Popen """ proc = subprocess.Popen(cmd, **kwargs) if kwargs.get('stdout') or kwargs.get('stderr'): try: out, err = proc.communicate(**cargs) except TimeoutExpired: if kwargs.get('start_new_session') and hasattr(os, 'killpg'): os.killpg(proc.pid, signal.SIGKILL) else: proc.kill() out, err = proc.communicate() exc = TimeoutExpired(proc.args, timeout=cargs['timeout'], output=out) exc.stderr = err raise exc status = proc.returncode else: out, err = (None, None) try: status = proc.wait(**cargs) except TimeoutExpired as e: if kwargs.get('start_new_session') and hasattr(os, 'killpg'): os.killpg(proc.pid, signal.SIGKILL) else: proc.kill() proc.wait() raise e return status, out, err def run_process(cmd, kwargs, cargs={}): """ Executes a subprocess by using a pre-forked process when possible or falling back to subprocess.Popen. See :py:func:`waflib.Utils.run_prefork_process` and :py:func:`waflib.Utils.run_regular_process` """ if kwargs.get('stdout') and kwargs.get('stderr'): return run_prefork_process(cmd, kwargs, cargs) else: return run_regular_process(cmd, kwargs, cargs) def alloc_process_pool(n, force=False): """ Allocates an amount of processes to the default pool so its size is at least *n*. It is useful to call this function early so that the pre-forked processes use as little memory as possible. :param n: pool size :type n: integer :param force: if True then *n* more processes are added to the existing pool :type force: bool """ # mandatory on python2, unnecessary on python >= 3.2 global run_process, get_process, alloc_process_pool if not force: n = max(n - len(process_pool), 0) try: lst = [get_process() for x in range(n)] except OSError: run_process = run_regular_process get_process = alloc_process_pool = nada else: for x in lst: process_pool.append(x) def atexit_pool(): for k in process_pool: try: os.kill(k.pid, 9) except OSError: pass else: k.wait() # see #1889 if (sys.hexversion<0x207000f and not is_win32) or sys.hexversion>=0x306000f: atexit.register(atexit_pool) if os.environ.get('WAF_NO_PREFORK') or sys.platform == 'cli' or not sys.executable: run_process = run_regular_process get_process = alloc_process_pool = nada kupfer-328/waflib/__init__.py000066400000000000000000000001071500175051100162320ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2018 (ita) kupfer-328/waflib/ansiterm.py000066400000000000000000000252731500175051100163300ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 """ Emulate a vt100 terminal in cmd.exe By wrapping sys.stdout / sys.stderr with Ansiterm, the vt100 escape characters will be interpreted and the equivalent actions will be performed with Win32 console commands. """ import os, re, sys from waflib import Utils wlock = Utils.threading.Lock() try: from ctypes import Structure, windll, c_short, c_ushort, c_ulong, c_int, byref, c_wchar, POINTER, c_long except ImportError: class AnsiTerm(object): def __init__(self, stream): self.stream = stream try: self.errors = self.stream.errors except AttributeError: pass # python 2.5 self.encoding = self.stream.encoding def write(self, txt): try: wlock.acquire() self.stream.write(txt) self.stream.flush() finally: wlock.release() def fileno(self): return self.stream.fileno() def flush(self): self.stream.flush() def isatty(self): return self.stream.isatty() else: class COORD(Structure): _fields_ = [("X", c_short), ("Y", c_short)] class SMALL_RECT(Structure): _fields_ = [("Left", c_short), ("Top", c_short), ("Right", c_short), ("Bottom", c_short)] class CONSOLE_SCREEN_BUFFER_INFO(Structure): _fields_ = [("Size", COORD), ("CursorPosition", COORD), ("Attributes", c_ushort), ("Window", SMALL_RECT), ("MaximumWindowSize", COORD)] class CONSOLE_CURSOR_INFO(Structure): _fields_ = [('dwSize', c_ulong), ('bVisible', c_int)] try: _type = unicode except NameError: _type = str to_int = lambda number, default: number and int(number) or default STD_OUTPUT_HANDLE = -11 STD_ERROR_HANDLE = -12 windll.kernel32.GetStdHandle.argtypes = [c_ulong] windll.kernel32.GetStdHandle.restype = c_ulong windll.kernel32.GetConsoleScreenBufferInfo.argtypes = [c_ulong, POINTER(CONSOLE_SCREEN_BUFFER_INFO)] windll.kernel32.GetConsoleScreenBufferInfo.restype = c_long windll.kernel32.SetConsoleTextAttribute.argtypes = [c_ulong, c_ushort] windll.kernel32.SetConsoleTextAttribute.restype = c_long windll.kernel32.FillConsoleOutputCharacterW.argtypes = [c_ulong, c_wchar, c_ulong, POINTER(COORD), POINTER(c_ulong)] windll.kernel32.FillConsoleOutputCharacterW.restype = c_long windll.kernel32.FillConsoleOutputAttribute.argtypes = [c_ulong, c_ushort, c_ulong, POINTER(COORD), POINTER(c_ulong) ] windll.kernel32.FillConsoleOutputAttribute.restype = c_long windll.kernel32.SetConsoleCursorPosition.argtypes = [c_ulong, POINTER(COORD) ] windll.kernel32.SetConsoleCursorPosition.restype = c_long windll.kernel32.SetConsoleCursorInfo.argtypes = [c_ulong, POINTER(CONSOLE_CURSOR_INFO)] windll.kernel32.SetConsoleCursorInfo.restype = c_long class AnsiTerm(object): """ emulate a vt100 terminal in cmd.exe """ def __init__(self, s): self.stream = s try: self.errors = s.errors except AttributeError: pass # python2.5 self.encoding = s.encoding self.cursor_history = [] handle = (s.fileno() == 2) and STD_ERROR_HANDLE or STD_OUTPUT_HANDLE self.hconsole = windll.kernel32.GetStdHandle(handle) self._sbinfo = CONSOLE_SCREEN_BUFFER_INFO() self._csinfo = CONSOLE_CURSOR_INFO() windll.kernel32.GetConsoleCursorInfo(self.hconsole, byref(self._csinfo)) # just to double check that the console is usable self._orig_sbinfo = CONSOLE_SCREEN_BUFFER_INFO() r = windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(self._orig_sbinfo)) self._isatty = r == 1 def screen_buffer_info(self): """ Updates self._sbinfo and returns it """ windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(self._sbinfo)) return self._sbinfo def clear_line(self, param): mode = param and int(param) or 0 sbinfo = self.screen_buffer_info() if mode == 1: # Clear from beginning of line to cursor position line_start = COORD(0, sbinfo.CursorPosition.Y) line_length = sbinfo.Size.X elif mode == 2: # Clear entire line line_start = COORD(sbinfo.CursorPosition.X, sbinfo.CursorPosition.Y) line_length = sbinfo.Size.X - sbinfo.CursorPosition.X else: # Clear from cursor position to end of line line_start = sbinfo.CursorPosition line_length = sbinfo.Size.X - sbinfo.CursorPosition.X chars_written = c_ulong() windll.kernel32.FillConsoleOutputCharacterW(self.hconsole, c_wchar(' '), line_length, line_start, byref(chars_written)) windll.kernel32.FillConsoleOutputAttribute(self.hconsole, sbinfo.Attributes, line_length, line_start, byref(chars_written)) def clear_screen(self, param): mode = to_int(param, 0) sbinfo = self.screen_buffer_info() if mode == 1: # Clear from beginning of screen to cursor position clear_start = COORD(0, 0) clear_length = sbinfo.CursorPosition.X * sbinfo.CursorPosition.Y elif mode == 2: # Clear entire screen and return cursor to home clear_start = COORD(0, 0) clear_length = sbinfo.Size.X * sbinfo.Size.Y windll.kernel32.SetConsoleCursorPosition(self.hconsole, clear_start) else: # Clear from cursor position to end of screen clear_start = sbinfo.CursorPosition clear_length = ((sbinfo.Size.X - sbinfo.CursorPosition.X) + sbinfo.Size.X * (sbinfo.Size.Y - sbinfo.CursorPosition.Y)) chars_written = c_ulong() windll.kernel32.FillConsoleOutputCharacterW(self.hconsole, c_wchar(' '), clear_length, clear_start, byref(chars_written)) windll.kernel32.FillConsoleOutputAttribute(self.hconsole, sbinfo.Attributes, clear_length, clear_start, byref(chars_written)) def push_cursor(self, param): sbinfo = self.screen_buffer_info() self.cursor_history.append(sbinfo.CursorPosition) def pop_cursor(self, param): if self.cursor_history: old_pos = self.cursor_history.pop() windll.kernel32.SetConsoleCursorPosition(self.hconsole, old_pos) def set_cursor(self, param): y, sep, x = param.partition(';') x = to_int(x, 1) - 1 y = to_int(y, 1) - 1 sbinfo = self.screen_buffer_info() new_pos = COORD( min(max(0, x), sbinfo.Size.X), min(max(0, y), sbinfo.Size.Y) ) windll.kernel32.SetConsoleCursorPosition(self.hconsole, new_pos) def set_column(self, param): x = to_int(param, 1) - 1 sbinfo = self.screen_buffer_info() new_pos = COORD( min(max(0, x), sbinfo.Size.X), sbinfo.CursorPosition.Y ) windll.kernel32.SetConsoleCursorPosition(self.hconsole, new_pos) def move_cursor(self, x_offset=0, y_offset=0): sbinfo = self.screen_buffer_info() new_pos = COORD( min(max(0, sbinfo.CursorPosition.X + x_offset), sbinfo.Size.X), min(max(0, sbinfo.CursorPosition.Y + y_offset), sbinfo.Size.Y) ) windll.kernel32.SetConsoleCursorPosition(self.hconsole, new_pos) def move_up(self, param): self.move_cursor(y_offset = -to_int(param, 1)) def move_down(self, param): self.move_cursor(y_offset = to_int(param, 1)) def move_left(self, param): self.move_cursor(x_offset = -to_int(param, 1)) def move_right(self, param): self.move_cursor(x_offset = to_int(param, 1)) def next_line(self, param): sbinfo = self.screen_buffer_info() self.move_cursor( x_offset = -sbinfo.CursorPosition.X, y_offset = to_int(param, 1) ) def prev_line(self, param): sbinfo = self.screen_buffer_info() self.move_cursor( x_offset = -sbinfo.CursorPosition.X, y_offset = -to_int(param, 1) ) def rgb2bgr(self, c): return ((c&1) << 2) | (c&2) | ((c&4)>>2) def set_color(self, param): cols = param.split(';') sbinfo = self.screen_buffer_info() attr = sbinfo.Attributes for c in cols: c = to_int(c, 0) if 29 < c < 38: # fgcolor attr = (attr & 0xfff0) | self.rgb2bgr(c - 30) elif 39 < c < 48: # bgcolor attr = (attr & 0xff0f) | (self.rgb2bgr(c - 40) << 4) elif c == 0: # reset attr = self._orig_sbinfo.Attributes elif c == 1: # strong attr |= 0x08 elif c == 4: # blink not available -> bg intensity attr |= 0x80 elif c == 7: # negative attr = (attr & 0xff88) | ((attr & 0x70) >> 4) | ((attr & 0x07) << 4) windll.kernel32.SetConsoleTextAttribute(self.hconsole, attr) def show_cursor(self,param): self._csinfo.bVisible = 1 windll.kernel32.SetConsoleCursorInfo(self.hconsole, byref(self._csinfo)) def hide_cursor(self,param): self._csinfo.bVisible = 0 windll.kernel32.SetConsoleCursorInfo(self.hconsole, byref(self._csinfo)) ansi_command_table = { 'A': move_up, 'B': move_down, 'C': move_right, 'D': move_left, 'E': next_line, 'F': prev_line, 'G': set_column, 'H': set_cursor, 'f': set_cursor, 'J': clear_screen, 'K': clear_line, 'h': show_cursor, 'l': hide_cursor, 'm': set_color, 's': push_cursor, 'u': pop_cursor, } # Match either the escape sequence or text not containing escape sequence ansi_tokens = re.compile(r'(?:\x1b\[([0-9?;]*)([a-zA-Z])|([^\x1b]+))') def write(self, text): try: wlock.acquire() if self._isatty: for param, cmd, txt in self.ansi_tokens.findall(text): if cmd: cmd_func = self.ansi_command_table.get(cmd) if cmd_func: cmd_func(self, param) else: self.writeconsole(txt) else: # no support for colors in the console, just output the text: # eclipse or msys may be able to interpret the escape sequences self.stream.write(text) finally: wlock.release() def writeconsole(self, txt): chars_written = c_ulong() writeconsole = windll.kernel32.WriteConsoleA if isinstance(txt, _type): writeconsole = windll.kernel32.WriteConsoleW # MSDN says that there is a shared buffer of 64 KB for the console # writes. Attempt to not get ERROR_NOT_ENOUGH_MEMORY, see waf issue #746 done = 0 todo = len(txt) chunk = 32<<10 while todo != 0: doing = min(chunk, todo) buf = txt[done:done+doing] r = writeconsole(self.hconsole, buf, doing, byref(chars_written), None) if r == 0: chunk >>= 1 continue done += doing todo -= doing def fileno(self): return self.stream.fileno() def flush(self): pass def isatty(self): return self._isatty if sys.stdout.isatty() or sys.stderr.isatty(): handle = sys.stdout.isatty() and STD_OUTPUT_HANDLE or STD_ERROR_HANDLE console = windll.kernel32.GetStdHandle(handle) sbinfo = CONSOLE_SCREEN_BUFFER_INFO() def get_term_cols(): windll.kernel32.GetConsoleScreenBufferInfo(console, byref(sbinfo)) # Issue 1401 - the progress bar cannot reach the last character return sbinfo.Size.X - 1 # just try and see try: import struct, fcntl, termios except ImportError: pass else: if (sys.stdout.isatty() or sys.stderr.isatty()) and os.environ.get('TERM', '') not in ('dumb', 'emacs'): FD = sys.stdout.isatty() and sys.stdout.fileno() or sys.stderr.fileno() def fun(): return struct.unpack("HHHH", fcntl.ioctl(FD, termios.TIOCGWINSZ, struct.pack("HHHH", 0, 0, 0, 0)))[1] try: fun() except Exception as e: pass else: get_term_cols = fun kupfer-328/waflib/extras/000077500000000000000000000000001500175051100154315ustar00rootroot00000000000000kupfer-328/waflib/extras/__init__.py000066400000000000000000000001071500175051100175400ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) kupfer-328/waflib/extras/compat15.py000066400000000000000000000270451500175051100174440ustar00rootroot00000000000000#! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) """ This file is provided to enable compatibility with waf 1.5 It was enabled by default in waf 1.6, but it is not used in waf 1.7 """ import sys from waflib import ConfigSet, Logs, Options, Scripting, Task, Build, Configure, Node, Runner, TaskGen, Utils, Errors, Context # the following is to bring some compatibility with waf 1.5 "import waflib.Configure → import Configure" sys.modules['Environment'] = ConfigSet ConfigSet.Environment = ConfigSet.ConfigSet sys.modules['Logs'] = Logs sys.modules['Options'] = Options sys.modules['Scripting'] = Scripting sys.modules['Task'] = Task sys.modules['Build'] = Build sys.modules['Configure'] = Configure sys.modules['Node'] = Node sys.modules['Runner'] = Runner sys.modules['TaskGen'] = TaskGen sys.modules['Utils'] = Utils sys.modules['Constants'] = Context Context.SRCDIR = '' Context.BLDDIR = '' from waflib.Tools import c_preproc sys.modules['preproc'] = c_preproc from waflib.Tools import c_config sys.modules['config_c'] = c_config ConfigSet.ConfigSet.copy = ConfigSet.ConfigSet.derive ConfigSet.ConfigSet.set_variant = Utils.nada Utils.pproc = Utils.subprocess Build.BuildContext.add_subdirs = Build.BuildContext.recurse Build.BuildContext.new_task_gen = Build.BuildContext.__call__ Build.BuildContext.is_install = 0 Node.Node.relpath_gen = Node.Node.path_from Utils.pproc = Utils.subprocess Utils.get_term_cols = Logs.get_term_cols def cmd_output(cmd, **kw): silent = False if 'silent' in kw: silent = kw['silent'] del(kw['silent']) if 'e' in kw: tmp = kw['e'] del(kw['e']) kw['env'] = tmp kw['shell'] = isinstance(cmd, str) kw['stdout'] = Utils.subprocess.PIPE if silent: kw['stderr'] = Utils.subprocess.PIPE try: p = Utils.subprocess.Popen(cmd, **kw) output = p.communicate()[0] except OSError as e: raise ValueError(str(e)) if p.returncode: if not silent: msg = "command execution failed: %s -> %r" % (cmd, str(output)) raise ValueError(msg) output = '' return output Utils.cmd_output = cmd_output def name_to_obj(self, s, env=None): if Logs.verbose: Logs.warn('compat: change "name_to_obj(name, env)" by "get_tgen_by_name(name)"') return self.get_tgen_by_name(s) Build.BuildContext.name_to_obj = name_to_obj def env_of_name(self, name): try: return self.all_envs[name] except KeyError: Logs.error('no such environment: '+name) return None Build.BuildContext.env_of_name = env_of_name def set_env_name(self, name, env): self.all_envs[name] = env return env Configure.ConfigurationContext.set_env_name = set_env_name def retrieve(self, name, fromenv=None): try: env = self.all_envs[name] except KeyError: env = ConfigSet.ConfigSet() self.prepare_env(env) self.all_envs[name] = env else: if fromenv: Logs.warn('The environment %s may have been configured already', name) return env Configure.ConfigurationContext.retrieve = retrieve Configure.ConfigurationContext.sub_config = Configure.ConfigurationContext.recurse Configure.ConfigurationContext.check_tool = Configure.ConfigurationContext.load Configure.conftest = Configure.conf Configure.ConfigurationError = Errors.ConfigurationError Utils.WafError = Errors.WafError Options.OptionsContext.sub_options = Options.OptionsContext.recurse Options.OptionsContext.tool_options = Context.Context.load Options.Handler = Options.OptionsContext Task.simple_task_type = Task.task_type_from_func = Task.task_factory Task.Task.classes = Task.classes def setitem(self, key, value): if key.startswith('CCFLAGS'): key = key[1:] self.table[key] = value ConfigSet.ConfigSet.__setitem__ = setitem @TaskGen.feature('d') @TaskGen.before('apply_incpaths') def old_importpaths(self): if getattr(self, 'importpaths', []): self.includes = self.importpaths from waflib import Context eld = Context.load_tool def load_tool(*k, **kw): ret = eld(*k, **kw) if 'set_options' in ret.__dict__: if Logs.verbose: Logs.warn('compat: rename "set_options" to options') ret.options = ret.set_options if 'detect' in ret.__dict__: if Logs.verbose: Logs.warn('compat: rename "detect" to "configure"') ret.configure = ret.detect return ret Context.load_tool = load_tool def get_curdir(self): return self.path.abspath() Context.Context.curdir = property(get_curdir, Utils.nada) def get_srcdir(self): return self.srcnode.abspath() Configure.ConfigurationContext.srcdir = property(get_srcdir, Utils.nada) def get_blddir(self): return self.bldnode.abspath() Configure.ConfigurationContext.blddir = property(get_blddir, Utils.nada) Configure.ConfigurationContext.check_message_1 = Configure.ConfigurationContext.start_msg Configure.ConfigurationContext.check_message_2 = Configure.ConfigurationContext.end_msg rev = Context.load_module def load_module(path, encoding=None): ret = rev(path, encoding) if 'set_options' in ret.__dict__: if Logs.verbose: Logs.warn('compat: rename "set_options" to "options" (%r)', path) ret.options = ret.set_options if 'srcdir' in ret.__dict__: if Logs.verbose: Logs.warn('compat: rename "srcdir" to "top" (%r)', path) ret.top = ret.srcdir if 'blddir' in ret.__dict__: if Logs.verbose: Logs.warn('compat: rename "blddir" to "out" (%r)', path) ret.out = ret.blddir Utils.g_module = Context.g_module Options.launch_dir = Context.launch_dir return ret Context.load_module = load_module old_post = TaskGen.task_gen.post def post(self): self.features = self.to_list(self.features) if 'cc' in self.features: if Logs.verbose: Logs.warn('compat: the feature cc does not exist anymore (use "c")') self.features.remove('cc') self.features.append('c') if 'cstaticlib' in self.features: if Logs.verbose: Logs.warn('compat: the feature cstaticlib does not exist anymore (use "cstlib" or "cxxstlib")') self.features.remove('cstaticlib') self.features.append(('cxx' in self.features) and 'cxxstlib' or 'cstlib') if getattr(self, 'ccflags', None): if Logs.verbose: Logs.warn('compat: "ccflags" was renamed to "cflags"') self.cflags = self.ccflags return old_post(self) TaskGen.task_gen.post = post def waf_version(*k, **kw): Logs.warn('wrong version (waf_version was removed in waf 1.6)') Utils.waf_version = waf_version import os @TaskGen.feature('c', 'cxx', 'd') @TaskGen.before('apply_incpaths', 'propagate_uselib_vars') @TaskGen.after('apply_link', 'process_source') def apply_uselib_local(self): """ process the uselib_local attribute execute after apply_link because of the execution order set on 'link_task' """ env = self.env from waflib.Tools.ccroot import stlink_task # 1. the case of the libs defined in the project (visit ancestors first) # the ancestors external libraries (uselib) will be prepended self.uselib = self.to_list(getattr(self, 'uselib', [])) self.includes = self.to_list(getattr(self, 'includes', [])) names = self.to_list(getattr(self, 'uselib_local', [])) get = self.bld.get_tgen_by_name seen = set() seen_uselib = set() tmp = Utils.deque(names) # consume a copy of the list of names if tmp: if Logs.verbose: Logs.warn('compat: "uselib_local" is deprecated, replace by "use"') while tmp: lib_name = tmp.popleft() # visit dependencies only once if lib_name in seen: continue y = get(lib_name) y.post() seen.add(lib_name) # object has ancestors to process (shared libraries): add them to the end of the list if getattr(y, 'uselib_local', None): for x in self.to_list(getattr(y, 'uselib_local', [])): obj = get(x) obj.post() if getattr(obj, 'link_task', None): if not isinstance(obj.link_task, stlink_task): tmp.append(x) # link task and flags if getattr(y, 'link_task', None): link_name = y.target[y.target.rfind(os.sep) + 1:] if isinstance(y.link_task, stlink_task): env.append_value('STLIB', [link_name]) else: # some linkers can link against programs env.append_value('LIB', [link_name]) # the order self.link_task.set_run_after(y.link_task) # for the recompilation self.link_task.dep_nodes += y.link_task.outputs # add the link path too tmp_path = y.link_task.outputs[0].parent.bldpath() if not tmp_path in env['LIBPATH']: env.prepend_value('LIBPATH', [tmp_path]) # add ancestors uselib too - but only propagate those that have no staticlib defined for v in self.to_list(getattr(y, 'uselib', [])): if v not in seen_uselib: seen_uselib.add(v) if not env['STLIB_' + v]: if not v in self.uselib: self.uselib.insert(0, v) # if the library task generator provides 'export_includes', add to the include path # the export_includes must be a list of paths relative to the other library if getattr(y, 'export_includes', None): self.includes.extend(y.to_incnodes(y.export_includes)) @TaskGen.feature('cprogram', 'cxxprogram', 'cstlib', 'cxxstlib', 'cshlib', 'cxxshlib', 'dprogram', 'dstlib', 'dshlib') @TaskGen.after('apply_link') def apply_objdeps(self): "add the .o files produced by some other object files in the same manner as uselib_local" names = getattr(self, 'add_objects', []) if not names: return names = self.to_list(names) get = self.bld.get_tgen_by_name seen = [] while names: x = names[0] # visit dependencies only once if x in seen: names = names[1:] continue # object does not exist ? y = get(x) # object has ancestors to process first ? update the list of names if getattr(y, 'add_objects', None): added = 0 lst = y.to_list(y.add_objects) lst.reverse() for u in lst: if u in seen: continue added = 1 names = [u]+names if added: continue # list of names modified, loop # safe to process the current object y.post() seen.append(x) for t in getattr(y, 'compiled_tasks', []): self.link_task.inputs.extend(t.outputs) @TaskGen.after('apply_link') def process_obj_files(self): if not hasattr(self, 'obj_files'): return for x in self.obj_files: node = self.path.find_resource(x) self.link_task.inputs.append(node) @TaskGen.taskgen_method def add_obj_file(self, file): """Small example on how to link object files as if they were source obj = bld.create_obj('cc') obj.add_obj_file('foo.o')""" if not hasattr(self, 'obj_files'): self.obj_files = [] if not 'process_obj_files' in self.meths: self.meths.append('process_obj_files') self.obj_files.append(file) old_define = Configure.ConfigurationContext.__dict__['define'] @Configure.conf def define(self, key, val, quote=True, comment=''): old_define(self, key, val, quote, comment) if key.startswith('HAVE_'): self.env[key] = 1 old_undefine = Configure.ConfigurationContext.__dict__['undefine'] @Configure.conf def undefine(self, key, comment=''): old_undefine(self, key, comment) if key.startswith('HAVE_'): self.env[key] = 0 # some people might want to use export_incdirs, but it was renamed def set_incdirs(self, val): Logs.warn('compat: change "export_incdirs" by "export_includes"') self.export_includes = val TaskGen.task_gen.export_incdirs = property(None, set_incdirs) def install_dir(self, path): if not path: return [] destpath = Utils.subst_vars(path, self.env) if self.is_install > 0: Logs.info('* creating %s', destpath) Utils.check_dir(destpath) elif self.is_install < 0: Logs.info('* removing %s', destpath) try: os.remove(destpath) except OSError: pass Build.BuildContext.install_dir = install_dir # before/after names repl = {'apply_core': 'process_source', 'apply_lib_vars': 'process_source', 'apply_obj_vars': 'propagate_uselib_vars', 'exec_rule': 'process_rule' } def after(*k): k = [repl.get(key, key) for key in k] return TaskGen.after_method(*k) def before(*k): k = [repl.get(key, key) for key in k] return TaskGen.before_method(*k) TaskGen.before = before kupfer-328/waflib/extras/local_rpath.py000066400000000000000000000011221500175051100202670ustar00rootroot00000000000000#! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 (ita) import copy from waflib.TaskGen import after_method, feature @after_method('propagate_uselib_vars') @feature('cprogram', 'cshlib', 'cxxprogram', 'cxxshlib', 'fcprogram', 'fcshlib') def add_rpath_stuff(self): all = copy.copy(self.to_list(getattr(self, 'use', []))) while all: name = all.pop() try: tg = self.bld.get_tgen_by_name(name) except: continue if hasattr(tg, 'link_task'): self.env.append_value('RPATH', tg.link_task.outputs[0].parent.abspath()) all.extend(self.to_list(getattr(tg, 'use', []))) kupfer-328/waflib/extras/make.py000066400000000000000000000062021500175051100167200ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 (ita) """ A make-like way of executing the build, following the relationships between inputs/outputs This algorithm will lead to slower builds, will not be as flexible as "waf build", but it might be useful for building data files (?) It is likely to break in the following cases: - files are created dynamically (no inputs or outputs) - headers - building two files from different groups """ import re from waflib import Options, Task from waflib.Build import BuildContext class MakeContext(BuildContext): '''executes tasks in a step-by-step manner, following dependencies between inputs/outputs''' cmd = 'make' fun = 'build' def __init__(self, **kw): super(MakeContext, self).__init__(**kw) self.files = Options.options.files def get_build_iterator(self): if not self.files: while 1: yield super(MakeContext, self).get_build_iterator() for g in self.groups: for tg in g: try: f = tg.post except AttributeError: pass else: f() provides = {} uses = {} all_tasks = [] tasks = [] for pat in self.files.split(','): matcher = self.get_matcher(pat) for tg in g: if isinstance(tg, Task.Task): lst = [tg] else: lst = tg.tasks for tsk in lst: all_tasks.append(tsk) do_exec = False for node in tsk.inputs: try: uses[node].append(tsk) except: uses[node] = [tsk] if matcher(node, output=False): do_exec = True break for node in tsk.outputs: try: provides[node].append(tsk) except: provides[node] = [tsk] if matcher(node, output=True): do_exec = True break if do_exec: tasks.append(tsk) # so we have the tasks that we need to process, the list of all tasks, # the map of the tasks providing nodes, and the map of tasks using nodes if not tasks: # if there are no tasks matching, return everything in the current group result = all_tasks else: # this is like a big filter... result = set() seen = set() cur = set(tasks) while cur: result |= cur tosee = set() for tsk in cur: for node in tsk.inputs: if node in seen: continue seen.add(node) tosee |= set(provides.get(node, [])) cur = tosee result = list(result) Task.set_file_constraints(result) Task.set_precedence_constraints(result) yield result while 1: yield [] def get_matcher(self, pat): # this returns a function inn = True out = True if pat.startswith('in:'): out = False pat = pat.replace('in:', '') elif pat.startswith('out:'): inn = False pat = pat.replace('out:', '') anode = self.root.find_node(pat) pattern = None if not anode: if not pat.startswith('^'): pat = '^.+?%s' % pat if not pat.endswith('$'): pat = '%s$' % pat pattern = re.compile(pat) def match(node, output): if output and not out: return False if not output and not inn: return False if anode: return anode == node else: return pattern.match(node.abspath()) return match kupfer-328/waflib/extras/objcopy.py000066400000000000000000000035201500175051100174500ustar00rootroot00000000000000#!/usr/bin/python # Grygoriy Fuchedzhy 2010 """ Support for converting linked targets to ihex, srec or binary files using objcopy. Use the 'objcopy' feature in conjunction with the 'cc' or 'cxx' feature. The 'objcopy' feature uses the following attributes: objcopy_bfdname Target object format name (eg. ihex, srec, binary). Defaults to ihex. objcopy_target File name used for objcopy output. This defaults to the target name with objcopy_bfdname as extension. objcopy_install_path Install path for objcopy_target file. Defaults to ${PREFIX}/fw. objcopy_flags Additional flags passed to objcopy. """ from waflib.Utils import def_attrs from waflib import Task, Options from waflib.TaskGen import feature, after_method class objcopy(Task.Task): run_str = '${OBJCOPY} -O ${TARGET_BFDNAME} ${OBJCOPYFLAGS} ${SRC} ${TGT}' color = 'CYAN' @feature('objcopy') @after_method('apply_link') def map_objcopy(self): def_attrs(self, objcopy_bfdname = 'ihex', objcopy_target = None, objcopy_install_path = "${PREFIX}/firmware", objcopy_flags = '') link_output = self.link_task.outputs[0] if not self.objcopy_target: self.objcopy_target = link_output.change_ext('.' + self.objcopy_bfdname).name task = self.create_task('objcopy', src=link_output, tgt=self.path.find_or_declare(self.objcopy_target)) task.env.append_unique('TARGET_BFDNAME', self.objcopy_bfdname) try: task.env.append_unique('OBJCOPYFLAGS', getattr(self, 'objcopy_flags')) except AttributeError: pass if self.objcopy_install_path: self.add_install_files(install_to=self.objcopy_install_path, install_from=task.outputs[0]) def configure(ctx): program_name = 'objcopy' prefix = getattr(Options.options, 'cross_prefix', None) if prefix: program_name = '{}-{}'.format(prefix, program_name) ctx.find_program(program_name, var='OBJCOPY', mandatory=True) kupfer-328/waflib/extras/package.py000066400000000000000000000030661500175051100174030ustar00rootroot00000000000000#! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 """ Obtain packages, unpack them in a location, and add associated uselib variables (CFLAGS_pkgname, LIBPATH_pkgname, etc). The default is use a Dependencies.txt file in the source directory. This is a work in progress. Usage: def options(opt): opt.load('package') def configure(conf): conf.load_packages() """ from waflib import Logs from waflib.Configure import conf try: from urllib import request except ImportError: from urllib import urlopen else: urlopen = request.urlopen CACHEVAR = 'WAFCACHE_PACKAGE' @conf def get_package_cache_dir(self): cache = None if CACHEVAR in conf.environ: cache = conf.environ[CACHEVAR] cache = self.root.make_node(cache) elif self.env[CACHEVAR]: cache = self.env[CACHEVAR] cache = self.root.make_node(cache) else: cache = self.srcnode.make_node('.wafcache_package') cache.mkdir() return cache @conf def download_archive(self, src, dst): for x in self.env.PACKAGE_REPO: url = '/'.join((x, src)) try: web = urlopen(url) try: if web.getcode() != 200: continue except AttributeError: pass except Exception: # on python3 urlopen throws an exception # python 2.3 does not have getcode and throws an exception to fail continue else: tmp = self.root.make_node(dst) tmp.write(web.read()) Logs.warn('Downloaded %s from %s', tmp.abspath(), url) break else: self.fatal('Could not get the package %s' % src) @conf def load_packages(self): self.get_package_cache_dir() # read the dependencies, get the archives, .. kupfer-328/waflib/extras/parallel_debug.py000066400000000000000000000274431500175051100207570ustar00rootroot00000000000000#! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2007-2010 (ita) """ Debugging helper for parallel compilation. Copy it to your project and load it with:: def options(opt): opt.load('parallel_debug', tooldir='.') def build(bld): ... The build will then output a file named pdebug.svg in the source directory. """ import re, sys, threading, time, traceback try: from Queue import Queue except: from queue import Queue from waflib import Runner, Options, Task, Logs, Errors SVG_TEMPLATE = """ ${if project.title} ${project.title} ${endif} ${for cls in project.groups} ${for rect in cls.rects} ${endfor} ${endfor} ${for info in project.infos} ${info.text} ${endfor} ${if project.tooltip} ${endif} """ COMPILE_TEMPLATE = '''def f(project): lst = [] def xml_escape(value): return value.replace("&", "&").replace('"', """).replace("'", "'").replace("<", "<").replace(">", ">") %s return ''.join(lst) ''' reg_act = re.compile(r"(?P\\)|(?P\$\$)|(?P\$\{(?P[^}]*?)\})", re.M) def compile_template(line): extr = [] def repl(match): g = match.group if g('dollar'): return "$" elif g('backslash'): return "\\" elif g('subst'): extr.append(g('code')) return "<<|@|>>" return None line2 = reg_act.sub(repl, line) params = line2.split('<<|@|>>') assert(extr) indent = 0 buf = [] app = buf.append def app(txt): buf.append(indent * '\t' + txt) for x in range(len(extr)): if params[x]: app("lst.append(%r)" % params[x]) f = extr[x] if f.startswith(('if', 'for')): app(f + ':') indent += 1 elif f.startswith('py:'): app(f[3:]) elif f.startswith(('endif', 'endfor')): indent -= 1 elif f.startswith(('else', 'elif')): indent -= 1 app(f + ':') indent += 1 elif f.startswith('xml:'): app('lst.append(xml_escape(%s))' % f[4:]) else: #app('lst.append((%s) or "cannot find %s")' % (f, f)) app('lst.append(str(%s))' % f) if extr: if params[-1]: app("lst.append(%r)" % params[-1]) fun = COMPILE_TEMPLATE % "\n\t".join(buf) # uncomment the following to debug the template #for i, x in enumerate(fun.splitlines()): # print i, x return Task.funex(fun) # red #ff4d4d # green #4da74d # lila #a751ff color2code = { 'GREEN' : '#4da74d', 'YELLOW' : '#fefe44', 'PINK' : '#a751ff', 'RED' : '#cc1d1d', 'BLUE' : '#6687bb', 'CYAN' : '#34e2e2', } mp = {} info = [] # list of (text,color) def map_to_color(name): if name in mp: return mp[name] try: cls = Task.classes[name] except KeyError: return color2code['RED'] if cls.color in mp: return mp[cls.color] if cls.color in color2code: return color2code[cls.color] return color2code['RED'] def process(self): m = self.generator.bld.producer try: # TODO another place for this? del self.generator.bld.task_sigs[self.uid()] except KeyError: pass self.generator.bld.producer.set_running(1, self) try: ret = self.run() except Exception: self.err_msg = traceback.format_exc() self.hasrun = Task.EXCEPTION # TODO cleanup m.error_handler(self) return if ret: self.err_code = ret self.hasrun = Task.CRASHED else: try: self.post_run() except Errors.WafError: pass except Exception: self.err_msg = traceback.format_exc() self.hasrun = Task.EXCEPTION else: self.hasrun = Task.SUCCESS if self.hasrun != Task.SUCCESS: m.error_handler(self) self.generator.bld.producer.set_running(-1, self) Task.Task.process_back = Task.Task.process Task.Task.process = process old_start = Runner.Parallel.start def do_start(self): try: Options.options.dband except AttributeError: self.bld.fatal('use def options(opt): opt.load("parallel_debug")!') self.taskinfo = Queue() old_start(self) if self.dirty: make_picture(self) Runner.Parallel.start = do_start lock_running = threading.Lock() def set_running(self, by, tsk): with lock_running: try: cache = self.lock_cache except AttributeError: cache = self.lock_cache = {} i = 0 if by > 0: vals = cache.values() for i in range(self.numjobs): if i not in vals: cache[tsk] = i break else: i = cache[tsk] del cache[tsk] self.taskinfo.put( (i, id(tsk), time.time(), tsk.__class__.__name__, self.processed, self.count, by, ",".join(map(str, tsk.outputs))) ) Runner.Parallel.set_running = set_running def name2class(name): return name.replace(' ', '_').replace('.', '_') def make_picture(producer): # first, cast the parameters if not hasattr(producer.bld, 'path'): return tmp = [] try: while True: tup = producer.taskinfo.get(False) tmp.append(list(tup)) except: pass try: ini = float(tmp[0][2]) except: return if not info: seen = [] for x in tmp: name = x[3] if not name in seen: seen.append(name) else: continue info.append((name, map_to_color(name))) info.sort(key=lambda x: x[0]) thread_count = 0 acc = [] for x in tmp: thread_count += x[6] acc.append("%d %d %f %r %d %d %d %s" % (x[0], x[1], x[2] - ini, x[3], x[4], x[5], thread_count, x[7])) data_node = producer.bld.path.make_node('pdebug.dat') data_node.write('\n'.join(acc)) tmp = [lst[:2] + [float(lst[2]) - ini] + lst[3:] for lst in tmp] st = {} for l in tmp: if not l[0] in st: st[l[0]] = len(st.keys()) tmp = [ [st[lst[0]]] + lst[1:] for lst in tmp ] THREAD_AMOUNT = len(st.keys()) st = {} for l in tmp: if not l[1] in st: st[l[1]] = len(st.keys()) tmp = [ [lst[0]] + [st[lst[1]]] + lst[2:] for lst in tmp ] BAND = Options.options.dband seen = {} acc = [] for x in range(len(tmp)): line = tmp[x] id = line[1] if id in seen: continue seen[id] = True begin = line[2] thread_id = line[0] for y in range(x + 1, len(tmp)): line = tmp[y] if line[1] == id: end = line[2] #print id, thread_id, begin, end #acc.append( ( 10*thread_id, 10*(thread_id+1), 10*begin, 10*end ) ) acc.append( (BAND * begin, BAND*thread_id, BAND*end - BAND*begin, BAND, line[3], line[7]) ) break if Options.options.dmaxtime < 0.1: gwidth = 1 for x in tmp: m = BAND * x[2] if m > gwidth: gwidth = m else: gwidth = BAND * Options.options.dmaxtime ratio = float(Options.options.dwidth) / gwidth gwidth = Options.options.dwidth gheight = BAND * (THREAD_AMOUNT + len(info) + 1.5) # simple data model for our template class tobject(object): pass model = tobject() model.x = 0 model.y = 0 model.width = gwidth + 4 model.height = gheight + 4 model.tooltip = not Options.options.dnotooltip model.title = Options.options.dtitle model.title_x = gwidth / 2 model.title_y = gheight + - 5 groups = {} for (x, y, w, h, clsname, name) in acc: try: groups[clsname].append((x, y, w, h, name)) except: groups[clsname] = [(x, y, w, h, name)] # groups of rectangles (else js highlighting is slow) model.groups = [] for cls in groups: g = tobject() model.groups.append(g) g.classname = name2class(cls) g.rects = [] for (x, y, w, h, name) in groups[cls]: r = tobject() g.rects.append(r) r.x = 2 + x * ratio r.y = 2 + y r.width = w * ratio r.height = h r.name = name r.color = map_to_color(cls) cnt = THREAD_AMOUNT # caption model.infos = [] for (text, color) in info: inf = tobject() model.infos.append(inf) inf.classname = name2class(text) inf.x = 2 + BAND inf.y = 5 + (cnt + 0.5) * BAND inf.width = BAND/2 inf.height = BAND/2 inf.color = color inf.text = text inf.text_x = 2 + 2 * BAND inf.text_y = 5 + (cnt + 0.5) * BAND + 10 cnt += 1 # write the file... template1 = compile_template(SVG_TEMPLATE) txt = template1(model) node = producer.bld.path.make_node('pdebug.svg') node.write(txt) Logs.warn('Created the diagram %r', node) def options(opt): opt.add_option('--dtitle', action='store', default='Parallel build representation for %r' % ' '.join(sys.argv), help='title for the svg diagram', dest='dtitle') opt.add_option('--dwidth', action='store', type='int', help='diagram width', default=800, dest='dwidth') opt.add_option('--dtime', action='store', type='float', help='recording interval in seconds', default=0.009, dest='dtime') opt.add_option('--dband', action='store', type='int', help='band width', default=22, dest='dband') opt.add_option('--dmaxtime', action='store', type='float', help='maximum time, for drawing fair comparisons', default=0, dest='dmaxtime') opt.add_option('--dnotooltip', action='store_true', help='disable tooltips', default=False, dest='dnotooltip') kupfer-328/waflib/extras/pep8.py000066400000000000000000000066241500175051100166670ustar00rootroot00000000000000#! /usr/bin/env python # encoding: utf-8 # # written by Sylvain Rouquette, 2011 ''' Install pep8 module: $ easy_install pep8 or $ pip install pep8 To add the pep8 tool to the waf file: $ ./waf-light --tools=compat15,pep8 or, if you have waf >= 1.6.2 $ ./waf update --files=pep8 Then add this to your wscript: [at]extension('.py', 'wscript') def run_pep8(self, node): self.create_task('Pep8', node) ''' import threading from waflib import Task, Options pep8 = __import__('pep8') class Pep8(Task.Task): color = 'PINK' lock = threading.Lock() def check_options(self): if pep8.options: return pep8.options = Options.options pep8.options.prog = 'pep8' excl = pep8.options.exclude.split(',') pep8.options.exclude = [s.rstrip('/') for s in excl] if pep8.options.filename: pep8.options.filename = pep8.options.filename.split(',') if pep8.options.select: pep8.options.select = pep8.options.select.split(',') else: pep8.options.select = [] if pep8.options.ignore: pep8.options.ignore = pep8.options.ignore.split(',') elif pep8.options.select: # Ignore all checks which are not explicitly selected pep8.options.ignore = [''] elif pep8.options.testsuite or pep8.options.doctest: # For doctest and testsuite, all checks are required pep8.options.ignore = [] else: # The default choice: ignore controversial checks pep8.options.ignore = pep8.DEFAULT_IGNORE.split(',') pep8.options.physical_checks = pep8.find_checks('physical_line') pep8.options.logical_checks = pep8.find_checks('logical_line') pep8.options.counters = dict.fromkeys(pep8.BENCHMARK_KEYS, 0) pep8.options.messages = {} def run(self): with Pep8.lock: self.check_options() pep8.input_file(self.inputs[0].abspath()) return 0 if not pep8.get_count() else -1 def options(opt): opt.add_option('-q', '--quiet', default=0, action='count', help="report only file names, or nothing with -qq") opt.add_option('-r', '--repeat', action='store_true', help="show all occurrences of the same error") opt.add_option('--exclude', metavar='patterns', default=pep8.DEFAULT_EXCLUDE, help="exclude files or directories which match these " "comma separated patterns (default: %s)" % pep8.DEFAULT_EXCLUDE, dest='exclude') opt.add_option('--filename', metavar='patterns', default='*.py', help="when parsing directories, only check filenames " "matching these comma separated patterns (default: " "*.py)") opt.add_option('--select', metavar='errors', default='', help="select errors and warnings (e.g. E,W6)") opt.add_option('--ignore', metavar='errors', default='', help="skip errors and warnings (e.g. E4,W)") opt.add_option('--show-source', action='store_true', help="show source code for each error") opt.add_option('--show-pep8', action='store_true', help="show text of PEP 8 for each error") opt.add_option('--statistics', action='store_true', help="count errors and warnings") opt.add_option('--count', action='store_true', help="print total number of errors and warnings " "to standard error and set exit code to 1 if " "total is not null") opt.add_option('--benchmark', action='store_true', help="measure processing speed") opt.add_option('--testsuite', metavar='dir', help="run regression tests from dir") opt.add_option('--doctest', action='store_true', help="run doctest on myself") kupfer-328/waflib/extras/proc.py000066400000000000000000000032751500175051100167550ustar00rootroot00000000000000#! /usr/bin/env python # per rosengren 2011 from os import environ, path from waflib import TaskGen, Utils def options(opt): grp = opt.add_option_group('Oracle ProC Options') grp.add_option('--oracle_home', action='store', default=environ.get('PROC_ORACLE'), help='Path to Oracle installation home (has bin/lib)') grp.add_option('--tns_admin', action='store', default=environ.get('TNS_ADMIN'), help='Directory containing server list (TNS_NAMES.ORA)') grp.add_option('--connection', action='store', default='dummy-user/dummy-password@dummy-server', help='Format: user/password@server') def configure(cnf): env = cnf.env if not env.PROC_ORACLE: env.PROC_ORACLE = cnf.options.oracle_home if not env.PROC_TNS_ADMIN: env.PROC_TNS_ADMIN = cnf.options.tns_admin if not env.PROC_CONNECTION: env.PROC_CONNECTION = cnf.options.connection cnf.find_program('proc', var='PROC', path_list=env.PROC_ORACLE + path.sep + 'bin') def proc(tsk): env = tsk.env gen = tsk.generator inc_nodes = gen.to_incnodes(Utils.to_list(getattr(gen,'includes',[])) + env['INCLUDES']) cmd = ( [env.PROC] + ['SQLCHECK=SEMANTICS'] + (['SYS_INCLUDE=(' + ','.join(env.PROC_INCLUDES) + ')'] if env.PROC_INCLUDES else []) + ['INCLUDE=(' + ','.join( [i.bldpath() for i in inc_nodes] ) + ')'] + ['userid=' + env.PROC_CONNECTION] + ['INAME=' + tsk.inputs[0].bldpath()] + ['ONAME=' + tsk.outputs[0].bldpath()] ) exec_env = { 'ORACLE_HOME': env.PROC_ORACLE, 'LD_LIBRARY_PATH': env.PROC_ORACLE + path.sep + 'lib', } if env.PROC_TNS_ADMIN: exec_env['TNS_ADMIN'] = env.PROC_TNS_ADMIN return tsk.exec_command(cmd, env=exec_env) TaskGen.declare_chain( name = 'proc', rule = proc, ext_in = '.pc', ext_out = '.c', ) kupfer-328/waflib/extras/relocation.py000066400000000000000000000043331500175051100201450ustar00rootroot00000000000000#! /usr/bin/env python # encoding: utf-8 """ Waf 1.6 Try to detect if the project directory was relocated, and if it was, change the node representing the project directory. Just call: waf configure build Note that if the project directory name changes, the signatures for the tasks using files in that directory will change, causing a partial build. """ import os from waflib import Build, ConfigSet, Task, Utils, Errors from waflib.TaskGen import feature, after_method EXTRA_LOCK = '.old_srcdir' old1 = Build.BuildContext.store def store(self): old1(self) db = os.path.join(self.variant_dir, EXTRA_LOCK) env = ConfigSet.ConfigSet() env.SRCDIR = self.srcnode.abspath() env.store(db) Build.BuildContext.store = store old2 = Build.BuildContext.init_dirs def init_dirs(self): if not (os.path.isabs(self.top_dir) and os.path.isabs(self.out_dir)): raise Errors.WafError('The project was not configured: run "waf configure" first!') srcdir = None db = os.path.join(self.variant_dir, EXTRA_LOCK) env = ConfigSet.ConfigSet() try: env.load(db) srcdir = env.SRCDIR except: pass if srcdir: d = self.root.find_node(srcdir) if d and srcdir != self.top_dir and getattr(d, 'children', ''): srcnode = self.root.make_node(self.top_dir) print("relocating the source directory %r -> %r" % (srcdir, self.top_dir)) srcnode.children = {} for (k, v) in d.children.items(): srcnode.children[k] = v v.parent = srcnode d.children = {} old2(self) Build.BuildContext.init_dirs = init_dirs def uid(self): try: return self.uid_ except AttributeError: # this is not a real hot zone, but we want to avoid surprises here m = Utils.md5() up = m.update up(self.__class__.__name__.encode()) for x in self.inputs + self.outputs: up(x.path_from(x.ctx.srcnode).encode()) self.uid_ = m.digest() return self.uid_ Task.Task.uid = uid @feature('c', 'cxx', 'd', 'go', 'asm', 'fc', 'includes') @after_method('propagate_uselib_vars', 'process_source') def apply_incpaths(self): lst = self.to_incnodes(self.to_list(getattr(self, 'includes', [])) + self.env['INCLUDES']) self.includes_nodes = lst bld = self.bld self.env['INCPATHS'] = [x.is_child_of(bld.srcnode) and x.path_from(bld.bldnode) or x.abspath() for x in lst] kupfer-328/waflib/extras/review.py000066400000000000000000000216021500175051100173050ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Laurent Birtz, 2011 # moved the code into a separate tool (ita) """ There are several things here: - a different command-line option management making options persistent - the review command to display the options set Assumptions: - configuration options are not always added to the right group (and do not count on the users to do it...) - the options are persistent between the executions (waf options are NOT persistent by design), even for the configuration - when the options change, the build is invalidated (forcing a reconfiguration) """ import os, textwrap, shutil from waflib import Logs, Context, ConfigSet, Options, Build, Configure class Odict(dict): """Ordered dictionary""" def __init__(self, data=None): self._keys = [] dict.__init__(self) if data: # we were provided a regular dict if isinstance(data, dict): self.append_from_dict(data) # we were provided a tuple list elif type(data) == list: self.append_from_plist(data) # we were provided invalid input else: raise Exception("expected a dict or a tuple list") def append_from_dict(self, dict): map(self.__setitem__, dict.keys(), dict.values()) def append_from_plist(self, plist): for pair in plist: if len(pair) != 2: raise Exception("invalid pairs list") for (k, v) in plist: self.__setitem__(k, v) def __delitem__(self, key): if not key in self._keys: raise KeyError(key) dict.__delitem__(self, key) self._keys.remove(key) def __setitem__(self, key, item): dict.__setitem__(self, key, item) if key not in self._keys: self._keys.append(key) def clear(self): dict.clear(self) self._keys = [] def copy(self): return Odict(self.plist()) def items(self): return zip(self._keys, self.values()) def keys(self): return list(self._keys) # return a copy of the list def values(self): return map(self.get, self._keys) def plist(self): p = [] for k, v in self.items(): p.append( (k, v) ) return p def __str__(self): buf = [] buf.append("{ ") for k, v in self.items(): buf.append('%r : %r, ' % (k, v)) buf.append("}") return ''.join(buf) review_options = Odict() """ Ordered dictionary mapping configuration option names to their optparse option. """ review_defaults = {} """ Dictionary mapping configuration option names to their default value. """ old_review_set = None """ Review set containing the configuration values before parsing the command line. """ new_review_set = None """ Review set containing the configuration values after parsing the command line. """ class OptionsReview(Options.OptionsContext): def __init__(self, **kw): super(self.__class__, self).__init__(**kw) def prepare_config_review(self): """ Find the configuration options that are reviewable, detach their default value from their optparse object and store them into the review dictionaries. """ gr = self.get_option_group('configure options') for opt in gr.option_list: if opt.action != 'store' or opt.dest in ("out", "top"): continue review_options[opt.dest] = opt review_defaults[opt.dest] = opt.default if gr.defaults.has_key(opt.dest): del gr.defaults[opt.dest] opt.default = None def parse_args(self): self.prepare_config_review() self.parser.get_option('--prefix').help = 'installation prefix' super(OptionsReview, self).parse_args() Context.create_context('review').refresh_review_set() class ReviewContext(Context.Context): '''reviews the configuration values''' cmd = 'review' def __init__(self, **kw): super(self.__class__, self).__init__(**kw) out = Options.options.out if not out: out = getattr(Context.g_module, Context.OUT, None) if not out: out = Options.lockfile.replace('.lock-waf', '') self.build_path = (os.path.isabs(out) and self.root or self.path).make_node(out).abspath() """Path to the build directory""" self.cache_path = os.path.join(self.build_path, Build.CACHE_DIR) """Path to the cache directory""" self.review_path = os.path.join(self.cache_path, 'review.cache') """Path to the review cache file""" def execute(self): """ Display and store the review set. Invalidate the cache as required. """ if not self.compare_review_set(old_review_set, new_review_set): self.invalidate_cache() self.store_review_set(new_review_set) print(self.display_review_set(new_review_set)) def invalidate_cache(self): """Invalidate the cache to prevent bad builds.""" try: Logs.warn("Removing the cached configuration since the options have changed") shutil.rmtree(self.cache_path) except: pass def refresh_review_set(self): """ Obtain the old review set and the new review set, and import the new set. """ global old_review_set, new_review_set old_review_set = self.load_review_set() new_review_set = self.update_review_set(old_review_set) self.import_review_set(new_review_set) def load_review_set(self): """ Load and return the review set from the cache if it exists. Otherwise, return an empty set. """ if os.path.isfile(self.review_path): return ConfigSet.ConfigSet(self.review_path) return ConfigSet.ConfigSet() def store_review_set(self, review_set): """ Store the review set specified in the cache. """ if not os.path.isdir(self.cache_path): os.makedirs(self.cache_path) review_set.store(self.review_path) def update_review_set(self, old_set): """ Merge the options passed on the command line with those imported from the previous review set and return the corresponding preview set. """ # Convert value to string. It's important that 'None' maps to # the empty string. def val_to_str(val): if val == None or val == '': return '' return str(val) new_set = ConfigSet.ConfigSet() opt_dict = Options.options.__dict__ for name in review_options.keys(): # the option is specified explicitly on the command line if name in opt_dict: # if the option is the default, pretend it was never specified if val_to_str(opt_dict[name]) != val_to_str(review_defaults[name]): new_set[name] = opt_dict[name] # the option was explicitly specified in a previous command elif name in old_set: new_set[name] = old_set[name] return new_set def import_review_set(self, review_set): """ Import the actual value of the reviewable options in the option dictionary, given the current review set. """ for name in review_options.keys(): if name in review_set: value = review_set[name] else: value = review_defaults[name] setattr(Options.options, name, value) def compare_review_set(self, set1, set2): """ Return true if the review sets specified are equal. """ if len(set1.keys()) != len(set2.keys()): return False for key in set1.keys(): if not key in set2 or set1[key] != set2[key]: return False return True def display_review_set(self, review_set): """ Return the string representing the review set specified. """ term_width = Logs.get_term_cols() lines = [] for dest in review_options.keys(): opt = review_options[dest] name = ", ".join(opt._short_opts + opt._long_opts) help = opt.help actual = None if dest in review_set: actual = review_set[dest] default = review_defaults[dest] lines.append(self.format_option(name, help, actual, default, term_width)) return "Configuration:\n\n" + "\n\n".join(lines) + "\n" def format_option(self, name, help, actual, default, term_width): """ Return the string representing the option specified. """ def val_to_str(val): if val == None or val == '': return "(void)" return str(val) max_name_len = 20 sep_len = 2 w = textwrap.TextWrapper() w.width = term_width - 1 if w.width < 60: w.width = 60 out = "" # format the help out += w.fill(help) + "\n" # format the name name_len = len(name) out += Logs.colors.CYAN + name + Logs.colors.NORMAL # set the indentation used when the value wraps to the next line w.subsequent_indent = " ".rjust(max_name_len + sep_len) w.width -= (max_name_len + sep_len) # the name string is too long, switch to the next line if name_len > max_name_len: out += "\n" + w.subsequent_indent # fill the remaining of the line with spaces else: out += " ".rjust(max_name_len + sep_len - name_len) # format the actual value, if there is one if actual != None: out += Logs.colors.BOLD + w.fill(val_to_str(actual)) + Logs.colors.NORMAL + "\n" + w.subsequent_indent # format the default value default_fmt = val_to_str(default) if actual != None: default_fmt = "default: " + default_fmt out += Logs.colors.NORMAL + w.fill(default_fmt) + Logs.colors.NORMAL return out # Monkey-patch ConfigurationContext.execute() to have it store the review set. old_configure_execute = Configure.ConfigurationContext.execute def new_configure_execute(self): old_configure_execute(self) Context.create_context('review').store_review_set(new_review_set) Configure.ConfigurationContext.execute = new_configure_execute kupfer-328/waflib/extras/syms.py000066400000000000000000000062101500175051100167750ustar00rootroot00000000000000#! /usr/bin/env python # encoding: utf-8 """ This tool supports the export_symbols_regex to export the symbols in a shared library. by default, all symbols are exported by gcc, and nothing by msvc. to use the tool, do something like: def build(ctx): ctx(features='c cshlib syms', source='a.c b.c', export_symbols_regex='mylib_.*', target='testlib') only the symbols starting with 'mylib_' will be exported. """ import re from waflib.Context import STDOUT from waflib.Task import Task from waflib.Errors import WafError from waflib.TaskGen import feature, after_method class gen_sym(Task): def run(self): obj = self.inputs[0] kw = {} reg = getattr(self.generator, 'export_symbols_regex', '.+?') if 'msvc' in (self.env.CC_NAME, self.env.CXX_NAME): re_nm = re.compile(r'External\s+\|\s+_(?P%s)\b' % reg) cmd = (self.env.DUMPBIN or ['dumpbin']) + ['/symbols', obj.abspath()] else: if self.env.DEST_BINFMT == 'pe': #gcc uses nm, and has a preceding _ on windows re_nm = re.compile(r'(T|D)\s+_(?P%s)\b' % reg) elif self.env.DEST_BINFMT=='mac-o': re_nm=re.compile(r'(T|D)\s+(?P_?(%s))\b' % reg) else: re_nm = re.compile(r'(T|D)\s+(?P%s)\b' % reg) cmd = (self.env.NM or ['nm']) + ['-g', obj.abspath()] syms = [m.group('symbol') for m in re_nm.finditer(self.generator.bld.cmd_and_log(cmd, quiet=STDOUT, **kw))] self.outputs[0].write('%r' % syms) class compile_sym(Task): def run(self): syms = {} for x in self.inputs: slist = eval(x.read()) for s in slist: syms[s] = 1 lsyms = list(syms.keys()) lsyms.sort() if self.env.DEST_BINFMT == 'pe': self.outputs[0].write('EXPORTS\n' + '\n'.join(lsyms)) elif self.env.DEST_BINFMT == 'elf': self.outputs[0].write('{ global:\n' + ';\n'.join(lsyms) + ";\nlocal: *; };\n") elif self.env.DEST_BINFMT=='mac-o': self.outputs[0].write('\n'.join(lsyms) + '\n') else: raise WafError('NotImplemented') @feature('syms') @after_method('process_source', 'process_use', 'apply_link', 'process_uselib_local', 'propagate_uselib_vars') def do_the_symbol_stuff(self): def_node = self.path.find_or_declare(getattr(self, 'sym_file', self.target + '.def')) compiled_tasks = getattr(self, 'compiled_tasks', None) if compiled_tasks: ins = [x.outputs[0] for x in compiled_tasks] self.gen_sym_tasks = [self.create_task('gen_sym', x, x.change_ext('.%d.sym' % self.idx)) for x in ins] self.create_task('compile_sym', [x.outputs[0] for x in self.gen_sym_tasks], def_node) link_task = getattr(self, 'link_task', None) if link_task: self.link_task.dep_nodes.append(def_node) if 'msvc' in (self.env.CC_NAME, self.env.CXX_NAME): self.link_task.env.append_value('LINKFLAGS', ['/def:' + def_node.bldpath()]) elif self.env.DEST_BINFMT == 'pe': # gcc on windows takes *.def as an additional input self.link_task.inputs.append(def_node) elif self.env.DEST_BINFMT == 'elf': self.link_task.env.append_value('LINKFLAGS', ['-Wl,-version-script', '-Wl,' + def_node.bldpath()]) elif self.env.DEST_BINFMT=='mac-o': self.link_task.env.append_value('LINKFLAGS',['-Wl,-exported_symbols_list,' + def_node.bldpath()]) else: raise WafError('NotImplemented') kupfer-328/waflib/fixpy2.py000066400000000000000000000027201500175051100157170ustar00rootroot00000000000000#!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010-2018 (ita) from __future__ import with_statement import os all_modifs = {} def fixdir(dir): """Call all substitution functions on Waf folders""" for k in all_modifs: for v in all_modifs[k]: modif(os.path.join(dir, 'waflib'), k, v) def modif(dir, name, fun): """Call a substitution function""" if name == '*': lst = [] for y in '. Tools extras'.split(): for x in os.listdir(os.path.join(dir, y)): if x.endswith('.py'): lst.append(y + os.sep + x) for x in lst: modif(dir, x, fun) return filename = os.path.join(dir, name) with open(filename, 'r') as f: txt = f.read() txt = fun(txt) with open(filename, 'w') as f: f.write(txt) def subst(*k): """register a substitution function""" def do_subst(fun): for x in k: try: all_modifs[x].append(fun) except KeyError: all_modifs[x] = [fun] return fun return do_subst @subst('*') def r1(code): "utf-8 fixes for python < 2.6" code = code.replace('as e:', ',e:') code = code.replace(".decode(sys.stdout.encoding or'latin-1',errors='replace')", '') return code.replace('.encode()', '') @subst('Runner.py') def r4(code): "generator syntax" return code.replace('next(self.biter)', 'self.biter.next()').replace('self.daemon = True', 'self.setDaemon(1)') @subst('Context.py') def r5(code): return code.replace("('Execution failure: %s'%str(e),ex=e)", "('Execution failure: %s'%str(e),ex=e),None,sys.exc_info()[2]") kupfer-328/waflib/processor.py000077500000000000000000000031011500175051100165120ustar00rootroot00000000000000#! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2016-2018 (ita) import os, sys, traceback, base64, signal try: import cPickle except ImportError: import pickle as cPickle try: import subprocess32 as subprocess except ImportError: import subprocess try: TimeoutExpired = subprocess.TimeoutExpired except AttributeError: class TimeoutExpired(Exception): pass def run(): txt = sys.stdin.readline().strip() if not txt: # parent process probably ended sys.exit(1) [cmd, kwargs, cargs] = cPickle.loads(base64.b64decode(txt)) cargs = cargs or {} if not 'close_fds' in kwargs: # workers have no fds kwargs['close_fds'] = False ret = 1 out, err, ex, trace = (None, None, None, None) try: proc = subprocess.Popen(cmd, **kwargs) try: out, err = proc.communicate(**cargs) except TimeoutExpired: if kwargs.get('start_new_session') and hasattr(os, 'killpg'): os.killpg(proc.pid, signal.SIGKILL) else: proc.kill() out, err = proc.communicate() exc = TimeoutExpired(proc.args, timeout=cargs['timeout'], output=out) exc.stderr = err raise exc ret = proc.returncode except Exception as e: exc_type, exc_value, tb = sys.exc_info() exc_lines = traceback.format_exception(exc_type, exc_value, tb) trace = str(cmd) + '\n' + ''.join(exc_lines) ex = e.__class__.__name__ # it is just text so maybe we do not need to pickle() tmp = [ret, out, err, ex, trace] obj = base64.b64encode(cPickle.dumps(tmp)) sys.stdout.write(obj.decode()) sys.stdout.write('\n') sys.stdout.flush() while 1: try: run() except KeyboardInterrupt: break kupfer-328/wscript000066400000000000000000000260341500175051100143020ustar00rootroot00000000000000#! /usr/bin/env python # encoding: utf-8 # pylint: disable=invalid-name # Kupfer's main wscript description file for Waf, written by Ulrik Sverdrup # may be distributed, changed, used, etc freely for any purpose import os import subprocess import sys from pathlib import Path import typing as ty try: from waflib import Errors, Logs, Options, Utils except ImportError: print("You need to upgrade to Waf 2! See README.") sys.exit(1) # the following two variables are used by the target "waf dist" APPNAME = "kupfer" VERSION = "undefined" def _get_git_version(): """try grab the current version number from git""" version = None if Path(".git").exists(): try: version = os.popen("git describe").read().strip() except Exception as e: print(e) return version def _read_git_version(): """Read version from git repo, or from GIT_VERSION""" version = _get_git_version() if not version: gitverfile = Path("GIT_VERSION") if gitverfile.exists(): version = gitverfile.read_text(encoding="UTF-8").strip() if version: global VERSION # pylint: disable=global-statement VERSION = version def _write_git_version(): """Write the revision to a file called GIT_VERSION, to grab the current version number from git when generating the dist tarball. """ version = _get_git_version() if not version: return False Path("GIT_VERSION").write_text(f"{version}\n", encoding="UTF-8") return True _read_git_version() # these variables are mandatory ('/' are converted automatically) top = "." out = "build" config_subdirs = "auxdata help" build_subdirs = "auxdata data po help" EXTRA_DIST = [ "GIT_VERSION", ] def _tarfile_append_as(tarname, filename, destname): import tarfile with tarfile.TarFile.open(tarname, "a") as tf: tarinfo = tf.gettarinfo(name=filename, arcname=destname) tarinfo.uid = 0 tarinfo.gid = 0 tarinfo.uname = "root" tarinfo.gname = "root" with open(filename, "rb") as f: tf.addfile(tarinfo, f) def gitdist(ctx): """Make the release tarball using git-archive""" if not _write_git_version(): raise Exception("No version") basename = f"{APPNAME}-{VERSION}" outname = f"{basename}.tar" with subprocess.Popen( ["git", "archive", "--format=tar", f"--prefix={basename}/", "HEAD"], stdout=subprocess.PIPE, ) as proc: fd = os.open(outname, os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0o666) os.write(fd, proc.communicate()[0]) os.close(fd) for distfile in EXTRA_DIST: _tarfile_append_as(outname, distfile, os.path.join(basename, distfile)) subprocess.call(["xz", "-6e", outname]) subprocess.call(["sha1sum", f"{outname}.xz"]) def _load_excludes(file: Path) -> ty.Iterable[str]: """Load excludes from .gitignore file and covert to glob format.""" for line in file.read_text().splitlines(): line = line.strip() if not line or line.startswith("#"): continue # if ignorefile contains '*' - skip whole catalog if line == "*": yield str(file.parent) return if line.startswith("/"): yield line[1:] else: yield f"**/{line}" def _find_gitignores() -> ty.Iterable[Path]: """File all .gitignore files, also add .git/info/exclude.""" for dirname, _dirs, filenames in os.walk("."): if ".gitignore" in filenames: yield Path(dirname, ".gitignore") # 'private' exclude file if (path := Path(".git/info/exclude")).exists(): yield path def dist(ctx): "The standard waf dist process" _write_git_version() # exclude .git folder excl: set[str] = {".git", ".gitattributes", ".gitignore", ".github"} # load excluded from .gitignore files for file in _find_gitignores(): excl.update(_load_excludes(file)) # always add GIT_VERSION to package if "GIT_VERSION" in excl: excl.remove("GIT_VERSION") print(excl) ctx.excl = " ".join(excl) def options(opt): # options for disabling pyc or pyo compilation opt.load("python") opt.load("gnu_dirs") opt.add_option( "--pyo", action="store_true", default=False, help="Install optimised compiled .pyo files " "[Default:not install]", dest="pyo", ) opt.add_option( "--no-runtime-deps", action="store_false", default=True, help="Do not check for any runtime dependencies", dest="check_deps", ) opt.add_option( "--nopycache", action="store_true", default=False, help="Do not install __pycache__ files ", dest="nopycache", ) opt.recurse(config_subdirs) def configure(conf): conf.load("python") try: conf.check_python_version((3, 5, 0)) except Errors.ConfigurationError: if os.getenv("PYTHON"): raise Logs.pprint("NORMAL", "Looking for Python 3 instead") conf.env["PYTHON"] = ["python3"] conf.check_python_version((3, 5, 0)) conf.load("gnu_dirs") conf.load("intltool") conf.env["KUPFER"] = Utils.subst_vars("${BINDIR}/kupfer", conf.env) conf.env["VERSION"] = VERSION conf.recurse(config_subdirs) # Setup PYTHONDIR so we install into $DATADIR conf.env["PYTHONDIR"] = Utils.subst_vars("${DATADIR}/kupfer", conf.env) Logs.pprint( "NORMAL", "Installing python modules into: %(PYTHONDIR)s" % conf.env ) opt_build_programs = { "rst2man": "Generate and install man page", } for prog, val in opt_build_programs.items(): try: conf.find_program(prog, var=prog.replace("-", "_").upper()) except conf.errors.ConfigurationError: Logs.pprint("YELLOW", f"Optional, allows: {val}") if not Options.options.check_deps: return python_modules = ("gi.repository.Gtk", "xdg", "dbus") for module in python_modules: conf.check_python_module(module) Logs.pprint("NORMAL", "Checking optional dependencies:") opt_programs = { "dbus-send": "Focus kupfer from the command line", } opt_pymodules = { "gi.repository.Wnck": "Jump to running applications and list windows", "gi.repository.Keybinder": "Register global keybindings", } for prog, val in opt_programs.items(): try: conf.find_program(prog, var=prog.replace("-", "_").upper()) except conf.errors.ConfigurationError: Logs.pprint("YELLOW", f"Optional, allows: {val}") for mod, val in opt_pymodules.items(): try: conf.check_python_module(mod) except Errors.ConfigurationError: Logs.pprint("YELLOW", f"module {mod} is recommended, allows {val}") def _new_package(bld, name): """Add module @name to sources to be installed, where the name is the full (relative) path to the package """ obj = bld("py") node = bld.path.find_dir(name) obj.source = node.ant_glob("*.py") obj.install_path = "${PYTHONDIR}/" # Find embedded package datafiles pkgnode = bld.path.find_dir(name) bld.install_files( obj.install_path, pkgnode.ant_glob("icon-list"), relative_trick=True ) bld.install_files( obj.install_path, pkgnode.ant_glob("*.png"), relative_trick=True ) bld.install_files( obj.install_path, pkgnode.ant_glob("*.svg"), relative_trick=True ) def _find_packages_in_directory(bld, name): """Go through directory @name and recursively add all Python packages with contents to the sources to be installed """ for dirname, _dirs, filenames in os.walk(name): if "__init__.py" in filenames: _new_package(bld, dirname) def _dict_slice(D, keys): return {k: D[k] for k in keys} def build(bld): # always read new version bld.env["VERSION"] = VERSION bld.env.NOPYCACHE = bld.options.nopycache bld.env.PYO = bld.options.pyo # kupfer/ # kupfer module version info file version_subst_file = "kupfer/version_subst.py" bld( features="subst", source=f"{version_subst_file}.in", target=version_subst_file, dict=_dict_slice( bld.env, ("VERSION", "DATADIR", "PACKAGE", "LOCALEDIR") ), ) bld.install_files("${PYTHONDIR}/kupfer", "kupfer/version_subst.py") bld(source="kupfer.py", install_path="${PYTHONDIR}") # Add all Python packages recursively _find_packages_in_directory(bld, "kupfer") # bin/ # Write in some variables in the shell script binaries bld( features="subst", source="bin/kupfer.in", target="bin/kupfer", dict=_dict_slice(bld.env, ("PYTHON", "PYTHONDIR")), ) bld.install_files("${BINDIR}", "bin/kupfer", chmod=0o755) bld( features="subst", source="bin/kupfer-exec.in", target="bin/kupfer-exec", dict=_dict_slice(bld.env, ("PYTHON", "PACKAGE", "LOCALEDIR")), ) bld.install_files("${BINDIR}", "bin/kupfer-exec", chmod=0o755) # Documentation/ if rst2man := bld.env["RST2MAN"]: # generate man page from Manpage.rst bld( source="Documentation/Manpage.rst", target="kupfer.1", rule="%s ${SRC} > ${TGT}" % rst2man[0], ) bld.add_group() # compress and install man page manpage = bld( source="kupfer.1", target="kupfer.1.gz", rule="gzip -n -9 -c ${SRC} > ${TGT}", install_path="${MANDIR}/man1", ) man_path = Utils.subst_vars( os.path.join(manpage.install_path, manpage.target), bld.env ) bld.symlink_as("${MANDIR}/man1/kupfer-exec.1.gz", man_path) # Separate subdirectories bld.recurse(build_subdirs) def distclean(bld): bld.exec_command("find ./ -name '*.pyc' -or -name '*.pyo' -delete") bld.exec_command("find ./ -name '__pycache__' -delete") def intlupdate(util): print("You should use intltool-update directly.") print("You can read about this in Documentation/Manual.rst") print("in the localization chapter!") def test(bld): # find all files with doctests python = os.getenv("PYTHON", "python") paths = os.popen("grep -lR 'doctest.testmod()' kupfer/").read().split() os.putenv("PYTHONPATH", ".") all_success = True verbose = "-v" in sys.argv for p in paths: print(p) cmd = [python, p] if verbose: cmd.append("-v") with subprocess.Popen( cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True, ) as pcmd: res = b"" sin, souterr = pcmd.stdin, pcmd.stdout if sin: sin.close() if souterr: res = souterr.read() souterr.close() print(res or "OK") all_success = all_success and bool(res) return all_success def shutdown(bld): pass