pax_global_header00006660000000000000000000000064142221713250014511gustar00rootroot0000000000000052 comment=51ae5c96e25fef795f29df0684f9c00e615e74e7 gaupol-1.11/000077500000000000000000000000001422217132500127225ustar00rootroot00000000000000gaupol-1.11/.flake8000066400000000000000000000000501422217132500140700ustar00rootroot00000000000000[flake8] select = E1,E9,F ignore = E129 gaupol-1.11/.github/000077500000000000000000000000001422217132500142625ustar00rootroot00000000000000gaupol-1.11/.github/FUNDING.yml000066400000000000000000000000471422217132500161000ustar00rootroot00000000000000custom: https://www.paypal.me/otsaloma gaupol-1.11/.github/workflows/000077500000000000000000000000001422217132500163175ustar00rootroot00000000000000gaupol-1.11/.github/workflows/test.yml000066400000000000000000000022261422217132500200230ustar00rootroot00000000000000name: Test on: [push] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Check Python version run: python -c "import sys; print(sys.version)" - name: Install dependencies run: > sudo apt-get update && sudo apt-get install -y flake8 gettext gir1.2-gspell-1 gir1.2-gst-plugins-base-1.0 gir1.2-gstreamer-1.0 gir1.2-gtk-3.0 gstreamer1.0-gtk3 gstreamer1.0-libav gstreamer1.0-plugins-bad gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly iso-codes python3 python3-chardet python3-dev python3-gi python3-gi-cairo python3-pytest xvfb - name: Run linter run: flake8 . - name: Run unit tests run: | py.test-3 aeidon xvfb-run py.test-3 gaupol xvfb-run py.test-3 data/extensions - name: Install run: | python3 setup.py install --prefix=/tmp/local python3 setup.py install --root=/tmp/pkg python3 setup.py clean gaupol-1.11/.gitignore000066400000000000000000000005151422217132500147130ustar00rootroot00000000000000*.egg-info *~ .cache .pytest_cache __pycache__ build data/extensions/*/*.extension data/io.otsaloma.gaupol.appdata.xml data/io.otsaloma.gaupol.desktop data/patterns/*.capitalization data/patterns/*.common-error data/patterns/*.hearing-impaired data/patterns/*.line-break dist flatpak/.flatpak-builder flatpak/build locale po/LINGUAS gaupol-1.11/.tx/000077500000000000000000000000001422217132500134335ustar00rootroot00000000000000gaupol-1.11/.tx/config000066400000000000000000000002161422217132500146220ustar00rootroot00000000000000[main] host = https://www.transifex.com [gaupol.gaupolpot] file_filter = po/.po source_file = po/gaupol.pot source_lang = en type = PO gaupol-1.11/AUTHORS.md000066400000000000000000000000371422217132500143710ustar00rootroot00000000000000Osmo Salomaa gaupol-1.11/COPYING000066400000000000000000001045131422217132500137610ustar00rootroot00000000000000 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 . gaupol-1.11/Makefile000066400000000000000000000025001422217132500143570ustar00rootroot00000000000000# -*- coding: utf-8-unix -*- # EDITOR must wait! EDITOR = nano check: flake8 bin/gaupol flake8 aeidon flake8 gaupol flake8 data/extensions/*/*.py flake8 *.py clean: ./setup.py clean install: ./setup.py install publish-aeidon: $(MAKE) check test clean ./setup-aeidon.py sdist bdist_wheel test -s dist/aeidon-*-py3-none-any.whl test -s dist/aeidon-*.tar.gz ls -l dist printf "Press Enter to upload or Ctrl+C to abort: "; read _ twine upload dist/* sudo pip3 uninstall -y aeidon || true sudo pip3 uninstall -y aeidon || true sudo pip3 install -U aeidon cd && python3 -c "import aeidon; print(aeidon.__file__, aeidon.__version__)" # Interactive! release: $(MAKE) check test clean @echo "BUMP VERSION NUMBERS" $(EDITOR) aeidon/__init__.py $(EDITOR) gaupol/__init__.py $(EDITOR) data/extensions/*/*.in @echo "ADD RELEASE NOTES" $(EDITOR) NEWS.md $(EDITOR) data/io.otsaloma.gaupol.appdata.xml.in sudo ./setup.py install --prefix=/usr/local clean /usr/local/bin/gaupol tools/release @echo "REMEMBER TO make publish-aeidon" @echo "REMEMBER TO UPDATE FLATPAK" @echo "REMEMBER TO UPDATE WEBSITE" test: py.test -xs aeidon gaupol data/extensions # Interactive! translations: tools/update-translations warnings: python3 -Wd bin/gaupol .PHONY: check clean install publish-aeidon release test translations warnings gaupol-1.11/NEWS.md000066400000000000000000001201251422217132500140210ustar00rootroot000000000000002022-04-03: Gaupol 1.11 ======================= * Add IBM858, ISO-8859-11 and ISO-8859-16 encodings * Fix displayed line lengths being incorrect for subtitles with special characters such as apostrophes 2021-10-06: Gaupol 1.10.1 ========================= * Fix playing selection (#188) 2021-09-30: Gaupol 1.10 ======================= * Fix subtitle display when seeking to selection start (#181) * Fix search dialog result sometimes not being selected * Fix rare RecursionError with spell-check 2020-12-31: Gaupol 1.9 ====================== * Add framerates 30, 50, 59.94 and 60 fps (#164) * Add selecting next/previous from video position (#154) * Allow shifting positions of all open projects (#66) * Fix error dialog when video playback fails (#153) * Fix the order of audio tracks in the menu (#129, qnga) * Fix spell-check split words correction task to not hang (#171) * Add Dutch translation (Heimen Stoffels) 2020-04-10: Gaupol 1.8 ====================== * Add action set start from video position (#148) * Add and fix English spell-check special cases * Add and fix OCR spell-check special cases * Add Interlingue translation (OIS) * Add Portuguese translation (Hugo Carvalho) * Update translations 2019-08-04: Gaupol 1.7 ====================== * New app icon, as full-color and symbolic SVGs (#119) * Better initial preview experience (#136) * Disable loading of problematic gstreamer-vaapi (#79) * Use gspell for spell-check instead of PyEnchant and GtkSpell (#12) * Use the reverse domain name "io.otsaloma.gaupol" for desktop file, appdata file and icons 2019-06-08: Gaupol 1.6 ====================== * Add text correction pattern to unpack ligatures * Don't show video files in recent file menus (#130) * Update translations 2019-02-03: Gaupol 1.5 ====================== * Add support for building a Flatpak * Highlight changed parts in "Correct Texts" (#34) * Add keybinding Ctrl+I for toggling italic (#118) * Add keybinding Ctrl+I for toggling italic while editing (#118) * Change keybinding for Invert Selection to Ctrl+J * When opening multiple files, skip ones already open * Adapt to various GTK deprecations * Add 64x64 and 128x128 icons * Update AppData XML file * Bump iso-codes dependency to >= 3.67 * Update translations 2018-07-07: Gaupol 1.4.1 ======================== * Fix TypeErrors due to video player pipeline queries failing (#78) * Make 'setup.py --record' include compiled extensios as well (#91) 2018-05-01: Gaupol 1.4 ====================== * Update the `--video-file` argument to not just select the video file, but also load it in the internal video player (#75) * Fix subtitles with special characters not being displayed by the internal video player (#74) * Fix seeking to selection start if at less than one second (#76) * Fix pasting texts from outside Gaupol, e.g. from a text editor * Update checks for required GStreamer elements (#73) * Update translations 2017-11-12: Gaupol 1.3.1 ======================== * Fix pattern file syntax to not be corrupted by msgfmt (#70) 2017-11-11: Gaupol 1.3 ====================== * Use gtksink instead of autovideosink with the integrated video player, making it work on Wayland too (#60) * Add a hidden preference to disable autoplay (#57) * Allow loading video by drag-and-drop (#59) * Fix missing icon in GNOME shell on Wayland (#62) * Fix unhandled exception when adding recent menu items * Fix video player actions being sensitive when playback initialization fails (#52) * Fix Gaupol freezing after changing audio track (#58) * Fix error quitting if a file is still being loaded (#54) * Fix duplicate tags when decoding MPL2 (devcompl, #68) * Install appdata XML file under /usr/share/metainfo * Prefer iso-codes JSON files over XML files (#10) * Bump GStreamer dependency ≥ 1.6 * Drop build dependency on intltool (use gettext instead, #13) * Add donate button to about dialog * Update translations 2017-04-23: Gaupol 1.2 ====================== * Add support for the WebVTT file format (#46) * Add support for the LRC file format (#39) 2017-03-18: Gaupol 1.1 ====================== * Fix error when using the Save All As dialog to save all time-based format documents as frame-based or vice versa * Fix unhandled exception when trying to write non-numeric data into integer or float cells * Add Icelandic translation (Sveinn í Felli) * Remove severely incomplete Catalan, Polish and Swedish translations * Update translations 2016-10-29: Gaupol 1.0 ====================== * Fix size of custom font with GTK 3.22 (#40) * Show an error dialog if the integrated video player fails to initialize playback due to e.g. missing codecs * Fix error trying to undo more actions than exist when holding down Ctrl+Z (#38) 2016-08-20: Gaupol 0.92 ======================= * Fix error saving document from a time-based format to a frame-based or vice versa ([#28][]) * Fix error clicking undo or redo button dropdown arrow when no document is yet open ([#29][]) * Fix action states after subtitle cell editing cancelled ([#30][]) * Fix recent file menu states to update correctly ([#31][]) * Fix save as dialog to always add filename extension ([#32][]) * Update AppData file * Update translations [#28]: https://github.com/otsaloma/gaupol/issues/28 [#29]: https://github.com/otsaloma/gaupol/issues/29 [#30]: https://github.com/otsaloma/gaupol/issues/30 [#31]: https://github.com/otsaloma/gaupol/issues/31 [#32]: https://github.com/otsaloma/gaupol/issues/32 2016-07-16: Gaupol 0.91 ======================= * Use header bars for dialogs * Migrate from deprecated `Gtk.UIManager`, `Gtk.Action` etc. to `Gtk.Application`, `Gio.Action` etc. * Add mpv for preview with precise seek (`--hr-seek=yes`) * Make mpv the default preview video player on non-Windows systems and set the default preview offset to one second * Make seek length configurable in the preferences dialog * Add find and replace to the toolbar * Have both Ctrl+F and Ctrl+H open the find and replace dialog * Have both Ctrl++, Ctrl+- and numpad equivalents control volume * Remove external video player output window (if you want to see that output, start Gaupol from a terminal) * Use a monospace editing font by default * Add support for IBM273, IBM1125, KOI8-T and KZ1048 character encodings (whether these are actually available depends on your version of Python) * Drop the bookmarks extension * Fix Cancel button behaviour when quitting Gaupol by closing the main window and having unsaved changes ([#14][]) * Fix line length measure em to be narrower ([#763589][]) * Have the text view right-click spell-check language menu set the language permanently * Don't show the "Use Shift+Return for line-break" help message if it's likely to overlap with the text being edited * Only force theme variant if `dark_theme` in config file is `true`, thus respecting any global settings ([#753315][]) * Make `GTK_THEME=Adwaita:dark gaupol` work correctly * Move web pages to * Move releases to * Move bug tracker to * Move documentation to * Close mailing lists, use Gitter instead: * Use Transifex for translations: * Update AppData file * Bump GTK dependency to ≥ 3.12 * Bump PyGObject dependency to ≥ 3.12 * Drop optional dependencies on PT fonts * Add Serbian translation (Miroslav Nikolić) * Update French translation (Jean van Kasteel) [#14]: https://github.com/otsaloma/gaupol/issues/14 [#753315]: https://bugzilla.gnome.org/show_bug.cgi?id=753315 [#763589]: https://bugzilla.gnome.org/show_bug.cgi?id=763589 2015-05-16: Gaupol 0.28.2 ========================= * Fix text view size in spell check dialog 2015-05-09: Gaupol 0.28.1 ========================= * Have the spell-check dialog remember its size * Work around a destructive override in gst-python that broke Gaupol's built-in video player ([#748813][]) * Update Hungarian translation (Andrássy László) * Update French translation (RyDroid) * Update Brazilian Portuguese translation (Rafael Ferreira, Felipe Braga) * Update Czech translation (Pavel Fric) [#748813]: http://bugzilla.gnome.org/show_bug.cgi?id=748813 2014-12-08: Gaupol 0.28 ======================= * Add target in the position shift dialog to shift subtitles from selection to end ([#734198][]) * Center tab labels * Fix mouse use in the cell text editor to not cause losing focus and thus cancelling editing * Fix bookmarks not being cleared when a file with bookmarks is closed ([#740481][]) * Remove buggy `text-shadow` use from CSS ([#740527][]) * Use markdown for documentation files (`README` etc.) * Update Spanish translation (Carlos Mella) [#734198]: http://bugzilla.gnome.org/show_bug.cgi?id=734198 [#740481]: http://bugzilla.gnome.org/show_bug.cgi?id=740481 [#740527]: http://bugzilla.gnome.org/show_bug.cgi?id=740527 2014-10-27: Gaupol 0.27 ======================= * Hide tabs when only one tab is open * Expand tabs to fill window width, use 24 characters at minimum * Fix dialog paddings with GTK 3.14 * Fix text view line length display with GTK 3.14 * Pack video player toolbar and seekbar horizontally * Avoid column resizing upon opening file * Fix `IndexError: list index out of range` when undoing or redoing by holding Ctrl+(Shift)+Z pressed * Remove use of deprecated stock items, `Gtk.Alignment`, `gi.types.Boxed.__init__` and non-transient dialogs * Update Spanish translation (Carlos Mella) 2014-06-21: Gaupol 0.26 ======================= * Update file selection dialogs to work better with GTK 3.12 * Default toolbar style to icons only (due to `gtk-toolbar-style` being deprecated since GTK 3.10) * Allow using the dark GTK theme variant (you need to edit `~/.config/gaupol/gaupol.conf` to enable this) * Fix errors and lack of updates in multiline text cells and their line length calculation and display (#728575) * Fix initially incorrect row heights after opening a file * Fix updating subtitle numbers when inserting or removing subtitles * Fix overlapping column header right-click menus * Fix saving enumeration values to configuration file * Use `Gtk.render_layout` instead of deprecated `Gtk.paint_layout` to render line length margin in text views * Remove header editing dialog * Remove non-functional speech recognition menu item (see ) * Drop support for the MPsub format * Add GTK (3.2 or greater) to list of dependencies in the `README` file (GTK has always been a dependency, its explicit mention was just forgotten when migrating from PyGTK to PyGObject) * Update Brazilian Portuguese translation (Rafael Ferreira) * Update Czech translation (Pavel Fric) 2014-02-08: Gaupol 0.25 ======================= * Depend on GtkSpell 3.0.0 or later instead of pygtkspellcheck for inline spell-check - http://gtkspell.sourceforge.net/ * Clarify GStreamer dependency as "at least the core, gst-plugins-base and gst-plugins-good; and for good container and codec support preferrably each of gst-plugins-bad, gst-plugins-ugly and gst-libav" (#710138) * Check that required GStreamer elements can be found and print error messages if not (#710138) * Filter open recent menu items by mimetype * Fix search dialog "Ignore case" option * Fix text correction assistant layout with GTK 3.10 * Fix newline handling on Windows (Python 3 does implicit conversions that were not accounted for) * Fix preview error dialog on Windows (#651675) * Fix video selection dialog on Windows (#654523) * Fix miscellaneous small Windows-specific issues * Rewrite Windows installer build scripts (thanks to TumaGonx Zakkum for pygi-aio binaries and Gian Mario Tagliaretti for a template cx\_Freeze setup script) * Update Spanish translation (Carlos Mella) 2013-10-06: Gaupol 0.24.3 ========================= * Fix preferences dialog subtitle and time overlay connections 2013-10-06: Gaupol 0.24.2 ========================= * Make AppData file translatable * Fix broken string formatting in the French translation that caused `KeyError`s handling encoding names (#709335) 2013-09-22: Gaupol 0.24.1 ========================= * Possibly fix floating status label colors on non-Adwaita themes * Add an AppData XML file - http://people.freedesktop.org/~hughsient/appdata/ * Add French translation (RyDroid) * Update Czech translation (Pavel Fric) 2013-07-22: Gaupol 0.24 ======================= * Add action to set the end time from video position (see also ) * Use a floating label for the statusbar * Show search dialog messages in a floating label in the search dialog * Use inline toolbars in the preferences dialog - https://wiki.gnome.org/Design/HIG/InlineToolbars * Apply GNOME Goal: Add keywords to application desktop files - https://wiki.gnome.org/GnomeGoals/DesktopFileKeywords * Hide translation text column by default and show only when a translation file is opened or the column is explicitly selected to be shown * Remove video toolbar (video file and framerate selectors) * Add a framerate selector to save dialogs (shown only when converting from a time-based file format to a frame-based or vice versa) * Change a couple keybindings * Move "Select Video" from the file menu to the tools menu (below "Preview") to clarify that it relates to the external preview * Add Galician translation (Leandro Regueiro) * Update Spanish translation (Carlos Mella) 2013-06-26: Gaupol 0.23 ======================= * Add a built-in GStreamer-based video player * Add a not-required, but recommended dependency on PT fonts (PT Sans Caption and PT Mono) used by default for video player's subtitle and timecode overlays - http://www.paratype.com/public/ * Bump PyGObject dependency to version 3.6.0 or later * Fix `KeyError` tearing down extension on quit (#702518) * Update Spanish translation (Carlos Mella) 2013-04-09: Gaupol 0.22 ======================= * Restore drop-down arrows on undo and redo toolbar buttons for those using PyGObject 3.7.90 or greater (#686608) * Restore almost proper keeping track of recent files for those using PyGObject 3.7.4 or greater (#678401, #695970) * Restore zebra-stripes, which were previously discarded by some GTK themes * Mostly fix cell rendering speed issues with GTK 3.6 and later * Add Czech translation (Pavel Fric) 2013-01-13: Gaupol 0.21.1 ========================= * Fix error disconnecting text view's line length margin handler (`AttributeError: 'TextView' object has no attribute 'gaupol_ruler_handler_id'`) * Fix atomic file writing in weird cases where the subtitle file to be written and its backup in the same directory would be on different filesystems (Florian Léger, Osmo Salomaa) * Fix speed issues updating subtitle list selection (e.g. when doing a search-and-replace-all with a alot of matches) * Speed up action sensitivity updates 2012-12-02: Gaupol 0.21 ======================= * Restore inline spell-check, replace the previous GtkSpell dependency with a dependency on pygtkspellcheck - http://koehlma.github.com/projects/pygtkspellcheck.html * Add partial support for fancy Unicode dashes, ellipses and quotation marks in text correction patterns and "Toggle dialogue dashes" action * Fix search dialog mnemonics * Apply GNOME Goal: Remove markup in translatable messages 2012-11-11: Gaupol 0.20.1 ========================= * Fix crash on startup on newer versions of PyGObject and/or GTK resulting from setting tool item types (#686608) * Fix side pane header menu (#686312) * Disable "Join or Split Words" task in the text correction assistant if no spell-check dictionaries are available (#686340) * Use a stock GTK close icon for tab close buttons if "window-close-symbolic" is not found * Fix behaviour of spell-check dialog's "Replace with" entry 2012-10-14: Gaupol 0.20 ======================= * Migrate to Python 3, GTK 3, GStreamer 1.0, PyGI and GNOME 3 * Bump Python dependency to 3.2 or greater * Replace PyGTK dependency with PyGObject 3.0.0 or greater * Bump optional GStreamer dependency to 1.0 or greater * Disable inline spell-checking while waiting for introspection support to be added to GtkSpell - https://bugzilla.redhat.com/show_bug.cgi?id=675504 * Disable speech recognition while waiting for pocketsphinx to be ported to GStreamer 1.0 - https://sourceforge.net/projects/cmusphinx/forums/forum/5471/topic/5497616 * Rewrite line-breaking algorithm to use a Knuth-Plass-style flexible system of penalties and a versatile measure of goodness * Write subtitle files in a proper atomic manner (on Windows this is fully atomic only with Python 3.3 or later) * Ellipsize tab labels in the middle (#686099) * Remove `-c`/`--config-file` option (you're better off setting `XDG_*` environment variables if you're doing something weird) * Add 48x48 and 256x256 pixel PNG icons and remove SVG icon * Fix bug in saving a temporary file for preview (#685706) * Fix signatures of decorated functions in API documentation * Use filename extension `.extension` for extension metadata files (instead of previous `.gaupol-extension`) * Use filename extension `.bookmarks` for bookmark files written by the bookmarks extension (instead of previous `.gaupol-bookmarks`) * Release source tarballs only compressed as `tar.xz` (instead of the previous `tar.gz` and `tar.bz2`) * Update Brazilian Portuguese translation (Átila Camurça, Darlildo Lima) * Update Hungarian translation (Andrássy László) * Update Spanish translation (Carlos Mella) 2011-11-26: Gaupol 0.19.2 ========================= * Allow preview of unsaved documents (#661242) * Use subtitles from selected range if applicable in the Transform Positions dialog (#663158) * Fix mplayer preview command to work if gaupol was started as a background process (with &) from a terminal window (#660035) * Fix `TypeError` when speech recognition stopped in the middle of a subtitle * Fix `IndexError` when speech recognition finished with no speech detected (#659411) * Fix `UnicodeDecodeError` when reading configuration file (#661123) * Rename `manifest` directory in source tarball to avoid clashes with `MANIFEST` file on case-insensitive filesystems 2011-09-07: Gaupol 0.19.1 ========================= * Fix gettext initialization in aeidon package to not make global changes (Olivier Aubert, Osmo Salomaa, Debian bug #639668) * Fix speech recognition advance length handling so that subtitles don't start too early * Update Russian translation (Alexandre Prokoudine) 2011-07-17: Gaupol 0.19 ======================= * Add speech recognition to allow generating subtitles from video - http://wiki.gnome.org/Apps/Gaupol/SpeechRecognition * Fix installation of custom-framerates extension * Add optional dependency on gst-python (this also implies a dependency on one or more of gst-plugins-base, gst-plugins-good, gst-plugins-ugly, gst-plugins-bad, gst-ffmpeg depending on what video and audio formats are being used) - http://gstreamer.freedesktop.org/ * Add optional dependency on pocketsphinx - http://cmusphinx.sourceforge.net/ * Add gaupol-i18n mailing list for translators * Update Spanish translation (Carlos Mella) * Update Hungarian translation (Andrássy László) 2011-05-30: Gaupol 0.18 ======================= * Add extension that allows use of custom framerates (#637503) * Add "Get more extensions" button to the preferences dialog * Relax SubRip file parsing in unambiguous cases (#634129) * Fix saving of last used directory in file dialogs with "paths that cannot be represented as a local filename" (#649347) * Add Brazilian Portuguese translation (Átila Camurça, Darlildo Souza) * Update German translation (Chris Leick) 2011-04-10: Gaupol 0.17.2 ========================= * Add framerate 24.0 fps found on Blu-rays and use three decimals for all framerates (#580345) * Fix broken inheritance of action classes, which caused Gaupol to fail to start with recent versions of (Py)GTK (#643958) * Fix previewing of changes in position shift and transformation dialogs * Fix eternal loop when opening translation files and having existing zero-duration subtitles * Fix names of filetype filters in open dialog * Update author email address * Move development repository from Gitorious to GitHub (https://github.com/otsaloma/gaupol) * Abandon use of Transifex for translations * Add Turkish translation (Koray Löker and Çağlar Kilimci) 2010-11-07: Gaupol 0.17.1 ========================= * Fix search dialog replace button to change sensitivity without delay to avoid concurrent replacements (#626976) * Save text assistant window size * Show line lengths in text assistant confirmation page * Hopefully fix spell-check not working on Windows (#623864) * Build Windows installer without UI translations to avoid a partly translated mess (especially due to pygtk bug #574520) * Add Hebrew translation (Yaron Shahrabani) * Update Hungarian translation (Andrássy László) * Update Spanish translation (Carlos Mella) 2010-07-05: Gaupol 0.17 ======================= * Add "Save All As" (under the Projects menu) to save all open documents with selected properties (fixes #595685) * Add an inline spell-check for editable multiline text fields (off by default, can be activated in the preferences dialog) * Add support for milliseconds (field `$MILLISECONDS`) in preview commands. Allows use of Media Player Classic for preview. * Add help button in the preferences dialog, clickable in the preview tab to launch web browser to view wiki documentation * Use reading speed (characters per second) instead of optimal duration (seconds per character) in duration adjust dialog * Fix writing subtitle file headers with chosen newlines * Fix reading and writing extension configurations * Fix minor i18n issues with individual strings * Add optional dependency of PyGtkSpell (part of gnome-python-extras) * Add `--mandir` global option to `setup.py` to allow installation of man pages to somewhere else than `.../share/man` (fixes #620665) * Add Finnish translation 2010-06-22: Gaupol 0.16.2 ========================= * Fix "Quit" and Close All" to ask to save unsaved changes * Update Russian translation (Алекс) * Update Hungarian translation (Andrássy László) 2010-06-09: Gaupol 0.16.1 ========================= * Add support for a variant of the TMPlayer format with two-digit hours, i.e. time strings of form HH:MM:SS: * Fix cropped close icons on tabs * Fix `AttributeError` related to locale functions on Windows * Fix launching web browser on Windows * Clarify dependencies of aeidon and gaupol in `README.aeidon` * Add Russian translation (Алекс) 2010-06-03: Gaupol 0.16 ======================= * Split general-purpose, user-interface-independent subtitle editing code to a separate Python package called "aeidon" while keeping the GTK user interface code under the package "gaupol". Allow installation of these two packages separate of one another. Developers and packagers are encouraged to read `./setup.py --help` message and the file `README.aeidon`. (Fixes #595809 and should allow fixing the likes of Debian bug #569983.) * Save menu item keybindings to a GtkAccelMap rc-file in the user's configuration directory * Have the interactive search look for times instead of subtitle numbers if the search string contains a colon (fixes #609176) * Add miscellaneous Latin common error corrections patterns * Add help menu item to browse wiki documentation at * Increase size of line length superscripts shown in list cells * Fix focus changing when pasting subtitles * Use `gtk.RecentAction` for recent file menus (fixes #615372 and probably #608951) * Work around a subprocess error launching video player on Windows systems, which resulted in `TypeError: environment can only contain strings` (fixes #605805) * Fix handling of Unicode BOMs that broke as a result of a hasty fix for subtitle file reading functions for 0.15.1 * Fix hearing impaired text removal pattern "Speaker before a colon" to not remove too much (fixes #618529) * Apply GNOME Goal: Correct Desktop Files * Migrate from Glade to GtkBuilder * Use attributes instead of markup in GtkBuilder files * Fix GtkBuilder constructed buttons to respect user preferences regarding whether or not to show icons in buttons * Use Python's JSON module instead of ConfigObj and Validate for reading and writing configuration files * Use enchant's user spell-check dictionaries (usually stored in `$HOME/.config/enchant`) instead gaupol-specific ones * Use copies of iso-codes XML files shipped with gaupol only as a fallback if they are not found under `/usr/share/xml/iso-codes` * Add global options `--with-iso-codes` and `--without-iso-codes` to `setup.py` to control whether or not to install iso-codes XML files (This means that packagers can use `--without-iso-codes` and mark the iso-codes package as a hard dependency to avoid duplicate files) * Probably fix i18n issues with Unicode ellipses of menu items * Fix i18n issues with locale codes and their fallbacks used in pattern files for "Name" and "Description" fields * Raise Python dependency to 2.6 * Raise PyGTK dependency to 2.16 * Raise PyEnchant dependency to 1.4.0 2010-03-24: Gaupol 0.15.1 ========================= * Fix complete breakage of opening subtitle files due to a change in newline handling of `codecs.open` in Python 2.6.5 * Use existing subtitle file mime-types instead of text/plain when adding files to the recent files database * Add German translation (Chris Leick) * Add Hungarian translation (László Andrássy) 2009-05-15: Gaupol 0.15 ======================= * Add text correction task to split joined words or to join split words using spell-check suggestions (#572667) * Show duration in time mode as seconds * Merge Latin and French common error text correction patterns from subtitleeditor (kitone) * Allow pasting times with comma as a decimal separator (#580339) * Allow bookmarks to be added or removed by double-clicking or pressing enter in the bookmark column (#580346) * Add validation for character encoding given as an argument on the command line using the `-e` option * Fix handling of Unicode BOMs (#568906) * Add UTF-8-SIG character encoding for opening and saving files with a UTF-8 signature/BOM * Fix incorrect handling of common error patterns that at worst caused gaupol to hang due to an eternal loop (#581003) * Abort installation if an `intltool-merge` or `msgfmt` call fails * Add messages for raised exceptions 2009-04-13: Gaupol 0.14 ======================= * Add an extension system (documentation to follow later) * Add two extensions: side pane and bookmarks * Adher to the home directory part of freedesktop.org's XDG Base Directory Specification * Handle reading and writing files with a UTF-8 BOM (#556956) * Save SSA and ASS files with `\N` linebreaks instead of `\n` * Resize columns after running text corrections * Make removing a large amount of subtitles significantly faster * Fix `GtkWarning: GtkSpinButton: setting an adjustment with non-zero page size is deprecated` * Remove deprecated Encoding-field from desktop file * Fix search dialog to not modify obsolete data (#572676) * Fix character count error with Unicode text * Fix updating of filenames in the projects menu * Fix erroneous cleaning of SubRip markup after removing hearing impaired subtitles * Fix open dialog file filter to list files with upper- and mixed case extensions as well * Fix AssertionError when installing multiple times * Switch version-control systems from subversion to git 2008-09-17: Gaupol 0.13.1 ========================= * Fix error saving subtitle files when trying to quit with unsaved changes in multiple documents (#552129) * Add all open projects as a target to the position shift dialog * Remove redundant tags with the SubRip format when doing automatic text corrections, e.g. removing hearing impaired texts 2008-08-30: Gaupol 0.13 ======================= * Raise PyGTK dependency to 2.12 or greater * Remove misuse of assertions that broke some parts of Gaupol, when used with Python's optimization (`-O` switch) * Preserve additional fields in SSA/ASS files * Preserve coordinate fields in extended SubRip format * By default always use UTF-8 character encoding for preview (#522868, Beni Cherniavsky, Osmo Salomaa) * Allow reordering of columns * Resize columns when their visibility is toggled * Allow comments (starting with number signs) in pattern files * Allow grouping of correction patterns under the same name * Improve commmon error patterns for spaces around quote marks * Fix error with encoding auto-detection (#10278) * Fix error starting spell-check if no dictionary (#10526) * Fix preview error dialog if video player not found (#518981) * Fix subtitle number search after subtitle removals or inserts * Fix error displaying right-click menu in cells (kitone) * Fix IndexError with multiline tags in text cells (#547170) * Fix window type and transientness for preferences dialog * Fix error closing the search dialog from the window titlebar * Fix updating of Alt+NUM shortcut keys * Fix color markup tag conversions with various formats * Fix conversions of font tags with the SubRip format * Replace `--adapt-translation` option with `--align-method` * Replace `--debug` option with using environment variable `GAUPOL_DEBUG` * Add GenericName field to the desktop file * Add mimetypes application/x-subrip, text/x-microdvd, text/x-mpsub, text/x-ssa and text/x-subviewer to the desktop file * Fix spell-check language listing with recent versions of Enchant * Run `update-desktop-database` in `setup.py` if `--root` not given * Move profile directory on Windows to `%APPDATA%/Gaupol` The five digit bug numbers refer to the old bug tracker at Gna and the six digit ones to the new bug tracker at GNOME Bugzilla. 2007-11-03: Gaupol 0.12.3 ========================= * Fix error in splitting frame-based subtitle projects (#10200) * Fix `UnboundLocalError` with preview (#10203) 2007-10-20: Gaupol 0.12.2 ========================= * Fix tag conversions that removed text (#10140) * Fix spacing issues in open and save dialogs 2007-10-02: Gaupol 0.12.1 ========================= * Fix text correction assistant's capitalization task * Fix remaining `NameError`s with function arguments (#10034) 2007-09-29: Gaupol 0.12 ======================= * Add a capitalization task to the text correction assistant * Add "All supported files" filter to the open dialog * Fix error saving after splitting project (#10041) * Fix `NameError`s with lambda functions (#10034) * Fix error opening SubRip file if the first line is blank (#10054) * Fix markup tooltip hack to work with (Py)GTK 2.12 * Remove license page from the Windows installer * Include iso-codes with the Windows installer 2007-09-14: Gaupol 0.11 ======================= * Add a line-break task to the text correction assistant * Add menu-items and keybindings for extending the current selection up to the first or the last subtitle without moving focus or scrolling (#9895) * Add missing "Auto-detected" encoding entry in the file dialogs * Save search history to `$HOME/.gaupol/search` instead of the configuration file to avoid quoting problems * Enable rubber-banding (selection of multiple rows by dragging the mouse) in the subtitle list * Add support for creating a Windows `.exe` with py2exe and a Windows installer with Inno Setup 2007-08-20: Gaupol 0.10 ======================= * Add a common error correction task for the text assistant * Fix default values of two configuration variables * Fix a selection bug in the text assistant confirmation page * Fix tag parsing error with multiple sets of tags on one line * Fix text cell renderer font sizes on Windows * Fix web browser launch on Windows * Fix recent file URI handling on Windows * Fix preview on Windows * Fix temporary file removals on Windows 2007-08-07: Gaupol 0.9 ====================== * Raise Python dependency to 2.5.1 or greater (#9685, this should have been done already for 0.8.) * Add a text correction assistant (Tools / Correct Texts) * Add a hearing impaired text removal task for the text correction assistant * Fix notification issue, which caused at least that in some cases the tab labels and the window title didn't update * Add quoting for number signs in the configuration file to avoid them being misinterpreted as in-line comments * For reading and writing non-xml files in `$HOME/.gaupol`, always try the locale encoding first and if it fails, use UTF-8 2007-07-09: Gaupol 0.8 ====================== * Python dependency raised to 2.5 or greater * PyGTK dependency raised to 2.10 or greater * License changed to GPL v3 or later * Configuration file backend and syntax changed; old configurations are discareded * Line lengths optionally shown on all text elements * Allow negative values in time and frame cells * Better (more preserving) handling of blank lines as well as leading and trailing spaces when opening files * Fixed numerous bugs with find and replace, especially when searching for zero-length regular expressions * Notify of invalid regular expressions when searching (#6690) * Regular expression searches are now always MULTILINE and DOTALL * Search notifications moved to main window's statusbar * Migrated to `gtk.RecentManager` and `gtk.RecentChooser` * Added a menu for recent translation files * Added "Text" menu to replace "Format", "Search" and part of "Edit" * Simplified and changed several keycombos * Tabs can now be freely reordered * Added more informative tooltips on tabs * Fixed cropped close button images on tabs * Redesigned search and spell-check dialogs * Redesigned position tranformation dialog to be less tall * Faster updates when inserting and removing subtitles * Subtitle number search now starts only on numeric key-presses * Use per-stream options (`:option` instead of `--option`) in default VLC preview command * Subtitle file and video file paths in preview commands are now automatically escaped and quoted * Use exact framerates in calculations (e.g. 24000/1001) and rounded integers in the user interface (e.g. 24) * Splitting a subtitle no longer duplicates texts * Position shift amount now always defaults to zero * Fixed a bug in the time entry validation * Fixed sensitivity of "Adjust Positions..." menu item (#7255) * Show confirmation dialog when closing a file that no longer exists * Applied GNOME Goal #3: Remove "Application" category from desktop files * Changed icon colors have a bit more contrast * SRTX support dropped * Added `--config-file`, `--debug`, `--encoding`, `--list-encodings`, `--translation-file`, `--adapt-translation`, `--video-file` and `+[NUM]` options * Added a manual page to document all options * Fixed translatable strings with multiple arguments in python files to use named fields and mappings * Source code directory structure changed * Uninstallation feature removed 2006-09-18: Gaupol 0.7.1 ======================== * Fixed cell renderers to work with GTK and PyGTK 2.10 * Fixed MicroDVD tag conversion errors (Bug #6938) * Fixed issue of disappearing tags when converting case * Polish (pl) 2006-07-11: Gaupol 0.7.0 ======================== * Append file * Split project * Fixed error opening file if no locale encoding set (bug #6319) * Catch `OSError` in case saving file fails and temporary backup copy is restored (bug #6316) * Fixed error launching preview if no column focused * Improved blank line handling of subtitle merge * `setup.py`: `AUTHORS`, `COPYING` and `README` files no longer installed 2006-07-07: Gaupol 0.6.0 ======================== * Subtitle split and merge * Smarter translation file opening * Show `.srtx` files as images * Support TMPlayer subtitle file format * Copy-paste now works from one project to another * Fixed target radio button defaults in case of no selection * Changed some keybindings * `setup.py`: Fixed paths module generation in case `--root` option given with a trailing directory separator 2006-06-28: Gaupol 0.5.0 ======================== * Find and replace, including regular expressions * Character encoding auto-detection * Support MPlayer's MPsub subtitle file format * New icon, as both PNG and SVG * Applied GNOME Goal 2.1: Install theme-friendly icons * Icon field in the desktop file no longer contains extension * Warning dialog displayed if opening unsorted file * Separate, locally overridable, header template files * Support MicroDVD headers ("{DEFAULT}{}{...}" lines) * Time decimal changed from comma (",") to period (".") * Framerate conversion available for time-based subs as well * Dialogs are again resizable to be smaller * Fixed spell-check recursion bugs * Fixed bug #6235: double-click on subtitle item cause exception * "Unselect All" menu item removed * "Save A Copy..." menu items removed * Unified target specifications in dialogs * Spell-check suggestion list now scrolls to top with new word * Gaupol no longer hangs if video player not closed before exit * Debug dialog no longer fails to start if PyEnchant not installed * Video selection dialog's file filter now defaults to video * Support default browsers on KDE and Mac OSX as well * Better video player defaults on Windows * Testing framework made compatible with py.test * Desktop file strings are now translated in .po files * Developer-specific options to gaupol made into separate scripts * `setup.cfg` no longer specifies prefix or optimization * Added clean command to `setup.py` * General polish here and there * Psyco no longer used * New optional dependency of Universal Encoding Detector (chardet) * Polish (pl) 2006-05-04: Gaupol 0.4.1 ======================== * #5880: Framerate conversion returns an error * Miguel Latorre: Spanish (es) 2006-03-10: Gaupol 0.4.0 ======================== * Time shift * Time adjustment * Duration adjustment * Framerate conversion * Partial support for SSA & ASS formats * Various errors in Micro DVD tag conversions * Newline counted as a character in text length statusbar * Rounding errors when undoing after having edited in unnative mode * Template header not written when converting to SubViewer 2.0 format * Distutils commands `sdist` and `bdist_*` broken * Gil Forcada: Catalan (ca) 2006-01-22: Gaupol 0.3.4 ======================== * Support SubViewer 2.0 format * Start-up fails if PyEnchant is not installed * Spell-check "Join Forward" button does not work 2006-01-20: Gaupol 0.3.3 ======================== * Preview current data instead of saved file * Allow selecting arbitrary video file * New toolbar for video * New window for video player output * Pre-configured commands for more than one video player * Spell-check not working with new PyEnchant releases 1.1.4 and 1.1.5 * File marked unchanged after saving a copy of it * Overwrite dialog not always presented when saving * Open button on the main toolbar missing tooltip * Open dialog not always defaulting to directory of last opened file 2006-01-12: Gaupol 0.3.2 ======================== * #5046: MPlayer freezes in preview 2006-01-11: Gaupol 0.3.1 ======================== * Save file before preview only if the file is changed * Have the spell-check dialog use the customizable editor font 2006-01-10: Gaupol 0.3.0 ======================== * Preview function * Smarter dialog sizes * Spell-check menu- and toolbar items grayed out when shouldn't * Unexpected exits return value 0 * Exception not raised when version check fails on `IOError` * Toggling dialog lines fails if document is unsaved * Italicization menu item not grayed out when document is unsaved 2006-01-02: Gaupol 0.2.0 ======================== * Spell-check * Debug dialog * Ability to try multiple character encodings when opening a file * Opening multiple files at once with the open dialog * Moving to edit an adjacent cell with Alt+Arrow keys * Smarter uninstallation * PyGTK dependency raised to 2.8 * Introduced PyEnchant 1.1.3 dependency * Introduced optional iso-codes dependency * Finnish (fi) translation removed Lots of code has been redesigned and rewritten. Most importantly the undo/redo system, the configuration module and all GUI building and updating functions have been rewritten. Separation between base and gtk modules is now far more sensible and should better suit possible alternative user interfaces. 2005-08-27: Gaupol 0.1.1 ======================== * Bug #2816: Settings not being saved. * Write correct version number to config file. 2005-08-25: Gaupol 0.1.0 ======================== Initial release. gaupol-1.11/README.aeidon.md000066400000000000000000000033701422217132500154420ustar00rootroot00000000000000Python Package aeidon for Subtitles =================================== [![PyPI](https://img.shields.io/pypi/v/aeidon.svg)](https://pypi.org/project/aeidon/) [![Downloads](https://pepy.tech/badge/aeidon/month)](https://pepy.tech/project/aeidon) aeidon is a Python package that provides classes and functions for dealing with text-based subtitle files of many different formats. Functions exist for reading and writing subtitle files as well as manipulating subtitle data, i.e. positions (times or frames) and texts. ## Installation The latest stable release is available via PyPI. ```bash pip install -U aeidon ``` ## Documentation https://otsaloma.io/gaupol/doc/api/aeidon.html ## Distro-Packaging When packaging both aeidon and gaupol in a Linux distro, it's best to use the switches in the main `setup.py` for a consistent whole. sudo python3 setup.py --without-gaupol install --prefix=/usr/local sudo python3 setup.py --without-aeidon install --prefix=/usr/local Note that the `--with-*` and `--without-*` are global options and must be placed before any commands. Of the dependencies listed in the [`README.md`](README.md) file, iso-codes and chardet are to be associated with aeidon. If aeidon is installed using the `--without-iso-codes` switch, then iso-codes is required instead of optional. gaupol should depend on the remaining dependencies as well as aeidon of the same version. ## History The aeidon package is part of the Gaupol subtitle editor, where the other package, gaupol, provides the GTK user interface. Separating a user interface independent general-purpose subtitle editing package from Gaupol has been an afterthought and thus not well designed to be a reusable component, but on the other hand is proven, working and maintained code. gaupol-1.11/README.md000066400000000000000000000064751422217132500142150ustar00rootroot00000000000000Gaupol ====== [![Test](https://github.com/otsaloma/gaupol/workflows/Test/badge.svg)](https://github.com/otsaloma/gaupol/actions) [![Packages](https://repology.org/badge/tiny-repos/gaupol.svg)](https://repology.org/metapackage/gaupol) [![Flathub](https://img.shields.io/badge/download-flathub-blue.svg)](https://flathub.org/apps/details/io.otsaloma.gaupol) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/otsaloma/gaupol) Gaupol is an editor for text-based subtitle files. It supports multiple subtitle file formats and provides means of creating, editing and translating subtitles and timing subtitles to match video. Gaupol also includes `aeidon`, a separately installable general-purpose Python package for reading, writing and manipulating text-based subtitle files. See [`README.aeidon.md`](README.aeidon.md) for details. ## Installing ### Linux #### Packages Gaupol is packaged for most of the popular [distros][], so easiest is to install via your distro's package management. If not packaged for your distro or you need a newer version than packaged, read below on how to install from Flatpak or the source code. [distros]: https://repology.org/metapackage/gaupol #### Flatpak Stable releases are available via [Flathub][]. The development version can be installed by running command `make install` under the `flatpak` directory. You need make, flatpak-builder and gettext to build the Flatpak. [Flathub]: https://flathub.org/apps/details/io.otsaloma.gaupol #### Source Gaupol requires Python ≥ 3.2, PyGObject ≥ 3.12 and GTK ≥ 3.12. Additionally, during installation you need gettext. Optional, but strongly recommended dependencies include: | Dependency | Version | Required for | | :--------- | :------ | :----------- | | [GStreamer](https://gstreamer.freedesktop.org/) | ≥ 1.6 | integrated video player | | [gspell](https://wiki.gnome.org/Projects/gspell) | ≥ 1.0.0 | spell-check | | [iso-codes](https://salsa.debian.org/iso-codes-team/iso-codes) | ≥ 3.67 | translations | | [chardet](https://github.com/chardet/chardet) | ≥ 2.2.1 | character encoding auto-detection | From GStreamer you need at least the core, gst-plugins-base, gst-plugins-good and gst-plugins-bad; and for good container and codec support preferrably both of gst-plugins-ugly and gst-libav. On Debian/Ubuntu you can install the dependencies with the following command. sudo apt install gettext \ gir1.2-gspell-1 \ gir1.2-gst-plugins-base-1.0 \ gir1.2-gstreamer-1.0 \ gir1.2-gtk-3.0 \ gstreamer1.0-gtk3 \ gstreamer1.0-libav \ gstreamer1.0-plugins-bad \ gstreamer1.0-plugins-good \ gstreamer1.0-plugins-ugly \ iso-codes \ python3 \ python3-chardet \ python3-dev \ python3-gi \ python3-gi-cairo Then, to install Gaupol, run command sudo python3 setup.py install --prefix=/usr/local ### Windows Windows installers are no longer built due to bad tooling, bad results, lack of time and lack of motivation. The latest version available for Windows is [1.3.1][]. [1.3.1]: https://github.com/otsaloma/gaupol/releases/tag/1.3.1 gaupol-1.11/aeidon/000077500000000000000000000000001422217132500141615ustar00rootroot00000000000000gaupol-1.11/aeidon/__init__.py000066400000000000000000000115631422217132500163000ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """ Reading, writing and manipulating text-based subtitle files. :mod:`aeidon` is a Python package that provides classes and functions for dealing with text-based subtitle files of many different formats. Functions exist for reading and writing subtitle files as well as manipulating subtitle data, i.e. positions (times or frames) and texts. Two examples of basic use of the :mod:`aeidon` package follow below. Converting a file from the SubRip format to the MicroDVD format:: project = aeidon.Project() project.open_main("/path/to/file.srt", "utf_8") project.set_framerate(aeidon.framerates.FPS_23_976) project.save_main(aeidon.files.new(aeidon.formats.MICRODVD, "/path/to/file.sub", "utf_8")) Making all subtitles in a file appear two seconds earlier:: project = aeidon.Project() project.open_main("/path/to/file.srt", "utf_8") project.shift_positions(None, aeidon.as_seconds(-2)) project.save_main() :mod:`aeidon` handles positions as either times (as strings of form ``HH:MM:SS.SSS``), frames (as integers) or in some cases seconds (as floats). All these can be used with functions that edit subtitle data regardless of what the native position type of the file format used is. :mod:`aeidon` handles two separate documents that comprise a project -- a main and a translation document. These correspond to separate files, but the subtitles are common since positions are shared. :mod:`aeidon` includes an undo/redo-system. Any subtitle data-editing methods of :class:`aeidon.Project` (ones marked with the :func:`aeidon.deco.revertable` decorator) can be undone and redone. If using :mod:`aeidon` in a context where reverting actions is never needed, greater flexibility can be achieved by accessing the subtitles directly (via :attr:`aeidon.Project.subtitles`). :var CONFIG_HOME_DIR: Path to the user's local configuration directory :var DATA_DIR: Path to the global data directory :var DATA_HOME_DIR: Path to the user's local data directory :var LOCALE_DIR: Path to the global locale directory :var RE_ANY_TAG: Regular expression for markup tags of any format :var align_methods: Enumerations for subtitle align methods :var documents: Enumerations for document types :var formats: Enumerations for subtitle file format types :var framerates: Enumerations for framerate types :var modes: Enumerations for position unit types :var newlines: Enumerations for newline character types :var players: Enumerations for video player application types :var registers: Enumerations for action action reversion register types """ import re import sys __version__ = "1.11" RUNNING_SPHINX = (sys.argv[0].endswith("autogen.py") or sys.argv[0].endswith("sphinx-build")) RE_ANY_TAG = re.compile(r"(^[/\\_]+|<.*?>|\{.*?\})") try: import gi gi.require_version("Gspell", "1") except Exception: pass from aeidon.paths import * # noqa from aeidon.position import * # noqa from aeidon import deco # noqa from aeidon import i18n # noqa from aeidon import util # noqa from aeidon import temp # noqa from aeidon.delegate import * # noqa from aeidon.singleton import * # noqa from aeidon.mutables import * # noqa from aeidon.observable import * # noqa from aeidon.errors import * # noqa from aeidon.enum import * # noqa from aeidon.enums import * # noqa from aeidon import encodings # noqa from aeidon import languages # noqa from aeidon import countries # noqa from aeidon import locales # noqa from aeidon import scripts # noqa from aeidon.metadata import * # noqa from aeidon.calculator import * # noqa from aeidon.finder import * # noqa from aeidon.parser import * # noqa from aeidon.liner import * # noqa from aeidon import containers # noqa from aeidon.subtitle import * # noqa from aeidon.file import * # noqa from aeidon import files # noqa from aeidon.markup import * # noqa from aeidon import markups # noqa from aeidon.markupconv import * # noqa from aeidon.pattern import * # noqa from aeidon.patternman import * # noqa from aeidon.clipboard import * # noqa from aeidon.revertable import * # noqa from aeidon.spell import * # noqa from aeidon import agents # noqa from aeidon.project import * # noqa from aeidon.unittest import * # noqa gaupol-1.11/aeidon/agents/000077500000000000000000000000001422217132500154425ustar00rootroot00000000000000gaupol-1.11/aeidon/agents/__init__.py000066400000000000000000000024521422217132500175560ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2006 Osmo Salomaa # # 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 . """Data editing extension delegates of :class:`aeidon.Project`.""" from .clipboard import ClipboardAgent # noqa from .edit import EditAgent # noqa from .format import FormatAgent # noqa from .open import OpenAgent # noqa from .position import PositionAgent # noqa from .preview import PreviewAgent # noqa from .register import RegisterAgent # noqa from .save import SaveAgent # noqa from .search import SearchAgent # noqa from .set import SetAgent # noqa from .text import TextAgent # noqa from .util import UtilityAgent # noqa __all__ = tuple(x for x in dir() if x.endswith("Agent")) gaupol-1.11/aeidon/agents/clipboard.py000066400000000000000000000045321422217132500177570ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Storing text to the clipboard and pasting from it.""" import aeidon from aeidon.i18n import _ class ClipboardAgent(aeidon.Delegate): """Storing text to the clipboard and pasting from it.""" @aeidon.deco.export def copy_texts(self, indices, doc): """Copy texts to the clipboard.""" self.clipboard.clear() for index in range(min(indices), max(indices) + 1): subtitle = self.subtitles[index] text = subtitle.get_text(doc) if index in indices else None self.clipboard.append(text) @aeidon.deco.export @aeidon.deco.revertable def cut_texts(self, indices, doc, register=-1): """Cut texts to the clipboard.""" self.copy_texts(indices, doc) self.clear_texts(indices, doc, register=register) self.set_action_description(register, _("Cutting texts")) @aeidon.deco.export @aeidon.deco.revertable def paste_texts(self, index, doc, register=-1): """Paste texts from the clipboard and return pasted indices.""" texts = self.clipboard.get_texts() length = len(self.subtitles) new_count = len(texts) - (length - index) if new_count > 0: indices = list(range(length, length + new_count)) self.insert_subtitles(indices, register=register) indices = [index+i for i in range(len(texts)) if texts[i] is not None] new_texts = [x for x in texts if x is not None] self.replace_texts(indices, doc, new_texts, register=register) if new_count > 0: self.group_actions(register, 2, "") self.set_action_description(register, _("Pasting texts")) return tuple(indices) gaupol-1.11/aeidon/agents/edit.py000066400000000000000000000164341422217132500167510ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Basic editing of entire subtitles.""" import aeidon from aeidon.i18n import _ class EditAgent(aeidon.Delegate): """Basic editing of entire subtitles.""" @aeidon.deco.export @aeidon.deco.revertable def clear_texts(self, indices, doc, register=-1): """Set texts to blank strings.""" new_texts = [""] * len(indices) self.replace_texts(indices, doc, new_texts, register=register) self.set_action_description(register, _("Clearing texts")) @aeidon.deco.revertable @aeidon.deco.notify_frozen def _insert_blank_subtitles(self, indices, register=-1): """Insert new blank subtitles at `indices`.""" for rindices in aeidon.util.get_ranges(indices): first_start = 0.0 if self.subtitles: start = self.subtitles[0].start_seconds first_start = 0.0 if start >= 0 else start - 3.0 if rindices[0] > 0: subtitle = self.subtitles[rindices[0] - 1] first_start = subtitle.end_seconds duration = 3.0 if rindices[0] < len(self.subtitles): subtitle = self.subtitles[rindices[0]] window = subtitle.start_seconds - first_start duration = window / len(rindices) for i, index in enumerate(rindices): subtitle = self.new_subtitle() subtitle.start_seconds = first_start + i*duration subtitle.duration_seconds = duration self.subtitles.insert(index, subtitle) action = aeidon.RevertableAction(register=register) action.docs = tuple(aeidon.documents) action.description = _("Inserting subtitles") action.revert_function = self.remove_subtitles action.revert_args = (indices,) self.register_action(action) self.emit("subtitles-inserted", indices) @aeidon.deco.export @aeidon.deco.revertable @aeidon.deco.notify_frozen def insert_subtitles(self, indices, subtitles=None, register=-1): """Insert `subtitles` at `indices`. If `subtitles` is ``None``, insert blank subtitles at `indices` with equal durations within time window before the next subtitle or with 3 second durations if inserting subtitles at the end. """ if subtitles is None: return self._insert_blank_subtitles(indices, register=register) for i, index in enumerate(indices): self.subtitles.insert(index, subtitles[i]) action = aeidon.RevertableAction(register=register) action.docs = tuple(aeidon.documents) action.description = _("Inserting subtitles") action.revert_function = self.remove_subtitles action.revert_args = (indices,) self.register_action(action) self.emit("subtitles-inserted", indices) @aeidon.deco.export @aeidon.deco.revertable def merge_subtitles(self, indices, register=-1): """Merge subtitles at `indices` to form one subtitle.""" indices = sorted(indices) subtitle = self.new_subtitle() subtitle.start = self.subtitles[indices[0]].start subtitle.end = self.subtitles[indices[-1]].end main_texts = [self.subtitles[i].main_text for i in indices] tran_texts = [self.subtitles[x].tran_text for x in indices] subtitle.main_text = "\n".join(filter(None, main_texts)) subtitle.tran_text = "\n".join(filter(None, tran_texts)) self.remove_subtitles(indices, register=register) self.insert_subtitles([indices[0]], [subtitle], register=register) self.group_actions(register, 2, _("Merging subtitles")) @aeidon.deco.export @aeidon.deco.revertable @aeidon.deco.notify_frozen def remove_subtitles(self, indices, register=-1): """Remove subtitles at `indices`.""" indices = sorted(indices) subtitles = [self.subtitles.pop(i) for i in reversed(indices)][::-1] action = aeidon.RevertableAction(register=register) action.docs = tuple(aeidon.documents) action.description = _("Removing subtitles") action.revert_function = self.insert_subtitles action.revert_args = (indices, subtitles) self.register_action(action) self.emit("subtitles-removed", indices) @aeidon.deco.export @aeidon.deco.revertable @aeidon.deco.notify_frozen def replace_positions(self, indices, subtitles, register=-1): """Replace positions at `indices` with those from `subtitles`.""" orig_subtitles = [self.subtitles[i].copy() for i in indices] for i, index in enumerate(indices): self.subtitles[index].start = subtitles[i].start self.subtitles[index].end = subtitles[i].end action = aeidon.RevertableAction(register=register) action.docs = tuple(aeidon.documents) action.description = _("Replacing positions") action.revert_function = self.replace_positions action.revert_args = (indices, orig_subtitles) self.register_action(action) self.emit("positions-changed", indices) @aeidon.deco.export @aeidon.deco.revertable @aeidon.deco.notify_frozen def replace_texts(self, indices, doc, texts, register=-1): """Replace texts in `doc`'s `indices` with `texts`.""" orig_texts = [self.subtitles[i].get_text(doc) for i in indices] for i, index in enumerate(indices): self.subtitles[index].set_text(doc, texts[i]) action = aeidon.RevertableAction(register=register) action.docs = (doc,) action.description = _("Replacing texts") action.revert_function = self.replace_texts action.revert_args = (indices, doc, orig_texts) self.register_action(action) self.emit(self.get_text_signal(doc), indices) @aeidon.deco.export @aeidon.deco.revertable def split_subtitle(self, index, register=-1): """Split subtitle in two equal duration ones.""" subtitle = self.subtitles[index] middle = self.calc.get_middle(subtitle.start, subtitle.end) subtitle_1 = self.new_subtitle() subtitle_1.start = subtitle.start subtitle_1.end = middle subtitle_1.main_text = subtitle.main_text subtitle_1.tran_text = subtitle.tran_text subtitle_2 = self.new_subtitle() subtitle_2.start = middle subtitle_2.end = subtitle.end self.remove_subtitles((index,), register=register) indices = (index, index + 1) subtitles = (subtitle_1, subtitle_2) self.insert_subtitles(indices, subtitles, register=register) self.group_actions(register, 2, _("Splitting subtitle")) gaupol-1.11/aeidon/agents/format.py000066400000000000000000000154431422217132500173130ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Changing the appearance of texts.""" import aeidon import re from aeidon.i18n import _ class FormatAgent(aeidon.Delegate): """Changing the appearance of texts.""" _re_alphanum = re.compile(r"\w") @aeidon.deco.export @aeidon.deco.revertable def add_dialogue_dashes(self, indices, doc, register=-1): """Add dialogue dashes to all lines of texts.""" new_texts = [] parser = self.get_parser(doc) for index in indices: subtitle = self.subtitles[index] parser.set_text(subtitle.get_text(doc)) parser.set_regex(r"^[\-\–\—]\s*") parser.replacement = "" parser.replace_all() parser.set_regex(r"^") parser.replacement = r"- " parser.replace_all() new_texts.append(parser.get_text()) self.replace_texts(indices, doc, new_texts, register=register) self.set_action_description(register, _("Adding dialogue dashes")) @aeidon.deco.export @aeidon.deco.revertable def change_case(self, indices, doc, method, register=-1): """ Change the case of texts with `method`. `method` should be a string: either "title", "capitalize", "upper" or "lower", which correspond to the built-in Python string methods. """ new_texts = [] parser = self.get_parser(doc) for index in indices: subtitle = self.subtitles[index] parser.set_text(subtitle.get_text(doc)) self._change_case_first(parser, method) new_texts.append(parser.get_text()) self.replace_texts(indices, doc, new_texts, register=register) self.set_action_description(register, _("Changing case")) def _change_case_first(self, parser, method): """Change the case of the alphanumeric substring.""" match = self._re_alphanum.search(parser.text) if match is None: return a = match.start() prefix = parser.text[:a] text = getattr(parser.text[a:], method)() parser.text = prefix + text @aeidon.deco.export @aeidon.deco.revertable def italicize(self, indices, doc, register=-1): """Surround texts with italic markup.""" new_texts = [] markup = self.get_markup(doc) re_italic_tag = markup.italic_tag for index in indices: text = self.subtitles[index].get_text(doc) text = re_italic_tag.sub("", text) text = markup.italicize(text) new_texts.append(text) self.replace_texts(indices, doc, new_texts, register=register) self.set_action_description(register, _("Italicizing")) @aeidon.deco.export @aeidon.deco.revertable def remove_dialogue_dashes(self, indices, doc, register=-1): """Remove dialogue dashes from all lines of texts.""" new_texts = [] parser = self.get_parser(doc) for index in indices: subtitle = self.subtitles[index] parser.set_text(subtitle.get_text(doc)) parser.set_regex(r"^[\-\–\—]\s*") parser.replacement = "" parser.replace_all() new_texts.append(parser.get_text()) self.replace_texts(indices, doc, new_texts, register=register) self.set_action_description(register, _("Removing dialogue dashes")) def _should_add_dialogue_dashes(self, indices, doc): """Return ``True`` if dialogue dashes should be added to texts.""" re_tag = self.get_markup_tag_regex(doc) for index in indices: text = self.subtitles[index].get_text(doc) for line in text.split("\n"): # Strip all tags from line. # If leftover doesn't start with "-", # dialogue dashes should be added. if re_tag is not None: line = re_tag.sub("", line) if not line.startswith("-"): return True return False def _should_italicize(self, indices, doc): """Return ``True`` if texts should be italicized.""" re_tag = self.get_markup_tag_regex(doc) markup = self.get_markup(doc) re_italic_tag = markup.italic_tag for index in indices: text = self.subtitles[index].get_text(doc) # Remove tags from the start of the text, # ending after all tags are removed # or when an italic tag is found. if re_tag is not None: while re_tag.match(text) is not None: if re_italic_tag.match(text) is not None: break text = re_tag.sub("", text, 1) # If there is no italic tag at the start of the text, # all texts should be italicized. if re_italic_tag.match(text) is None: return True return False @aeidon.deco.export @aeidon.deco.revertable def toggle_dialogue_dashes(self, indices, doc, register=-1): """Show or hide dialogue dashes on texts.""" if self._should_add_dialogue_dashes(indices, doc): return self.add_dialogue_dashes(indices, doc, register=register) return self.remove_dialogue_dashes(indices, doc, register=register) @aeidon.deco.export @aeidon.deco.revertable def toggle_italicization(self, indices, doc, register=-1): """Add or remove italic markup surrounding texts.""" if self._should_italicize(indices, doc): return self.italicize(indices, doc, register=register) return self.unitalicize(indices, doc, register=register) @aeidon.deco.export @aeidon.deco.revertable def unitalicize(self, indices, doc, register=-1): """Remove any italic markup surrounding texts.""" new_texts = [] markup = self.get_markup(doc) re_italic_tag = markup.italic_tag for index in indices: text = self.subtitles[index].get_text(doc) text = re_italic_tag.sub("", text) new_texts.append(text) self.replace_texts(indices, doc, new_texts, register=register) self.set_action_description(register, _("Unitalicizing")) gaupol-1.11/aeidon/agents/open.py000066400000000000000000000202621422217132500167570ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Reading and parsing data from subtitle files.""" import aeidon import bisect class OpenAgent(aeidon.Delegate): """Reading and parsing data from subtitle files.""" def _align_translations_by_number(self, subtitles): """Add translation texts by aligning subtitle numbers.""" indices = list(range(len(self.subtitles), len(subtitles))) self.insert_subtitles(indices, register=None) for i, subtitle in enumerate(subtitles): self.subtitles[i].tran_text = subtitle.main_text def _align_translations_by_position(self, subtitles): """Add translation texts by aligning subtitle positions.""" subtitles = [x.copy() for x in subtitles] mode = self.main_file.mode i = 0 while subtitles: # Examine subtitles to be added one-by-one by comparing # their temporal middle positions with the start and end # positions of existing subtitles. ts = subtitles[0].get_start(mode) te = subtitles[0].get_end(mode) tm = self.calc.get_middle(ts, te) while True: # Skip over existing subtitles when # no suitable match found among translations. if i == len(self.subtitles): break ms = self.subtitles[i].get_start(mode) me = self.subtitles[i].get_end(mode) if not self.calc.is_earlier(me, tm): break i += 1 if i == len(self.subtitles) or self.calc.is_later(ms, tm): # Add a new subtitle when no suitable match # found among existing subtitles. subtitle = self.new_subtitle() subtitle.start = subtitles[0].start subtitle.end = subtitles[0].end self.subtitles.insert(i, subtitle) self.subtitles[i].tran_text = subtitles[0].main_text subtitles.pop(0) i += 1 @aeidon.deco.export def open(self, doc, path, encoding=None, align_method=None): """ Read and parse subtitle data for `doc` from `path`. `encoding` can be ``None`` to use the system default encoding. Return the amount of subtitles that needed to be moved in order to arrange them in ascending chronological order. Raise :exc:`IOError` if reading fails. Raise :exc:`UnicodeError` if decoding fails. Raise :exc:`aeidon.FormatError` if unable to detect format. Raise :exc:`aeidon.ParseError` if parsing fails. """ if doc == aeidon.documents.MAIN: return self.open_main(path, encoding) if doc == aeidon.documents.TRAN: return self.open_translation(path, encoding, align_method) raise ValueError("Invalid document: {!r}".format(doc)) @aeidon.deco.export @aeidon.deco.notify_frozen def open_main(self, path, encoding=None): """ Read and parse subtitle data for main file from `path`. `encoding` can be ``None`` to use the system default encoding. Return the amount of subtitles that needed to be moved in order to arrange them in ascending chronological order. Raise :exc:`IOError` if reading fails. Raise :exc:`UnicodeError` if decoding fails. Raise :exc:`aeidon.FormatError` if unable to detect format. Raise :exc:`aeidon.ParseError` if parsing fails. """ encoding = encoding or aeidon.util.get_default_encoding() bom_encoding = aeidon.encodings.detect_bom(path) if not bom_encoding in (encoding, None): return self.open_main(path, bom_encoding) format = aeidon.util.detect_format(path, encoding) self.main_file = aeidon.files.new(format, path, encoding) subtitles = self._read_file(self.main_file) self.subtitles, sort_count = self._sort_subtitles(subtitles) self.set_framerate(self.framerate, register=None) self.main_changed = 0 # Deactivate possible translation file. self.tran_file = None self.tran_changed = None self.emit("main-file-opened", self.main_file) return sort_count @aeidon.deco.export @aeidon.deco.notify_frozen def open_translation(self, path, encoding=None, align_method=None): """ Read and parse subtitle data for translation file from `path`. `encoding` can be ``None`` to use the system default encoding. `align_method` specifies how translation texts are attached to existing subtitles. :attr:`aeidon.align_methods.NUMBER` is the simple way, which adds the translation texts in order, one-by-one to the exising subtitles. :attr:`aeidon.align_methods.POSITION` (the default) is the smarter way, which compares the position data in the translation subtitles with the existing subtitles, skips and inserts subtitles as needed to have at least a rough chronological match. The latter thus takes into account that not all subtitles are translated, or vice versa and that one main subtitle may correspond to two translation subtitles, or vice versa, as per length restrictions etc. Return the amount of subtitles that needed to be moved in order to arrange them in ascending chronological order. Raise :exc:`IOError` if reading fails. Raise :exc:`UnicodeError` if decoding fails. Raise :exc:`aeidon.FormatError` if unable to detect format. Raise :exc:`aeidon.ParseError` if parsing fails. """ encoding = encoding or aeidon.util.get_default_encoding() align_method = align_method or aeidon.align_methods.POSITION bom_encoding = aeidon.encodings.detect_bom(path) if not bom_encoding in (encoding, None): return self.open_translation(path, bom_encoding, align_method) format = aeidon.util.detect_format(path, encoding) self.tran_file = aeidon.files.new(format, path, encoding) subtitles = self._read_file(self.tran_file) subtitles, sort_count = self._sort_subtitles(subtitles) for subtitle in subtitles: subtitle.framerate = self.framerate for subtitle in self.subtitles: subtitle.tran_text = "" blocked = self.block("subtitles-inserted") if align_method == aeidon.align_methods.NUMBER: self._align_translations_by_number(subtitles) if align_method == aeidon.align_methods.POSITION: self._align_translations_by_position(subtitles) self.unblock("subtitles-inserted", blocked) self.tran_changed = 0 self.emit("translation-file-opened", self.tran_file) return sort_count def _read_file(self, file): """Read `file` and return subtitles.""" try: return file.read() except (IOError, UnicodeError): raise except Exception: # It's difficult to tell the difference between a syntactic # problem in the file to be read and a bug in our own parsing # code. Raise both as parse errors. raise aeidon.ParseError("Failed to parse file {!r}" .format(file.path)) def _sort_subtitles(self, subtitles): """Return sorted `subtitles` and sort count.""" sort_count = 0 sorted_starts = [] for start in (x.start_frame for x in subtitles): bisect.insort(sorted_starts, start) if sorted_starts[-1] != start: sort_count += 1 return sorted(subtitles), sort_count gaupol-1.11/aeidon/agents/position.py000066400000000000000000000177621422217132500176750ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Manipulating times and frames.""" import aeidon from aeidon.i18n import _ class PositionAgent(aeidon.Delegate): """Manipulating times and frames.""" @aeidon.deco.export @aeidon.deco.revertable def adjust_durations(self, indices=None, speed=None, lengthen=False, shorten=False, minimum=None, maximum=None, gap=None, register=-1): """ Lengthen or shorten durations by changing end positions. `indices` can be ``None`` to process all subtitles. `speed` is reading speed in characters per second. `lengthen` is ``True`` to increase durations to match reading speed. `shorten` is ``True`` to decrease durations to match reading speed. `maximum` is the longest allowed duration in seconds. `minimum` is the shortest allowed duration in seconds. `gap` is seconds to be left between consecutive subtitles. Using a gap of at least zero is always a good idea if overlapping is not desired. Return changed indices. """ new_indices = [] new_subtitles = [] for index in indices or self.get_all_indices(): start = self.subtitles[index].start_seconds end = self.subtitles[index].end_seconds if speed is not None: length = self.get_text_length(index, aeidon.documents.MAIN) optimal_duration = length / speed dol = lengthen and end - start < optimal_duration dos = shorten and end - start > optimal_duration end = start + optimal_duration if dol or dos else end domin = minimum and end - start < minimum domax = maximum and end - start > maximum end = start + minimum if domin else end end = start + maximum if domax else end end_max = (self.subtitles[index + 1].start_seconds if index < len(self.subtitles) - 1 else 360000) dogap = gap is not None and end_max - end < gap end = max(start, end_max - gap) if dogap else end if end != self.subtitles[index].end_seconds: new_indices.append(index) subtitle = self.subtitles[index].copy() subtitle.end_seconds = end new_subtitles.append(subtitle) if not new_indices: return [] self.replace_positions(new_indices, new_subtitles, register=register) self.set_action_description(register, _("Adjusting durations")) return new_indices @aeidon.deco.export @aeidon.deco.revertable def convert_framerate(self, indices, framerate_in, framerate_out, register=-1): """ Set the value of framerate and convert subtitles to it. `indices` can be ``None`` to process all subtitles. `framerate_in` and `framerate_out` should be constants from :attr:`aeidon.framerates`. """ new_subtitles = [] indices = indices or self.get_all_indices() self.set_framerate(framerate_in, register=None) for index in indices: subtitle = self.subtitles[index].copy() subtitle.convert_framerate(framerate_out) new_subtitles.append(subtitle) self.set_framerate(framerate_out) self.replace_positions(indices, new_subtitles, register=register) self.group_actions(register, 2, _("Converting framerate")) def _get_frame_transform(self, p1, p2): """Return a formula for linear correction of positions.""" # Think of this as a linear transformation where input positions # are located on the x-axis and output positions on the y-axis. x1 = self.subtitles[p1[0]].start_frame x2 = self.subtitles[p2[0]].start_frame y1 = p1[1] y2 = p2[1] coefficient = (y2 - y1) / (x2 - x1) constant = int(round(-coefficient * x1 + y1, 0)) return coefficient, constant def _get_seconds_transform(self, p1, p2): """Return a formula for linear correction of positions.""" # Think of this as a linear transformation where input positions # are located on the x-axis and output positions on the y-axis. x1 = self.subtitles[p1[0]].start_seconds x2 = self.subtitles[p2[0]].start_seconds y1 = p1[1] y2 = p2[1] coefficient = (y2 - y1) / (x2 - x1) constant = -coefficient * x1 + y1 return coefficient, constant def _get_time_transform(self, p1, p2): """Return a formula for linear correction of positions.""" p1 = [p1[0], self.calc.time_to_seconds(p1[1])] p2 = [p2[0], self.calc.time_to_seconds(p2[1])] return self._get_seconds_transform(p1, p2) def _get_transform(self, p1, p2): """Return a formula for linear correction of positions.""" if aeidon.is_time(p1[1]): return self._get_time_transform(p1, p2) if aeidon.is_frame(p1[1]): return self._get_frame_transform(p1, p2) if aeidon.is_seconds(p1[1]): return self._get_seconds_transform(p1, p2) raise ValueError("Bad position argument: {!r}".format(p1)) @aeidon.deco.export @aeidon.deco.revertable def set_framerate(self, framerate, register=-1): """Set the value of framerate.""" orig_framerate = self.framerate self.framerate = framerate self.calc = aeidon.Calculator(framerate) for subtitle in self.subtitles: subtitle.framerate = framerate action = aeidon.RevertableAction(register=register) action.docs = tuple(aeidon.documents) action.description = _("Setting framerate") action.revert_function = self.set_framerate action.revert_args = (orig_framerate,) self.register_action(action) @aeidon.deco.export @aeidon.deco.revertable def shift_positions(self, indices, value, register=-1): """ Make subtitles appear earlier or later. `indices` can be ``None`` to process all subtitles. `value` can be any valid position type, negative to make subtitles appear ealier, positive to make subtitles appear later. """ new_subtitles = [] indices = indices or self.get_all_indices() for index in indices: subtitle = self.subtitles[index].copy() subtitle.shift_positions(value) new_subtitles.append(subtitle) self.replace_positions(indices, new_subtitles, register=register) self.set_action_description(register, _("Shifting positions")) @aeidon.deco.export @aeidon.deco.revertable def transform_positions(self, indices, p1, p2, register=-1): """ Change positions by a linear two-point correction. `indices` can be ``None`` to process all subtitles. `p1` and `p2` should be tuples of index, position. """ new_subtitles = [] indices = indices or self.get_all_indices() coefficient, constant = self._get_transform(p1, p2) for index in indices: subtitle = self.subtitles[index].copy() subtitle.scale_positions(coefficient) subtitle.shift_positions(constant) new_subtitles.append(subtitle) self.replace_positions(indices, new_subtitles, register=register) self.set_action_description(register, _("Transforming positions")) gaupol-1.11/aeidon/agents/preview.py000066400000000000000000000105721422217132500175020ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Previewing subtitles with a video player.""" import aeidon import os import string class PreviewAgent(aeidon.Delegate): """Previewing subtitles with a video player.""" def __init__(self, master): """Initialize a :class:`aeidon.PreviewAgent` instance.""" aeidon.Delegate.__init__(self, master) aeidon.util.connect(self, self, "notify::main_file") @aeidon.deco.export def find_video(self): """ Find and return the video file path based on main file's path. The video file is searched for in the same directory as the subtitle file. The subtitle file's filename without extension is assumed to start with or match the video file's filename without extension, e.g. 'movie.avi' for 'movie.en.srt'. """ if self.main_file is None: return None dirname = os.path.dirname(self.main_file.path) subname = os.path.basename(self.main_file.path) for name in os.listdir(dirname): path = os.path.join(dirname, name) root = os.path.splitext(name)[0] if not subname.startswith(root): continue if aeidon.util.is_video_file(path): self.video_path = path return self.video_path return None def _get_subtitle_path(self, doc, encoding=None, temp=False): """ Return path to a file to preview, either real or temporary. Raise :exc:`IOError` if writing to temporary file fails. Raise :exc:`UnicodeError` if encoding temporary file fails. """ file = self.get_file(doc) if file is None or encoding != file.encoding: return self.new_temp_file(doc) if doc == aeidon.documents.MAIN: if not self.main_changed and not temp: return self.main_file.path if doc == aeidon.documents.TRAN: if not self.tran_changed and not temp: return self.tran_file.path return self.new_temp_file(doc) def _on_notify_main_file(self, *args): """Try to find the video file path if unset.""" if self.video_path is None: self.find_video() @aeidon.deco.export def preview(self, position, doc, command, offset, encoding=None, temp=False): """ Start video player with `command` from `position`. `command` can have variables ``$MILLISECONDS``, ``$SECONDS``, ``$SUBFILE`` and ``$VIDEOFILE``. `offset` should be the amount of seconds before `position` to start. `encoding` can be specified if different from `doc` file encoding. Use ``True`` for `temp` to always use a temporary file for preview regardless of whether the file is changed or not. Return a three tuple of :class:`subprocess.POpen` instance, command with variables expanded and a file object to which process standard output and standard error are directed. Raise :exc:`IOError` if writing to temporary file fails. Raise :exc:`UnicodeError` if encoding temporary file fails. Raise :exc:`aeidon.ProcessError` if unable to start process. """ sub_path = self._get_subtitle_path(doc, encoding, temp=temp) fout = open(aeidon.temp.create(".output"), "w") seconds = max(0, self.calc.to_seconds(position) - offset) command = string.Template(command).safe_substitute( MILLISECONDS=("{:.0f}".format(seconds * 1000)), SECONDS=("{:.3f}".format(seconds)), SUBFILE=aeidon.util.shell_quote(sub_path), VIDEOFILE=aeidon.util.shell_quote(self.video_path)) process = aeidon.util.start_process(command, stderr=fout, stdout=fout) return process, command, fout gaupol-1.11/aeidon/agents/register.py000066400000000000000000000200721422217132500176410ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """ Managing revertable actions. To hook a method up with the undo/redo system, the following need to be done: (1) The last argument to the method must be a keyword argument `register` with a default value of -1. This argument indicates which of doing, undoing or redoing is in process. (2) At the end of the method, :meth:`register_action` needs to be called with an instance of :class:`aeidon.RevertableAction`. Calling this method takes care of the management of undo and redo stacks. (3) The method should be marked with the :func:`aeidon.deco.revertable` decorator. This decorator takes care of emitting an action signal once the method has been run, cuts the undo and redo stacks if needed and defaults the `register` keyword argument to :attr:`aeidon.registers.DO`. Each method marked as revertable should match exactly one action in the undo and redo stacks. Hence, if a method calls other revertable methods, the resulting action needs to be grouped as one using :meth:`group_actions`. If a revertable method needs to be performed without the possibility of reverting, the `register` keyword argument should be given a value of ``None``. This way it will not be in any way processed by the undo/redo system. """ import aeidon class RegisterAgent(aeidon.Delegate): """ Managing revertable actions. :ivar _do_description: Original description of the action """ def __init__(self, master): """Initialize a :class:`RegisterAgent` instance.""" aeidon.Delegate.__init__(self, master) self._do_description = None aeidon.util.connect(self, self, "notify::undo_limit") def _break_action_group(self, stack, index=0): """Break the action group in `stack` and return amount broken into.""" action_group = stack.pop(index) for action in reversed(action_group.actions): stack.insert(index, action) return len(action_group.actions) @aeidon.deco.export def can_redo(self, count=1): """Return ``True`` if one or more actions can be redone.""" return len(self.redoables) >= count @aeidon.deco.export def can_undo(self, count=1): """Return ``True`` if one or more actions can be undone.""" return len(self.undoables) >= count @aeidon.deco.export def cut_reversion_stacks(self): """Cut undo and redo stacks to their maximum lengths.""" if self.undo_limit is not None: del self.redoables[self.undo_limit:] del self.undoables[self.undo_limit:] @aeidon.deco.export def emit_action_signal(self, register): """Emit an action signal for the most recent registered action.""" if register is not None: self.emit(register.signal, self._get_destination_stack(register)[0]) def _get_destination_stack(self, register): """Return the stack where the registered action will be placed.""" if register.shift == 1: return self.undoables if register.shift == -1: return self.redoables raise ValueError("Invalid register: {!r}" .format(register)) def _get_source_stack(self, register): """Return the stack where the action to register is taken from.""" if register.shift == 1: return self.redoables if register.shift == -1: return self.undoables raise ValueError("Invalid register: {!r}" .format(register)) @aeidon.deco.export def group_actions(self, register, count, description): """Group the registered actions as one item in the stack.""" if register is None: return action_group = aeidon.RevertableActionGroup() action_group.actions = [] action_group.description = description stack = self._get_destination_stack(register) for i in range(count): action = stack.pop(0) if isinstance(action, aeidon.RevertableActionGroup): action_group.actions.extend(action.actions) else: # Single action action_group.actions.append(action) stack.insert(0, action_group) def _on_notify_undo_limit(self, *args): """Cut reversion stacks if limit set.""" if self.undo_limit is not None: self.cut_reversion_stacks() @aeidon.deco.export def redo(self, count=1): """Redo `count` amount of actions from the redoable stack.""" group = aeidon.RevertableActionGroup if count > 1 or isinstance(self.redoables[0], group): return self._revert_multiple(count, aeidon.registers.REDO) self._do_description = self.redoables[0].description self.redoables.pop(0).revert() @aeidon.deco.export def register_action(self, action): """Register `action` as done, undone or redone.""" if action.register == aeidon.registers.DO: self.undoables.insert(0, action) self.redoables = [] self._shift_changed_value(action, action.register.shift) if action.register == aeidon.registers.UNDO: self.redoables.insert(0, action) action.description = self._do_description self._shift_changed_value(action, action.register.shift) if action.register == aeidon.registers.REDO: self.undoables.insert(0, action) action.description = self._do_description self._shift_changed_value(action, action.register.shift) def _revert_multiple(self, count, register): """Revert multiple actions.""" self.block(register.signal) stack = self._get_source_stack(register) for i in range(count): part_count = 1 if isinstance(stack[0], aeidon.RevertableActionGroup): description = stack[0].description part_count = self._break_action_group(stack) for j in range(part_count): self._do_description = stack[0].description stack.pop(0).revert() if part_count > 1: self.group_actions(register, part_count, description) self.unblock(register.signal) self.cut_reversion_stacks() self.emit_action_signal(register) @aeidon.deco.export def set_action_description(self, register, description): """Set the description of the most recent registered action.""" if register is None: return stack = self._get_destination_stack(register) stack[0].description = description def _shift_changed_value(self, action, shift): """Shift the values of changed attributes.""" if aeidon.documents.MAIN in action.docs: self.main_changed += shift if tuple(action.docs) == (aeidon.documents.TRAN,): # Make translation document active. if self.tran_changed is None: self.tran_changed = 0 if aeidon.documents.TRAN in action.docs: if self.tran_changed is not None: self.tran_changed += shift @aeidon.deco.export def undo(self, count=1): """Undo `count` amount of actions from the undoable stack.""" group = aeidon.RevertableActionGroup if count > 1 or isinstance(self.undoables[0], group): return self._revert_multiple(count, aeidon.registers.UNDO) self._do_description = self.undoables[0].description self.undoables.pop(0).revert() gaupol-1.11/aeidon/agents/save.py000066400000000000000000000103401422217132500167500ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Writing subtitle data to file.""" import aeidon class SaveAgent(aeidon.Delegate): """Writing subtitle data to file.""" def _save(self, doc, file, keep_changes): """ Write subtitle data from `doc` to `file`. Return indices of texts changed due to markup conversion. Raise :exc:`IOError` if writing fails. Raise :exc:`UnicodeError` if encoding fails. """ current_format = self.get_format(doc) orig_texts = [x.get_text(doc) for x in self.subtitles] indices = [] if current_format is not None and file.format != current_format: # Convert markup if saving in different format. converter = aeidon.MarkupConverter(current_format, file.format) for i, subtitle in enumerate(self.subtitles): text = subtitle.get_text(doc) new_text = converter.convert(text) if new_text == text: continue subtitle.set_text(doc, new_text) indices.append(i) file.write(self.subtitles, doc) if keep_changes: return indices for i, subtitle in enumerate(self.subtitles): subtitle.set_text(doc, orig_texts[i]) return [] @aeidon.deco.export def save(self, doc, file=None, keep_changes=True): """ Write subtitle data from `doc` to `file`. `file` can be ``None`` to use existing file. Raise :exc:`IOError` if writing fails. Raise :exc:`UnicodeError` if encoding fails. """ if doc == aeidon.documents.MAIN: return self.save_main(file, keep_changes) if doc == aeidon.documents.TRAN: return self.save_translation(file, keep_changes) raise ValueError("Invalid document: {!r}".format(doc)) @aeidon.deco.export def save_main(self, file=None, keep_changes=True): """ Write subtitle data from main document to `file`. `file` can be ``None`` to use :attr:`main_file`. Raise :exc:`IOError` if writing fails. Raise :exc:`UnicodeError` if encoding fails. """ file = file or self.main_file if file is not None and self.main_file is not None: file.copy_from(self.main_file) indices = self._save(aeidon.documents.MAIN, file, keep_changes) if keep_changes: if (self.main_file is not None and file.mode != self.main_file.mode): # Apply possibly changed mode (times vs. frames). for i, subtitle in enumerate(self.subtitles): subtitle.mode = file.mode self.emit("positions-changed", self.get_all_indices()) self.main_file = file self.main_changed = 0 self.emit("main-texts-changed", indices) self.emit("main-file-saved", file) @aeidon.deco.export def save_translation(self, file=None, keep_changes=True): """ Write subtitle data from translation document to `file`. `file` can be ``None`` to use :attr:`tran_file`. Raise :exc:`IOError` if writing fails. Raise :exc:`UnicodeError` if encoding fails. """ file = file or self.tran_file if file is not None and self.tran_file is not None: file.copy_from(self.tran_file) indices = self._save(aeidon.documents.TRAN, file, keep_changes) if keep_changes: self.tran_file = file self.tran_changed = 0 self.emit("translation-texts-changed", indices) self.emit("translation-file-saved", file) gaupol-1.11/aeidon/agents/search.py000066400000000000000000000260241422217132500172650ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Searching for and replacing text.""" import aeidon import re from aeidon.i18n import _ class SearchAgent(aeidon.Delegate): """ Searching for and replacing text. :ivar _docs: Sequence of :attr:`aeidon.documents` items :ivar _finder: Instance of :class:`aeidon.Finder` used :ivar _match_doc: :attr:`aeidon.documents` item of the last match :ivar _match_passed: ``True`` if the position of last match has been passed :ivar _match_index: Index of the last match :ivar _match_span: Start and end positions of the last match :ivar _indices: Sequence of target indices or ``None`` for all :ivar _wrap: ``True`` to wrap search, ``False`` to stop at the last index Searching is done with the help of an instance of :class:`aeidon.Finder`. This agent provides for looping over the subtitles and their texts, feeding those texts to the finder and raising :exc:`StopIteration` when no more matches are found. """ def __init__(self, master): """Initialize a :class:`SearchAgent` instance.""" aeidon.Delegate.__init__(self, master) self._docs = None self._finder = aeidon.Finder() self._indices = None self._match_doc = None self._match_index = None self._match_passed = None self._match_span = None self._wrap = None # Set targets to defaults. self.set_search_target() def _find(self, index, doc, pos, next): """ Find pattern starting from given position. `pos` can be ``None`` for beginning or end. `next` should be ``True`` to find next, ``False`` for previous. Raise :exc:`StopIteration` if no match. Return tuple of index, document, match span. """ find = (self._next_in_document if next else self._previous_in_document) self._match_index = index self._match_doc = doc self._match_passed = False indices = self._indices or self.get_all_indices() while True: with aeidon.util.silent(ValueError): # Return match in document after location. return find(index, doc, pos) # Proceed to the next document or raise StopIteration. self._match_passed = True doc = self._get_document(doc, next) index = min(indices) if next else max(indices) pos = None @aeidon.deco.export def find_next(self, index=None, doc=None, pos=None): """ Find the next match starting from given position. `index`, `doc` and `pos` can be ``None`` to start from beginning. Raise :exc:`StopIteration` if no (more) matches exist. Return tuple of index, document, match span. """ index = 0 if index is None else index doc = self._docs[0] if doc is None else doc return self._find(index, doc, pos, next=True) @aeidon.deco.export def find_previous(self, index=None, doc=None, pos=None): """ Find the previous match starting from given position. `index`, `doc` and `pos` can be ``None`` to start from end. Raise :exc:`StopIteration` if no (more) matches exist. Return tuple of index, document, match span. """ index = len(self.subtitles)-1 if index is None else index doc = self._docs[-1] if doc is None else doc return self._find(index, doc, pos, next=False) def _get_document(self, doc, next): """ Return the document to proceed to. `next` should be ``True`` to find next, ``False`` for previous. Raise :exc:`StopIteration` if nowhere to proceed. """ if len(self._docs) == 1: if self._wrap: return doc raise StopIteration if next and doc == aeidon.documents.MAIN: return aeidon.documents.TRAN if next and doc == aeidon.documents.TRAN: if self._wrap: return aeidon.documents.MAIN raise StopIteration if not next and doc == aeidon.documents.MAIN: if self._wrap: return aeidon.documents.TRAN raise StopIteration if not next and doc == aeidon.documents.TRAN: return aeidon.documents.MAIN raise ValueError("Invalid document: {!r} or invalid next: {!r}" .format(doc, next)) def _next_in_document(self, index, doc, pos=None): """ Find the next match in `doc` starting from `pos`. `pos` can be ``None`` to start from beginning. Raise :exc:`StopIteration` if no matches at all anywhere. Raise :exc:`ValueError` if no match in this `doc` after `pos`. Return tuple of index, document, match span. """ indices = self._indices or self.get_all_indices() for index in range(index, max(indices) + 1): text = self.subtitles[index].get_text(doc) # Avoid resetting finder's match span. if text != self._finder.text: self._finder.set_text(text) self._finder.pos = 0 if pos is not None: self._finder.pos = pos try: match_span = self._finder.next() except StopIteration: # Raise StopIteration if a full loop around all target # documents and indices has been made with no matches. if doc == self._match_doc: if index == self._match_index: if self._match_passed: raise StopIteration pos = None continue self._match_index = index self._match_doc = doc self._match_span = match_span self._match_passed = False return index, doc, match_span # Raise ValueError if no match found in this document after position. raise ValueError("No more matches in document") def _previous_in_document(self, index, doc, pos=None): """ Find the previous match in `doc` starting from `pos`. `pos` can be ``None`` to start from end. Raise :exc:`StopIteration` if no matches at all anywhere. Raise :exc:`ValueError` if no match in this `doc` before `pos`. Return tuple of index, document, match span. """ indices = self._indices or self.get_all_indices() for index in reversed(range(min(indices), index + 1)): text = self.subtitles[index].get_text(doc) # Avoid resetting finder's match span. if text != self._finder.text: self._finder.set_text(text) self._finder.pos = len(self._finder.text) if pos is not None: self._finder.pos = pos try: match_span = self._finder.previous() except StopIteration: # Raise StopIteration if a full loop around all target # documents and indices has been made with no matches. if doc == self._match_doc: if index == self._match_index: if self._match_passed: raise StopIteration pos = None continue self._match_index = index self._match_doc = doc self._match_span = match_span self._match_passed = False return index, doc, match_span # Raise ValueError if no match found in this document after position. raise ValueError("No more matches in document") @aeidon.deco.export @aeidon.deco.revertable def replace(self, register=-1): """ Replace the current match of pattern. Raise :exc:`re.error` if bad replacement. """ orig_text = self._finder.text self._finder.replace() if self._finder.text == orig_text: return self.set_text(self._match_index, self._match_doc, self._finder.text, register=register) self.set_action_description(register, _("Replacing")) @aeidon.deco.export @aeidon.deco.revertable def replace_all(self, register=-1): """ Replace all matches of pattern and return amount of replacements made. Raise :exc:`re.error` if bad replacement. """ counts = {} for doc in self._docs: counts[doc] = 0 new_indices = [] new_texts = [] for index, subtitle in enumerate(self.subtitles): text = subtitle.get_text(doc) self._finder.set_text(text) sub_count = self._finder.replace_all() if sub_count > 0: new_indices.append(index) new_texts.append(self._finder.text) counts[doc] += sub_count if not new_indices: continue self.replace_texts(new_indices, doc, new_texts, register=register) self.set_action_description(register, _("Replacing all")) if len(list(counts.keys())) == 2 and all(counts.values()): self.group_actions(register, 2, _("Replacing all")) return sum(counts.values()) @aeidon.deco.export def set_search_regex(self, pattern, flags=re.DOTALL|re.MULTILINE): """ Set the regular expression pattern to find. Raise :exc:`re.error` if bad pattern. """ # Ignore case only if in flags. self._finder.ignore_case = False self._finder.set_regex(pattern, flags) @aeidon.deco.export def set_search_replacement(self, replacement): """Set the replacement string.""" self._finder.replacement = replacement @aeidon.deco.export def set_search_string(self, pattern, ignore_case=False): """Set the string pattern to find.""" self._finder.pattern = pattern self._finder.ignore_case = ignore_case @aeidon.deco.export def set_search_target(self, indices=None, docs=None, wrap=True): """ Set the targets to search in. `indices` can be ``None`` to target all subtitles. `docs` can be ``None`` to target all documents. """ self._indices = tuple(indices) if indices else None self._docs = tuple(docs or aeidon.documents) self._wrap = wrap gaupol-1.11/aeidon/agents/set.py000066400000000000000000000124241422217132500166120ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Setting values of single subtitle fields.""" import aeidon import bisect from aeidon.i18n import _ class SetAgent(aeidon.Delegate): """Setting values of single subtitle fields.""" def _move_if_needed(self, index): """Move subtitle for correct order and return new index.""" subtitle = self.subtitles[index] subtitles = self.subtitles[:index] + self.subtitles[(index + 1):] new_index = bisect.bisect_right(subtitles, subtitle) if new_index == index: return new_index subtitle = self.subtitles.pop(index) self.emit("subtitles-removed", (index,)) self.subtitles.insert(new_index, subtitle) self.emit("subtitles-inserted", (new_index,)) return new_index @aeidon.deco.export @aeidon.deco.revertable def set_duration(self, index, value, register=-1): """ Set the value of duration position. `value` can be time, frame or seconds. Use :func:`aeidon.as_time`, :func:`aeidon.as_frame` or :func:`aeidon.as_seconds` if necessary to ensure correct type. """ subtitle = self.subtitles[index] orig_end = subtitle.end subtitle.duration = value if subtitle.end == orig_end: return action = aeidon.RevertableAction(register=register) action.docs = tuple(aeidon.documents) action.description = _("Editing position") action.revert_function = self.set_end action.revert_args = (index, orig_end) self.register_action(action) self.emit("positions-changed", (index,)) @aeidon.deco.export @aeidon.deco.revertable def set_end(self, index, value, register=-1): """ Set the value of end position. `value` can be time, frame or seconds. Use :func:`aeidon.as_time`, :func:`aeidon.as_frame` or :func:`aeidon.as_seconds` if necessary to ensure correct type. """ subtitle = self.subtitles[index] orig_value = subtitle.end subtitle.end = value if subtitle.end == orig_value: return action = aeidon.RevertableAction(register=register) action.docs = tuple(aeidon.documents) action.description = _("Editing position") action.revert_function = self.set_end action.revert_args = (index, orig_value) self.register_action(action) self.emit("positions-changed", (index,)) @aeidon.deco.export @aeidon.deco.revertable def set_main_text(self, index, value, register=-1): """Set the value of main document's text.""" return self.set_text(index, aeidon.documents.MAIN, value, register=register) @aeidon.deco.export @aeidon.deco.revertable @aeidon.deco.notify_frozen def set_start(self, index, value, register=-1): """ Set the value of start position. `value` can be time, frame or seconds. Use :func:`aeidon.as_time`, :func:`aeidon.as_frame` or :func:`aeidon.as_seconds` if necessary to ensure correct type. """ subtitle = self.subtitles[index] orig_value = subtitle.start subtitle.start = value if subtitle.start == orig_value: return index = self._move_if_needed(index) action = aeidon.RevertableAction(register=register) action.docs = tuple(aeidon.documents) action.description = _("Editing position") action.revert_function = self.set_start action.revert_args = (index, orig_value) self.register_action(action) self.emit("positions-changed", (index,)) @aeidon.deco.export @aeidon.deco.revertable def set_text(self, index, doc, value, register=-1): """Set the value of `doc`'s text.""" subtitle = self.subtitles[index] orig_value = subtitle.get_text(doc) if value == orig_value: return subtitle.set_text(doc, value) action = aeidon.RevertableAction(register=register) action.docs = (doc,) action.description = _("Editing text") action.revert_function = self.set_text action.revert_args = (index, doc, orig_value) self.register_action(action) signal = self.get_text_signal(doc) self.emit(signal, (index,)) @aeidon.deco.export @aeidon.deco.revertable def set_translation_text(self, index, value, register=-1): """Set the value of translation document's text.""" return self.set_text(index, aeidon.documents.TRAN, value, register=register) gaupol-1.11/aeidon/agents/test/000077500000000000000000000000001422217132500164215ustar00rootroot00000000000000gaupol-1.11/aeidon/agents/test/__init__.py000066400000000000000000000000001422217132500205200ustar00rootroot00000000000000gaupol-1.11/aeidon/agents/test/test_clipboard.py000066400000000000000000000026611422217132500217760ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class TestClipboardAgent(aeidon.TestCase): def setup_method(self, method): self.project = self.new_project() @aeidon.deco.reversion_test def test_cut_texts(self): self.project.cut_texts((0, 2), aeidon.documents.MAIN) @aeidon.deco.reversion_test def test_paste_texts(self): self.project.copy_texts((0, 1), aeidon.documents.TRAN) self.project.paste_texts(2, aeidon.documents.MAIN) @aeidon.deco.reversion_test def test_paste_texts__new(self): nsubtitles = len(self.project.subtitles) self.project.copy_texts((0, 1), aeidon.documents.TRAN) self.project.paste_texts(nsubtitles-1, aeidon.documents.MAIN) assert len(self.project.subtitles) == nsubtitles + 1 gaupol-1.11/aeidon/agents/test/test_edit.py000066400000000000000000000105541422217132500207640ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class TestEditAgent(aeidon.TestCase): def setup_method(self, method): self.project = self.new_project() @aeidon.deco.reversion_test def test_clear_texts(self): self.project.clear_texts((0, 1), aeidon.documents.MAIN) assert self.project.subtitles[0].main_text == "" assert self.project.subtitles[1].main_text == "" @aeidon.deco.reversion_test def test_insert_subtitles(self): subtitles = self.project.subtitles orig_length = len(subtitles) new_subtitles = [] for i in range(3): subtitle = self.project.new_subtitle() subtitle.start_frame = i subtitle.end_frame = i + 1 new_subtitles.append(subtitle) self.project.insert_subtitles((0, 1, 2), new_subtitles) assert len(subtitles) == orig_length + 3 assert subtitles[0:3] == new_subtitles @aeidon.deco.reversion_test def test_insert_subtitles__blank_end(self): subtitles = self.project.subtitles orig_length = len(subtitles) indices = list(range(orig_length, orig_length + 3)) self.project.insert_subtitles(indices) assert len(subtitles) == orig_length + 3 assert subtitles == sorted(subtitles) @aeidon.deco.reversion_test def test_insert_subtitles__blank_middle(self): subtitles = self.project.subtitles orig_length = len(subtitles) self.project.insert_subtitles((1, 2, 3)) assert len(subtitles) == orig_length + 3 assert subtitles == sorted(subtitles) @aeidon.deco.reversion_test def test_insert_subtitles__blank_start(self): subtitles = self.project.subtitles orig_length = len(subtitles) self.project.insert_subtitles((0, 1, 2)) assert len(subtitles) == orig_length + 3 assert subtitles == sorted(subtitles) @aeidon.deco.reversion_test def test_merge_subtitles(self): subtitles = self.project.subtitles subtitle_1 = subtitles[1].copy() subtitle_2 = subtitles[2].copy() orig_length = len(subtitles) self.project.merge_subtitles((1, 2)) assert len(subtitles) == orig_length - 1 assert subtitles[1].start == subtitle_1.start assert subtitles[1].end == subtitle_2.end @aeidon.deco.reversion_test def test_remove_subtitles(self): subtitles = self.project.subtitles orig_length = len(subtitles) self.project.remove_subtitles((2, 3)) assert len(subtitles) == orig_length - 2 @aeidon.deco.reversion_test def test_replace_positions(self): new_subtitles = [] for i in range(3): subtitle = self.project.new_subtitle() subtitle.start_frame = i subtitle.end_frame = i + 1 new_subtitles.append(subtitle) self.project.replace_positions((0, 1, 2), new_subtitles) subtitles = self.project.subtitles for i in range(3): assert subtitles[i].start == new_subtitles[i].start assert subtitles[i].end == new_subtitles[i].end @aeidon.deco.reversion_test def test_replace_texts(self): doc = aeidon.documents.MAIN self.project.replace_texts((1, 2), doc, ("", "")) assert self.project.subtitles[1].main_text == "" assert self.project.subtitles[2].main_text == "" @aeidon.deco.reversion_test def test_split_subtitle(self): subtitles = self.project.subtitles subtitle = subtitles[1].copy() orig_length = len(subtitles) self.project.split_subtitle(1) assert len(subtitles) == orig_length + 1 assert subtitles[1].start == subtitle.start assert subtitles[2].end == subtitle.end gaupol-1.11/aeidon/agents/test/test_format.py000066400000000000000000000223611422217132500213260ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon MAIN = aeidon.documents.MAIN TRAN = aeidon.documents.TRAN class TestFormatAgent(aeidon.TestCase): def setup_method(self, method): self.project = self.new_project() def test_add_dialogue_dashes(self): self.project.subtitles[0].main_text = ( "- You have cut your beard?\n" "- Yes, don't you like it?") self.project.subtitles[1].main_text = ( "It was the only beautiful thing you had.\n" "Now you seem a different person.") self.project.add_dialogue_dashes((0, 1), MAIN) assert self.project.subtitles[0].main_text == ( "- You have cut your beard?\n" "- Yes, don't you like it?") assert self.project.subtitles[1].main_text == ( "- It was the only beautiful thing you had.\n" "- Now you seem a different person.") def test_change_case__dialogue(self): self.project.subtitles[0].main_text = ( "- mrs. pavinato?\n" "- yes, what do you want?") self.project.change_case((0,), MAIN, "title") assert self.project.subtitles[0].main_text == ( "- Mrs. Pavinato?\n" "- Yes, What Do You Want?") def test_change_case__italic(self): self.project.subtitles[0].main_text = ( "mrs. pavinato?\n" "yes, what do you want?") self.project.change_case((0,), MAIN, "capitalize") assert self.project.subtitles[0].main_text == ( "Mrs. pavinato?\n" "yes, what do you want?") def test_change_case__plain(self): self.project.subtitles[0].main_text = ( "mrs. pavinato?\n" "yes, what do you want?") self.project.change_case((0,), MAIN, "upper") assert self.project.subtitles[0].main_text == ( "MRS. PAVINATO?\n" "YES, WHAT DO YOU WANT?") def test_italicize(self): self.project.subtitles[0].main_text = ( "I am no thief, I am an officer\n" "and a university student.") self.project.subtitles[1].main_text = ( "I look like this because\n" "I'm hunted for by the Germans.") self.project.italicize((0, 1), MAIN) assert self.project.subtitles[0].main_text == ( "I am no thief, I am an officer\n" "and a university student.") assert self.project.subtitles[1].main_text == ( "I look like this because\n" "I'm hunted for by the Germans.") def test_remove_dialogue_dashes__all(self): self.project.subtitles[0].main_text = ( "- You have cut your beard?\n" "- Yes, don't you like it?") self.project.subtitles[1].main_text = ( "- It was the only beautiful thing you had.\n" "- Now you seem a different person.") self.project.remove_dialogue_dashes((0, 1), MAIN) assert self.project.subtitles[0].main_text == ( "You have cut your beard?\n" "Yes, don't you like it?") assert self.project.subtitles[1].main_text == ( "It was the only beautiful thing you had.\n" "Now you seem a different person.") def test_remove_dialogue_dashes__some(self): self.project.subtitles[0].main_text = ( "- You have cut your beard?\n" "- Yes, don't you like it?") self.project.subtitles[1].main_text = ( "It was the only beautiful thing you had.\n" "Now you seem a different person.") self.project.remove_dialogue_dashes((0, 1), MAIN) assert self.project.subtitles[0].main_text == ( "You have cut your beard?\n" "Yes, don't you like it?") assert self.project.subtitles[1].main_text == ( "It was the only beautiful thing you had.\n" "Now you seem a different person.") def test_toggle_dialogue_dashes__all(self): self.project.subtitles[0].main_text = ( "- You have cut your beard?\n" "- Yes, don't you like it?") self.project.subtitles[1].main_text = ( "- It was the only beautiful thing you had.\n" "- Now you seem a different person.") self.project.toggle_dialogue_dashes((0, 1), MAIN) assert self.project.subtitles[0].main_text == ( "You have cut your beard?\n" "Yes, don't you like it?") assert self.project.subtitles[1].main_text == ( "It was the only beautiful thing you had.\n" "Now you seem a different person.") def test_toggle_dialogue_dashes__none(self): self.project.subtitles[0].main_text = ( "You have cut your beard?\n" "Yes, don't you like it?") self.project.subtitles[1].main_text = ( "It was the only beautiful thing you had.\n" "Now you seem a different person.") self.project.toggle_dialogue_dashes((0, 1), MAIN) assert self.project.subtitles[0].main_text == ( "- You have cut your beard?\n" "- Yes, don't you like it?") assert self.project.subtitles[1].main_text == ( "- It was the only beautiful thing you had.\n" "- Now you seem a different person.") def test_toggle_dialogue_dashes__some(self): self.project.subtitles[0].main_text = ( "- You have cut your beard?\n" "- Yes, don't you like it?") self.project.subtitles[1].main_text = ( "It was the only beautiful thing you had.\n" "Now you seem a different person.") self.project.toggle_dialogue_dashes((0, 1), MAIN) assert self.project.subtitles[0].main_text == ( "- You have cut your beard?\n" "- Yes, don't you like it?") assert self.project.subtitles[1].main_text == ( "- It was the only beautiful thing you had.\n" "- Now you seem a different person.") def test_toggle_italicization__all(self): self.project.subtitles[0].main_text = ( "I am no thief, I am an officer\n" "and a university student.") self.project.subtitles[1].main_text = ( "I look like this because\n" "I'm hunted for by the Germans.") self.project.toggle_italicization((0, 1), MAIN) assert self.project.subtitles[0].main_text == ( "I am no thief, I am an officer\n" "and a university student.") assert self.project.subtitles[1].main_text == ( "I look like this because\n" "I'm hunted for by the Germans.") def test_toggle_italicization__none(self): self.project.subtitles[0].main_text = ( "I am no thief, I am an officer\n" "and a university student.") self.project.subtitles[1].main_text = ( "I look like this because\n" "I'm hunted for by the Germans.") self.project.toggle_italicization((0, 1), MAIN) assert self.project.subtitles[0].main_text == ( "I am no thief, I am an officer\n" "and a university student.") assert self.project.subtitles[1].main_text == ( "I look like this because\n" "I'm hunted for by the Germans.") def test_toggle_italicization__some(self): self.project.subtitles[0].main_text = ( "I am no thief, I am an officer\n" "and a university student.") self.project.subtitles[1].main_text = ( "I look like this because\n" "I'm hunted for by the Germans.") self.project.toggle_italicization((0, 1), MAIN) assert self.project.subtitles[0].main_text == ( "I am no thief, I am an officer\n" "and a university student.") assert self.project.subtitles[1].main_text == ( "I look like this because\n" "I'm hunted for by the Germans.") def test_unitalicize(self): self.project.subtitles[0].main_text = ( "I am no thief, I am an officer\n" "and a university student.") self.project.subtitles[1].main_text = ( "I look like this because\n" "I'm hunted for by the Germans.") self.project.unitalicize((0, 1), MAIN) assert self.project.subtitles[0].main_text == ( "I am no thief, I am an officer\n" "and a university student.") assert self.project.subtitles[1].main_text == ( "I look like this because\n" "I'm hunted for by the Germans.") gaupol-1.11/aeidon/agents/test/test_open.py000066400000000000000000000047101422217132500207750ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon import codecs class TestOpenAgent(aeidon.TestCase): def setup_method(self, method): self.project = self.new_project() def test_open_main(self): for format in aeidon.formats: path = self.new_temp_file(format) self.project.open_main(path, "ascii") assert self.project.subtitles def test_open_main__bom(self): path = self.new_subrip_file() blob = open(path, "rb").read() open(path, "wb").write(codecs.BOM_UTF8 + blob) self.project.open_main(path, "ascii") assert self.project.subtitles assert self.project.main_file.encoding == "utf_8_sig" def test_open_main__sort(self): path = self.new_microdvd_file() with open(path, "w") as f: f.write("{100}{200}\n") f.write("{500}{600}\n") f.write("{300}{400}\n") sort_count = self.project.open_main(path, "ascii") assert sort_count == 1 def test_open_translation__align_number(self): for format in aeidon.formats: path = self.new_temp_file(format) method = aeidon.align_methods.NUMBER self.project.open_translation(path, "ascii", method) def test_open_translation__align_position(self): for format in aeidon.formats: path = self.new_temp_file(format) method = aeidon.align_methods.POSITION self.project.open_translation(path, "ascii", method) def test_open_translation__bom(self): path = self.new_subrip_file() blob = open(path, "rb").read() open(path, "wb").write(codecs.BOM_UTF8 + blob) self.project.open_translation(path, "ascii") assert self.project.subtitles assert self.project.tran_file.encoding == "utf_8_sig" gaupol-1.11/aeidon/agents/test/test_position.py000066400000000000000000000136321422217132500217030ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class TestPositionAgent(aeidon.TestCase): def setup_method(self, method): self.project = self.new_project() def test_adjust_durations__gap(self): subtitles = self.project.subtitles subtitles[0].start = "00:00:01.000" subtitles[0].end = "00:00:02.000" subtitles[1].start = "00:00:02.000" subtitles[1].end = "00:00:03.000" subtitles[2].start = "00:00:04.000" self.project.adjust_durations(None, gap=0.3) assert subtitles[0].start == "00:00:01.000" assert subtitles[0].end == "00:00:01.700" assert subtitles[1].start == "00:00:02.000" assert subtitles[1].end == "00:00:03.000" assert subtitles[2].start == "00:00:04.000" def test_adjust_durations__lengthen(self): subtitles = self.project.subtitles subtitles[0].start = "00:00:01.000" subtitles[0].end = "00:00:01.100" subtitles[1].start = "00:00:02.000" subtitles[1].end = "00:00:02.100" subtitles[0].main_text = "1234567890" subtitles[1].main_text = "12345678901234567890" self.project.adjust_durations(None, speed=20, lengthen=True) assert subtitles[0].start == "00:00:01.000" assert subtitles[0].end == "00:00:01.500" assert subtitles[1].start == "00:00:02.000" assert subtitles[1].end == "00:00:03.000" def test_adjust_durations__maximum(self): subtitles = self.project.subtitles subtitles[0].start = "00:00:01.000" subtitles[0].end = "00:00:01.100" subtitles[1].start = "00:00:02.000" subtitles[1].end = "00:00:02.100" self.project.adjust_durations(None, speed=10, lengthen=True, maximum=0.5) assert subtitles[0].start == "00:00:01.000" assert subtitles[0].end == "00:00:01.500" assert subtitles[1].start == "00:00:02.000" assert subtitles[1].end == "00:00:02.500" def test_adjust_durations__minimum(self): subtitles = self.project.subtitles subtitles[0].start = "00:00:01.000" subtitles[0].end = "00:00:01.900" subtitles[1].start = "00:00:02.000" subtitles[1].end = "00:00:02.900" self.project.adjust_durations(None, speed=1000, shorten=True, minimum=0.5) assert subtitles[0].start == "00:00:01.000" assert subtitles[0].end == "00:00:01.500" assert subtitles[1].start == "00:00:02.000" assert subtitles[1].end == "00:00:02.500" def test_adjust_durations__shorten(self): subtitles = self.project.subtitles subtitles[0].start = "00:00:01.000" subtitles[0].end = "00:00:01.900" subtitles[1].start = "00:00:02.000" subtitles[1].end = "00:00:02.900" subtitles[0].main_text = "1234567890" subtitles[1].main_text = "12345678901234567890" self.project.adjust_durations(None, speed=100, shorten=True) assert subtitles[0].start == "00:00:01.000" assert subtitles[0].end == "00:00:01.100" assert subtitles[1].start == "00:00:02.000" assert subtitles[1].end == "00:00:02.200" def test_convert_framerate(self): self.project.open_main(self.new_microdvd_file(), "ascii") self.project.subtitles[0].start = 100 self.project.subtitles[1].start = 200 ifps = aeidon.framerates.FPS_23_976 ofps = aeidon.framerates.FPS_25_000 self.project.convert_framerate(None, ifps, ofps) assert self.project.framerate == ofps for subtitle in self.project.subtitles: assert subtitle.framerate == ofps assert self.project.subtitles[0].start == 104 assert self.project.subtitles[1].start == 209 def test_set_framerate(self): framerate = aeidon.framerates.FPS_25_000 self.project.set_framerate(framerate) assert self.project.framerate == framerate for subtitle in self.project.subtitles: assert subtitle.framerate == framerate @aeidon.deco.reversion_test def test_shift_positions(self): orig_subtitles = [x.copy() for x in self.project.subtitles] indices = self.project.get_all_indices() self.project.shift_positions(indices, -10) for i, subtitle in enumerate(self.project.subtitles): start = orig_subtitles[i].start_frame - 10 end = orig_subtitles[i].end_frame - 10 assert subtitle.start_frame == start assert subtitle.end_frame == end @aeidon.deco.reversion_test def test_transform_positions(self): a, b = "00:00:01.000", "00:00:45.000" self.project.transform_positions(None, (2, a), (6, b)) assert self.project.subtitles[2].start_time == a for subtitle in self.project.subtitles[3:6]: assert a < subtitle.start_time < b assert self.project.subtitles[6].start_time == b gaupol-1.11/aeidon/agents/test/test_register.py000066400000000000000000000046371422217132500216700ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon MAIN = aeidon.documents.MAIN TRAN = aeidon.documents.TRAN class TestRegisterAgent(aeidon.TestCase): def setup_method(self, method): self.project = self.new_project() self.delegate = self.project.undo.__self__ def test_redo(self): text_0 = self.project.subtitles[0].main_text text_1 = self.project.subtitles[1].main_text text_2 = self.project.subtitles[2].main_text self.project.clear_texts((0,), MAIN) self.project.clear_texts((1,), MAIN) self.project.clear_texts((2,), MAIN) self.project.undo(3) assert self.project.subtitles[0].main_text == text_0 assert self.project.subtitles[1].main_text == text_1 assert self.project.subtitles[2].main_text == text_2 self.project.redo(1) self.project.redo(2) assert self.project.subtitles[0].main_text == "" assert self.project.subtitles[1].main_text == "" assert self.project.subtitles[2].main_text == "" def test_undo(self): text_0 = self.project.subtitles[0].main_text text_1 = self.project.subtitles[1].main_text text_2 = self.project.subtitles[2].main_text self.project.clear_texts((0,), MAIN) self.project.clear_texts((1,), MAIN) self.project.clear_texts((2,), MAIN) self.project.undo(1) self.project.undo(2) assert self.project.subtitles[0].main_text == text_0 assert self.project.subtitles[1].main_text == text_1 assert self.project.subtitles[2].main_text == text_2 self.project.redo(3) assert self.project.subtitles[0].main_text == "" assert self.project.subtitles[1].main_text == "" assert self.project.subtitles[2].main_text == "" gaupol-1.11/aeidon/agents/test/test_save.py000066400000000000000000000034471422217132500210000ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class TestSaveAgent(aeidon.TestCase): def setup_method(self, method): self.project = self.new_project() def test_save_main(self): for format in aeidon.formats: self.project.clear_texts((0,), aeidon.documents.MAIN) path = self.project.main_file.path file = aeidon.files.new(format, path, "ascii") self.project.save_main(file, keep_changes=False) assert self.project.main_changed == 1 file = aeidon.files.new(format, path, "ascii") self.project.save_main(file, keep_changes=True) assert self.project.main_changed == 0 def test_save_translation(self): for format in aeidon.formats: self.project.clear_texts((0,), aeidon.documents.TRAN) path = self.project.tran_file.path file = aeidon.files.new(format, path, "ascii") self.project.save_translation(file, keep_changes=False) assert self.project.tran_changed == 1 self.project.save_translation(file, keep_changes=True) assert self.project.tran_changed == 0 gaupol-1.11/aeidon/agents/test/test_search.py000066400000000000000000000076571422217132500213160ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon MAIN = aeidon.documents.MAIN TRAN = aeidon.documents.TRAN class TestSearchAgent(aeidon.TestCase): ######### 0000000000111111111122222222223333333333444444444 ######### 0123456789012345678901234567890123456789012345678 texts = ("God has promised you that\nyou will go to Heaven?", "So you are certain of\nbeing saved?", "Be careful,\nit's a dangerous answer.") def setup_method(self, method): self.project = self.new_project() for i, text in enumerate(self.texts): self.project.subtitles[i].main_text = text self.project.subtitles[i].tran_text = text indices = list(range(3, len(self.project.subtitles))) self.project.remove_subtitles(indices, register=None) def test_find_next(self): matches = iter(((0, MAIN, ( 0, 0)), (0, MAIN, (26, 26)), (1, MAIN, ( 0, 0)), (1, MAIN, (22, 22)), (2, MAIN, ( 0, 0)), (2, MAIN, (12, 12)), StopIteration)) self.project.set_search_target(None, (MAIN,), wrap=False) self.project.set_search_regex(r"^") index, doc, pos = None, MAIN, None while True: try: index, doc, span = self.project.find_next(index, doc, pos) assert (index, doc, span) == next(matches) pos = span[1] except StopIteration: assert next(matches) is StopIteration break def test_find_previous(self): matches = iter(((1, MAIN, ( 3, 6)), (0, MAIN, (26, 29)), (0, MAIN, (17, 20)), StopIteration)) self.project.set_search_target(None, (MAIN,), wrap=False) self.project.set_search_string("you", ignore_case=False) index, doc, pos = None, MAIN, None while True: try: index, doc, span = self.project.find_previous(index, doc, pos) assert (index, doc, span) == next(matches) pos = span[0] except StopIteration: assert next(matches) is StopIteration break @aeidon.deco.reversion_test def test_replace(self): self.project.set_search_target(None, (MAIN,)) self.project.set_search_regex(r"\b\s") self.project.set_search_replacement("") self.project.find_next(index=0, doc=MAIN, pos=4) self.project.replace() text = self.project.subtitles[0].main_text assert text == "God haspromised you that\nyou will go to Heaven?" @aeidon.deco.reversion_test def test_replace_all(self): self.project.set_search_target(None, (MAIN, TRAN)) self.project.set_search_regex(r"$") self.project.set_search_replacement("--") self.project.replace_all() texts = ("God has promised you that--\nyou will go to Heaven?--", "So you are certain of--\nbeing saved?--", "Be careful,--\nit's a dangerous answer.--") for i, text in enumerate(texts): assert self.project.subtitles[i].main_text == text assert self.project.subtitles[i].tran_text == text gaupol-1.11/aeidon/agents/test/test_set.py000066400000000000000000000051601422217132500206270ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class TestSetAgent(aeidon.TestCase): def setup_method(self, method): self.project = self.new_project() @aeidon.deco.reversion_test def test_set_duration(self): subtitles = self.project.subtitles self.project.set_duration(0, "00:01:11.111") assert subtitles[0].duration_time == "00:01:11.111" @aeidon.deco.reversion_test def test_set_end(self): subtitles = self.project.subtitles self.project.set_end(0, 600000) assert subtitles[0].end_frame == 600000 @aeidon.deco.reversion_test def test_set_main_text(self): subtitles = self.project.subtitles self.project.set_main_text(0, "m") assert subtitles[0].main_text == "m" @aeidon.deco.reversion_test def test_set_start(self): subtitles = self.project.subtitles self.project.set_start(0, -100.0) assert subtitles[0].start_seconds == -100.0 @aeidon.deco.reversion_test def test_set_start__reorder(self): subtitles = self.project.subtitles text_0 = subtitles[0].main_text text_3 = subtitles[3].main_text self.project.set_start(3, -1000) assert subtitles[0].start_frame == -1000 assert subtitles[0].main_text == text_3 assert subtitles[1].main_text == text_0 @aeidon.deco.reversion_test def test_set_text__main(self): subtitles = self.project.subtitles self.project.set_text(0, aeidon.documents.MAIN, "m") assert subtitles[0].main_text == "m" @aeidon.deco.reversion_test def test_set_text__translation(self): subtitles = self.project.subtitles self.project.set_text(0, aeidon.documents.TRAN, "t") assert subtitles[0].tran_text == "t" @aeidon.deco.reversion_test def test_set_translation_text(self): subtitles = self.project.subtitles self.project.set_translation_text(0, "t") assert subtitles[0].tran_text == "t" gaupol-1.11/aeidon/agents/test/test_text.py000066400000000000000000000101221422217132500210120ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 aeidon class TestTextAgent(aeidon.TestCase): def setup_method(self, method): self.project = self.new_project() def test_break_lines(self): manager = aeidon.PatternManager("line-break") for subtitle in self.project.subtitles: subtitle.main_text = subtitle.main_text.replace(" ", "\n") self.project.break_lines(indices=None, doc=aeidon.documents.MAIN, patterns=manager.get_patterns("Latn"), length_func=len, max_length=44, max_lines=2) for subtitle in self.project.subtitles: assert subtitle.main_text.count("\n") <= 2 def test_capitalize(self): for subtitle in self.project.subtitles: subtitle.main_text = "test. test i." manager = aeidon.PatternManager("capitalization") self.project.capitalize(self.project.get_all_indices(), aeidon.documents.MAIN, manager.get_patterns("Latn", "en")) for subtitle in self.project.subtitles: assert subtitle.main_text == "Test. Test I." def test_correct_common_errors(self): self.project.subtitles[0].main_text = "''Test''" self.project.subtitles[1].main_text = "123o456o789" manager = aeidon.PatternManager("common-error") self.project.correct_common_errors(self.project.get_all_indices(), aeidon.documents.MAIN, manager.get_patterns("Latn")) assert self.project.subtitles[0].main_text == '"Test"' assert self.project.subtitles[1].main_text == "12304560789" def test_remove_hearing_impaired(self): orig_length = len(self.project.subtitles) self.project.subtitles[0].main_text = "[Boo] Test." self.project.subtitles[1].main_text = "[Boo]" manager = aeidon.PatternManager("hearing-impaired") patterns = manager.get_patterns("Latn") for pattern in patterns: pattern.enabled = True self.project.remove_hearing_impaired(self.project.get_all_indices(), aeidon.documents.MAIN, patterns) assert self.project.subtitles[0].main_text == "Test." assert len(self.project.subtitles) == orig_length - 1 def test_spell_check_join_words(self): for subtitle in self.project.subtitles: subtitle.main_text = subtitle.main_text.replace("a", " a") subtitle.main_text = subtitle.main_text.replace("e", "e ") language = self.get_spell_check_language("en") self.project.spell_check_join_words(indices=None, doc=aeidon.documents.MAIN, language=language) def test_spell_check_split_words(self): for subtitle in self.project.subtitles: subtitle.main_text = subtitle.main_text.replace("s ", "s") subtitle.main_text = subtitle.main_text.replace("y ", "y") language = self.get_spell_check_language("en") self.project.spell_check_split_words(indices=None, doc=aeidon.documents.MAIN, language=language) gaupol-1.11/aeidon/agents/text.py000066400000000000000000000362141422217132500170060ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 . """Automatic correcting of texts.""" import aeidon import re from aeidon.i18n import _ class TextAgent(aeidon.Delegate): """Automatic correcting of texts.""" _re_capitalizable = re.compile(r"^\W*(? max_skip_length and length_down lines_fixed = line_count > max_skip_lines and lines_down if not length_fixed and not lines_fixed: # Skip if part in violation not fixed. if skip: continue if text != subtitle.get_text(doc): new_indices.append(index) new_texts.append(text) if not new_indices: return self.replace_texts(new_indices, doc, new_texts, register=register) self.set_action_description(register, _("Breaking lines")) @aeidon.deco.export @aeidon.deco.revertable def capitalize(self, indices, doc, patterns, register=-1): """ Capitalize texts as defined by `patterns`. `indices` can be ``None`` to process all subtitles. `patterns` should be a sequence of instances of :class:`aeidon.Pattern`. Raise :exc:`re.error` if a bad regular expression among `patterns`. """ new_indices = [] new_texts = [] parser = self.get_parser(doc) patterns = [x for x in patterns if x.enabled] indices = indices or self.get_all_indices() for indices in aeidon.util.get_ranges(indices): cap_next = False for index in indices: subtitle = self.subtitles[index] parser.set_text(subtitle.get_text(doc)) if cap_next or index == 0: self._capitalize_first(parser, 0) cap_next = False for pattern in patterns: string = pattern.get_field("Pattern") flags = pattern.get_flags() parser.set_regex(string, flags) parser.pos = 0 cap_next = self._capitalize_text(parser, pattern, cap_next) text = parser.get_text() if text != subtitle.get_text(doc): new_indices.append(index) new_texts.append(text) if not new_indices: return self.replace_texts(new_indices, doc, new_texts, register=register) self.set_action_description(register, _("Capitalizing texts")) def _capitalize_first(self, parser, pos): """Capitalize the first alphanumeric character from `pos`.""" match = self._re_capitalizable.search(parser.text[pos:]) if match is not None: i = pos + match.end() - 1 prefix = parser.text[:i] text = parser.text[i:i+1].capitalize() suffix = parser.text[i+1:] parser.text = prefix + text + suffix return match is not None def _capitalize_text(self, parser, pattern, cap_next): """Capitalize all matches of `pattern` in `parser`'s text.""" try: a, z = parser.next() except StopIteration: return cap_next if pattern.get_field("Capitalize") == "Start": self._capitalize_first(parser, a) if pattern.get_field("Capitalize") == "After": cap_next = not self._capitalize_first(parser, z) return self._capitalize_text(parser, pattern, cap_next) @aeidon.deco.export @aeidon.deco.revertable def correct_common_errors(self, indices, doc, patterns, register=-1): """ Correct common human and OCR errors in texts. `indices` can be ``None`` to process all subtitles. `patterns` should be a sequence of instances of :class:`aeidon.Pattern`. Raise :exc:`re.error` if a bad regular expression among `patterns`. """ new_indices = [] new_texts = [] parser = self.get_parser(doc) patterns = [x for x in patterns if x.enabled] re_patterns = self._get_substitutions(patterns) repeats = [x.get_field_boolean("Repeat") for x in patterns] for index in indices or self.get_all_indices(): subtitle = self.subtitles[index] parser.set_text(subtitle.get_text(doc)) for i, item in enumerate(re_patterns): string, flags, replacement = item parser.set_regex(string, flags) parser.replacement = replacement count = parser.replace_all() while repeats[i] and count: count = parser.replace_all() text = parser.get_text() if text != subtitle.get_text(doc): new_indices.append(index) new_texts.append(text) if not new_indices: return self.replace_texts(new_indices, doc, new_texts, register=register) self.set_action_description(register, _("Correcting common errors")) def _get_penalties(self, patterns): """Return a list of penalty definitions.""" return [{ "pattern": x.get_field("Pattern"), "flags": x.get_flags(), "group": int(x.get_field("Group")), "value": float(x.get_field("Penalty")), } for x in patterns] def _get_substitutions(self, patterns): """Return a list of substitution definitions.""" return [( x.get_field("Pattern"), x.get_flags(), x.get_field("Replacement"), ) for x in patterns] @aeidon.deco.export @aeidon.deco.revertable def remove_hearing_impaired(self, indices, doc, patterns, remove_blank=True, register=-1): """ Remove hearing impaired parts from subtitles. `indices` can be ``None`` to process all subtitles. `patterns` should be a sequence of instances of :class:`aeidon.Pattern`. Raise :exc:`re.error` if a bad regular expression among `patterns`. """ new_indices = [] new_texts = [] parser = self.get_parser(doc) patterns = [x for x in patterns if x.enabled] re_patterns = self._get_substitutions(patterns) for index in indices or self.get_all_indices(): subtitle = self.subtitles[index] parser.set_text(subtitle.get_text(doc)) for string, flags, replacement in re_patterns: parser.set_regex(string, flags) parser.replacement = replacement parser.replace_all() text = parser.get_text() if text != subtitle.get_text(doc): new_indices.append(index) new_texts.append(text) if not new_indices: return new_texts = self._remove_leftover_hi(new_texts, parser) self.replace_texts(new_indices, doc, new_texts, register=register) description = _("Removing hearing impaired texts") self.set_action_description(register, description) if not remove_blank: return remove_indices = [] for i, text in (x for x in enumerate(new_texts) if not x[1]): remove_indices.append(new_indices[i]) if not remove_indices: return self.remove_subtitles(remove_indices, register=register) self.group_actions(register, 2, description) def _remove_leftover_hi(self, texts, parser): """Remove leftover hearing impaired whitespace and junk.""" texts = texts[:] for i, text in enumerate(texts): parser.set_text(text) # Remove leading and trailing spaces. self._replace_all(parser, r"(^\s+|\s+$)", "") # Consolidate multiple consequtive spaces. self._replace_all(parser, r" {2,}", " ") # Remove lines with no alphanumeric characters. self._replace_all(parser, r"^\W*$", "") # Remove empty lines. self._replace_all(parser, r"(^\n|\n$)", "") # Add space after dialogue dashes. self._replace_all(parser, r"^([\-\–\—])(\S)", r"\1 \2") # Remove dialogue dashes if not present on other lines. self._replace_all(parser, r"^[\-\–\—] (.*?^[^\-\–\—])", r"\1") # Remove dialogue dashes from single-line subtitles. self._replace_all(parser, r"\A[\-\–\—] ([^\n]*)\Z", r"\1") texts[i] = parser.get_text() return texts def _replace_all(self, parser, pattern, replacement): """Replace all matches of `pattern` in `parser`'s text.""" parser.set_regex(pattern) parser.replacement = replacement parser.replace_all() @aeidon.deco.export @aeidon.deco.revertable def spell_check_join_words(self, indices, doc, language, register=-1): """ Join misspelled words based on spell-checker suggestions. `indices` can be ``None`` to process all subtitles. Raise :exc:`Exception` if dictionary instatiation fails. """ new_indices = [] new_texts = [] checker = aeidon.SpellChecker(language) navigator = aeidon.SpellCheckNavigator(language) for index in indices or self.get_all_indices(): subtitle = self.subtitles[index] text = subtitle.get_text(doc) text = re.sub(r" +", " ", text) navigator.reset(text) for pos, word in navigator: text = navigator.text a = navigator.pos z = navigator.endpos ok_with_prev = False if navigator.leading_context(1) == " ": candidate = re.split(r"\W+", text[:a-1])[-1] + word ok_with_prev = checker.check(candidate) ok_with_next = False if navigator.trailing_context(1) == " ": candidate = word + re.split(r"\W+", text[z+1:])[0] ok_with_next = checker.check(candidate) # Join backwards or forwards if only one direction, # but not both, produce a correctly spelled result. if ok_with_prev == ok_with_next: navigator.ignore() elif ok_with_prev: navigator.join_with_previous() elif ok_with_next: navigator.join_with_next() if navigator.text != text: new_indices.append(index) new_texts.append(navigator.text) if not new_indices: return self.replace_texts(new_indices, doc, new_texts, register=register) description = _("Joining words by spell-check suggestions") self.set_action_description(register, description) @aeidon.deco.export @aeidon.deco.revertable def spell_check_split_words(self, indices, doc, language, register=-1): """ Split misspelled words based on spell-checker suggestions. `indices` can be ``None`` to process all subtitles. Raise :exc:`Exception` if dictionary instatiation fails. """ new_indices = [] new_texts = [] navigator = aeidon.SpellCheckNavigator(language) for index in indices or self.get_all_indices(): subtitle = self.subtitles[index] text = subtitle.get_text(doc) text = re.sub(r" +", " ", text) navigator.reset(text) for pos, word in navigator: # Skip capitalized words, which are usually names # and thus not always found in dictionaries. if word.istitle(): navigator.ignore() continue suggestions = navigator.suggest() suggestions = [x for x in suggestions if x.replace(" ", "") == word] # Split word only if only one two-word suggestion found that # has all the same characters as the original unsplit word. if len(suggestions) == 1: navigator.replace(suggestions[0]) else: navigator.ignore() if navigator.text != text: new_indices.append(index) new_texts.append(navigator.text) if not new_indices: return self.replace_texts(new_indices, doc, new_texts, register=register) description = _("Splitting words by spell-check suggestions") self.set_action_description(register, description) gaupol-1.11/aeidon/agents/util.py000066400000000000000000000136121422217132500167740ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Miscellaneous helper methods.""" import aeidon class UtilityAgent(aeidon.Delegate): """Miscellaneous helper methods.""" @aeidon.deco.export def get_all_indices(self): """Return a list of all indices of subtitles.""" return list(range(len(self.subtitles))) @aeidon.deco.export def get_changed(self, doc): """Return the changed value corresponding to `doc`.""" if doc == aeidon.documents.MAIN: return self.main_changed if doc == aeidon.documents.TRAN: return self.tran_changed raise ValueError("Invalid document: {!r}" .format(doc)) @aeidon.deco.export def get_file(self, doc): """Return the file corresponding to `doc`.""" if doc == aeidon.documents.MAIN: return self.main_file if doc == aeidon.documents.TRAN: return self.tran_file raise ValueError("Invalid document: {!r}" .format(doc)) @aeidon.deco.export def get_format(self, doc): """ Return format of the file corresponding to `doc`. For a translation file that is ``None``, return format of main file. If main file is ``None``, return ``None``. """ if doc == aeidon.documents.MAIN: if self.main_file is not None: return self.main_file.format return None if doc == aeidon.documents.TRAN: if self.tran_file is not None: return self.tran_file.format return self.get_format(aeidon.documents.MAIN) raise ValueError("Invalid document: {!r}" .format(doc)) @aeidon.deco.export def get_liner(self, doc): """Return a new :class:`aeidon.Liner` instance.""" re_tag = self.get_markup_tag_regex(doc) clean_func = self.get_markup_clean_func(doc) return aeidon.Liner(re_tag, clean_func) @aeidon.deco.export def get_markup(self, doc): """Return `doc`'s markup instance or ``None``.""" format = self.get_format(doc) if format is None: return None return aeidon.markups.new(format) @aeidon.deco.export def get_markup_clean_func(self, doc): """Return the function to clean markup or ``None``.""" format = self.get_format(doc) if format is None: return None return aeidon.markups.new(format).clean @aeidon.deco.export def get_markup_tag_regex(self, doc): """Return the regular expression for a markup tag or ``None``.""" format = self.get_format(doc) if format is None: return None return aeidon.markups.new(format).tag @aeidon.deco.export def get_mode(self): """Return mode of the main file or default.""" if self.main_file is not None: return self.main_file.mode return aeidon.modes.TIME @aeidon.deco.export def get_parser(self, doc): """Return a new :class:`aeidon.Parser` instance.""" re_tag = self.get_markup_tag_regex(doc) clean_func = self.get_markup_clean_func(doc) return aeidon.Parser(re_tag, clean_func) @aeidon.deco.export def get_text_length(self, index, doc): """Return the amount of characters in text excluding markup.""" text = self.subtitles[index].get_text(doc) re_tag = self.get_markup_tag_regex(doc) if re_tag is not None: text = re_tag.sub("", text) return len(text) @aeidon.deco.export def get_text_signal(self, doc): """Return the ``texts-changed`` signal corresponding to `doc`.""" if doc == aeidon.documents.MAIN: return "main-texts-changed" if doc == aeidon.documents.TRAN: return "translation-texts-changed" raise ValueError("Invalid document: {!r}" .format(doc)) @aeidon.deco.export def new_subtitle(self): """Return a new :class:`aeidon.Subtitle` instance.""" return aeidon.Subtitle(self.get_mode(), self.framerate) @aeidon.deco.export def new_temp_file(self, doc, encoding=None): """ Return path to a new temporary file with subtitles from `doc`. Raise :exc:`IOError` if writing to temporary file fails. Raise :exc:`UnicodeError` if encoding temporary file fails. """ file = self.get_file(doc) if file is None and doc == aeidon.documents.TRAN: # For an unsaved translation document, # fall back to main document's properties. file = self.get_file(aeidon.documents.MAIN) if file is not None: path = aeidon.temp.create(file.format.extension) encoding = encoding or file.encoding temp_file = aeidon.files.new(file.format, path, encoding) temp_file.copy_from(file) else: # If no saved document to pull properties from, # fall back to SubRip format and UTF-8 encoding. format = aeidon.formats.SUBRIP path = aeidon.temp.create(format.extension) encoding = encoding or "utf_8" temp_file = aeidon.files.new(format, path, encoding) self.save(doc, temp_file, keep_changes=False) return temp_file.path gaupol-1.11/aeidon/calculator.py000066400000000000000000000213611422217132500166670ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Time and frame calculator.""" import aeidon __all__ = ("Calculator",) class Calculator: """ Time and frame calculator. Times are handled as strings, frames as integers and seconds as floats. Only one instance of :class:`Calculator` exists for a given framerate. """ _instances = {} def __new__(cls, framerate=None): """ Return possibly existing instance for `framerate`. `framerate` can be either an :attr:`aeidon.framerates` item (preferred to be able to reuse instances) or an exact float value. """ if framerate is None: framerate = aeidon.framerates.FPS_23_976 if not framerate in aeidon.framerates: # Always return a new instance for float values. return object.__new__(cls) if not framerate in cls._instances: cls._instances[framerate] = object.__new__(cls) return cls._instances[framerate] def __init__(self, framerate=None): """ Initialize a :class:`Calculator` instance. `framerate` can be either an :attr:`aeidon.framerates` item (preferred to be able to reuse instances) or an exact float value. """ if framerate is None: framerate = aeidon.framerates.FPS_23_976 if framerate in aeidon.framerates: self._framerate = framerate.value else: # Use non-constant values as is. self._framerate = float(framerate) def add(self, x, y): """Add position `y` to `x`.""" if aeidon.is_time(x): x = self.to_seconds(x) y = self.to_seconds(y) return self.seconds_to_time(x + y) if aeidon.is_frame(x): return x + self.to_frame(y) if aeidon.is_seconds(x): return x + self.to_seconds(y) raise ValueError("Invalid type for x: {!r}" .format(type(x))) def frame_to_seconds(self, frame): """Convert `frame` to seconds.""" return aeidon.as_seconds(frame / self._framerate) def frame_to_time(self, frame): """Convert `frame` to time.""" seconds = self.frame_to_seconds(frame) return self.seconds_to_time(seconds) def get_middle(self, x, y): """Return time, frame or seconds halfway between `x` and `y`.""" if aeidon.is_time(x): x = self.time_to_seconds(x) y = self.to_seconds(y) return self.seconds_to_time((x + y) / 2) if aeidon.is_frame(x): y = self.to_frame(y) return aeidon.as_frame(round((x + y) / 2, 0)) if aeidon.is_seconds(x): y = self.to_seconds(y) return aeidon.as_seconds(((x + y) / 2)) raise ValueError("Invalid type for x: {!r}" .format(type(x))) def is_earlier(self, x, y): """Return ``True`` if `x` is earlier than `y`.""" if aeidon.is_time(x): x = self.time_to_seconds(x) return self.is_earlier(x, y) if aeidon.is_frame(x): return (x < self.to_frame(y)) if aeidon.is_seconds(x): return (x < self.to_seconds(y)) raise ValueError("Invalid type for x: {!r}" .format(type(x))) def is_later(self, x, y): """Return ``True`` if `x` is later than `y`.""" if aeidon.is_time(x): x = self.time_to_seconds(x) return self.is_later(x, y) if aeidon.is_frame(x): return (x > self.to_frame(y)) if aeidon.is_seconds(x): return (x > self.to_seconds(y)) raise ValueError("Invalid type for x: {!r}" .format(type(x))) def is_valid_time(self, time): """Return ``True`` if `time` is a valid time string.""" if time.startswith("-"): time = time[1:] try: hours = int(time[ :2]) minutes = int(time[3:5]) seconds = int(time[6:8]) mseconds = int(time[9: ]) except ValueError: return False return (0 <= hours <= 99 and 0 <= minutes <= 59 and 0 <= seconds <= 59 and 0 <= mseconds <= 999) def normalize_time(self, time): """ Convert `time` to valid format. >>> calc = aeidon.Calculator() >>> calc.normalize_time("1:2:3,4") '01:02:03.400' """ time = time.strip() sign = "-" if time.startswith("-") else "" time = time.replace("-", "") time = time.replace(",", ".") if time.count(":") == 1: # Allow hours to be missing, # used at least in the WebVTT format. time = "00:{}".format(time) hours, minutes, seconds = time.split(":") return ("{}{:02.0f}:{:02.0f}:{:02.0f}.{:03.0f}" .format(sign, int(hours), int(minutes), int(float(seconds)), (float(seconds) % 1) * 1000)) def round(self, pos, ndigits): """ Round `pos` to given precision in decimal digits. `ndigits` may be negative. For frames zero will be used if given `ndigits` is greater than zero. """ if aeidon.is_time(pos): pos = self.time_to_seconds(pos) pos = round(pos, ndigits) return self.seconds_to_time(pos) if aeidon.is_frame(pos): ndigits = min(0, ndigits) pos = round(pos, ndigits) return aeidon.as_frame(pos) if aeidon.is_seconds(pos): pos = round(pos, ndigits) return aeidon.as_seconds(pos) raise ValueError("Invalid type for pos: {!r}" .format(type(pos))) def seconds_to_frame(self, seconds): """Convert `seconds` to frame.""" return int(round(seconds * self._framerate, 0)) def seconds_to_time(self, seconds): """Convert `seconds` to time.""" sign = "-" if seconds < 0 else "" seconds = abs(round(seconds, 3)) if seconds > 359999.999: return "{}99:59:59.999".format(sign) return ("{}{:02.0f}:{:02.0f}:{:02.0f}.{:03.0f}" .format(sign, seconds // 3600, (seconds % 3600) // 60, int(seconds % 60), (seconds % 1) * 1000)) def time_to_frame(self, time): """Convert `time` to frame.""" seconds = self.time_to_seconds(time) return self.seconds_to_frame(seconds) def time_to_seconds(self, time): """Convert `time` to seconds.""" coefficient = -1 if time.startswith("-") else 1 time = time[1:] if time.startswith("-") else time return coefficient * sum((float(time[ :2]) * 3600, float(time[3:5]) * 60, float(time[6:8]), float(time[9: ]) / 1000)) def to_frame(self, pos): """Convert `pos` to frame.""" if aeidon.is_time(pos): return self.time_to_frame(pos) if aeidon.is_frame(pos): return pos if aeidon.is_seconds(pos): return self.seconds_to_frame(pos) raise ValueError("Invalid type for pos: {!r}" .format(type(pos))) def to_seconds(self, pos): """Convert `pos` to seconds.""" if aeidon.is_time(pos): return self.time_to_seconds(pos) if aeidon.is_frame(pos): return self.frame_to_seconds(pos) if aeidon.is_seconds(pos): return pos raise ValueError("Invalid type for pos: {!r}" .format(type(pos))) def to_time(self, pos): """Convert `pos` to time.""" if aeidon.is_time(pos): return pos if aeidon.is_frame(pos): return self.frame_to_time(pos) if aeidon.is_seconds(pos): return self.seconds_to_time(pos) raise ValueError("Invalid type for pos: {!r}" .format(type(pos))) gaupol-1.11/aeidon/clipboard.py000066400000000000000000000036271422217132500165020ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Internal text clipboard.""" __all__ = ("Clipboard",) class Clipboard: """Internal text clipboard.""" def __init__(self): """Initialize a :class:`Clipboard` instance.""" # List of strings, each being the text of one subtitle. Nones in the # list express that those subtitles are skipped, i.e. the range of # subtitles is not unified, but contains gaps. self._texts = [] def append(self, item): """Append `item` to texts.""" self._texts.append(item) def clear(self): """Clear texts.""" self._texts = [] def get_string(self): """Return texts as one string.""" strings = [x or "" for x in self._texts] return "\n\n".join(strings) def get_texts(self): """Return texts as a list of strings.""" return self._texts[:] def is_empty(self): """Return ``True`` if empty.""" return not bool(self._texts) def set_string(self, string): """Set the list of texts from a single string.""" strings = [x or None for x in string.split("\n\n")] self.set_texts(strings) def set_texts(self, texts): """Set the list of texts.""" self._texts = list(texts) gaupol-1.11/aeidon/containers.py000066400000000000000000000050761422217132500167100ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2008 Osmo Salomaa # # 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 . """Containers for additional format-specific subtitle attributes.""" class SubRip: """ Subtitle box pixel coordinates for extended SubRip format. :ivar x1: Subtitle corner X coordinate in pixels :ivar y1: Subtitle corner Y coordinate in pixels :ivar x2: Subtitle corner X coordinate in pixels :ivar y2: Subtitle corner Y coordinate in pixels """ x1 = 0 y1 = 0 x2 = 0 y2 = 0 class SubStationAlpha: """ Attributes for all versions of Sub Station Alpha formats. :ivar marked: 0 for not marked or 1 for marked (default 0) :ivar layer: Layer used by collusion detection (default 0) :ivar style: Style name (default "Default") :ivar name: Name of the character speaking (default "") :ivar margin_l: Left margin override (default 0, i.e. default margins) :ivar margin_r: Right margin override (default 0, i.e. default margins) :ivar margin_v: Bottom margin override (default 0, i.e. default margins) :ivar effect: Transition effect (default "", i.e. no effect) """ marked = 0 layer = 0 style = "Default" name = "" margin_l = 0 margin_r = 0 margin_v = 0 effect = "" class WebVTT: """ Attributes for the WebVTT format. :ivar comment: Optional comment string (including "NOTE") :ivar id: Optional cue identifier :ivar settings: Optional cue settings (position etc.) :ivar style: Optional CSS style block (including "STYLE") https://developer.mozilla.org/en-US/docs/Web/API/WebVTT_API """ comment = "" id = "" settings = "" style = "" def new(name): """Return a new container instance given the container's `name`.""" if name == "ssa": return SubStationAlpha() if name == "subrip": return SubRip() if name == "webvtt": return WebVTT() raise ValueError("Invalid name: {!r}" .format(name)) gaupol-1.11/aeidon/countries.py000066400000000000000000000037731422217132500165600ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Names and ISO 3166 codes for countries and conversions between them.""" import aeidon import json import os from aeidon.i18n import d_ _countries = {} def _init_countries(): """Initialize the dictionary mapping codes to names.""" # Prefer globally installed, fall back on possibly bundled. path = "/usr/share/iso-codes/json/iso_3166-1.json" if os.path.isfile(path): return _init_countries_json(path) path = os.path.join(aeidon.DATA_DIR, "iso-codes", "iso_3166-1.json") if os.path.isfile(path): return _init_countries_json(path) def _init_countries_json(path): """Initialize the dictionary mapping codes to names.""" with open(path, "r", encoding="utf_8") as f: iso = json.load(f) for country in iso["3166-1"]: code = country.get("alpha_2", None) name = country.get("name", None) if not code or not name: continue _countries[code] = name def code_to_name(code): """Convert ISO 3166 `code` to localized country name.""" if not _countries: _init_countries() with aeidon.util.silent(LookupError): return d_("iso_3166", _countries[code]) return code def is_valid(code): """Return ``True`` if `code` is a valid ISO 3166 country code.""" if not _countries: _init_countries() return code in _countries gaupol-1.11/aeidon/deco.py000066400000000000000000000177221422217132500154560ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2006 Osmo Salomaa # # 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 . """Miscellaneous decorators for functions and methods.""" import aeidon import collections import functools import pickle import traceback # Python decorators normally do not preserve the signature of the original # function. We, however, absolutely need those function signatures kept to able # to autogenerate useful API documentation with sphinx. Let's use the # 'decorator' module [1] designed to solve this problem, but only if running # sphinx in order to avoid an unnecessary dependency and to avoid an additional # layer of code with its own runtime speed penalty and potential bugs. # Specifically, let's use the 'decorator_apply' function as instructed [2] to # avoid rewriting our standard-form decorators. # # [1] https://pypi.python.org/pypi/decorator/ # [2] https://decorator.readthedocs.io/en/latest/tests.documentation.html#dealing-with-third-party-decorators def decorator_apply(dec, fun): """Rewrap `dec` to preserve function signature.""" import decorator return decorator.FunctionMaker.create( fun, "return decorated(%(signature)s)", dict(decorated=dec(fun)), __wrapped__=fun) def export(function): """Decorator for delegate functions that are exported to master.""" function.export = True return function if aeidon.RUNNING_SPHINX: _export = export def export(function): return decorator_apply(_export, function) export.__doc__ = _export.__doc__ def _dump_subtitles(subtitles): """Return a tuple of essential attributes of subtitles.""" return tuple((subtitle._start, subtitle._end, subtitle._main_text, subtitle._tran_text, subtitle._framerate) for subtitle in subtitles) def _is_method(function, args): """ Return ``True`` if `function` to be decorated is a method. Decorator is required to have set an `original` attribute on the wrapped method pointing to the original unwrapped function. """ try: method = getattr(args[0], function.__name__) return (method.original is function) except (IndexError, AttributeError): return False def memoize(limit=100): """ Decorator for functions that cache their return values. Use ``None`` for `limit` for a boundless cache. """ # Since 3.2 Python has functools.lru_cache, # but it doesn't seem to handle methods gracefully. def outer_wrapper(function): cache = collections.OrderedDict() @functools.wraps(function) def inner_wrapper(*args, **kwargs): params = (args, kwargs) if _is_method(function, args): # XXX: Is id + hash + repr together unique enough? params = (id(args[0]), hash(args[0]), repr(args[0]), args[1:], kwargs) key = pickle.dumps(params) with aeidon.util.silent(KeyError): return cache[key] cache[key] = function(*args, **kwargs) if limit is not None: while len(cache) > limit: cache.popitem(last=False) return cache[key] inner_wrapper.original = function return inner_wrapper if aeidon.RUNNING_SPHINX: _outer_wrapper = outer_wrapper def outer_wrapper(function): return decorator_apply(_outer_wrapper, function) return outer_wrapper def notify_frozen(function): """Decorator for methods to be run in notify frozen state.""" @functools.wraps(function) def wrapper(*args, **kwargs): frozen = args[0].freeze_notify() try: return function(*args, **kwargs) finally: args[0].thaw_notify(frozen) return wrapper if aeidon.RUNNING_SPHINX: _notify_frozen = notify_frozen def notify_frozen(function): return decorator_apply(_notify_frozen, function) notify_frozen.__doc__ = _notify_frozen.__doc__ def once(function): """Decorator for functions that cache their only return value.""" cache = [] @functools.wraps(function) def wrapper(*args, **kwargs): with aeidon.util.silent(IndexError): return cache[0] cache.append(function(*args, **kwargs)) return cache[0] return wrapper if aeidon.RUNNING_SPHINX: _once = once def once(function): return decorator_apply(_once, function) once.__doc__ = _once.__doc__ def reversion_test(function): """Decorator for unit testing reversions of one action.""" @functools.wraps(function) def wrapper(*args, **kwargs): project = args[0].project original = _dump_subtitles(project.subtitles) value = function(*args, **kwargs) changed = _dump_subtitles(project.subtitles) assert changed != original for i in range(2): project.undo() current = _dump_subtitles(project.subtitles) assert current == original project.redo() current = _dump_subtitles(project.subtitles) assert current == changed return value return wrapper if aeidon.RUNNING_SPHINX: _reversion_test = reversion_test def reversion_test(function): return decorator_apply(_reversion_test, function) reversion_test.__doc__ = _reversion_test.__doc__ def revertable(function): """Decorator for revertable methods of :class:`aeidon.Project`.""" @functools.wraps(function) def wrapper(*args, **kwargs): project = args[0] main_changed = project.main_changed tran_changed = project.tran_changed register = kwargs.setdefault("register", aeidon.registers.DO) if register is None: # Execute plain function for special-case actions # that are not to be pushed to the undo stack. return function(*args, **kwargs) blocked = project.block(register.signal) if not blocked: # Execute plain function for nested function calls # that are part of another revertable action. return function(*args, **kwargs) try: value = function(*args, **kwargs) finally: project.unblock(register.signal) project.cut_reversion_stacks() if (project.main_changed != main_changed or project.tran_changed != tran_changed): project.emit_action_signal(register) return value return wrapper if aeidon.RUNNING_SPHINX: _revertable = revertable def revertable(function): return decorator_apply(_revertable, function) revertable.__doc__ = _revertable.__doc__ def silent(*exceptions, tb=False): """ Decorator for ignoring `exceptions` raised by function. If no exceptions specified, ignore :exc:`Exception`. Return ``None`` if an exception encountered. """ if not exceptions: exceptions = (Exception,) def outer_wrapper(function): @functools.wraps(function) def inner_wrapper(*args, **kwargs): try: return function(*args, **kwargs) except exceptions: if tb: traceback.print_exc() return None return inner_wrapper if aeidon.RUNNING_SPHINX: _outer_wrapper = outer_wrapper def outer_wrapper(function): return decorator_apply(_outer_wrapper, function) return outer_wrapper gaupol-1.11/aeidon/delegate.py000066400000000000000000000027151422217132500163120ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Base class for objects that dispatch ``self``-lookups.""" __all__ = ("Delegate",) class Delegate: """ Base class for objects that dispatch ``self``-lookups. :ivar master: Object to where attribute calls are dispatched """ def __init__(self, master): """Initialize a :class:`Delegate` instance.""" object.__setattr__(self, "master", master) def __getattr__(self, name): """Return value of master attribute.""" return getattr(self.master, name) def __setattr__(self, name, value): """Set value of master attribute.""" # Do not create new attributes for master. if hasattr(self.master, name): return setattr(self.master, name, value) return object.__setattr__(self, name, value) gaupol-1.11/aeidon/encodings.py000066400000000000000000000260611422217132500165110ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """ Codes, names and descriptions of character encodings. For functions dealing with character encodings, see also :mod:`aeidon.util`. """ import aeidon import codecs import locale import re from aeidon.i18n import _ # Tuples of code, name and description for each supported character encoding. # Codes are the official names used by Python. Names are mostly taken from # IANA. Descriptions are mostly copied from gedit. _encodings = ( # TRANSLATORS: Most of the character encoding descriptions are copied from # gedit, which is translated to very many languages. Check the gedit .po # files for a reference: . ("ascii" , "US-ASCII" , _("English")), ("big5" , "Big5" , _("Chinese traditional")), ("big5hkscs" , "Big5-HKSCS" , _("Chinese traditional")), ("cp037" , "IBM037" , _("English")), ("cp273" , "IBM273" , _("German")), ("cp424" , "IBM242" , _("Hebrew")), ("cp437" , "IBM437" , _("English")), ("cp500" , "IBM500" , _("Western")), ("cp720" , "IBM720" , _("Arabic")), ("cp737" , "IBM737" , _("Greek")), ("cp775" , "IBM775" , _("Baltic")), ("cp850" , "IBM850" , _("Western")), ("cp852" , "IBM852" , _("Central European")), ("cp855" , "IBM855" , _("Cyrillic")), ("cp856" , "IBM856" , _("Hebrew")), ("cp857" , "IBM857" , _("Turkish")), ("cp858" , "IBM858" , _("Western")), ("cp860" , "IBM860" , _("Portuguese")), ("cp861" , "IBM861" , _("Icelandic")), ("cp862" , "IBM862" , _("Hebrew")), ("cp863" , "IBM863" , _("Canadian")), ("cp864" , "IBM864" , _("Arabic")), ("cp865" , "IBM865" , _("Nordic")), ("cp866" , "IBM866" , _("Russian")), ("cp869" , "IBM869" , _("Greek")), ("cp874" , "IBM874" , _("Thai")), ("cp875" , "IBM875" , _("Greek")), ("cp932" , "IBM932" , _("Japanese")), ("cp949" , "IBM949" , _("Korean")), ("cp950" , "IBM950" , _("Chinese traditional")), ("cp1006" , "IBM1006" , _("Urdu")), ("cp1026" , "IBM1026" , _("Turkish")), ("cp1125" , "IBM1125" , _("Ukrainian")), ("cp1140" , "IBM1140" , _("Western")), ("cp1250" , "windows-1250" , _("Central European")), ("cp1251" , "windows-1251" , _("Cyrillic")), ("cp1252" , "windows-1252" , _("Western")), ("cp1253" , "windows-1253" , _("Greek")), ("cp1254" , "windows-1254" , _("Turkish")), ("cp1255" , "windows-1255" , _("Hebrew")), ("cp1256" , "windows-1256" , _("Arabic")), ("cp1257" , "windows-1257" , _("Baltic")), ("cp1258" , "windows-1258" , _("Vietnamese")), ("euc_jp" , "EUC-JP" , _("Japanese")), ("euc_jis_2004" , "EUC-JIS-2004" , _("Japanese")), ("euc_jisx0213" , "EUC-JISX0213" , _("Japanese")), ("euc_kr" , "EUC-KR" , _("Korean")), ("gb2312" , "GB2312" , _("Chinese simplified")), ("gbk" , "GBK" , _("Chinese unified")), ("gb18030" , "GB18030" , _("Chinese unified")), ("hz" , "HZ" , _("Chinese simplified")), ("iso2022_jp" , "ISO-2022-JP" , _("Japanese")), ("iso2022_jp_1" , "ISO-2022-JP-1" , _("Japanese")), ("iso2022_jp_2" , "ISO-2022-JP-2" , _("Japanese")), ("iso2022_jp_2004", "ISO-2022-JP-2004", _("Japanese")), ("iso2022_jp_3" , "ISO-2022-JP-3" , _("Japanese")), ("iso2022_jp_ext" , "ISO-2022-JP-EXT" , _("Japanese")), ("iso2022_kr" , "ISO-2022-KR" , _("Korean")), ("latin_1" , "ISO-8859-1" , _("Western")), ("iso8859_2" , "ISO-8859-2" , _("Central European")), ("iso8859_3" , "ISO-8859-3" , _("South European")), ("iso8859_4" , "ISO-8859-4" , _("Baltic")), ("iso8859_5" , "ISO-8859-5" , _("Cyrillic")), ("iso8859_6" , "ISO-8859-6" , _("Arabic")), ("iso8859_7" , "ISO-8859-7" , _("Greek")), ("iso8859_8" , "ISO-8859-8" , _("Hebrew")), ("iso8859_9" , "ISO-8859-9" , _("Turkish")), ("iso8859_10" , "ISO-8859-10" , _("Nordic")), ("iso8859_11" , "ISO-8859-11" , _("Thai")), ("iso8859_13" , "ISO-8859-13" , _("Baltic")), ("iso8859_14" , "ISO-8859-14" , _("Celtic")), ("iso8859_15" , "ISO-8859-15" , _("Western")), ("iso8859_16" , "ISO-8859-16" , _("South European")), ("johab" , "Johab" , _("Korean")), ("koi8_r" , "KOI8-R" , _("Russian")), ("koi8_t" , "KOI8-T" , _("Tajik")), ("koi8_u" , "KOI8-U" , _("Ukrainian")), ("kz1048" , "KZ1048" , _("Kazakh")), ("mac_cyrillic" , "MacCyrillic" , _("Cyrillic")), ("mac_greek" , "MacGreek" , _("Greek")), ("mac_iceland" , "MacIceland" , _("Icelandic")), ("mac_latin2" , "MacCentralEurope", _("Central European")), ("mac_roman" , "MacRoman" , _("Western")), ("mac_turkish" , "MacTurkish" , _("Turkish")), ("ptcp154" , "PTCP154" , _("Cyrillic Asian")), ("shift_jis" , "Shift_JIS" , _("Japanese")), ("shift_jis_2004" , "Shift_JIS-2004" , _("Japanese")), ("shift_jisx0213" , "Shift_JISX0213" , _("Japanese")), ("utf_32" , "UTF-32" , _("Unicode")), ("utf_32_be" , "UTF-32BE" , _("Unicode")), ("utf_32_le" , "UTF-32LE" , _("Unicode")), ("utf_16" , "UTF-16" , _("Unicode")), ("utf_16_be" , "UTF-16BE" , _("Unicode")), ("utf_16_le" , "UTF-16LE" , _("Unicode")), ("utf_7" , "UTF-7" , _("Unicode")), ("utf_8" , "UTF-8" , _("Unicode")), ("utf_8_sig" , "UTF-8-SIG" , _("Unicode")),) CODE, NAME, DESC = range(3) # Illegal characters in encoding codes. _re_illegal = re.compile(r"[^a-z0-9_]") def code_to_description(code): """Convert encoding `code` to localized description.""" for item in _encodings: if item[CODE] == code: return item[DESC] raise ValueError("Code {!r} not found" .format(code)) def code_to_long_name(code): """Convert encoding `code` to localized long name.""" for item in _encodings: if item[CODE] == code: return (_("{description} ({name})") .format(name=item[NAME], description=item[DESC])) raise ValueError("Code {!r} not found" .format(code)) def code_to_name(code): """Convert encoding `code` to name.""" for item in _encodings: if item[CODE] == code: return item[NAME] raise ValueError("Code {!r} not found" .format(code)) def detect(path): """ Detect the encoding of file at `path` and return code or ``None``. Raise :exc:`IOError` if reading fails. """ bom_encoding = detect_bom(path) if bom_encoding is not None: return bom_encoding from chardet import universaldetector detector = universaldetector.UniversalDetector() with open(path, "rb") as f: detector.reset() for line in f: detector.feed(line) if detector.done: break detector.close() code = detector.result["encoding"] if code is None: return None try: # chardet returns what seem to be IANA names. They need to be # translated to their Python equivalents. Some of the encodings # returned by chardet are not supported by Python. return translate_code(code) except ValueError: return None def detect_bom(path): """Return corresponding encoding if BOM found, else ``None``.""" with open(path, "rb") as f: line = f.readline() if (line.startswith(codecs.BOM_UTF32_BE) and is_valid_code("utf_32_be")): return "utf_32_be" if (line.startswith(codecs.BOM_UTF32_LE) and is_valid_code("utf_32_le")): return "utf_32_le" if (line.startswith(codecs.BOM_UTF8) and is_valid_code("utf_8_sig")): return "utf_8_sig" if (line.startswith(codecs.BOM_UTF16_BE) and is_valid_code("utf_16_be")): return "utf_16_be" if (line.startswith(codecs.BOM_UTF16_LE) and is_valid_code("utf_16_le")): return "utf_16_le" return None @aeidon.deco.once def get_locale_code(): """Return code of the locale encoding or ``None``.""" code = locale.getpreferredencoding() if code is None: return None code = _re_illegal.sub("_", code.lower()) code = aeidon.util.get_encoding_alias(code) return code @aeidon.deco.once def get_locale_long_name(): """Return localized long name for locale encoding.""" name = code_to_name(get_locale_code()) return _("Current locale ({})").format(name) @aeidon.deco.once def get_valid(): """Return a list of code, name, description of valid encodings.""" valid_encodings = [] for i, item in enumerate(_encodings): if is_valid_code(item[CODE]): valid_encodings.append(item) return valid_encodings def is_valid_code(code): """Return ``True`` if encoding `code` is valid.""" try: codecs.lookup(code) return True except LookupError: return False def name_to_code(name): """Convert encoding `name` to code.""" for item in _encodings: if item[NAME] == name: return item[CODE] raise ValueError("Name {!r} not found" .format(name)) def translate_code(code): """Return normalized encoding `code`.""" code = _re_illegal.sub("_", code.lower()) code = aeidon.util.get_encoding_alias(code) for item in _encodings: if item[CODE] == code: return item[CODE] raise ValueError("Code {!r} not found" .format(code)) gaupol-1.11/aeidon/enum.py000066400000000000000000000066461422217132500155130ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """ Lists of named constants with integer values. :class:`EnumerationItem`s are subclassed from :class:`int`, so they are actual integers. The string value of an item will be the name that it was defined with in its set. New items can always be added to an enumeration. """ __all__ = ("EnumerationItem", "Enumeration",) class EnumerationItem(int): """ Named constant with an integer value. :class:`EnumerationItem` can be instantiated without any specified values and users need not bother with them. Instantiation with correct values harmonous with the rest of the items should be left up to the parent list. """ def __new__(cls, value=0, name="", parent=None): """Return integer instance with additional attributes.""" instance = int.__new__(cls, value) instance.name = name instance.parent = parent return instance def __bool__(self): """For consistency, always return ``True``.""" return True def __str__(self): """Return name as the string representation.""" return self.name class Enumeration(list): """ List of named constants with integer values. :class:`Enumeration` is an actual :class:`list` where enumeration items are stored as both list items and instance attributes. New items should be added by setting an instance attribute. Typical use to create a new enumeration would be something like:: fruits = aeidon.Enumeration() fruits.APPLE = aeidon.EnumerationItem() fruits.MANGO = aeidon.EnumerationItem() fruits.APPLE.size = 10 fruits.MANGO.size = 20 Note that there is no finalization of an enumeration. New items can always be added just by assigning a new attribute to the enumeration. Likewise, existing items can always be removed using :func:`delattr`. """ NONE = None def __contains__(self, item): """Return ``True`` if enumeration contains `item`.""" return list.__contains__(self, item) def __delattr__(self, name): """Delete enumeration item and attribute.""" list.remove(self, getattr(self, name)) return object.__delattr__(self, name) def find_item(self, name, value): """Return the first found item with the given attribute `value`.""" for item in self: if getattr(item, name) == value: return item raise ValueError("Name {!r} not found".format(name)) def __setattr__(self, name, value): """Set value of enumeration item with correct attributes.""" if isinstance(value, EnumerationItem): value = value.__class__(len(self), name, self) list.append(self, value) return object.__setattr__(self, name, value) gaupol-1.11/aeidon/enums.py000066400000000000000000000235631422217132500156730ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2016 Osmo Salomaa # # 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 . """Miscellanous enumerations.""" import aeidon import os import shutil import sys from aeidon.i18n import _ __all__ = [ "align_methods", "documents", "formats", "framerates", "modes", "newlines", "players", "registers", ] class AlignMethodNumber(aeidon.EnumerationItem): label = _("Subtitle number") class AlignMethodPosition(aeidon.EnumerationItem): label = _("Subtitle position") align_methods = aeidon.Enumeration() align_methods.NUMBER = AlignMethodNumber() align_methods.POSITION = AlignMethodPosition() class DocumentMain(aeidon.EnumerationItem): pass class DocumentTranslation(aeidon.EnumerationItem): pass documents = aeidon.Enumeration() documents.MAIN = DocumentMain() documents.TRAN = DocumentTranslation() class Framerate23976(aeidon.EnumerationItem): label = _("23.976 fps") value = 24 / 1.001 class Framerate24000(aeidon.EnumerationItem): label = _("24.000 fps") value = 24.0 class Framerate25000(aeidon.EnumerationItem): label = _("25.000 fps") value = 25.0 class Framerate29970(aeidon.EnumerationItem): label = _("29.970 fps") value = 30 / 1.001 class Framerate30000(aeidon.EnumerationItem): label = _("30.000 fps") value = 30.0 class Framerate50000(aeidon.EnumerationItem): label = _("50.000 fps") value = 50.0 class Framerate59940(aeidon.EnumerationItem): label = _("59.940 fps") value = 60 / 1.001 class Framerate60000(aeidon.EnumerationItem): label = _("60.000 fps") value = 60.0 framerates = aeidon.Enumeration() framerates.FPS_23_976 = Framerate23976() framerates.FPS_24_000 = Framerate24000() framerates.FPS_25_000 = Framerate25000() framerates.FPS_29_970 = Framerate29970() framerates.FPS_30_000 = Framerate30000() framerates.FPS_50_000 = Framerate50000() framerates.FPS_59_940 = Framerate59940() framerates.FPS_60_000 = Framerate60000() class ModeTime(aeidon.EnumerationItem): pass class ModeFrame(aeidon.EnumerationItem): pass class ModeSeconds(aeidon.EnumerationItem): pass modes = aeidon.Enumeration() modes.TIME = ModeTime() modes.FRAME = ModeFrame() modes.SECONDS = ModeSeconds() class NewlinesMac(aeidon.EnumerationItem): label = _("Mac (classic)") value = "\r" class NewlinesUnix(aeidon.EnumerationItem): label = "Unix" value = "\n" class NewlinesWindows(aeidon.EnumerationItem): label = "Windows" value = "\r\n" newlines = aeidon.Enumeration() newlines.MAC = NewlinesMac() newlines.UNIX = NewlinesUnix() newlines.WINDOWS = NewlinesWindows() def _get_mplayer_executable(): if sys.platform == "win32": directory = os.environ.get("PROGRAMFILES", "C:\\Program Files") path = os.path.join(directory, "MPlayer", "mplayer.exe") return aeidon.util.shell_quote(path) return "mplayer" def _get_mpv_executable(): if sys.platform == "win32": directory = os.environ.get("PROGRAMFILES", "C:\\Program Files") path = os.path.join(directory, "MPV", "mpv.exe") return aeidon.util.shell_quote(path) return "mpv" def _get_vlc_executable(): if sys.platform == "win32": directory = os.environ.get("PROGRAMFILES", "C:\\Program Files") path = os.path.join(directory, "VideoLAN", "VLC", "vlc.exe") return aeidon.util.shell_quote(path) return "vlc" class PlayerMPlayer(aeidon.EnumerationItem): command = " ".join((_get_mplayer_executable(), "-quiet", "-identify", "-osdlevel 2", "-ss $SECONDS", "-slang", "-noautosub", "-sub $SUBFILE", "$VIDEOFILE",)) if sys.platform != "win32": # Required for mplayer to work if gaupol was started # as a background process (&) from a terminal window. # http://www.mplayerhq.hu/DOCS/HTML/en/faq.html#idm5930 command = "{} < /dev/null".format(command) command_utf_8 = " ".join((_get_mplayer_executable(), "-quiet", "-osdlevel 2", "-ss $SECONDS", "-slang", "-noautosub", "-sub $SUBFILE", "-utf8", "$VIDEOFILE",)) if sys.platform != "win32": # Required for mplayer to work if gaupol was started # as a background process (&) from a terminal window. # http://www.mplayerhq.hu/DOCS/HTML/en/faq.html#idm5930 command_utf_8 = "{} < /dev/null".format(command_utf_8) executable = _get_mplayer_executable() found = shutil.which(_get_mplayer_executable()) is not None label = "MPlayer" class PlayerMPV(aeidon.EnumerationItem): command = " ".join((_get_mpv_executable(), "--quiet", "--osd-level=2", "--hr-seek=yes", "--start=$SECONDS", "--sub-file=$SUBFILE", "$VIDEOFILE",)) command_utf_8 = " ".join((_get_mpv_executable(), "--quiet", "--osd-level=2", "--hr-seek=yes", "--start=$SECONDS", "--sub-file=$SUBFILE", "--sub-codepage=utf-8", "$VIDEOFILE",)) executable = _get_mpv_executable() found = shutil.which(_get_mpv_executable()) is not None label = "mpv" class PlayerVLC(aeidon.EnumerationItem): command = " ".join((_get_vlc_executable(), "$VIDEOFILE", ":start-time=$SECONDS", ":sub-file=$SUBFILE",)) command_utf_8 = " ".join((_get_vlc_executable(), "$VIDEOFILE", ":start-time=$SECONDS", ":sub-file=$SUBFILE", ":subsdec-encoding=UTF-8",)) executable = _get_vlc_executable() found = shutil.which(_get_vlc_executable()) is not None label = "VLC" players = aeidon.Enumeration() players.MPLAYER = PlayerMPlayer() players.MPV = PlayerMPV() players.VLC = PlayerVLC() class RegisterDo(aeidon.EnumerationItem): shift = 1 signal = "action-done" class RegisterUndo(aeidon.EnumerationItem): shift = -1 signal = "action-undone" class RegisterRedo(aeidon.EnumerationItem): shift = 1 signal = "action-redone" registers = aeidon.Enumeration() registers.DO = RegisterDo() registers.UNDO = RegisterUndo() registers.REDO = RegisterRedo() class FormatAdvSubStationAlpha(aeidon.EnumerationItem): container = "ssa" extension = ".ass" has_header = True identifier = r"^ScriptType:\s*[vV]4.00\+\s*$" label = "Advanced Sub Station Alpha" mime_type = "text/x-ssa" mode = modes.TIME class FormatLRC(aeidon.EnumerationItem): container = None extension = ".lrc" has_header = True identifier = r"^\[-?\d\d:\d\d\.\d\d\]" label = "LRC" mime_type = "text/plain" mode = modes.TIME class FormatMicroDVD(aeidon.EnumerationItem): container = None extension = ".sub" has_header = True identifier = r"^\{-?\d+\}\{-?\d+\}" label = "MicroDVD" mime_type = "text/x-microdvd" mode = modes.FRAME class FormatMPL2(aeidon.EnumerationItem): container = None extension = ".txt" has_header = False identifier = r"^\[-?\d+\]\[-?\d+\]" label = "MPL2" mime_type = "text/plain" mode = modes.TIME class FormatSubRip(aeidon.EnumerationItem): container = "subrip" extension = ".srt" has_header = False identifier = (r"^-?\d\d:\d\d:\d\d,\d\d\d -->" r" -?\d\d:\d\d:\d\d,\d\d\d" r"( X1:\d+ X2:\d+ Y1:\d+ Y2:\d+)?\s*$") label = "SubRip" mime_type = "application/x-subrip" mode = modes.TIME class FormatSubStationAlpha(aeidon.EnumerationItem): container = "ssa" extension = ".ssa" has_header = True identifier = r"^ScriptType:\s*[vV]4.00\s*$" label = "Sub Station Alpha" mime_type = "text/x-ssa" mode = modes.TIME class FormatSubViewer2(aeidon.EnumerationItem): container = None extension = ".sub" has_header = True identifier = (r"^-?\d\d:\d\d:\d\d\.\d\d" r",-?\d\d:\d\d:\d\d\.\d\d\s*$") label = "SubViewer 2.0" mime_type = "text/x-subviewer" mode = modes.TIME class FormatTMPlayer(aeidon.EnumerationItem): container = None extension = ".txt" has_header = False identifier = r"^-?\d?\d:\d\d:\d\d:" label = "TMPlayer" mime_type = "text/plain" mode = modes.TIME class FormatWebVTT(aeidon.EnumerationItem): container = "webvtt" extension = ".vtt" has_header = True identifier = r"^\s*[wW][eE][bB][vV][tT][tT]\b" label = "WebVTT" mime_type = "text/vtt" mode = modes.TIME formats = aeidon.Enumeration() formats.ASS = FormatAdvSubStationAlpha() formats.LRC = FormatLRC() formats.MICRODVD = FormatMicroDVD() formats.MPL2 = FormatMPL2() formats.SUBRIP = FormatSubRip() formats.SSA = FormatSubStationAlpha() formats.SUBVIEWER2 = FormatSubViewer2() formats.TMPLAYER = FormatTMPlayer() formats.WEBVTT = FormatWebVTT() gaupol-1.11/aeidon/errors.py000066400000000000000000000033131422217132500160470ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """All :mod:`aeidon` error classes.""" __all__ = ( "Error", "AffirmationError", "FormatError", "ParseError", "ProcessError", ) class Error(Exception): """Base class for all :mod:`aeidon` errors.""" pass class AffirmationError(Error): """ Something expected to be ``True`` was ``False``. :exc:`AffirmationError` is like :exc:`AssertionError`, but without the special reliance on :const:`__debug__` and given optimization options. :exc:`AffirmationError` can be used to provide essential checks of boolean values instead of optional debug checks. """ pass class FormatError(Error): """Unrecognized subtitle file format.""" pass class ParseError(Error): """ Failed to parse a subtitle file into positions and texts. :exc:`ParseError` is caused by either a syntax error in the file being parsed or a programming error in the code doing the parsing. """ pass class ProcessError(Error): """Error in an external process.""" pass gaupol-1.11/aeidon/file.py000066400000000000000000000137521422217132500154620ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Base class for subtitle files.""" import aeidon import codecs import os import re __all__ = ("SubtitleFile",) class SubtitleFile: """ Base class for subtitle files. :cvar format: :attr:`aeidon.formats` item corresponding to file format :cvar mode: :attr:`aeidon.modes` item corresponding to native positions :ivar encoding: Character encoding used to read and write file :ivar has_utf_16_bom: True if BOM found for UTF-16-BE or UTF-16-LE :ivar header: String of metadata at the top of the file :ivar newline: :attr:`aeidon.newlines` item, detected upon read :ivar path: Full, absolute path to the file on disk If the file format contains a header, it will default to a fairly blank template header read upon instantiation of the class, from either ``aeidon.DATA_DIR/headers`` or ``aeidon.DATA_HOME_DIR/headers``. If the read file contains a header, it will replace the template. """ format = aeidon.formats.NONE mode = aeidon.modes.NONE def __init__(self, path, encoding, newline=None): """Initialize a :class:`SubtitleFile` instance.""" self.encoding = encoding self.has_utf_16_bom = False self.header = (aeidon.util.get_template_header(self.format) if self.format.has_header else "") self.newline = newline or aeidon.util.get_default_newline() self.path = os.path.abspath(path) def copy_from(self, other): """Copy generic properties from `other`.""" self.has_utf_16_bom = other.has_utf_16_bom if self.format != other.format: return self.header = other.header def _get_subtitle(self): """Return a new subtitle instance with proper properties.""" return aeidon.Subtitle(self.mode) def read(self): """ Read file and return subtitles. Raise :exc:`IOError` if reading fails. Raise :exc:`UnicodeError` if decoding fails. """ raise NotImplementedError def _read_lines(self): """ Read file to a list of lines. All newlines are stripped. All blank lines from beginning and end are removed. Raise :exc:`IOError` if reading fails. Raise :exc:`UnicodeError` if decoding fails. Return a list of lines read. """ re_newline_char = re.compile(r"\r?\n?$") with open(self.path, "r", encoding=self.encoding) as f: lines = f.readlines() lines = [re_newline_char.sub("", x) for x in lines] for index in (0, -1): while lines and not lines[index].strip(): lines.pop(index) newline = aeidon.util.detect_newlines(self.path) if newline is not None: self.newline = newline if self.encoding == "utf_8": bom = str(codecs.BOM_UTF8, "utf_8") if lines and lines[0].startswith(bom): # If a UTF-8 BOM (a.k.a. signature) is found, reread file with # UTF-8-SIG encoding, which automatically strips the BOM when # reading and adds it when writing. self.encoding = "utf_8_sig" return SubtitleFile._read_lines(self) if self.encoding.startswith("utf_16"): # Python automatically strips the UTF-16 BOM when reading, but only # when using UTF-16. If using UTF-16-BE or UTF-16-LE, the BOM is # kept at the beginning of the first line. It is read correctly, so # it should FE FF for both BE and LE. bom = str(codecs.BOM_UTF16_BE, "utf_16_be") if lines and lines[0].startswith(bom): self.has_utf_16_bom = True lines[0] = lines[0].replace(bom, "") # Handle erroneous (?) UTF-16 encoded subtitles that use # NULL-character filled linebreaks '\x00\r\x00\n', which # readlines interprets as two separate linebreaks. if not any(lines[i] for i in range(1, len(lines), 2)): lines = [lines[i] for i in range(0, len(lines), 2)] return lines def write(self, subtitles, doc): """ Write `subtitles` with text from `doc` to file. Raise :exc:`IOError` if writing fails. Raise :exc:`UnicodeError` if encoding fails. """ with aeidon.util.atomic_open(self.path, mode="w", encoding=self.encoding, newline=self.newline.value) as f: # UTF-8-SIG automatically adds the UTF-8 signature BOM. Likewise, # UTF-16 automatically adds the system default BOM, but # UTF-16-BE and UTF-16-LE don't. For the latter two, add the BOM, # if it was originally read in the file. if self.has_utf_16_bom and self.encoding == "utf_16_be": f.write(str(codecs.BOM_UTF16_BE, "utf_16_be")) if self.has_utf_16_bom and self.encoding == "utf_16_le": f.write(str(codecs.BOM_UTF16_LE, "utf_16_le")) self.write_to_file(subtitles, doc, f) def write_to_file(self, subtitles, doc, f): """ Write `subtitles` with text from `doc` to file `f`. Raise :exc:`IOError` if writing fails. Raise :exc:`UnicodeError` if encoding fails. """ raise NotImplementedError gaupol-1.11/aeidon/files/000077500000000000000000000000001422217132500152635ustar00rootroot00000000000000gaupol-1.11/aeidon/files/__init__.py000066400000000000000000000033001422217132500173700ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Subtitle files of all formats.""" import aeidon aeidon.util.install_module("files", lambda: None) from .ssa import SubStationAlpha from .ass import AdvSubStationAlpha from .lrc import LRC from .microdvd import MicroDVD from .mpl2 import MPL2 from .subrip import SubRip from .subviewer2 import SubViewer2 from .tmplayer import TMPlayer from .webvtt import WebVTT __all__ = [ "SubStationAlpha", "AdvSubStationAlpha", "LRC", "MicroDVD", "MPL2", "SubRip", "SubViewer2", "TMPlayer", "WebVTT", ] def add(cls): """Add a new :class:`aeidon.SubtitleFile` class.""" globals()[cls.__name__] = cls __all__.append(cls.__name__) def new(format, path, encoding, newline=None): """Return a new :class:`aeidon.SubtitleFile` instance given `format`.""" for cls in map(eval, __all__): if cls.format == format: return cls(path, encoding, newline) raise ValueError("Format {!r} not found" .format(format)) gaupol-1.11/aeidon/files/ass.py000066400000000000000000000037171422217132500164330ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Advanced Sub Station Alpha file.""" import aeidon __all__ = ("AdvSubStationAlpha",) class AdvSubStationAlpha(aeidon.files.SubStationAlpha): """ Advanced Sub Station Alpha file. :ivar event_fields: Tuple of field names for the ``[Events]`` section """ format = aeidon.formats.ASS def __init__(self, path, encoding, newline=None): """Initialize an :class:`AdvSubStationAlpha` instance.""" aeidon.files.SubStationAlpha.__init__(self, path, encoding, newline) self.event_fields = ( "Layer", "Start", "End", "Style", "Name", "MarginL", "MarginR", "MarginV", "Effect", "Text") def _decode_field(self, field_name, value, subtitle): """Save `value` of field as a subtitle attribute.""" if field_name == "Layer": return setattr(subtitle.ssa, "layer", int(value)) decode = aeidon.files.SubStationAlpha._decode_field return decode(self, field_name, value, subtitle) def _encode_field(self, field_name, subtitle, doc): """Return value of field as string to be written to file.""" if field_name == "Layer": return str(subtitle.ssa.layer) encode = aeidon.files.SubStationAlpha._encode_field return encode(self, field_name, subtitle, doc) gaupol-1.11/aeidon/files/lrc.py000066400000000000000000000051341422217132500164200ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2017 Osmo Salomaa # # 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 . """LRC file.""" import aeidon import re __all__ = ("LRC",) class LRC(aeidon.SubtitleFile): """ LRC file. https://en.wikipedia.org/wiki/LRC_(file_format) """ format = aeidon.formats.LRC mode = aeidon.modes.TIME _re_line = re.compile(r"^\[(-?\d\d:\d\d.\d\d)\](.*)$") def read(self): """ Read file and return subtitles. Raise :exc:`IOError` if reading fails. Raise :exc:`UnicodeError` if decoding fails. """ self.header = "" subtitles = [self._get_subtitle()] for line in self._read_lines(): match = self._re_line.match(line) if match is None and len(subtitles) == 1: # Read line into file header. if self.header: self.header += "\n" self.header += line elif match is not None: subtitle = self._get_subtitle() normalize = subtitle.calc.normalize_time subtitle.start_time = normalize(match.group(1)) subtitles[-1].end_time = subtitle.start_time subtitle.main_text = match.group(2) or "" subtitles.append(subtitle) subtitles[-1].duration_seconds = 5 return subtitles[1:] def write_to_file(self, subtitles, doc, f): """ Write `subtitles` from `doc` to file `f`. Raise :exc:`IOError` if writing fails. Raise :exc:`UnicodeError` if encoding fails. """ if self.header.strip(): f.write(self.header.strip() + "\n\n") for subtitle in subtitles: start = subtitle.calc.round(subtitle.start_time, 2) sign = "-" if start.startswith("-") else "" first = 4 if start.startswith("-") else 3 start = sign + start[first:-1] text = subtitle.get_text(doc).replace("\n", " ") f.write("[{}]{}\n".format(start, text)) gaupol-1.11/aeidon/files/microdvd.py000066400000000000000000000043051422217132500174460ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """MicroDVD file.""" import aeidon import re __all__ = ("MicroDVD",) class MicroDVD(aeidon.SubtitleFile): """MicroDVD file.""" format = aeidon.formats.MICRODVD mode = aeidon.modes.FRAME _re_line = re.compile(r"^\{(-?\d+)\}\{(-?\d+)\}(.*?)$") def read(self): """ Read file and return subtitles. Raise :exc:`IOError` if reading fails. Raise :exc:`UnicodeError` if decoding fails. """ subtitles = [] for line in self._read_lines(): match = self._re_line.match(line) if match is not None: subtitle = self._get_subtitle() subtitle.start_frame = int(match.group(1)) subtitle.end_frame = int(match.group(2)) subtitle.main_text = match.group(3).replace("|", "\n") subtitles.append(subtitle) elif line.startswith("{DEFAULT}"): self.header = line return subtitles def write_to_file(self, subtitles, doc, f): """ Write `subtitles` from `doc` to file `f`. Raise :exc:`IOError` if writing fails. Raise :exc:`UnicodeError` if encoding fails. """ if self.header.strip(): f.write(self.header + "\n") for subtitle in subtitles: text = subtitle.get_text(doc).replace("\n", "|") f.write(("{{{:d}}}{{{:d}}}{}\n" .format(subtitle.start_frame, subtitle.end_frame, text))) gaupol-1.11/aeidon/files/mpl2.py000066400000000000000000000040471422217132500165140ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """MPL2 file.""" import aeidon import re __all__ = ("MPL2",) class MPL2(aeidon.SubtitleFile): """MPL2 file.""" format = aeidon.formats.MPL2 mode = aeidon.modes.TIME _re_line = re.compile(r"^\[(-?\d+)\]\[(-?\d+)\](.*?)$") def read(self): """ Read file and return subtitles. Raise :exc:`IOError` if reading fails. Raise :exc:`UnicodeError` if decoding fails. """ subtitles = [] for line in self._read_lines(): match = self._re_line.match(line) if match is None: continue subtitle = self._get_subtitle() subtitle.start_seconds = float(match.group(1)) / 10 subtitle.end_seconds = float(match.group(2)) / 10 subtitle.main_text = match.group(3).replace("|", "\n") subtitles.append(subtitle) return subtitles def write_to_file(self, subtitles, doc, f): """ Write `subtitles` from `doc` to file `f`. Raise :exc:`IOError` if writing fails. Raise :exc:`UnicodeError` if encoding fails. """ for subtitle in subtitles: text = subtitle.get_text(doc).replace("\n", "|") f.write(("[{:.0f}][{:.0f}]{}\n" .format(subtitle.start_seconds * 10, subtitle.end_seconds * 10, text))) gaupol-1.11/aeidon/files/ssa.py000066400000000000000000000131361422217132500164270ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Sub Station Alpha file.""" import aeidon import re __all__ = ("SubStationAlpha",) class SubStationAlpha(aeidon.SubtitleFile): """ Sub Station Alpha file. :ivar event_fields: Tuple of field names for the ``[Events]`` section """ format = aeidon.formats.SSA mode = aeidon.modes.TIME _re_file_time = re.compile(r"^(-?)(.+)$") _re_separator = re.compile(r",\s*") _re_subtitle_time = re.compile(r"(-?)\d(.{10})\d") def __init__(self, path, encoding, newline=None): """Initialize a :class:`SubStationAlpha` instance.""" aeidon.SubtitleFile.__init__(self, path, encoding, newline) self.event_fields = ( "Marked", "Start", "End", "Style", "Name", "MarginL", "MarginR", "MarginV", "Effect", "Text") def copy_from(self, other): """Copy generic properties from `other` file.""" aeidon.SubtitleFile.copy_from(self, other) if self.format != other.format: return self.event_fields = tuple(other.event_fields) def _decode_field(self, field_name, value, subtitle): """Save string `value` from file as a subtitle attribute.""" if field_name == "Marked": value = int(value.split("=")[-1]) return setattr(subtitle.ssa, "marked", value) if field_name == "Start": value = self._re_file_time.sub(r"\1\060\2\060", value) return setattr(subtitle, "start_time", value) if field_name == "End": value = self._re_file_time.sub(r"\1\060\2\060", value) return setattr(subtitle, "end_time", value) if field_name == "Text": value = value.replace("\\n", "\n") value = value.replace("\\N", "\n") return setattr(subtitle, "main_text", value) if field_name in ("MarginL", "MarginR", "MarginV"): name = aeidon.util.title_to_lower_case(field_name) return setattr(subtitle.ssa, name, int(value)) # Set plain string container attribute value. name = aeidon.util.title_to_lower_case(field_name) setattr(subtitle.ssa, name, value) def _encode_field(self, field_name, subtitle, doc): """Return value of field as string to be written to file.""" if field_name == "Marked": return "Marked={:d}".format(subtitle.ssa.marked) if field_name == "Start": value = subtitle.calc.round(subtitle.start_time, 2) return self._re_subtitle_time.sub(r"\1\2", value) if field_name == "End": value = subtitle.calc.round(subtitle.end_time, 2) return self._re_subtitle_time.sub(r"\1\2", value) if field_name == "Text": value = subtitle.get_text(doc) return value.replace("\n", "\\N") if field_name in ("MarginL", "MarginR", "MarginV"): name = aeidon.util.title_to_lower_case(field_name) return "{:04d}".format(getattr(subtitle.ssa, name)) # Return plain string container attribute value. name = aeidon.util.title_to_lower_case(field_name) return getattr(subtitle.ssa, name) def read(self): """ Read file and return subtitles. Raise :exc:`IOError` if reading fails. Raise :exc:`UnicodeError` if decoding fails. """ subtitles = [] lines = self._read_lines() self._read_header(lines) for line in lines: if not line.startswith("Format:"): continue line = line.replace("Format:", "").strip() fields = self._re_separator.split(line) indices = dict((x, fields.index(x)) for x in fields) max_split = len(fields) - 1 for line in lines: if not line.startswith("Dialogue:"): continue line = line.replace("Dialogue:", "").lstrip() values = self._re_separator.split(line, max_split) subtitle = self._get_subtitle() for name, index in indices.items(): self._decode_field(name, values[index], subtitle) subtitles.append(subtitle) self.event_fields = tuple(fields) return subtitles def _read_header(self, lines): """Read header and remove its lines.""" self.header = "" while not lines[0].startswith("[Events]"): self.header += "\n" self.header += lines.pop(0) self.header = self.header.strip() def write_to_file(self, subtitles, doc, f): """ Write `subtitles` from `doc` to file `f`. Raise :exc:`IOError` if writing fails. Raise :exc:`UnicodeError` if encoding fails. """ f.write(self.header + "\n\n") f.write("[Events]\n") fields = ", ".join(self.event_fields) f.write("Format: {}\n".format(fields)) for subtitle in subtitles: f.write("Dialogue: {}\n".format(",".join([ self._encode_field(x, subtitle, doc) for x in self.event_fields]))) gaupol-1.11/aeidon/files/subrip.py000066400000000000000000000076531422217132500171540ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """SubRip file.""" import aeidon import re __all__ = ("SubRip",) class SubRip(aeidon.SubtitleFile): """SubRip file.""" format = aeidon.formats.SUBRIP mode = aeidon.modes.TIME _re_time_line = re.compile(( # Techically all these fields should have fixed widths, but in the # name of being liberal in accepting input, accept lesser widths # assuming that they are just lacking zero-padding from the side # that is farther from the decimal point. r"^(-?\d{1,2}:\d{1,2}:\d{1,2},\d{1,3}) -->" r" (-?\d{1,2}:\d{1,2}:\d{1,2},\d{1,3})" r"( X1:(\d+) X2:(\d+) Y1:(\d+) Y2:(\d+))?\s*$")) def read(self): """ Read file and return subtitles. Raise :exc:`IOError` if reading fails. Raise :exc:`UnicodeError` if decoding fails. """ subtitles = [] for line in self._read_lines(): match = self._re_time_line.match(line) if match is None: if subtitles[-1].main_text: subtitles[-1].main_text += "\n" subtitles[-1].main_text += line continue subtitle = self._get_subtitle() subtitle.start_time = subtitle.calc.normalize_time(match.group(1)) subtitle.end_time = subtitle.calc.normalize_time(match.group(2)) if match.group(3) is not None: subtitle.subrip.x1 = int(match.group(4)) subtitle.subrip.x2 = int(match.group(5)) subtitle.subrip.y1 = int(match.group(6)) subtitle.subrip.y2 = int(match.group(7)) subtitles.append(subtitle) return subtitles def _read_lines(self): """Read file to a unicoded list of lines.""" lines = ["\n"] for line in aeidon.SubtitleFile._read_lines(self): lines.append(line) match = self._re_time_line.match(line) if match is None: continue # Remove numbers and blank lines above them. if lines[-2].strip().isdigit(): if not lines[-3].strip(): lines.pop(-3) lines.pop(-2) return lines def write_to_file(self, subtitles, doc, f): """ Write `subtitles` from `doc` to file `f`. Raise :exc:`IOError` if writing fails. Raise :exc:`UnicodeError` if encoding fails. """ for i, subtitle in enumerate(subtitles): if i > 0: f.write("\n") f.write("{:d}\n".format(i + 1)) start = subtitle.start_time.replace(".", ",") end = subtitle.end_time.replace(".", ",") f.write("{} --> {}".format(start, end)) # Write Extended SubRip coordinates only if the container # has been initialized and the coordinates make some sense. if subtitle.has_container("subrip"): x1 = subtitle.subrip.x1 x2 = subtitle.subrip.x2 y1 = subtitle.subrip.y1 y2 = subtitle.subrip.y2 if not x1 == x2 == y1 == y2 == 0: f.write(" X1:{:03d} X2:{:03d}".format(x1, x2)) f.write( " Y1:{:03d} Y2:{:03d}".format(y1, y2)) f.write("\n{}\n".format(subtitle.get_text(doc))) gaupol-1.11/aeidon/files/subviewer2.py000066400000000000000000000046361422217132500177430ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """SubViewer 2.0 file.""" import aeidon import re __all__ = ("SubViewer2",) class SubViewer2(aeidon.SubtitleFile): """SubViewer 2.0 file.""" format = aeidon.formats.SUBVIEWER2 mode = aeidon.modes.TIME _re_time_line = re.compile((r"^(-?\d\d:\d\d:\d\d.\d\d)" r",(-?\d\d:\d\d:\d\d.\d\d)\s*$")) def read(self): """ Read file and return subtitles. Raise :exc:`IOError` if reading fails. Raise :exc:`UnicodeError` if decoding fails. """ self.header = "" subtitles = [] lines = self._read_lines() while lines[0].startswith("["): self.header += "\n" self.header += lines.pop(0) self.header = self.header.lstrip() for i, line in enumerate(lines + [""]): match = self._re_time_line.match(line) if match is None: continue subtitle = self._get_subtitle() subtitle.start_time = match.group(1) + "0" subtitle.end_time = match.group(2) + "0" text = lines[i+1].replace("[br]", "\n") subtitle.main_text = text subtitles.append(subtitle) return subtitles def write_to_file(self, subtitles, doc, f): """ Write `subtitles` from `doc` to file `f`. Raise :exc:`IOError` if writing fails. Raise :exc:`UnicodeError` if encoding fails. """ f.write(self.header + "\n") for subtitle in subtitles: start = subtitle.calc.round(subtitle.start_time, 2)[:-1] end = subtitle.calc.round(subtitle.end_time, 2)[:-1] text = subtitle.get_text(doc).replace("\n", "[br]") f.write("\n{},{}\n{}\n".format(start, end, text)) gaupol-1.11/aeidon/files/test/000077500000000000000000000000001422217132500162425ustar00rootroot00000000000000gaupol-1.11/aeidon/files/test/__init__.py000066400000000000000000000000001422217132500203410ustar00rootroot00000000000000gaupol-1.11/aeidon/files/test/test_ass.py000066400000000000000000000024051422217132500204420ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class TestSubStationAlpha(aeidon.TestCase): format = aeidon.formats.ASS def setup_method(self, method): self.file = aeidon.files.new(self.format, self.new_temp_file(self.format), "ascii") def test_read(self): assert self.file.read() assert self.file.header def test_write(self): self.file.write(self.file.read(), aeidon.documents.MAIN) text = open(self.file.path, "r").read().strip() assert text == self.get_sample_text(self.format) gaupol-1.11/aeidon/files/test/test_lrc.py000066400000000000000000000023121422217132500204310ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2017 Osmo Salomaa # # 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 aeidon class TestLRC(aeidon.TestCase): format = aeidon.formats.LRC name = "lrc" def setup_method(self, method): path = self.new_temp_file(self.format, self.name) self.file = aeidon.files.new(self.format, path, "ascii") def test_read(self): assert self.file.read() def test_write(self): self.file.write(self.file.read(), aeidon.documents.MAIN) text = open(self.file.path, "r").read().strip() assert text == self.get_sample_text(self.format, self.name) gaupol-1.11/aeidon/files/test/test_microdvd.py000066400000000000000000000023431422217132500214640ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class TestMicroDVD(aeidon.TestCase): format = aeidon.formats.MICRODVD def setup_method(self, method): self.file = aeidon.files.new(self.format, self.new_temp_file(self.format), "ascii") def test_read(self): assert self.file.read() def test_write(self): self.file.write(self.file.read(), aeidon.documents.MAIN) text = open(self.file.path, "r").read().strip() assert text == self.get_sample_text(self.format) gaupol-1.11/aeidon/files/test/test_mpl2.py000066400000000000000000000023331422217132500205260ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class TestMPL2(aeidon.TestCase): format = aeidon.formats.MPL2 def setup_method(self, method): self.file = aeidon.files.new(self.format, self.new_temp_file(self.format), "ascii") def test_read(self): assert self.file.read() def test_write(self): self.file.write(self.file.read(), aeidon.documents.MAIN) text = open(self.file.path, "r").read().strip() assert text == self.get_sample_text(self.format) gaupol-1.11/aeidon/files/test/test_ssa.py000066400000000000000000000024051422217132500204420ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class TestSubStationAlpha(aeidon.TestCase): format = aeidon.formats.SSA def setup_method(self, method): self.file = aeidon.files.new(self.format, self.new_temp_file(self.format), "ascii") def test_read(self): assert self.file.read() assert self.file.header def test_write(self): self.file.write(self.file.read(), aeidon.documents.MAIN) text = open(self.file.path, "r").read().strip() assert text == self.get_sample_text(self.format) gaupol-1.11/aeidon/files/test/test_subrip.py000066400000000000000000000024311422217132500211570ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class TestSubRip(aeidon.TestCase): format = aeidon.formats.SUBRIP name = "subrip" def setup_method(self, method): path = self.new_temp_file(self.format, self.name) self.file = aeidon.files.new(self.format, path, "ascii") def test_read(self): assert self.file.read() def test_write(self): self.file.write(self.file.read(), aeidon.documents.MAIN) text = open(self.file.path, "r").read().strip() assert text == self.get_sample_text(self.format, self.name) class TestSubRipExtended(TestSubRip): name = "subrip-extended" gaupol-1.11/aeidon/files/test/test_subviewer2.py000066400000000000000000000024071422217132500217530ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class TestSubViewer2(aeidon.TestCase): format = aeidon.formats.SUBVIEWER2 def setup_method(self, method): self.file = aeidon.files.new(self.format, self.new_temp_file(self.format), "ascii") def test_read(self): assert self.file.read() assert self.file.header def test_write(self): self.file.write(self.file.read(), aeidon.documents.MAIN) text = open(self.file.path, "r").read().strip() assert text == self.get_sample_text(self.format) gaupol-1.11/aeidon/files/test/test_tmplayer.py000066400000000000000000000024741422217132500215170ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class TestTMPlayerOneDigitHour(aeidon.TestCase): format = aeidon.formats.TMPLAYER name = "tmplayer-1" def setup_method(self, method): path = self.new_temp_file(self.format, self.name) self.file = aeidon.files.new(self.format, path, "ascii") def test_read(self): assert self.file.read() def test_write(self): self.file.write(self.file.read(), aeidon.documents.MAIN) text = open(self.file.path, "r").read().strip() assert text == self.get_sample_text(self.format, self.name) class TestTMPlayerTwoDigitHour(TestTMPlayerOneDigitHour): name = "tmplayer-2" gaupol-1.11/aeidon/files/test/test_webvtt.py000066400000000000000000000023231422217132500211660ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2017 Osmo Salomaa # # 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 aeidon class TestWebVTT(aeidon.TestCase): format = aeidon.formats.WEBVTT name = "webvtt" def setup_method(self, method): path = self.new_temp_file(self.format, self.name) self.file = aeidon.files.new(self.format, path, "ascii") def test_read(self): assert self.file.read() def test_write(self): self.file.write(self.file.read(), aeidon.documents.MAIN) text = open(self.file.path, "r").read().strip() assert text == self.get_sample_text(self.format, self.name) gaupol-1.11/aeidon/files/tmplayer.py000066400000000000000000000067021422217132500174770ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2006 Osmo Salomaa # # 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 . """TMPlayer file.""" import aeidon import re __all__ = ("TMPlayer",) class TMPlayer(aeidon.SubtitleFile): """TMPlayer file.""" format = aeidon.formats.TMPLAYER mode = aeidon.modes.TIME _re_one_digit_hour = re.compile(r"^-?\d:\d\d:\d\d:") _re_two_digit_hour = re.compile(r"^-?\d\d:\d\d:\d\d:") def __init__(self, path, encoding, newline=None): """Initialize an :class:`TMPlayer` instance.""" aeidon.SubtitleFile.__init__(self, path, encoding, newline) self.two_digit_hour = True def copy_from(self, other): """Copy generic properties from `other` file.""" aeidon.SubtitleFile.copy_from(self, other) if self.format != other.format: return self.two_digit_hour = other.two_digit_hour def read(self): """ Read file and return subtitles. Raise :exc:`IOError` if reading fails. Raise :exc:`UnicodeError` if decoding fails. """ subtitles = [self._get_subtitle()] for line in self._read_lines(): match = self._re_one_digit_hour.search(line) if match is not None: i = match.span()[1] subtitle = self._get_subtitle() sign = "-" if line.startswith("-") else "" time = line[:i-1] + ".000" if time.startswith("-"): time = time[1:] time = sign + "0" + time subtitle.start_time = time subtitles[-1].end_time = time subtitle.main_text = line[i:].replace("|", "\n") subtitles.append(subtitle) self.two_digit_hour = False match = self._re_two_digit_hour.search(line) if match is not None: i = match.span()[1] subtitle = self._get_subtitle() subtitle.start_time = line[:i-1] + ".000" subtitles[-1].end_time = subtitle.start_time subtitle.main_text = line[i:].replace("|", "\n") subtitles.append(subtitle) self.two_digit_hour = True subtitles[-1].duration_seconds = 5 return subtitles[1:] def write_to_file(self, subtitles, doc, f): """ Write `subtitles` from `doc` to file `f`. Raise :exc:`IOError` if writing fails. Raise :exc:`UnicodeError` if encoding fails. """ for subtitle in subtitles: start = subtitle.calc.round(subtitle.start_time, 0) start = (start[:-4] if self.two_digit_hour else ("-" + start[2:-4] if start.startswith("-") else start[1:-4])) text = subtitle.get_text(doc).replace("\n", "|") f.write("{}:{}\n".format(start, text)) gaupol-1.11/aeidon/files/webvtt.py000066400000000000000000000123561422217132500171570ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2017 Osmo Salomaa # # 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 . """WebVTT file.""" import aeidon import re __all__ = ("WebVTT",) class WebVTT(aeidon.SubtitleFile): """ WebVTT file. https://developer.mozilla.org/en-US/docs/Web/API/WebVTT_API """ format = aeidon.formats.WEBVTT mode = aeidon.modes.TIME _re_comment = re.compile(r"^\s*NOTE\b") _re_style = re.compile(r"^\s*STYLE\b") _re_time_line = re.compile(( # Techically all these fields should have fixed widths, but in the # name of being liberal in accepting input, accept lesser widths # assuming that they are just lacking zero-padding from the side # that is farther from the decimal point. r"^(-?(?:\d{1,2}:)?\d{1,2}:\d{1,2}\.\d{1,3}) -->" r" (-?(?:\d{1,2}:)?\d{1,2}:\d{1,2}\.\d{1,3})" r"(\s+.+)?\s*$")) def read(self): """ Read file and return subtitles. Raise :exc:`IOError` if reading fails. Raise :exc:`UnicodeError` if decoding fails. """ subtitles = [] current = "header" self.header = "" lines = list(self._read_lines()) + [""] for i, line in enumerate(lines): if not line.strip(): # A blank line terminates the preceding block. if current in ("header", "text"): subtitles.append(self._get_subtitle()) current = None elif current == "header": # Header should be one line, but allow a block. if self.header: self.header += "\n" self.header += line elif (self._re_style.match(line) or current == "style"): # Bind CSS styles to following subtitle. subtitle = subtitles[-1] if subtitle.webvtt.style: subtitle.webvtt.style += "\n" subtitle.webvtt.style += line current = "style" elif (self._re_comment.match(line) or current == "comment"): # Bind comments to following subtitle. subtitle = subtitles[-1] if subtitle.webvtt.comment: subtitle.webvtt.comment += "\n" subtitle.webvtt.comment += line current = "comment" elif self._re_time_line.match(line): # Time lines form a block with an optional preceding # cue identifier and following text. subtitle = subtitles[-1] if lines[i-1].strip(): subtitle.webvtt.id = lines[i-1] match = self._re_time_line.match(line) normalize = subtitle.calc.normalize_time subtitle.start_time = normalize(match.group(1)) subtitle.end_time = normalize(match.group(2)) subtitle.webvtt.settings = match.group(3) or "" current = "text" elif current == "text": # Append inividual lines to text block. subtitle = subtitles[-1] if subtitle.main_text: subtitle.main_text += "\n" subtitle.main_text += line # The last blank line has opened a new subtitle without times or text, # which we skip. This also means that any possible styles or comments # after the last actual subtitle are thrown out as well. return subtitles[:-1] def write_to_file(self, subtitles, doc, f): """ Write `subtitles` from `doc` to file `f`. Raise :exc:`IOError` if writing fails. Raise :exc:`UnicodeError` if encoding fails. """ writen = lambda x: f.write(x + "\n") nwriten = lambda x: f.write("\n" + x + "\n") writen(self.header.strip() or "WEBVTT") first = 3 if subtitles[-1].end_seconds < 3600 else 0 for i, subtitle in enumerate(subtitles): if subtitle.webvtt.style: nwriten(subtitle.webvtt.style) if subtitle.webvtt.comment: nwriten(subtitle.webvtt.comment) f.write("\n") if subtitle.webvtt.id: writen(subtitle.webvtt.id) # Write times as MM:SS.SSS if all times are less # than an hour, else the usual HH:MM:SS.SSS. start = subtitle.start_time[first:] end = subtitle.end_time[first:] f.write("{} --> {}".format(start, end)) if subtitle.webvtt.settings: f.write(" {}".format(subtitle.webvtt.settings.strip())) f.write("\n{}\n".format(subtitle.get_text(doc))) gaupol-1.11/aeidon/finder.py000066400000000000000000000147561422217132500160170ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """String and regular expression finder and replacer.""" import re __all__ = ("Finder",) class Finder: """ String and regular expression finder and replacer. :ivar ignore_case: ``True`` to ignore case when finding matches :ivar match: Regular expression object for the latest match of pattern :ivar match_span: Tuple of start and end position for match :ivar pattern: String or regular expression object to find :ivar pos: Current offset from the beginning of the text :ivar replacement: Plain- or regular expression replacement string :ivar text: Target text to find matches of pattern in """ def __init__(self): """Initialize a :class:`Finder` instance.""" self.ignore_case = False self.match = None self.match_span = None self.pattern = None self.pos = None self.replacement = None self.text = None def next(self): """ Find the next match of pattern. Raise :exc:`StopIteration` if no next match found. Return tuple of match start, end position. """ if self.pos is None: # Start new search from beginning. self.pos = 0 if isinstance(self.pattern, str): text = self.text pattern = self.pattern if self.ignore_case: text = text.lower() pattern = pattern.lower() try: index = text.index(pattern, self.pos) except ValueError: raise StopIteration self.match_span = (index, index + len(pattern)) else: # Regular expression match = self.pattern.search(self.text, self.pos) if match is None: raise StopIteration # Avoid getting stuck with zero-length regular expressions. if match.span() == self.match_span == (self.pos, self.pos): if self.pos == len(self.text): raise StopIteration self.pos += 1 return self.next() self.match = match self.match_span = match.span() self.pos = self.match_span[1] return self.match_span def previous(self): """ Find the previous match of pattern. Raise :exc:`StopIteration` if no previous match found. Return tuple of match start, end position. """ if self.pos is None: # Start new search from end. self.pos = len(self.text) if isinstance(self.pattern, str): text = self.text pattern = self.pattern if self.ignore_case: text = text.lower() pattern = pattern.lower() try: index = text.rindex(pattern, 0, self.pos) except ValueError: raise StopIteration self.match_span = (index, index + len(pattern)) else: # Regular expression iterator = self.pattern.finditer(self.text) match = None while True: try: candidate = next(iterator) if candidate.end() > self.pos: raise StopIteration except StopIteration: break match = candidate if match is None: raise StopIteration # Avoid getting stuck with zero-length regular expressions. if match.span() == self.match_span == (self.pos, self.pos): if self.pos == 0: raise StopIteration self.pos -= 1 return self.previous() self.match = match self.match_span = match.span() self.pos = self.match_span[0] return self.match_span def replace(self, next=True): """ Replace the current match of pattern. `next` should be ``True`` to finish at end of match, ``False`` for beginning. Raise :exc:`re.error` if bad replacement. """ a, z = self.match_span orig_length = len(self.text) replacement = self.replacement if not isinstance(self.pattern, str): replacement = self.match.expand(self.replacement) self.text = self.text[:a] + replacement + self.text[z:] shift = len(self.text) - orig_length self.pos = (z + shift) if next else a # Adapt match span to new text length to avoid # getting stuck with zero-length regular expressions. if next and (self.match_span[0] == self.match_span[1]): self.match_span = (self.pos, self.pos) def replace_all(self): """ Replace all occurences of pattern. Raise :exc:`re.error` if bad replacement. Return the amount of substitutions made. """ self.pos = 0 self.match = None self.match_span = None count = 0 while True: try: self.next() except StopIteration: self.pos = len(self.text) self.match_span = None break self.replace() count += 1 return count def set_regex(self, pattern, flags=re.DOTALL|re.MULTILINE): """ Set and use regular expression as pattern. The default value for `flags` is ``DOTALL`` and ``MULTILINE``. ``IGNORECASE`` is automatically added to flags if :attr:`ignore_case` is ``True``. Raise :exc:`re.error` if bad pattern. """ if self.ignore_case: flags = flags | re.IGNORECASE self.pattern = re.compile(pattern, flags) def set_text(self, text): """Set the target text to search in and reset position.""" self.text = text self.match = None self.match_span = None self.pos = None gaupol-1.11/aeidon/i18n.py000066400000000000000000000036751422217132500153250ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 . """Internationalization functions.""" import aeidon import gettext import locale _translation = gettext.NullTranslations() def bind(localedir=aeidon.LOCALE_DIR): """Bind translation domains and initialize gettext.""" with aeidon.util.silent(Exception): # Set locale to the user's default setting. # Might fail on misconfigured systems. locale.setlocale(locale.LC_ALL, "") # Make translations available to the gettext module. gettext.bindtextdomain("gaupol", localedir) gettext.textdomain("gaupol") with aeidon.util.silent(Exception): # Make translations available to GTK as well. # Not available on all platforms. locale.bindtextdomain("gaupol", localedir) locale.textdomain("gaupol") globals()["_translation"] = gettext.translation( "gaupol", localedir=localedir, fallback=True) def _(message): """Return the localized translation of `message`.""" return _translation.gettext(message) def d_(domain, message): """Return the localized translation of `message` from `domain`.""" return gettext.dgettext(domain, message) def n_(singular, plural, n): """Return the localized translation of `singular` or `plural`.""" return _translation.ngettext(singular, plural, n) gaupol-1.11/aeidon/languages.py000066400000000000000000000037711422217132500165110ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Names and ISO 639 codes for languages and conversions between them.""" import aeidon import json import os from aeidon.i18n import d_ _languages = {} def _init_languages(): """Initialize the dictionary mapping codes to names.""" # Prefer globally installed, fall back on possibly bundled. path = "/usr/share/iso-codes/json/iso_639-2.json" if os.path.isfile(path): return _init_languages_json(path) path = os.path.join(aeidon.DATA_DIR, "iso-codes", "iso_639-2.json") if os.path.isfile(path): return _init_languages_json(path) def _init_languages_json(path): """Initialize the dictionary mapping codes to names.""" with open(path, "r", encoding="utf_8") as f: iso = json.load(f) for language in iso["639-2"]: code = language.get("alpha_2", None) name = language.get("name", None) if not code or not name: continue _languages[code] = name def code_to_name(code): """Convert ISO 639 `code` to localized language name.""" if not _languages: _init_languages() with aeidon.util.silent(LookupError): return d_("iso_639", _languages[code]) return code def is_valid(code): """Return ``True`` if `code` is a valid ISO 639 language code.""" if not _languages: _init_languages() return code in _languages gaupol-1.11/aeidon/liner.py000066400000000000000000000255111422217132500156500ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2011 Osmo Salomaa # # 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 . """Breaking lines to a specified width.""" import aeidon import re import sys __all__ = ("Liner",) class Liner(aeidon.Parser): """ Breaking lines to a specified width. :ivar length_func: A function that returns the length of its argument :ivar max_length: Maximum length of a line in units of :attr:`length_func` :ivar max_lines: Maximum preferred amount of lines (may be exceeded) :ivar _penalties: List of penalty pattern dictionaries """ # Reading Donald E. Knuth and Michael F. Plass's "Breaking Paragraphs into # Lines" from "Software--Practice and Experience" vol. 11 from 1981 is # recommended to understand the general problem of breaking a paragraph # of text into lines, the terminology used here as well of boxes, penalties # and demerits and the computational complexity of finding the optimal # solution in each case. Subtitling is in many ways a different # application, which is a lot simpler, but also more ambiguous and # subjective in terms of the minimized demerit measure. _re_multi_space = re.compile(r" {2,}") def __init__(self, re_tag=None, clean_func=None): """Initialize a :class:`Liner` instance.""" aeidon.Parser.__init__(self, re_tag, clean_func) self._penalties = [] self.length_func = len self.max_length = 40 self.max_lines = 3 def _boxes_to_lines(self, boxes, breaks): """Return `boxes` joined to form lines.""" edges = [0] + [x + 1 for x in breaks] + [len(boxes)] return [" ".join(boxes[edges[i]:edges[i+1]]) for i in range(len(edges) - 1)] def _break_lines(self, boxes, penalties, nlines): """ Break `boxes` into lines and return break points and demerit. If keeping all boxes on a single line results in a valid and better result than splitting to `nlines` return an empty list. If no valid break points can be found, return ``None``. """ breaks = self._list_possible_breaks(boxes, penalties, nlines) best_breaks = None best_demerit = sys.maxsize text = " ".join(boxes) if self.length_func(text) <= self.max_length: # Use a valid one-line solution as the benchmark, # that any more-line solution must beat. best_breaks = [] best_demerit = self._calculate_demerit(boxes, penalties, []) if nlines == 1: return best_breaks, best_demerit if nlines == 2: for i in breaks: if penalties[i] > best_demerit: break demerit = self._calculate_demerit(boxes, penalties, [i]) if demerit < best_demerit: best_breaks = [i] best_demerit = demerit return best_breaks, best_demerit # For more than two lines, loop over first break points and # recursively figure out rest of the breaks in each case. for i in breaks: # Use the maximum total negative penalty # that can accumulate from all later breaks. negpen = sorted(x for x in penalties[i+1:] if x < 0) negpen = sum(negpen[:min(len(negpen), nlines - 2)]) if (penalties[i] + negpen) > best_demerit: break value = self._break_lines(boxes[i+1:], penalties[i+1:], nlines-1) if value[0] is None: continue later = [i + 1 + x for x in value[0]] demerit = self._calculate_demerit(boxes, penalties, [i] + later) if demerit < best_demerit: best_breaks = [i] + later best_demerit = demerit return best_breaks, best_demerit def break_lines(self): """Break lines and return text.""" self.text = self.text.replace("\n", " ") self.pattern = self._re_multi_space self.replacement = " " self.replace_all() boxes = self.text.split(" ") if len(boxes) == 1: return self.get_text() penalties = self._detect_penalties(boxes) best_breaks = None best_demerit = sys.maxsize # We can probably handle up to ten lines of text # before finding break points gets intolerably slow. min_nlines = min(2, self.max_lines) max_nlines = min(10, len(boxes)) for nlines in range(min_nlines, max_nlines + 1): breaks, demerit = self._break_lines(boxes, penalties, nlines) if breaks is None: continue if demerit < best_demerit: best_breaks = breaks best_demerit = demerit if nlines < self.max_lines: continue pos = -1 for i in range(len(boxes)): pos = pos + 1 + len(boxes[i]) text = self.text if i in best_breaks: text = text[:pos] + "\n" + text[pos+1:] self.text = text return self.get_text() # If text cannot be broken, return original text. return self.get_text() def _calculate_demerit(self, boxes, penalties, breaks): """Return demerit measure for `boxes` broken by `breaks`.""" nlines = len(breaks) + 1 penalties = [penalties[i] for i in breaks] lines = self._boxes_to_lines(boxes, breaks) lengths = list(map(self.length_func, lines)) mlength = sum(lengths) / len(lengths) xlength = self.max_length # Use two subjective measures of badness: (1) 'deviation', # which is the variance of line lengths relative to the # maximum line length and (2) upside-down 'pyramid', which # is the sum of how much longer each line is than the next. return (sum(penalties) + 50 * sum(((x - mlength) / xlength)**2 for x in lengths) + 50 * sum(((lengths[i] - lengths[i+1]) / xlength)**2 for i in range(len(lengths) - 1) if lengths[i] > lengths[i+1]) + 100 * (nlines-1)**3 + 1000 * max(0, nlines - self.max_lines)**3) def _detect_penalties(self, boxes): """Detect penalties for break points following `boxes`.""" text = " ".join(self._boxes_to_lines(boxes, breaks=[])) textpen = [0] * len(text) for penalty in self._penalties: self.pattern = penalty["regex"] self.pos = 0 while True: try: self.next() except StopIteration: break start, end = self.match.span(penalty["group"]) # Use sum, since in some rare cases multiple # patterns can match the same space. textpen[start] += penalty["value"] penalties = [0] * len(boxes) pos = -1 for i in range(len(boxes) - 1): pos = pos + 1 + len(boxes[i]) penalties[i] = textpen[pos] return penalties @aeidon.deco.memoize(100) def _list_possible_breaks(self, boxes, penalties, nlines): """ Return a list of all possible break points for `boxes`. All break points that would necessarily cause `max_length` to be violated are discarded. Breaks are returned sorted in ascending order of associated `penalties`, so that all remaining breaks can be discarded once a demerit threshold is crossed. """ breaks = list(range(len(boxes) - (nlines - 1))) breakpen = penalties[:len(breaks)] if nlines == 1: return [] if nlines == 2: keep = [False] * len(breaks) for i in range(len(breaks)): lines = self._boxes_to_lines(boxes, breaks=[i]) lengths = map(self.length_func, lines) keep[i] = max(lengths) <= self.max_length breaks = [breaks[i] for i in range(len(breaks)) if keep[i]] breakpen = [breakpen[i] for i in range(len(breakpen)) if keep[i]] # Sort breaks in ascending order by penalties, # so that all remaining breaks can be discarded once # a demerit threshold is crossed. if not breaks: return [] points = sorted(zip(breakpen, breaks)) breakpen, breaks = zip(*points) return(breaks) # For more than two lines, loop over first break points and # recursively figure out rest of the breaks in each case. keep = [False] * len(breaks) for i in range(len(breaks)): lines = self._boxes_to_lines(boxes, breaks=[i]) alength = self.length_func(lines[0]) if alength > self.max_length: break later = self._list_possible_breaks(boxes[i+1:], penalties[i+1:], nlines-1) keep[i] = bool(later) breaks = [breaks[i] for i in range(len(breaks)) if keep[i]] breakpen = [breakpen[i] for i in range(len(breakpen)) if keep[i]] # Sort breaks in ascending order by penalties, # so that all remaining breaks can be discarded once # a demerit threshold is crossed. if not breaks: return [] points = sorted(zip(breakpen, breaks)) breakpen, breaks = zip(*points) return(breaks) def set_penalties(self, penalties): """ Set penalty patterns. `penalties` should be a list of dictionaries with items "pattern", "flags", "group" and "value", where pattern is a regular expression with group parentheses around a space, group is the number of the group in pattern to hold the penalty of value. A negative penalty encourages a break and a positive penalty discourages. """ self._penalties = [] for penalty in penalties: regex = re.compile(penalty["pattern"], penalty["flags"]) self._penalties.append(dict(regex=regex, group=penalty["group"], value=penalty["value"])) def set_text(self, text): """Set the target text to search in and parse it.""" aeidon.Parser.set_text(self, text.strip()) self.text = self.text.strip() gaupol-1.11/aeidon/locales.py000066400000000000000000000043071422217132500161610ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """ Names and codes for locales and conversions between them. Locale codes are of form ``aa[_BB][@Cccc]``, where ``aa`` is a language code, ``BB`` a country code and ``Cccc`` a script. See :mod:`aeidon.languages`, :mod:`aeidon.countries` and :mod:`aeidon.scripts` for details. """ import aeidon import os from aeidon.i18n import _ def code_to_country(code): """Convert locale `code` to localized country name or ``None``.""" if len(code) < 5: return None return aeidon.countries.code_to_name(code[-2:]) def code_to_language(code): """Convert locale `code` to localized language name.""" if len(code) < 2: return None return aeidon.languages.code_to_name(code[:2]) def code_to_name(code): """Convert locale `code` to localized name.""" if len(code) < 5: return code_to_language(code) return (_("{language} ({country})") .format(language=code_to_language(code), country=code_to_country(code))) @aeidon.deco.once def get_system_code(): """Return the locale code preferred by system or ``None``.""" import locale return locale.getdefaultlocale()[0] @aeidon.deco.once def get_system_modifier(): """Return the system default script modifier or ``None``.""" for name in ("LANGUAGE", "LC_ALL", "LC_MESSAGES", "LANG"): value = os.environ.get(name, None) if value and value.count("@") == 1: i = value.index("@") return value[i+1:i+5] # No script modifier found implies the language default script. return None gaupol-1.11/aeidon/markup.py000066400000000000000000000216361422217132500160420ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Base class for text markup.""" import aeidon import re __all__ = ("Markup",) class Markup(aeidon.Singleton): """ Base class for text markup. Markup conversions between different formats are done via an internal format, which has the following BBcode-style tags with angle brackets. Conversions are best done via the ``_decode_*`` and ``_encode_*`` methods rather than hard-coding internal tags in regular expression substitutions. * ``...................`` * ``...................`` * ``...................`` * ``...`` * ``........`` * ``......`` :class:`Markup` is effectively equivalent to a format with no markup and can therefore be merely subclassed with a ``pass``-statement by formats that do not implement any markup. The caller of any tagging methods, e.g. :meth:`bolden`, must be prepared to handle :exc:`NotImplementedError`. """ _flags = re.DOTALL | re.MULTILINE format = aeidon.formats.NONE def bolden(self, text, bounds=None): """Return bolded `text`.""" raise NotImplementedError def clean(self, text): """ Return `text` with less ugly markup. Subclasses can implement this to, for example, remove redundant markup, finetune tag positioning or to join or split tags; in general, whatever that changes the style of the markup but not that of the text. """ return text def colorize(self, text, color, bounds=None): """Return `text` colorized to hexadecimal value.""" raise NotImplementedError def decode(self, text): """Return `text` with markup converted from this to internal format.""" text = self._pre_decode(text) text = self._main_decode(text) return self._post_decode(text) def _decode_apply(self, text, regex, replacement, groups): """ Return `text` with all matches of `regex` replaced. `replacement` may contain one or more of ``{}``, which are replaced with parts of the match as defined by `groups`, a ``tuple`` of numbers. """ orig_text = text match = regex.search(text) if match is None: return text a, z = match.span() new = replacement.format(*tuple(map(match.group, groups))) text = "".join((text[:a], new, text[z:])) if text == orig_text: return text return self._decode_apply(text, regex, replacement, groups) def _decode_b(self, text, pattern, target, flags=0): """Return `text` with bold markup converted to internal format.""" regex = self._get_regex(pattern, flags) replacement = "{}" return self._decode_apply(text, regex, replacement, (target,)) def _decode_c(self, text, pattern, value, target, flags=0): """Return `text` with color markup converted to internal format.""" regex = self._get_regex(pattern, flags) replacement = "{}" return self._decode_apply(text, regex, replacement, (value, target)) def _decode_f(self, text, pattern, value, target, flags=0): """Return `text` with font markup converted to internal format.""" regex = self._get_regex(pattern, flags) replacement = "{}" return self._decode_apply(text, regex, replacement, (value, target)) def _decode_i(self, text, pattern, target, flags=0): """Return `text` with italic markup converted to internal format.""" regex = self._get_regex(pattern, flags) replacement = "{}" return self._decode_apply(text, regex, replacement, (target,)) def _decode_s(self, text, pattern, value, target, flags=0): """Return `text` with size markup converted to internal format.""" regex = self._get_regex(pattern, flags) replacement = "{}" return self._decode_apply(text, regex, replacement, (value, target)) def _decode_u(self, text, pattern, target, flags=0): """Return `text` with underline markup converted to internal format.""" regex = self._get_regex(pattern, flags) replacement = "{}" return self._decode_apply(text, regex, replacement, (target,)) def encode(self, text): """Return `text` with markup converted from internal to this format.""" text = self._encode_b(text) text = self._encode_c(text) text = self._encode_f(text) text = self._encode_i(text) text = self._encode_s(text) return self._encode_u(text) def _encode_apply(self, text, regex, method, target, value=None): """ Return `text` with internal tags removed and `method` applied. `method` should be one the tagging methods, e.g. meth:`bolden`. `target` and `value` should be group numbers in `regex`. """ orig_text = text match = regex.search(text) if match is None: return text text = regex.sub(r"\{}".format(target), text, 1) a = match.start() z = a + len(match.group(target)) args = (text, (a, z)) if value is not None: args = (text, match.group(value), (a, z)) with aeidon.util.silent(NotImplementedError): text = method(*args) if text == orig_text: return text return self._encode_apply(text, regex, method, target, value) def _encode_b(self, text): """Return `text` with bold markup converted to this format.""" regex = self._get_regex(r"(.*?)") return self._encode_apply(text, regex, self.bolden, 1) def _encode_c(self, text): """Return `text` with color markup converted to this format.""" regex = self._get_regex(r"(.*?)") return self._encode_apply(text, regex, self.colorize, 2, 1) def _encode_f(self, text): """Return `text` with font markup converted to this format.""" regex = self._get_regex(r"(.*?)") return self._encode_apply(text, regex, self.fontify, 2, 1) def _encode_i(self, text): """Return `text` with italic markup converted to this format.""" regex = self._get_regex(r"(.*?)") return self._encode_apply(text, regex, self.italicize, 1) def _encode_s(self, text): """Return `text` with size markup converted to this format.""" regex = self._get_regex(r"(.*?)") return self._encode_apply(text, regex, self.scale, 2, 1) def _encode_u(self, text): """Return `text` with underline markup converted to this format.""" regex = self._get_regex(r"(.*?)") return self._encode_apply(text, regex, self.underline, 1) def fontify(self, text, font, bounds=None): """Return `text` changed to `font`.""" raise NotImplementedError @aeidon.deco.memoize(100) def _get_regex(self, pattern, flags=0): """Return compiled regular expression from cache.""" flags = self._flags | flags return re.compile(pattern, flags) @property def italic_tag(self): """Regular expression for an italic markup tag or ``None``.""" return None def italicize(self, text, bounds=None): """Return italicized `text`.""" raise NotImplementedError def _main_decode(self, text): """Return `text` with decodable markup decoded.""" return text def _post_decode(self, text): """Return `text` with markup finalized after decoding.""" return text def _pre_decode(self, text): """Return `text` with markup prepared for decoding.""" return text def scale(self, text, size, bounds=None): """Return `text` scaled to `size`.""" raise NotImplementedError def _substitute(self, text, pattern, replacement, flags=0): """Return `text` with matches of `pattern` replaced.""" regex = self._get_regex(pattern, flags) return regex.sub(replacement, text) @property def tag(self): """Regular expression for any markup tag or ``None``.""" return None def underline(self, text, bounds=None): """Return underlined `text`.""" raise NotImplementedError gaupol-1.11/aeidon/markupconv.py000066400000000000000000000024421422217132500167220ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Subtitle text markup converter.""" import aeidon __all__ = ("MarkupConverter",) class MarkupConverter: """Subtitle text markup converter.""" def __init__(self, from_format, to_format): """ Initialize a :class:`MarkupConverter` instance. `from_format` and `to_format` should be :attr:`aeidon.formats` enumeration items. """ self._from = aeidon.markups.new(from_format) self._to = aeidon.markups.new(to_format) def convert(self, text): """Return `text` with markup converted.""" return self._to.encode(self._from.decode(text)) gaupol-1.11/aeidon/markups/000077500000000000000000000000001422217132500156435ustar00rootroot00000000000000gaupol-1.11/aeidon/markups/__init__.py000066400000000000000000000031761422217132500177630ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Text markup of all formats.""" import aeidon aeidon.util.install_module("markups", lambda: None) from .ssa import SubStationAlpha from .ass import AdvSubStationAlpha from .lrc import LRC from .microdvd import MicroDVD from .mpl2 import MPL2 from .subrip import SubRip from .subviewer2 import SubViewer2 from .tmplayer import TMPlayer from .webvtt import WebVTT __all__ = [ "SubStationAlpha", "AdvSubStationAlpha", "LRC", "MicroDVD", "MPL2", "SubRip", "SubViewer2", "TMPlayer", "WebVTT", ] def add(cls): """Add a new :class:`aeidon.Markup` class.""" globals()[cls.__name__] = cls __all__.append(cls.__name__) def new(format): """Return a new :class:`aeidon.Markup` instance given `format`.""" for cls in map(eval, __all__): if cls.format == format: return cls() raise ValueError("Format {!r} not found" .format(format)) gaupol-1.11/aeidon/markups/ass.py000066400000000000000000000041201422217132500170000ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Text markup for the Advanced Sub Station Alpha format.""" import aeidon __all__ = ("AdvSubStationAlpha",) class AdvSubStationAlpha(aeidon.markups.SubStationAlpha): """ Text markup for the Advanced Sub Station Alpha format. In addition to the markup in Sub Station Alpha, Advanced Sub Station Alpha contains a whole lof of markup tags of which the following are of interest to us. The further complicated color tags that define numbered (?) colors and alpha channels are ignored. The reset tag is allowed a style definiton, e.g. ``{\\rDefault}`` to revert to style "Default". * ``{\\bWEIGHT}...{\\b0}`` * ``{\\u1}........{\\u0}`` * ``........{\\r[STYLE]}`` """ format = aeidon.formats.ASS _closing_pattern = r"\{\\([biu])0\}" _opening_pattern = r"\{\\(?![biu]0)(b|i|u|c|fn|fs).*?\}" _reset_pattern = r"\{\\r.*?\}" def _main_decode(self, text): """Return `text` with decodable markup decoded.""" text = self._decode_b(text, r"\{\\b[1-9]\d*\}(.*?)\{\\b[0\\]\}", 1) text = self._decode_u(text, r"\{\\u1\}(.*?)\{\\u[0\\]\}", 1) return aeidon.markups.SubStationAlpha._main_decode(self, text) def underline(self, text, bounds=None): """Return underlined `text`.""" a, z = bounds or (0, len(text)) target = "{{\\u1}}{}{{\\u0}}".format(text[a:z]) return "".join((text[:a], target, text[z:])) gaupol-1.11/aeidon/markups/lrc.py000066400000000000000000000016421422217132500170000ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2017 Osmo Salomaa # # 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 . """Text markup for the LRC format.""" import aeidon __all__ = ("LRC",) class LRC(aeidon.Markup): """ Text markup for the LRC format. LRC format is assumed to contain no markup. """ format = aeidon.formats.LRC gaupol-1.11/aeidon/markups/microdvd.py000066400000000000000000000145101422217132500200250ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Text markup for the MicroDVD format.""" import aeidon __all__ = ("MicroDVD",) class MicroDVD(aeidon.Markup): """ Text markup for the MicroDVD format. The MicroDVD format contains a lot of markup tags, of which the following are of interest to us. Tags that start with a lower case letter end at the end of the line, upper case ones at the end of the subtitle. * ``{c:$BBGGRR}..., {C:$BBGGRR}...`` * ``{f:NAME}......, {F:NAME}......`` * ``{s:SIZE}......, {S:SIZE}......`` * ``{y:STYLE}....., {Y:STYLE}.....`` Note the reverse order of the color tag, ``BBGGRR`` instead of the normal ``RRGGBB``. ``STYLE`` in the ``y`` is a string containing one or more of the letters "b", "i" and "u" and any amount of any possible separators or other characters. """ format = aeidon.formats.MICRODVD def bolden(self, text, bounds=None): """Return bolded `text`.""" return self._style(text, "Y", "y", "b", bounds) def colorize(self, text, color, bounds=None): """Return `text` colorized to hexadecimal value.""" # Reverse the color value from RRGGBB to BBGGRR. color = "${}{}{}".format(color[4:], color[2:4], color[:2]) return self._style(text, "C", "c", color, bounds) def fontify(self, text, font, bounds=None): """Return `text` changed to `font`.""" return self._style(text, "F", "f", font, bounds) @property def italic_tag(self): """Regular expression for an italic markup tag.""" return self._get_regex(r"\{[Yy]:i\}") def italicize(self, text, bounds=None): """Return italicized `text`.""" return self._style(text, "Y", "y", "i", bounds) def _main_decode(self, text): """Return `text` with decodable markup decoded.""" text = self._decode_b(text, r"\{([Yy]:b)\}(.*?)\{/\1\}", 2) text = self._decode_c(text, r"\{([Cc]:#(.*?))\}(.*?)\{/\1\}", 2, 3) text = self._decode_f(text, r"\{([Ff]:(.*?))\}(.*?)\{/\1\}", 2, 3) text = self._decode_i(text, r"\{([Yy]:i)\}(.*?)\{/\1\}", 2) text = self._decode_s(text, r"\{([Ss]:(.*?))\}(.*?)\{/\1\}", 2, 3) text = self._decode_u(text, r"\{([Yy]:u)\}(.*?)\{/\1\}", 2) return text def _pre_decode(self, text): """Return `text` with markup prepared for decoding.""" text = self._pre_decode_break(text) text = self._pre_decode_color(text) text = self._pre_decode_close(text) return text def _pre_decode_break(self, text): """ Return `text` with combined markup tags separated. For example, ``{y:biu}`` is replaced with ``{y:b}{y:i}{y:u}``. """ pattern = r"\{([Yy]):([^}]{2,})\}" regex = self._get_regex(pattern) match = regex.search(text) if match is None: return text y = match.group(1) replacement = "" for m in ("b", "i", "u"): if m in match.group(2): replacement += "{{{}:{}}}".format(y, m) text = regex.sub(replacement, text, 1) return self._pre_decode_break(text) def _pre_decode_close(self, text): """ Return `text` with all markup tags closed. The artificial closing tags are of form ``{/X:VALUE}``. """ # Add lower case closing tags to the end of each line. lines = text.split("\n") re_tag = self._get_regex(r"\{([cfsy]:.*?)\}") for i, line in enumerate(lines): matches = [x for x in re_tag.finditer(line)] for j in reversed(range(len(matches))): lines[i] += "{{/{}}}".format(matches[j].group(1)) text = "\n".join(lines) # Add upper case closing tags to the end of the text. re_tag = self._get_regex(r"\{([CFSY]:.*?)\}") matches = [x for x in re_tag.finditer(text)] for j in reversed(range(len(matches))): text += "{{/{}}}".format(matches[j].group(1)) return text def _pre_decode_color(self, text): """ Return `text` with colors converted to standard hexadecimal form. Color tags are converted from ``{c:$BBGGRR}`` to ``{c:#RRGGBB}``. """ regex = self._get_regex(r"\{([Cc]:)\$([0-9A-Fa-f]{6})\}") match = regex.search(text) if match is None: return text color = match.group(2) color = "{}{}{}".format(color[4:], color[2:4], color[:2]) text = regex.sub(r"{{\1#{}}}".format(color), text, 1) return self._pre_decode_color(text) def scale(self, text, size, bounds=None): """Return `text` scaled to `size`.""" return self._style(text, "S", "s", str(size), bounds) def _style(self, text, upper, lower, value, bounds=None): """Return `text` wrapped in ``upper`` or ``lower`` markup tag.""" a, z = bounds or (0, len(text)) prefix = text[:a].split("\n")[-1] suffix = text[z:].split("\n")[0] re_alpha = self._get_regex(r"\w") # Return plain text if bounds does not define an entire line or # subtitle and thus cannot be marked without side-effects. if re_alpha.search(prefix): return text if re_alpha.search(suffix): return text if (not "\n" in text) or ("\n" in text[a:z]): tag = "{{{}:{}}}".format(upper, value) else: tag = "{{{}:{}}}".format(lower, value) return "".join((text[:a], "{}{}".format(tag, text[a:]))) @property def tag(self): """Regular expression for any markup tag.""" return self._get_regex(r"\{[CFSYcfsy]:.*?\}") def underline(self, text, bounds=None): """Return underlined `text`.""" return self._style(text, "Y", "y", "u", bounds) gaupol-1.11/aeidon/markups/mpl2.py000066400000000000000000000074731422217132500171020ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Text markup for the MPL2 format.""" import aeidon from collections import OrderedDict __all__ = ("MPL2",) class MPL2(aeidon.markups.MicroDVD): """ Text markup for the MPL2 format. MPL2 contains the following markup tags, all of which appear at the beginning of the line and affect up to the end of the line. In addition, any MicroDVD markup can be used. * ``\\...`` (bold) * ``/....`` (italic) * ``_....`` (underline) """ format = aeidon.formats.MPL2 def bolden(self, text, bounds=None): """Return bolded `text`.""" return self._style_mpl2(text, "\\", bounds) @property def italic_tag(self): """Regular expression for an italic markup tag.""" return self._get_regex(r"(^/)|(\{[Yy]:i\})") def italicize(self, text, bounds=None): """Return italicized `text`.""" return self._style_mpl2(text, "/", bounds) def _main_decode(self, text): """Return `text` with decodable markup decoded.""" text = self._decode_b(text, r"<\\>(.*?)", 1) text = self._decode_i(text, r"(.*?)", 1) text = self._decode_u(text, r"<_>(.*?)", 1) return aeidon.markups.MicroDVD._main_decode(self, text) def _pre_decode(self, text): """Return `text` with markup prepared for decoding.""" text = self._pre_decode_identify(text) return aeidon.markups.MicroDVD._pre_decode(self, text) def _pre_decode_identify(self, text): """ Return `text` with all tags identified and closed. ``\\``, ``/`` and ``_`` characters at the beginnings of lines are identified as tags and replaced with artificial tags ``<\\>``, ```` and ``<_>``. Closing tags are added to the ends of lines as artificial tags ````, ```` and ````. """ lines = text.split("\n") re_tag = self._get_regex(r"^([\\/_]+)(.*)$") for i, line in enumerate(lines): match = re_tag.search(line) if match is None: continue lines[i] = match.group(2) for tag in reversed(OrderedDict.fromkeys(match.group(1))): lines[i] = "<{}>{}".format(tag, lines[i], tag) return "\n".join(lines) def _style_mpl2(self, text, tag, bounds=None): """Return `text` wrapped in markup `tag`.""" a, z = bounds or (0, len(text)) prefix = text[:a].split("\n")[-1] suffix = text[z:].split("\n")[0] re_alpha = self._get_regex(r"\w") # Return plain text if bounds does not define an entire line or # subtitle and thus cannot be marked without side-effects. if re_alpha.search(prefix): return text if re_alpha.search(suffix): return text styled_text = text[a:z].replace("\n", "\n{}".format(tag)) return "".join((text[:a], tag, styled_text, text[z:])) @property def tag(self): """Regular expression for any markup tag.""" return self._get_regex(r"(^[\\/_]+)|(\{[CFSYcfsy]:.*?\})") def underline(self, text, bounds=None): """Return underlined `text`.""" return self._style_mpl2(text, "_", bounds) gaupol-1.11/aeidon/markups/ssa.py000066400000000000000000000157271422217132500170170ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Text markup for the Sub Station Alpha format.""" import aeidon import re __all__ = ("SubStationAlpha",) class SubStationAlpha(aeidon.Markup): """ Text markup for the Sub Station Alpha format. Sub Station Alpha format contains a lot of markup tags of which the following are of interest to us. The generic reset ``{\\r}`` is used to revert to regular text, i.e. to close all open tags. Most of the tagging methods, e.g. :meth:`colorize`, leave tags unclosed, instead of explicitly closing them and possibly other tags with ``{\\r}``. Usually this is not a problem as such tags tend to be applied to the whole subtitle. * ``{\\b1}...........{\\b0}`` * ``{\\i1}...........{\\i0}`` * ``{\\fnNAME}............`` * ``{\\fsPOINTS}..........`` * ``{\\c&HBBGGRR&}........`` * ``.................{\\r}`` The hexadecimal color value is in reverse order, ``BBGGRR`` instead of the normal ``RRGGBB``. Furthermore, leading zeros can be omitted, e.g. ``ff00`` can be used instead of ``00ff00``. """ _flags = re.DOTALL | re.MULTILINE | re.IGNORECASE format = aeidon.formats.SSA # Defined here so that AdvSubStationAlpha can override them. _closing_pattern = r"\{\\([bi])0\}" _opening_pattern = r"\{\\(?![bi]0)(b|i|c|fn|fs).*?\}" _reset_pattern = r"\{\\r\}" def bolden(self, text, bounds=None): """Return bolded `text`.""" a, z = bounds or (0, len(text)) target = "{{\\b1}}{}{{\\b0}}".format(text[a:z]) return "".join((text[:a], target, text[z:])) def colorize(self, text, color, bounds=None): """Return `text` colorized to hexadecimal value.""" a, z = bounds or (0, len(text)) # Reverse the color value from RRGGBB to BBGGRR. color = "{}{}{}".format(color[4:], color[2:4], color[:2]) target = "{{\\c&H{}&}}{}".format(color, text[a:z]) return "".join((text[:a], target, text[z:])) def fontify(self, text, font, bounds=None): """Return `text` changed to `font`.""" a, z = bounds or (0, len(text)) target = "{{\\fn{}}}{}".format(font, text[a:z]) return "".join((text[:a], target, text[z:])) @property def italic_tag(self): """Regular expression for an italic markup tag.""" return self._get_regex(r"\{\\i[01]\}") def italicize(self, text, bounds=None): """Return italicized `text`.""" a, z = bounds or (0, len(text)) target = "{{\\i1}}{}{{\\i0}}".format(text[a:z]) return "".join((text[:a], target, text[z:])) def _main_decode(self, text): """Return `text` with decodable markup decoded.""" text = self._decode_b(text, r"\{\\b1\}(.*?)\{\\b[0\\]\}", 1) text = self._decode_c(text, r"\{\\c#(.+?)\}(.*?)\{\\c\\\}", 1, 2) text = self._decode_f(text, r"\{\\fn(.+?)\}(.*?)\{\\fn\\\}", 1, 2) text = self._decode_i(text, r"\{\\i1\}(.*?)\{\\i[0\\]\}", 1) text = self._decode_s(text, r"\{\\fs(\d+)\}(.*?)\{\\fs\\\}", 1, 2) return text def _post_decode(self, text): """Return `text` with markup finalized after decoding.""" # Remove all unsupported markup tags. return self._substitute(text, r"\{\\.*?\}", "") def _pre_decode(self, text): """Return `text` with markup prepared for decoding.""" text = self._pre_decode_break(text) text = self._pre_decode_reset(text) text = self._pre_decode_color(text) return text def _pre_decode_break(self, text): """ Return `text` with combined markup tags separated. For example, ``{\\b1\\i1}`` is replaced with ``{\\b1}{\\i1}``. """ parts = text.split("\\") for i in range(1, len(parts)): text_so_far = "\\".join(parts[:i]) if text_so_far.endswith("{"): continue opening_index = text_so_far.rfind("{") closing_index = text_so_far.rfind("}") if opening_index > closing_index: parts[i - 1] += "}{" return "\\".join(parts) def _pre_decode_color(self, text): """ Return `text` with colors converted to standard hexadecimal form. Color tags are converted from ``{\\c&HBBGGRR&}`` to ``{\\c#RRGGBB}``. """ pattern = r"\{\\c&H([0-9a-fA-F]*)&\}" regex = self._get_regex(pattern) match = regex.search(text) if match is None: return text color = ("{:0>6s}".format(match.group(1))).replace(" ", "0") color = "{}{}{}".format(color[4:], color[2:4], color[:2]) text = regex.sub(r"{{\\c#{}}}".format(color), text, 1) return self._pre_decode_color(text) def _pre_decode_reset(self, text): """ Return `text` with all markup tags closed explicitly. Tags of form ``{\\nameVALUE}`` are closed with ``{\\name\\}``. The returned text will not contain reset ``{\\r}`` tags. """ re_opening = self._get_regex(self._opening_pattern) re_closing = self._get_regex(self._closing_pattern) re_reset = self._get_regex(self._reset_pattern) parts = re_reset.split(text + "{\\r}") for i, part in enumerate(parts): opening_matches = [x for x in re_opening.finditer(part)] closing_matches = [x for x in re_closing.finditer(part)] # Find out which tags have already been closed. for j in reversed(range(len(closing_matches))): closing_core = closing_matches[j].group(1) for k in range(len(opening_matches)): opening_core = opening_matches[k].group(1) if opening_core == closing_core: opening_matches.pop(k) break # Add artificial closing tags to close remaining tags. for j in reversed(range(len(opening_matches))): parts[i] += "{{\\{}\\}}".format(opening_matches[j].group(1)) return "".join(parts) def scale(self, text, size, bounds=None): """Return `text` scaled to `size`.""" a, z = bounds or (0, len(text)) target = "{{\\fs{}}}{}".format(str(size), text[a:z]) return "".join((text[:a], target, text[z:])) @property def tag(self): """Regular expression for any markup tag.""" return self._get_regex(r"\{\\.*?\}") gaupol-1.11/aeidon/markups/subrip.py000066400000000000000000000065621422217132500175320ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Text markup for the SubRip format.""" import aeidon import re __all__ = ("SubRip",) class SubRip(aeidon.Markup): """ Text markup for the SubRip format. SubRip format is assumed (based on the SubRip application GUI) to contain the following HTML-style tags, in either lower- or upper case. * ``.........................`` * ``.........................`` * ``.........................`` * ``...`` """ _flags = re.DOTALL | re.MULTILINE | re.IGNORECASE format = aeidon.formats.SUBRIP def bolden(self, text, bounds=None): """Return bolded `text`.""" a, z = bounds or (0, len(text)) return "".join((text[:a], "{}".format(text[a:z]), text[z:])) def clean(self, text): """Return `text` with less ugly markup.""" # Remove tags that are immediately closed after opening. text = self._substitute(text, r"<([a-z]+)[^<]*?>( *)", r"\2") # Remove tags that are immediately opened after closing. text = self._substitute(text, r"( *)<\1[^<]*?>", r"\2") # Remove or relocate space right after an opening tag. text = self._substitute(text, r" ?(<(?!/)[^>]+?>) ", r" \1") # Remove or relocate space right before a closing tag. text = self._substitute(text, r" (]+?>) ?", r"\1 ") return text def colorize(self, text, color, bounds=None): """Return `text` colorized to hexadecimal value.""" a, z = bounds or (0, len(text)) target = '{}'.format(color, text[a:z]) return "".join((text[:a], target, text[z:])) @property def italic_tag(self): """Regular expression for an italic markup tag.""" return self._get_regex(r"") def italicize(self, text, bounds=None): """Return italicized `text`.""" a, z = bounds or (0, len(text)) return "".join((text[:a], "{}".format(text[a:z]), text[z:])) def _main_decode(self, text): """Return `text` with decodable markup decoded.""" text = self._decode_b(text, r"(.*?)", 1) text = self._decode_i(text, r"(.*?)", 1) text = self._decode_u(text, r"(.*?)", 1) pattern = r'(.*?)' return self._decode_c(text, pattern, 1, 2) @property def tag(self): """Regular expression for any markup tag.""" return self._get_regex(r"<.*?>") def underline(self, text, bounds=None): """Return underlined `text`.""" a, z = bounds or (0, len(text)) return "".join((text[:a], "{}".format(text[a:z]), text[z:])) gaupol-1.11/aeidon/markups/subviewer2.py000066400000000000000000000017551422217132500203220ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Text markup for the SubViewer 2.0 format.""" import aeidon __all__ = ("SubViewer2",) class SubViewer2(aeidon.markups.SubRip): """ Text markup for the SubViewer 2.0 format. SubViewer 2.0 format is assumed to contain the same markup as SubRip. """ format = aeidon.formats.SUBVIEWER2 gaupol-1.11/aeidon/markups/test/000077500000000000000000000000001422217132500166225ustar00rootroot00000000000000gaupol-1.11/aeidon/markups/test/__init__.py000066400000000000000000000000001422217132500207210ustar00rootroot00000000000000gaupol-1.11/aeidon/markups/test/test_ass.py000066400000000000000000000034751422217132500210320ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon from aeidon.markups.test.test_ssa import TestSubStationAlpha class TestAdvSubStationAlpha(TestSubStationAlpha): text = ("All things weird are normal\n" "in this whore of cities.") def setup_method(self, method): self.markup = aeidon.markups.new(aeidon.formats.ASS) def test_decode__bold_weight(self): text = ("All things weird are normal\n" "in {\\b500}this{\\b0} whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__underline(self): text = ("{\\u1}All things weird are normal\n" "in this whore of cities{\\rDefault}.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_encode__underline(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == ( "All things weird are normal\n" "{\\u1}in this whore of cities.{\\u0}") gaupol-1.11/aeidon/markups/test/test_microdvd.py000066400000000000000000000133651422217132500220520ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class TestMicroDVD(aeidon.TestCase): text = ("All things weird are normal\n" "in this whore of cities.") def setup_method(self, method): self.markup = aeidon.markups.new(aeidon.formats.MICRODVD) def test_bolden(self): assert self.markup.bolden(self.text, (0, 27)) == ( "{y:b}All things weird are normal\n" "in this whore of cities.") def test_colorize(self): assert self.markup.colorize(self.text, "ccff00") == ( "{C:$00ffcc}All things weird are normal\n" "in this whore of cities.") def test_decode__bold(self): text = ("{Y:b}All things weird are normal\n" "in this whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__color(self): text = ("All things weird are normal\n" "{c:$0000ff}in this whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__combined(self): text = ("{Y:bi}All things weird are normal\n" "{y:u}in this whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__font(self): text = ("{f:sans}All things weird are normal\n" "in this whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__italic(self): text = ("{y:i}All things weird are normal\n" "{y:i}in this whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__size(self): text = ("All things weird are normal\n" "{s:12}in this whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__underline(self): text = ("{Y:u}All things weird are normal\n" "in this whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_encode__bold(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == ( "{Y:b}All things weird are normal\n" "in this whore of cities.") def test_encode__color(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == ( "{C:$ffcccc}All things weird are normal\n" "in this whore of cities.") def test_encode__font(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == ( "{F:sans}All things weird are normal\n" "in this whore of cities.") def test_encode__italic(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_encode__size(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == ( "All things weird are normal\n" "{s:12}in this whore of cities.") def test_encode__underline(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == ( "All things weird are normal\n" "{y:u}in this whore of cities.") def test_fontify(self): assert self.markup.fontify(self.text, "sans") == ( "{F:sans}All things weird are normal\n" "in this whore of cities.") def test_italic_tag(self): assert self.markup.italic_tag.match("{Y:i}") assert self.markup.italic_tag.match("{y:i}") def test_italicize(self): assert self.markup.italicize(self.text) == ( "{Y:i}All things weird are normal\n" "in this whore of cities.") def test_scale(self): assert self.markup.scale(self.text, 12) == ( "{S:12}All things weird are normal\n" "in this whore of cities.") def test_tag(self): assert self.markup.tag.match("{y:ibu}") assert self.markup.tag.match("{c:$000000}") def test_underline(self): assert self.markup.underline(self.text, (0, 3)) == ( "All things weird are normal\n" "in this whore of cities.") gaupol-1.11/aeidon/markups/test/test_mpl2.py000066400000000000000000000100541422217132500211050ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon from aeidon.markups.test.test_microdvd import TestMicroDVD class TestMPL2(TestMicroDVD): text = ("All things weird are normal\n" "in this whore of cities.") def setup_method(self, method): self.markup = aeidon.markups.new(aeidon.formats.MPL2) def test_bolden(self): assert self.markup.bolden(self.text, (0, 27)) == ( "\\All things weird are normal\n" "in this whore of cities.") def test_decode__bold(self): text = ("\\All things weird are normal\n" "\\in this whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__italic(self): text = ("/All things weird are normal\n" "in this whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__multiple(self): text = ("/_All things weird are normal\n" "\\/_in this whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__duplicate(self): text = ("//All things weird are normal\n" "/_/_in this whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__underline(self): text = ("All things weird are normal\n" "_in this whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_encode__bold(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == ( "\\All things weird are normal\n" "\\in this whore of cities.") def test_encode__italic(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_encode__underline(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == ( "All things weird are normal\n" "_in this whore of cities.") def test_italic_tag(self): assert self.markup.italic_tag.match("/") assert self.markup.italic_tag.match("{Y:i}") assert self.markup.italic_tag.match("{y:i}") def test_italicize(self): assert self.markup.italicize(self.text) == ( "/All things weird are normal\n" "/in this whore of cities.") def test_tag(self): assert self.markup.tag.match("\\") assert self.markup.tag.match("/") assert self.markup.tag.match("_") assert self.markup.tag.match("{y:ibu}") assert self.markup.tag.match("{c:$000000}") def test_underline(self): assert self.markup.underline(self.text, (0, 3)) == ( "All things weird are normal\n" "in this whore of cities.") gaupol-1.11/aeidon/markups/test/test_ssa.py000066400000000000000000000131461422217132500210260ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class TestSubStationAlpha(aeidon.TestCase): text = ("All things weird are normal\n" "in this whore of cities.") def setup_method(self, method): self.markup = aeidon.markups.new(aeidon.formats.SSA) def test_bolden(self): assert self.markup.bolden(self.text) == ( "{\\b1}All things weird are normal\n" "in this whore of cities.{\\b0}") def test_colorize(self): assert self.markup.colorize(self.text, "ccff00") == ( "{\\c&H00ffcc&}All things weird are normal\n" "in this whore of cities.") def test_decode__bold(self): text = ("{\\b1}All things weird are normal\n" "in this whore of cities.{\\b0}") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__color(self): text = ("All things weird are normal\n" "in {\\c&Hff&}this whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__combined(self): text = ("{\\b1\\i1}All things weird are normal\n" "in this{\\i0\\b0} whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__font(self): text = ("All things {\\fnsans}weird{\\r} are normal\n" "in this whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__italic(self): text = ("{\\i1}All{\\r} things weird are normal\n" "in this whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__reset(self): text = ("{\\b1\\i1}All{\\i0} things weird are normal\n" "{\\fs12}in this whore of cities{\\r}.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__size(self): text = ("All things weird are normal\n" "{\\fs12}in this whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_encode__bold(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == ( "{\\b1}All things weird are normal\n" "in this whore of cities.{\\b0}") def test_encode__color(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == ( "{\\c&Hffcccc&}All things weird are normal\n" "in this whore of cities.") def test_encode__font(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == ( "{\\fnsans}All things weird are normal\n" "in this whore of cities.") def test_encode__italic(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == ( "All {\\i1}things{\\i0} weird are normal\n" "in {\\i1}this{\\i0} whore of cities.") def test_encode__size(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == ( "All things weird are normal\n" "in this whore of {\\fs12}cities.") def test_encode__underline(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == self.text def test_fontify(self): assert self.markup.fontify(self.text, "sans") == ( "{\\fnsans}All things weird are normal\n" "in this whore of cities.") def test_italic_tag(self): assert self.markup.italic_tag.match("{\\i1}") assert self.markup.italic_tag.match("{\\i0}") def test_italicize(self): assert self.markup.italicize(self.text, (0, 3)) == ( "{\\i1}All{\\i0} things weird are normal\n" "in this whore of cities.") def test_scale(self): assert self.markup.scale(self.text, 12) == ( "{\\fs12}All things weird are normal\n" "in this whore of cities.") def test_tag(self): assert self.markup.tag.match("{\\b500}") assert self.markup.tag.match("{\\c&H&}") gaupol-1.11/aeidon/markups/test/test_subrip.py000066400000000000000000000114351422217132500215430ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class TestSubRip(aeidon.TestCase): text = ("All things weird are normal\n" "in this whore of cities.") def setup_method(self, method): self.markup = aeidon.markups.new(aeidon.formats.SUBRIP) def test_bolden(self): assert self.markup.bolden(self.text) == ( "All things weird are normal\n" "in this whore of cities.") def test_clean__closing(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.clean(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_clean__opening(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.clean(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_colorize(self): assert self.markup.colorize(self.text, "ccffcc") == ( 'All things weird are normal\n' 'in this whore of cities.') def test_decode__bold(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__color(self): text = ('All things weird are normal\n' 'in this whore of cities.') assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__italic(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_decode__underline(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.decode(text) == ( "All things weird are normal\n" "in this whore of cities.") def test_encode__bold(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == text def test_encode__color(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == ( 'All things weird are normal\n' 'in this whore of cities.') def test_encode__font(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == self.text def test_encode__italic(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == text def test_encode__size(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == self.text def test_encode__underline(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == text def test_italic_tag(self): assert self.markup.italic_tag.match("") assert self.markup.italic_tag.match("") def test_italicize(self): assert self.markup.italicize(self.text, (0, 3)) == ( "All things weird are normal\n" "in this whore of cities.") def test_tag(self): assert self.markup.tag.match('') assert self.markup.tag.match('') def test_underline(self): assert self.markup.underline(self.text, (45, 51)) == ( "All things weird are normal\n" "in this whore of cities.") gaupol-1.11/aeidon/markups/test/test_webvtt.py000066400000000000000000000023741422217132500215540ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2017 Osmo Salomaa # # 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 aeidon from aeidon.markups.test.test_subrip import TestSubRip class TestWebVTT(TestSubRip): text = ("All things weird are normal\n" "in this whore of cities.") def setup_method(self, method): self.markup = aeidon.markups.new(aeidon.formats.WEBVTT) def test_colorize(self): pass def test_decode__color(self): pass def test_encode__color(self): text = ("All things weird are normal\n" "in this whore of cities.") assert self.markup.encode(text) == self.text gaupol-1.11/aeidon/markups/tmplayer.py000066400000000000000000000017001422217132500200500ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2006 Osmo Salomaa # # 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 . """Text markup for the TMPlayer format.""" import aeidon __all__ = ("TMPlayer",) class TMPlayer(aeidon.Markup): """ Text markup for the TMPlayer format. TMPlayer format is assumed to contain no markup. """ format = aeidon.formats.TMPLAYER gaupol-1.11/aeidon/markups/webvtt.py000066400000000000000000000034611422217132500175340ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2017 Osmo Salomaa # # 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 . """Text markup for the WebVTT format.""" import aeidon __all__ = ("WebVTT",) class WebVTT(aeidon.markups.SubRip): """ Text markup for the WebVTT format. WebVTT is very similar to the SubRip format, except it doesn't support the tag and it includes a few other tags, such as the class tag , which we cannot support for conversions. https://developer.mozilla.org/en-US/docs/Web/API/WebVTT_API """ format = aeidon.formats.WEBVTT def colorize(self, text, color, bounds=None): """Return `text` colorized to hexadecimal value.""" raise NotImplementedError def _main_decode(self, text): """Return `text` with decodable markup decoded.""" text = self._decode_b(text, r"(.*?)", 1) text = self._decode_i(text, r"(.*?)", 1) return self._decode_u(text, r"(.*?)", 1) def _post_decode(self, text): """Return `text` with markup finalized after decoding.""" # Remove all unsupported markup tags. text = self._substitute(text, r"", "") return self._substitute(text, r"]{2,}>", "") gaupol-1.11/aeidon/metadata.py000066400000000000000000000107271422217132500163220ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 . """Metadata store for one item in a desktop-style file.""" import aeidon __all__ = ("MetadataItem",) class MetadataItem: """ Metadata store for one item in a desktop-style file. :ivar fields: Dictionary mapping field names to their string values Common localized fields with custom handling are ``Name`` and ``Description``; arbitrary fields are accessible with :meth:`get_field`. Strings ``True`` and ``False`` are used for boolean fields. For the string syntax and especially the localization handling, see freedesktop.org_'s Desktop Entry Specification_. .. _freedesktop.org: https://www.freedesktop.org/ .. _Specification: https://www.freedesktop.org/wiki/Specifications/desktop-entry-spec/ """ def __init__(self, fields=None): """Initialize a :class:`MetadataItem` instance.""" self.fields = fields or {} def get_description(self, localize=True): """Return description as defined by the ``Description`` field.""" if not localize: return self.get_field("Description") return self._get_localized_field("Description") def get_field(self, name, fallback=None): """Return the string value of field or `fallback`.""" if not name in self.fields: return fallback return self.fields[name] def get_field_boolean(self, name, fallback=None): """Return the boolean value of field or `fallback`.""" if not name in self.fields: return fallback value = self.fields[name] if value == "True": return True if value == "False": return False raise ValueError("Invalid boolean value: {!r}" .format(value)) def get_field_list(self, name, fallback=None): """Return the list of strings value of field or `fallback`.""" if not name in self.fields: return fallback lst = self.fields[name].split(";") if not lst[-1]: lst.pop(-1) return lst def _get_localized_field(self, name): """Return the localized value of field.""" locale = aeidon.locales.get_system_code() modifier = aeidon.locales.get_system_modifier() if locale is None: return self.get_field(name) # 'xx_YY@Zzzz', fall back to 'xx@Zzzz'. if ("_" in locale) and (modifier is not None): key = "{}[{}@{}]".format(name, locale, modifier) if key in self.fields: return self.get_field(key) locale = locale[0:2] # 'xx_YY', fall back to 'xx'. if ("_" in locale) and (modifier is None): key = "{}[{}]".format(name, locale) if key in self.fields: return self.get_field(key) locale = locale[0:2] # 'xx@Zzzz', fall back to unlocalized. if (not "_" in locale) and (modifier is not None): key = "{}[{}@{}]".format(name, locale, modifier) if key in self.fields: return self.get_field(key) return self.get_field(name) # 'xx', fall back to unlocalized. if (not "_" in locale) and (modifier is None): key = "{}[{}]".format(name, locale) if key in self.fields: return self.get_field(key) return self.get_field(name) return self.get_field(name) def get_name(self, localize=True): """Return name as defined by the ``Name`` field.""" if not localize: return self.get_field("Name") return self._get_localized_field("Name") def has_field(self, name): """Return ``True`` if field exists.""" return (name in self.fields) def set_field(self, name, value): """Set the string value of field.""" self.fields[name] = str(value) gaupol-1.11/aeidon/mutables.py000066400000000000000000000145061422217132500163550ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2006 Osmo Salomaa # # 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 . """Observable versions of built-in mutable objects.""" import copy import functools __all__ = ("ObservableDict", "ObservableList", "ObservableSet",) def _mutation(function): """Decorator for sending a notification after mutating object.""" @functools.wraps(function) def wrapper(*args, **kwargs): value = function(*args, **kwargs) args[0].master.notify(args[0].name) return value return wrapper class ObservableDict(dict): """ Observable version of ``dict``. :ivar master: Master instance with a ``notify`` method :ivar name: Argument passed when calling :attr:`master`'s ``notify`` method """ def __init__(self, *args, **kwargs): dict.__init__(self, *args[:-2], **kwargs) self.master = args[-2] self.name = args[-1] def __copy__(self): dic = dict(copy.copy(x) for x in self.items()) return self.__class__(dic, self.master, self.name) def __deepcopy__(self, memo): dic = dict(copy.deepcopy(x) for x in self.items()) return self.__class__(dic, self.master, self.name) @_mutation def __delitem__(self, *args, **kwargs): return dict.__delitem__(self, *args, **kwargs) @_mutation def __setitem__(self, *args, **kwargs): return dict.__setitem__(self, *args, **kwargs) @_mutation def clear(self, *args, **kwargs): return dict.clear(self, *args, **kwargs) @_mutation def pop(self, *args, **kwargs): return dict.pop(self, *args, **kwargs) @_mutation def popitem(self, *args, **kwargs): return dict.popitem(self, *args, **kwargs) @_mutation def setdefault(self, *args, **kwargs): return dict.setdefault(self, *args, **kwargs) @_mutation def update(self, *args, **kwargs): return dict.update(self, *args, **kwargs) class ObservableList(list): """ Observable version of ``list``. :ivar master: Master instance with a ``notify`` method :ivar name: Argument passed when calling :attr:`master`'s ``notify`` method """ def __init__(self, *args, **kwargs): list.__init__(self, *args[:-2], **kwargs) self.master = args[-2] self.name = args[-1] def __copy__(self): lst = list(copy.copy(x) for x in self) return self.__class__(lst, self.master, self.name) def __deepcopy__(self, memo): lst = [copy.deepcopy(x) for x in self] return self.__class__(lst, self.master, self.name) @_mutation def __delitem__(self, *args, **kwargs): return list.__delitem__(self, *args, **kwargs) @_mutation def __iadd__(self, *args, **kwargs): return list.__iadd__(self, *args, **kwargs) @_mutation def __imul__(self, *args, **kwargs): return list.__imul__(self, *args, **kwargs) @_mutation def __setitem__(self, *args, **kwargs): return list.__setitem__(self, *args, **kwargs) @_mutation def append(self, *args, **kwargs): return list.append(self, *args, **kwargs) @_mutation def extend(self, *args, **kwargs): return list.extend(self, *args, **kwargs) @_mutation def insert(self, *args, **kwargs): return list.insert(self, *args, **kwargs) @_mutation def pop(self, *args, **kwargs): return list.pop(self, *args, **kwargs) @_mutation def remove(self, *args, **kwargs): return list.remove(self, *args, **kwargs) @_mutation def reverse(self, *args, **kwargs): return list.reverse(self, *args, **kwargs) @_mutation def sort(self, *args, **kwargs): return list.sort(self, *args, **kwargs) class ObservableSet(set): """ Observable version of ``set``. :ivar master: Master instance with a ``notify`` method :ivar name: Argument passed when calling :attr:`master`'s ``notify`` method """ def __init__(self, *args, **kwargs): set.__init__(self, *args[:-2], **kwargs) self.master = args[-2] self.name = args[-1] def __copy__(self): zet = set(copy.copy(x) for x in self) return self.__class__(zet, self.master, self.name) def __deepcopy__(self, memo): zet = set(copy.deepcopy(x) for x in self) return self.__class__(zet, self.master, self.name) @_mutation def __iand__(self, *args, **kwargs): return set.__iand__(self, *args, **kwargs) @_mutation def __ior__(self, *args, **kwargs): return set.__ior__(self, *args, **kwargs) @_mutation def __isub__(self, *args, **kwargs): return set.__isub__(self, *args, **kwargs) @_mutation def __ixor__(self, *args, **kwargs): return set.__ixor__(self, *args, **kwargs) @_mutation def add(self, *args, **kwargs): return set.add(self, *args, **kwargs) @_mutation def clear(self, *args, **kwargs): return set.clear(self, *args, **kwargs) @_mutation def difference_update(self, *args, **kwargs): return set.difference_update(self, *args, **kwargs) @_mutation def discard(self, *args, **kwargs): return set.discard(self, *args, **kwargs) @_mutation def intersection_update(self, *args, **kwargs): return set.intersection_update(self, *args, **kwargs) @_mutation def pop(self, *args, **kwargs): return set.pop(self, *args, **kwargs) @_mutation def remove(self, *args, **kwargs): return set.remove(self, *args, **kwargs) @_mutation def symmetric_difference_update(self, *args, **kwargs): return set.symmetric_difference_update(self, *args, **kwargs) @_mutation def update(self, *args, **kwargs): return set.update(self, *args, **kwargs) gaupol-1.11/aeidon/observable.py000066400000000000000000000161651422217132500166700ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Base class for observable objects.""" import aeidon __all__ = ("Observable",) class Observable: """ Base class for observable objects. :cvar signals: Tuple of emittable signals added automatically In addition to the signals defined in :attr:`signals`, all public instance variables have a ``notify::NAME`` signal generated automatically based on the ``NAME`` of the variable. ``notify::NAME`` signals will be emitted whenever the value of the corresponding instance variable changes. Notify signals will be emitted for mutable variables as well, which means that care should be taken not to emit thousands of signals when e.g. appending one-by-one to a large list. :meth:`freeze_notify` and :meth:`thaw_notify` will queue notify signals and emit only one of each once thawed. The Observable philosophy and API is highly inspired by GObject_. .. _GObject: https://developer.gnome.org/gobject/ """ __slots__ = ( "_blocked_signals", "_blocked_state", "_notify_frozen", "_notify_queue", "_signal_handlers", ) signals = () def __init__(self): """Initialize an :class:`Observable` instance.""" self._blocked_signals = [] self._blocked_state = False self._notify_frozen = False self._notify_queue = [] self._signal_handlers = {} for signal in self.signals: self._add_signal(signal) def __setattr__(self, name, value): """Set value of observable attribute.""" if (name in self.__slots__) or name.startswith("_"): return object.__setattr__(self, name, value) value = self._validate(name, value) signal = "notify::{}".format(name) if not signal in self._signal_handlers: self._add_signal(signal) return object.__setattr__(self, name, value) return_value = object.__setattr__(self, name, value) self.emit(signal, value) return return_value def _add_signal(self, signal): """Add `signal` to the list of signals emitted.""" self._signal_handlers[signal] = [] def block(self, signal): """ Block all emissions of `signal`. Return ``False`` if already blocked, otherwise ``True``. """ if not signal in self._blocked_signals: self._blocked_signals.append(signal) return True return False def block_all(self): """ Block all emissions of all signals. Return ``False`` if already blocked, otherwise ``True``. """ if not self._blocked_state: self._blocked_state = True return True return False def connect(self, signal, method, *args): """Register to receive notifications of ``signal``.""" self._signal_handlers[signal].append((method, args)) def disconnect(self, signal, method): """Remove registration to receive notifications of ``signal``.""" for i in reversed(range(len(self._signal_handlers[signal]))): if self._signal_handlers[signal][i][0] == method: self._signal_handlers[signal].pop(i) def emit(self, signal, *args): """Send notification of ``signal`` to all registered observers.""" if signal.startswith("notify::") and self._notify_frozen: if not signal in self._notify_queue: self._notify_queue.append(signal) return if (not self._blocked_state and not signal in self._blocked_signals): if signal.startswith("notify::"): name = signal.replace("notify::", "") args = (getattr(self, name),) for method, data in self._signal_handlers[signal]: method(*((self,) + args + data)) def freeze_notify(self): """ Queue notify signals instead of emitting them. Return ``False`` if already frozen, otherwise ``True``. """ if not self._notify_frozen: self._notify_frozen = True return True return False def notify(self, name): """Emit notification signal for variable.""" return self.emit("notify::{}".format(name)) def thaw_notify(self, do=True): """ Emit all queued notify signals and queue no more. The optional `do` keyword argument should be the return value from :meth:`freeze_notify` to avoid problems with nested functions where notifications were frozen at a higher level. If `do` is ``False``, nothing will be done. Return ``False`` if already thawed, otherwise ``True``. """ if do and self._notify_frozen: self._notify_frozen = False for signal in self._notify_queue: name = signal.replace("notify::", "") self.emit(signal, getattr(self, name)) self._notify_queue = [] return True return False def unblock(self, signal, do=True): """ Unblock all emissions of `signal`. The optional `do` keyword argument should be the return value from :meth:`block` to avoid problems with nested functions where signals were blocked at a higher level. If `do` is ``False``, nothing will be done. Return ``False`` if already unblocked, otherwise ``True``. """ if do and (signal in self._blocked_signals): self._blocked_signals.remove(signal) return True return False def unblock_all(self, do=True): """ Unblock all emissions of all signals. The optional `do` keyword argument should be the return value from :meth:`block_all` to avoid problems with nested functions where signals were blocked at a higher level. If `do` is ``False``, nothing will be done. Return ``False`` if already unblocked, otherwise ``True``. """ if do and self._blocked_state: self._blocked_state = False return True return False def _validate(self, name, value): """Return `value` or an observable version if `value` is mutable.""" args = (value, self, name) if isinstance(value, dict): return aeidon.ObservableDict(*args) if isinstance(value, list): return aeidon.ObservableList(*args) if isinstance(value, set): return aeidon.ObservableSet(*args) return value gaupol-1.11/aeidon/parser.py000066400000000000000000000141121422217132500160260ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Text parser for markup-tag-aware text editing.""" import aeidon __all__ = ("Parser",) class Parser(aeidon.Finder): """ Text parser for markup-tag-aware text editing. :ivar clean_func: Function to clean tags or ``None`` :ivar _margins: Start tag, end tag that every line is wrapped in :ivar re_tag: Regular expression object to match any tag :ivar _tags: List of lists of markup tag, position The purpose of :class:`Parser` is to split text to the actual text and its markup tags, allowing the text to be edited while keeping its tags separate and intact. An example would be replacing all "i"s with "j"s without changing italic markup:: >>> import re >>> parser = aeidon.Parser(re.compile(r"<.+?>")) >>> parser.set_text("iii") >>> parser.pattern = "i" >>> parser.replacement = "j" >>> parser.replace_all() 3 >>> parser.get_text() 'jjj' """ def __init__(self, re_tag=None, clean_func=None): """Initialize a :class:`Parser` instance.""" aeidon.Finder.__init__(self) self.clean_func = clean_func self._margins = None self.re_tag = re_tag self._tags = None def get_text(self): """Reassemble the full text and return it.""" if not self.text: self._margins = [] self._tags = [] text = self.text[:] for pos, tag in self._tags: text = text[:pos] + tag + text[pos:] if self._margins: text = text.replace("\n", "{1}\n{0}".format(*self._margins)) text = self._margins[0] + text + self._margins[1] if self.clean_func is not None: text = self.clean_func(text) return text def replace(self, next=True): """ Replace the current match of pattern. `next` should be ``True`` to finish at end of match, ``False`` for beginning. Raise :exc:`re.error` if bad replacement. """ a = self.match_span[0] orig_text = self.text[:] aeidon.Finder.replace(self, next) shift = len(self.text) - len(orig_text) self._shift_tags(a, shift, orig_text) def _set_margins(self, text): """Find the margin markup tags in `text` if such exist.""" lines = text.split("\n") line = lines[0] start_tag = "" while True: match = self.re_tag.match(line) if match is None: break a, z = match.span() start_tag += line[a:z] line = line[z:] if not start_tag: return if not all(x.startswith(start_tag) for x in lines): return end_tag = "" while True: iterator = self.re_tag.finditer(line) match = aeidon.util.last(iterator) if match is None: break a, z = match.span() if z != len(line): return end_tag = line[a:z] + end_tag line = line[:a] if not all(x.endswith(end_tag) for x in lines): return for line in (x[len(start_tag):-len(end_tag)] for x in lines): # Ensure that no other tags exists on any of the lines. if self.re_tag.search(line) is not None: return self._margins = [start_tag, end_tag] def _set_tags(self, text): """Find markup tags in `text`.""" for match in self.re_tag.finditer(text): a, z = match.span() self._tags.append([a, text[a:z]]) def set_text(self, text): """Set the target text to search in and parse it.""" aeidon.Finder.set_text(self, text) self._margins = [] self._tags = [] if self.re_tag is None: return if text.count("\n"): self._set_margins(text) if not self._margins: self._set_tags(text) self.text = self.re_tag.sub("", text) def _shift_tags(self, pos, shift, orig_text): """Shift all markup tags after `pos`.""" if not shift: return if not self._tags: return # Try to determine whether a tag at position pos would be an opening # or a closing tag, i.e. attached to the next or the previous word. opening = True if pos < len(orig_text): if orig_text[pos].isspace(): opening = False elif pos == len(orig_text): opening = False closing = not opening # Get length of tags *before* position. Try to add strings (positive # shift) inside tags and remove strings (negative shift) after tags. pos_with_tags = pos for tag_pos, tag in self._tags: if shift > 0 and closing: if tag_pos < pos_with_tags: pos_with_tags += len(tag) elif tag_pos <= pos_with_tags: pos_with_tags += len(tag) between_length = 0 for i, (tag_pos, tag) in enumerate(self._tags): orig_end = pos_with_tags - shift + between_length if (shift < 0) and (pos_with_tags < tag_pos < orig_end): # If tag is in the middle of what is being removed, it must be # shifted to the start of the removal block, but not so far # that it would overlap with preceding tags. self._tags[i][0] = pos_with_tags + between_length between_length += len(tag) elif tag_pos >= pos_with_tags: self._tags[i][0] += shift gaupol-1.11/aeidon/paths.py000066400000000000000000000105571422217132500156620ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Paths to files and directories used.""" import os import sys __all__ = ("CONFIG_HOME_DIR", "DATA_DIR", "DATA_HOME_DIR", "LOCALE_DIR",) def get_config_home_directory(): """Return path to the user's configuration directory.""" if sys.platform == "win32": return get_config_home_directory_windows() return get_config_home_directory_xdg() def get_config_home_directory_windows(): """Return path to the user's configuration directory on Windows.""" directory = os.path.expanduser("~") directory = os.environ.get("APPDATA", directory) directory = os.path.join(directory, "Gaupol") return os.path.abspath(directory) def get_config_home_directory_xdg(): """Return path to the user's XDG configuration directory.""" directory = os.path.join(os.path.expanduser("~"), ".config") directory = os.environ.get("XDG_CONFIG_HOME", directory) directory = os.path.join(directory, "gaupol") return os.path.abspath(directory) def get_data_directory(): """Return path to the global data directory.""" if hasattr(sys, "frozen"): return get_data_directory_frozen() if os.path.isdir(get_data_directory_package()): return get_data_directory_package() return get_data_directory_source() def get_data_directory_frozen(): """Return path to the global data directory on ``frozen``.""" directory = os.path.dirname(sys.argv[0]) directory = os.path.join(directory, "share", "gaupol") return os.path.abspath(directory) def get_data_directory_package(): """Return path to the global data directory when data in the package.""" directory = os.path.dirname(os.path.abspath(__file__)) directory = os.path.join(directory, "data") return os.path.abspath(directory) def get_data_directory_source(): """Return path to the global data directory when running from source.""" directory = os.path.dirname(os.path.abspath(__file__)) directory = os.path.abspath(os.path.join(directory, "..")) directory = os.path.join(directory, "data") return os.path.abspath(directory) def get_data_home_directory(): """Return path to the user's data directory.""" if sys.platform == "win32": return get_data_home_directory_windows() return get_data_home_directory_xdg() def get_data_home_directory_windows(): """Return path to the user's data directory on Windows.""" directory = os.path.expanduser("~") directory = os.environ.get("APPDATA", directory) directory = os.path.join(directory, "Gaupol") return os.path.abspath(directory) def get_data_home_directory_xdg(): """Return path to the user's XDG data directory.""" directory = os.path.expanduser("~/.local/share") directory = os.environ.get("XDG_DATA_HOME", directory) directory = os.path.join(directory, "gaupol") return os.path.abspath(directory) def get_locale_directory(): """Return path to the locale directory.""" if hasattr(sys, "frozen"): return get_locale_directory_frozen() return get_locale_directory_source() def get_locale_directory_frozen(): """Return path to the locale directory on ``frozen``.""" directory = os.path.dirname(sys.argv[0]) directory = os.path.join(directory, "share", "locale") return os.path.abspath(directory) def get_locale_directory_source(): """Return path to the locale directory when running from source.""" directory = os.path.dirname(os.path.abspath(__file__)) directory = os.path.abspath(os.path.join(directory, "..")) directory = os.path.join(directory, "locale") return os.path.abspath(directory) CONFIG_HOME_DIR = get_config_home_directory() DATA_DIR = get_data_directory() DATA_HOME_DIR = get_data_home_directory() LOCALE_DIR = get_locale_directory() gaupol-1.11/aeidon/pattern.py000066400000000000000000000030141422217132500162060ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 . """Regular expression substitution for subtitle text.""" import aeidon import re __all__ = ("Pattern",) class Pattern(aeidon.MetadataItem): """ Regular expression substitution for subtitle text. :ivar enabled: ``True`` if pattern should be used, ``False`` if not :ivar fields: Dictionary of all data field names and values :ivar local: ``True`` if pattern is defined by user, ``False`` if system """ def __init__(self, fields=None): """Initialize a :class:`Pattern` instance.""" aeidon.MetadataItem.__init__(self, fields) self.enabled = True self.local = False def get_flags(self): """Return the evaluated value of the ``Flags`` field.""" flags = 0 for name in self.get_field_list("Flags"): flags = flags | getattr(re, name) return flags gaupol-1.11/aeidon/patternman.py000066400000000000000000000242011422217132500167030ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 . """Managing regular expression substitutions for subtitle texts.""" import aeidon import os import re import xml.etree.ElementTree as ET __all__ = ("PatternManager",) class PatternManager: """ Managing regular expression substitutions for subtitle texts. :ivar _patterns: Dictionary mapping codes to pattern lists :ivar pattern_type: String to indentify what the pattern matches :attr:`pattern_type` should be a string with value "line-break", "common-error", "capitalization" or "hearing-impaired". Codes are of form ``Script[-language-[COUNTRY]]`` using the corresponding ISO codes. """ _re_comment = re.compile(r"^\s*#.*$") def __init__(self, pattern_type): """Initialize a :class:`PatternManager` instance.""" self.pattern_type = pattern_type self._patterns = {} self._read_patterns() def _filter_patterns(self, patterns): """ Return `patterns` with name-clashes resolved. Patterns with a more specific code replace those with a less specific code if they have the same name and the more specific pattern's policy is explicitly set to ``Replace`` (instead of the implicit ``Append``). Order is maintained so that all patterns with the same name are always located in the position of the earliest of such patterns. """ filtered_patterns = [] for pattern in patterns: name = pattern.get_name(False) policy = pattern.get_field("Policy") last_index = len(filtered_patterns) - 1 for j, filtered_pattern in enumerate(filtered_patterns): if filtered_pattern.get_name() == name: last_index = j if policy == "Replace": filtered_patterns[j] = None filtered_patterns.insert(last_index + 1, pattern) while None in filtered_patterns: filtered_patterns.remove(None) return filtered_patterns def _get_codes(self, script=None, language=None, country=None): """Return a sequence of all codes to be used by arguments.""" codes = ["Zyyy"] if not None in (script,): codes.append(script) if not None in (script, language): codes.append("{}-{}".format(script, language)) if not None in (script, language, country): codes.append("{}-{}-{}".format(script, language, country)) return tuple(codes) def get_countries(self, script, language): """Return a sequence of countries for which patterns exist.""" codes = list(self._patterns.keys()) start = "{}-{}-".format(script, language) codes = [x for x in codes if x.startswith(start)] countries = [x.split("-")[2] for x in codes] return tuple(aeidon.util.get_unique(countries)) def get_languages(self, script): """Return a sequence of languages for which patterns exist.""" codes = list(self._patterns.keys()) start = "{}-".format(script) codes = [x for x in codes if x.startswith(start)] languages = [x.split("-")[1] for x in codes] return tuple(aeidon.util.get_unique(languages)) def get_patterns(self, script=None, language=None, country=None): """Return patterns for `script`, `language` and `country`.""" patterns = [] codes = self._get_codes(script, language, country) for code in codes: for pattern in self._patterns.get(code, []): # Skip patterns that define exceptions to their use # that match a more speficic group being requested. skip = pattern.get_field_list("SkipIn", []) if set(skip) & set(codes): continue patterns.append(pattern) return self._filter_patterns(patterns) def get_scripts(self): """Return a sequence of scripts for which patterns exist.""" codes = list(self._patterns.keys()) while "Zyyy" in codes: codes.remove("Zyyy") scripts = [x.split("-")[0] for x in codes] return tuple(aeidon.util.get_unique(scripts)) def _read_config_from_directory(self, directory, encoding): """Read configurations from files in `directory`.""" if not os.path.isdir(directory): return extension = ".{}.conf".format(self.pattern_type) files = os.listdir(directory) for name in (x for x in files if x.endswith(extension)): path = os.path.join(directory, name) self._read_config_from_file(path, encoding) def _read_config_from_file(self, path, encoding): """Read configurations from file at `path`.""" if not os.path.isfile(path): return basename = os.path.basename(path) extension = ".{}.conf".format(self.pattern_type) code = basename.replace(extension, "") if not code in self._patterns: return patterns = self._patterns[code] for element in ET.parse(path).findall("pattern"): name = element.get("name") name = name.replace(""", '"') name = name.replace("&", "&") enabled = (element.get("enabled") == "true") for pattern in patterns: if pattern.get_name(localize=False) == name: pattern.enabled = enabled def _read_patterns(self): """Read all patterns of :attr:`pattern_type` from files.""" data_dir = os.path.join(aeidon.DATA_DIR, "patterns") data_home_dir = os.path.join(aeidon.DATA_HOME_DIR, "patterns") config_home_dir = os.path.join(aeidon.CONFIG_HOME_DIR, "patterns") encoding = aeidon.util.get_default_encoding() self._read_patterns_from_directory(data_dir, "utf_8") self._read_patterns_from_directory(data_home_dir, encoding) self._read_config_from_directory(data_dir, "utf_8") self._read_config_from_directory(config_home_dir, encoding) def _read_patterns_from_directory(self, directory, encoding): """Read all patterns from files in `directory`.""" if not os.path.isdir(directory): return extension = ".{}".format(self.pattern_type) extensions = (extension, "{}.in".format(extension)) files = [x for x in os.listdir(directory) if x.endswith(extensions)] for name in [x for x in files if x.endswith(".in")]: # If both untranslated and translated pattern files are found, # load patterns only from the translated one. if name[:-3] in files: files.remove(name) for name in files: path = os.path.join(directory, name) self._read_patterns_from_file(path, encoding) def _read_patterns_from_file(self, path, encoding): """Read all patterns from file at `path`.""" if not os.path.isfile(path): return basename = os.path.basename(path) extension = ".{}".format(self.pattern_type) if basename.endswith(".in"): extension = ".{}.in".format(self.pattern_type) code = basename.replace(extension, "") local = path.startswith(aeidon.DATA_HOME_DIR) patterns = self._patterns.setdefault(code, []) lines = aeidon.util.readlines(path, encoding) lines = [self._re_comment.sub("", x) for x in lines] lines = [x.strip() for x in lines] for line in (x for x in lines if x): if line.startswith("["): # [HEADER] patterns.append(aeidon.Pattern()) patterns[-1].local = local else: # [_]KEY=VALUE name, value = line.split("=", 1) # Translatable fields used to be marked with a leading # underscore prior to version 1.3. We continue to support that # syntax in case users have local pattern files. name = name[1:] if name.startswith("_") else name # Regular expression patterns and replacements use null # character to avoid syntax issues that go against the GKeyFile # spec and would be "fixed" by msgfmt when merging translations. # https://github.com/otsaloma/gaupol/issues/70 value = re.sub(r"\\0(?!\d)", "", value) patterns[-1].set_field(name, value) def save_config(self, script=None, language=None, country=None): """Save pattern configurations to files.""" codes = self._get_codes(script, language, country) for code in (x for x in codes if x in self._patterns): self._write_config_to_file(code, "utf_8") def _write_config_to_file(self, code, encoding): """Write configurations of all patterns to file.""" local_dir = os.path.join(aeidon.CONFIG_HOME_DIR, "patterns") basename = "{}.{}.conf".format(code, self.pattern_type) path = os.path.join(local_dir, basename) lines = [''] lines.append('') written_names = set() for pattern in self._patterns[code]: name = pattern.get_name(localize=False) if name in written_names: continue written_names.add(name) name = name.replace("&", "&") name = name.replace('"', """) enabled = "true" if pattern.enabled else "false" lines.append(' ' .format(name, enabled)) lines.append('') aeidon.util.writelines(path, lines, encoding) gaupol-1.11/aeidon/position.py000066400000000000000000000034561422217132500164070ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2011 Osmo Salomaa # # 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 . """Mapping position types to basic Python types.""" # aeidon handles frames as integers, seconds as floats and times as strings. # Some functions accept a "position" argument, which will be interpreted based # on its type. These functions are introduced here so that callers can use # 'as_*' to ensure argument types and functions can use 'is_*' to check # argument types, all in a way which is compatible with the old ambiguous way # of using int, float and str directly. __all__ = ( "as_frame", "as_seconds", "as_time", "is_frame", "is_seconds", "is_time", ) def as_frame(pos): """Return `pos` as type frame.""" return int(pos) def as_seconds(pos): """Return `pos` as type seconds.""" return float(pos) def as_time(pos): """Return `pos` as type time.""" return str(pos) def is_frame(pos): """Return ``True`` if `pos` is of type frame.""" return isinstance(pos, int) def is_seconds(pos): """Return ``True`` if `pos` is of type seconds.""" return isinstance(pos, float) def is_time(pos): """Return ``True`` if `pos` is of type time.""" return isinstance(pos, str) gaupol-1.11/aeidon/project.py000066400000000000000000000141401422217132500162010ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Model for subtitle data.""" import aeidon __all__ = ("Project",) class ProjectMeta(type): """ Project metaclass with delegated methods added. Public methods are added to the class dictionary during :meth:`__new__` in order to fool Sphinx (and perhaps other API documentation generators) into thinking that the resulting instantiated class actually contains those methods, which it does not since the methods are removed during :meth:`Project.__init__`. """ def __new__(meta, class_name, bases, dic): new_dict = dic.copy() for agent_class_name in aeidon.agents.__all__: agent_class = getattr(aeidon.agents, agent_class_name) def is_delegate_method(name): value = getattr(agent_class, name) return (callable(value) and hasattr(value, "export") and value.export is True) attr_names = list(filter(is_delegate_method, dir(agent_class))) for attr_name in attr_names: new_dict[attr_name] = getattr(agent_class, attr_name) return type.__new__(meta, class_name, bases, new_dict) class Project(aeidon.Observable, metaclass=ProjectMeta): """ Model for subtitle data. :ivar calc: Instance of :class:`aeidon.Calculator` used :ivar clipboard: Instance of :class:`aeidon.Clipboard` used :ivar _delegations: Dictionary mapping method names to agent methods :ivar framerate: :attr:`aeidon.framerates` item corresponding to video :ivar main_changed: Integer, status of main document At unchanged state (i.e. file on disk corresponds to the state of the document) this value is zero. Doing and redoing increase the value by one and undoing decreases value by one. :ivar main_file: Main instance of :class:`aeidon.SubtitleFile` :ivar redoables: Stack of :class:`aeidon.RevertableAction` instances :ivar subtitles: List of :class:`aeidon.Subtitle` instances :ivar tran_changed: Integer, status of translation document At unchanged state (i.e. file on disk corresponds to the state of the document) this value is zero. Doing and redoing increase the value by one and undoing decreases value by one. :ivar tran_file: Translation instance of :class:`aeidon.SubtitleFile` :ivar undo_limit: Maximum size of undo/redo stacks or None for no limit :ivar undoables: Stack of :class:`aeidon.RevertableAction` instances :ivar video_path: Full, absolute path to the video file on disk Signals and their arguments for callback functions: * ``action-done``: project, action * ``action-redone``: project, action * ``action-undone``: project, action * ``main-file-opened``: project, main_file * ``main-file-saved``: project, main_file * ``main-texts-changed``: project, indices * ``positions-changed``: project, indices * ``subtitles-changed``: project, indices * ``subtitles-inserted``: project, indices * ``subtitles-removed``: project, indices * ``translation-file-opened``: project, tran_file * ``translation-file-saved``: project, tran_file * ``translation-texts-changed``: project, indices """ signals = ( "action-done", "action-redone", "action-undone", "main-file-opened", "main-file-saved", "main-texts-changed", "positions-changed", "subtitles-inserted", "subtitles-removed", "subtitles-changed", "translation-file-opened", "translation-file-saved", "translation-texts-changed", ) def __init__(self, framerate=None): """Initialize a :class:`Project` instance.""" aeidon.Observable.__init__(self) framerate = framerate or aeidon.framerates.FPS_23_976 self.calc = aeidon.Calculator(framerate) self.clipboard = aeidon.Clipboard() self._delegations = {} self.framerate = framerate self.main_changed = 0 self.main_file = None self.redoables = [] self.subtitles = [] self.tran_changed = None self.tran_file = None self.undo_limit = 100000 self.undoables = [] self.video_path = None self._init_delegations() def __getattr__(self, name): """Return method delegated to an agent.""" try: return self._delegations[name] except LookupError: raise AttributeError def _init_delegations(self): """Initialize the delegation mappings.""" for agent_class_name in aeidon.agents.__all__: agent = getattr(aeidon.agents, agent_class_name)(self) def is_delegate_method(name): value = getattr(agent, name) return (callable(value) and hasattr(value, "export") and value.export is True) attr_names = list(filter(is_delegate_method, dir(agent))) for attr_name in attr_names: attr_value = getattr(agent, attr_name) if attr_name in self._delegations: raise ValueError("Multiple definitions of {!r}" .format(attr_name)) self._delegations[attr_name] = attr_value # Remove class-level function added by ProjectMeta. if hasattr(self.__class__, attr_name): delattr(self.__class__, attr_name) gaupol-1.11/aeidon/revertable.py000066400000000000000000000062611422217132500166730ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Actions that can be reverted, i.e. undone and redone.""" import aeidon __all__ = ("RevertableAction", "RevertableActionGroup",) class RevertableAction: """ Action that can be reverted, i.e. undone and redone. :ivar description: Short one line description :ivar docs: Sequence of :attr:`aeidon.documents` items affected :ivar register: :attr:`aeidon.registers` item for action taken :ivar revert_args: Arguments passed to the revert method :ivar revert_function: Method called to revert this action :ivar revert_kwargs: Keyword arguments passed to the revert method """ def __init__(self, **kwargs): """ Initialize a :class:`RevertableAction` instance. `kwargs` can contain any of the names of public instance variables, of which :attr:`description`, :attr:`docs`, :attr:`register` and :attr:`revert_function` are required to be set eventually, either with `kwargs` or direct assignment later. """ self.description = None self.docs = None self.register = None self.revert_args = () self.revert_function = None self.revert_kwargs = {} for key, value in kwargs.items(): setattr(self, key, value) def _get_reversion_register(self): """Return the :attr:`aeidon.registers` item for reversion.""" if self.register.shift == 1: return aeidon.registers.UNDO if self.register.shift == -1: return aeidon.registers.REDO raise ValueError("Invalid register: {!r}" .format(self.register)) def revert(self): """Call the reversion function.""" kwargs = self.revert_kwargs.copy() kwargs["register"] = self._get_reversion_register() return self.revert_function(*self.revert_args, **kwargs) class RevertableActionGroup: """ Group of :class:`RevertableAction`. :ivar actions: Sequence of :class:`RevertableAction` in group :ivar description: Short one line description """ def __init__(self, **kwargs): """ Initialize a :class:`RevertableAction` instance. `kwargs` can contain any of the names of public instance variables, of which :attr:`actions` and :attr:`description` are required to be set eventually, either with `kwargs` or direct assignment later. """ self.actions = None self.description = None for key, value in kwargs.items(): setattr(self, key, value) gaupol-1.11/aeidon/scripts.py000066400000000000000000000037351422217132500162320ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 . """Names and ISO 15924 codes for scripts and conversions between them.""" import aeidon import json import os from aeidon.i18n import d_ _scripts = {} def _init_scripts(): """Initialize the dictionary mapping codes to names.""" # Prefer globally installed, fall back on possibly bundled. path = "/usr/share/iso-codes/json/iso_15924.json" if os.path.isfile(path): return _init_scripts_json(path) path = os.path.join(aeidon.DATA_DIR, "iso-codes", "iso_15924.json") if os.path.isfile(path): return _init_scripts_json(path) def _init_scripts_json(path): """Initialize the dictionary mapping codes to names.""" with open(path, "r", encoding="utf_8") as f: iso = json.load(f) for script in iso["15924"]: code = script.get("alpha_4", None) name = script.get("name", None) if not code or not name: continue _scripts[code] = name def code_to_name(code): """Convert ISO 15924 `code` to localized script name.""" if not _scripts: _init_scripts() with aeidon.util.silent(LookupError): return d_("iso_15924", _scripts[code]) return code def is_valid(code): """Return ``True`` if `code` is a valid ISO 15924 script code.""" if not _scripts: _init_scripts() return code in _scripts gaupol-1.11/aeidon/singleton.py000066400000000000000000000020471422217132500165400ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 . """Base class for single-instance classes.""" __all__ = ("Singleton",) class Singleton: """Base class for single-instance classes.""" def __new__(cls, *args, **kwargs): """Return possibly existing instance.""" if not "_instance" in cls.__dict__: cls._instance = object.__new__(cls, *args, **kwargs) return cls._instance gaupol-1.11/aeidon/spell.py000066400000000000000000000233161422217132500156570ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2019 Osmo Salomaa # # 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 . """Checking and correcting spelling.""" import aeidon import os import re with aeidon.util.silent(Exception): from gi.repository import Gspell __all__ = ("SpellChecker", "SpellCheckNavigator", "SpellCheckTokenizer") class SpellChecker: """Checking the spelling of an individual word.""" def __init__(self, language): """Initialize a :class:`SpellChecker` instance.""" glanguage = Gspell.language_lookup(language) if glanguage is None: raise aeidon.Error('Language "{}" not supported'.format(language)) self.checker = Gspell.Checker(language=glanguage) self.language = language self.replacements = [] self.read_replacements() def add_replacement(self, word, replacement): """Inform that `word` is to be replaced with `replacement`.""" self.replacements.append((word, replacement)) def add_to_personal(self, word): """Add `word` to personal word list.""" self.checker.add_word_to_personal(word, -1) def add_to_session(self, word): """Add `word` to session word list.""" self.checker.add_word_to_session(word, -1) @classmethod def available(cls): """Return ``True`` if spell-check is available.""" return "Gspell" in globals() def check(self, word, leading_context="", trailing_context=""): """Return ``True`` if `word` is correct, ``False`` otherwise.""" # Include special cases to deal with suboptimal tokenization # and informal spoken language common in subtitles. if self.language.startswith("en"): if word.endswith("in") and trailing_context.startswith("'"): # Also check word with formal "ing" ending. return self.check_any(word, word + "g") for suffix in ["'d", "'ll", "'re", "'s", "'ve"]: # Strip certain suffixes to also check just the main word. # https://en.wikipedia.org/wiki/English_possessive # https://en.wikipedia.org/wiki/Contraction_(grammar)#English if word.endswith(suffix): return self.check_any(word, word[:-len(suffix)]) if (re.match(r"^\d*?(? 1 and not word.isdigit(): yield (i, word) i += len(word) else: i += 1 gaupol-1.11/aeidon/subtitle.py000066400000000000000000000353151422217132500163750ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 . """Data store and basic position manipulation of a single subtitle.""" import aeidon import copy __all__ = ("Subtitle",) class Subtitle: """ Data store and basic position manipulation of a single subtitle. :ivar start: Start position in native units :ivar start_time: Start time as string :ivar start_frame: Start frame as integer :ivar start_seconds: Start seconds as float :ivar end: End position in native units :ivar end_time: End time as string :ivar end_frame: End frame as integer :ivar end_seconds: End seconds as float :ivar duration: Duration in native units :ivar duration_time: Duration in time as string :ivar duration_frame: Duration in frames as integer :ivar duration_seconds: Duration in seconds as float :ivar main_text: Main text :ivar tran_text: Translation text :ivar calc: :class:`aeidon.Calculator` instance used :ivar framerate: :attr:`aeidon.framerates` item :ivar mode: :attr:`aeidon.modes` item Positions can be set as times, frames or seconds. Use :func:`aeidon.as_time`, :func:`aeidon.as_frame` or :func:`aeidon.as_seconds` if necessary to ensure correct type. Additional format-specific attributes are kept under separate containers, e.g. ``ssa`` for Sub Station Alpha formats, accessed as ``subtitle.ssa.*``. These containers are lazily created upon first use in order to avoid slow instantiation and excessive memory use when handling simpler formats. """ def __init__(self, mode=None, framerate=None): """Initialize a :class:`Subtitle` instance.""" self._start = None self._end = None self._main_text = "" self._tran_text = "" self._mode = mode or aeidon.modes.TIME self._framerate = framerate or aeidon.framerates.FPS_23_976 self.calc = aeidon.Calculator(self._framerate) self.start = "00:00:00.000" self.end = "00:00:00.000" def __eq__(self, other): """Compare subtitle equality by value.""" if not isinstance(other, Subtitle): raise NotImplementedError return (self.start == other.start and self.end == other.end and self.main_text == other.main_text and self.tran_text == other.tran_text and self.framerate == other.framerate and self.mode == other.mode) def __getattr__(self, name): """Return lazily instantiated format-specific attribute container.""" if name in (x.container for x in aeidon.formats): # Lazily instantiate a new container. container = aeidon.containers.new(name) object.__setattr__(self, name, container) return container raise AttributeError("Invalid container name: {!r}" .format(name)) def __ge__(self, other): """Compare start positions.""" if self._mode == aeidon.modes.TIME: return self.start_seconds >= other.start_seconds if self._mode == aeidon.modes.FRAME: return self.start_frame >= other.start_frame raise ValueError("Invalid mode: {!r}" .format(self._mode)) def __gt__(self, other): """Compare start positions.""" if self._mode == aeidon.modes.TIME: return self.start_seconds > other.start_seconds if self._mode == aeidon.modes.FRAME: return self.start_frame > other.start_frame raise ValueError("Invalid mode: {!r}" .format(self._mode)) def __le__(self, other): """Compare start positions.""" if self._mode == aeidon.modes.TIME: return self.start_seconds <= other.start_seconds if self._mode == aeidon.modes.FRAME: return self.start_frame <= other.start_frame raise ValueError("Invalid mode: {!r}" .format(self._mode)) def __lt__(self, other): """Compare start positions.""" if self._mode == aeidon.modes.TIME: return self.start_seconds < other.start_seconds if self._mode == aeidon.modes.FRAME: return self.start_frame < other.start_frame raise ValueError("Invalid mode: {!r}" .format(self._mode)) def convert_framerate(self, framerate): """Set framerate and convert positions to it.""" coefficient = framerate.value / self._framerate.value if self._mode == aeidon.modes.TIME: self.start_seconds = self.start_seconds / coefficient self.end_seconds = self.end_seconds / coefficient if self._mode == aeidon.modes.FRAME: self.start_frame = round(coefficient * self.start_frame) self.end_frame = round(coefficient * self.end_frame) self.framerate = framerate def _convert_position(self, value): """Return `value` of position in correct mode.""" if aeidon.is_time(value): if self._mode == aeidon.modes.TIME: return value if self._mode == aeidon.modes.FRAME: return self.calc.time_to_frame(value) if aeidon.is_frame(value): if self._mode == aeidon.modes.TIME: return self.calc.frame_to_time(value) if self._mode == aeidon.modes.FRAME: return value if aeidon.is_seconds(value): if self._mode == aeidon.modes.TIME: return self.calc.seconds_to_time(value) if self._mode == aeidon.modes.FRAME: return self.calc.seconds_to_frame(value) raise ValueError("Invalid type for value: {!r}" .format(type(value))) def copy(self): """Return a new subtitle instance with the same values.""" subtitle = Subtitle(self._mode, self._framerate) subtitle._start = self._start subtitle._end = self._end subtitle._main_text = self._main_text subtitle._tran_text = self._tran_text # Copy all containers that have been instantiated. containers = (x.container for x in aeidon.formats) for name in set(dir(self)) & set(containers): container = copy.deepcopy(getattr(self, name)) setattr(subtitle, name, container) return subtitle @property def duration(self): """Return duration in correct mode.""" if self._mode == aeidon.modes.TIME: return self.duration_time if self._mode == aeidon.modes.FRAME: return self.duration_frame raise ValueError("Invalid mode: {!r}" .format(self._mode)) @duration.setter def duration(self, value): """Set duration from `value`.""" value = self._convert_position(value) self._end = self.calc.add(self._start, value) @property def duration_frame(self): """Return duration as frames.""" return self.end_frame - self.start_frame @duration_frame.setter def duration_frame(self, value): """Set duration from `value`.""" self.duration = aeidon.as_frame(value) @property def duration_seconds(self): """Return duration as seconds.""" return self.end_seconds - self.start_seconds @duration_seconds.setter def duration_seconds(self, value): """Set duration from `value`.""" self.duration = aeidon.as_seconds(value) @property def duration_time(self): """Return duration as time.""" return self.calc.seconds_to_time(self.duration_seconds) @duration_time.setter def duration_time(self, value): """Set duration from `value`.""" self.duration = aeidon.as_time(value) @property def end(self): """Return end position in correct mode.""" return self._end @end.setter def end(self, value): """Set end position from `value`.""" self._end = self._convert_position(value) @property def end_frame(self): """Return end position as frames.""" if self._mode == aeidon.modes.TIME: return self.calc.time_to_frame(self._end) if self._mode == aeidon.modes.FRAME: return self._end raise ValueError("Invalid mode: {!r}" .format(self._mode)) @end_frame.setter def end_frame(self, value): """Set end position from `value`.""" self.end = aeidon.as_frame(value) @property def end_seconds(self): """Return end position as seconds.""" return self.calc.time_to_seconds(self.end_time) @end_seconds.setter def end_seconds(self, value): """Set end position from `value`.""" self.end = aeidon.as_seconds(value) @property def end_time(self): """Return end position as time.""" if self._mode == aeidon.modes.TIME: return self._end if self._mode == aeidon.modes.FRAME: return self.calc.frame_to_time(self._end) raise ValueError("Invalid mode: {!r}" .format(self._mode)) @end_time.setter def end_time(self, value): """Set end position from `value`.""" self.end = aeidon.as_time(value) @property def framerate(self): """Return framerate.""" return self._framerate @framerate.setter def framerate(self, value): """Set framerate from `value`.""" self._framerate = value self.calc = aeidon.Calculator(value) def get_duration(self, mode): """Return duration in `mode`.""" if mode == aeidon.modes.TIME: return self.duration_time if mode == aeidon.modes.FRAME: return self.duration_frame raise ValueError("Invalid mode: {!r}" .format(mode)) def get_end(self, mode): """Return end position in `mode`.""" if mode == aeidon.modes.TIME: return self.end_time if mode == aeidon.modes.FRAME: return self.end_frame raise ValueError("Invalid mode: {!r}" .format(mode)) def get_start(self, mode): """Return start position in `mode`.""" if mode == aeidon.modes.TIME: return self.start_time if mode == aeidon.modes.FRAME: return self.start_frame raise ValueError("Invalid mode: {!r}" .format(mode)) def get_text(self, doc): """Return text corresponding to `doc`.""" if doc == aeidon.documents.MAIN: return self._main_text if doc == aeidon.documents.TRAN: return self._tran_text raise ValueError("Invalid document: {!r}" .format(doc)) def has_container(self, name): """Return ``True`` if container has been instantiated.""" return name in dir(self) @property def main_text(self): """Return main text.""" return self._main_text @main_text.setter def main_text(self, value): """Set main text from `value`.""" self._main_text = value @property def mode(self): """Return current position mode.""" return self._mode @mode.setter def mode(self, mode): """Set current position mode.""" if mode == aeidon.modes.TIME: self._start = self.start_time self._end = self.end_time if mode == aeidon.modes.FRAME: self._start = self.start_frame self._end = self.end_frame self._mode = mode def scale_positions(self, value): """Multiply start and end positions by `value`.""" if self._mode == aeidon.modes.TIME: self.start_seconds = self.start_seconds * value self.end_seconds = self.end_seconds * value if self._mode == aeidon.modes.FRAME: self.start_frame = round(self._start * value) self.end_frame = round(self._end * value) def set_text(self, doc, value): """Set text corresponding to `doc` to `value`.""" if doc == aeidon.documents.MAIN: self.main_text = value if doc == aeidon.documents.TRAN: self.tran_text = value def shift_positions(self, value): """Add `value` to start and end positions.""" self._start = self.calc.add(self._start, value) self._end = self.calc.add(self._end, value) @property def start(self): """Return start position in correct mode.""" return self._start @start.setter def start(self, value): """Set start position from `value`.""" self._start = self._convert_position(value) @property def start_frame(self): """Return start position as frames.""" if self._mode == aeidon.modes.TIME: return self.calc.time_to_frame(self._start) if self._mode == aeidon.modes.FRAME: return self._start raise ValueError("Invalid mode: {!r}" .format(self._mode)) @start_frame.setter def start_frame(self, value): """Set start position from `value`.""" self.start = aeidon.as_frame(value) @property def start_seconds(self): """Return start position as seconds.""" return self.calc.time_to_seconds(self.start_time) @start_seconds.setter def start_seconds(self, value): """Set start position from `value`.""" self.start = aeidon.as_seconds(value) @property def start_time(self): """Return start position as time.""" if self._mode == aeidon.modes.TIME: return self._start if self._mode == aeidon.modes.FRAME: return self.calc.frame_to_time(self._start) raise ValueError("Invalid mode: {!r}" .format(self._mode)) @start_time.setter def start_time(self, value): """Set start position from `value`.""" self.start = aeidon.as_time(value) @property def tran_text(self): """Return translation text.""" return self._tran_text @tran_text.setter def tran_text(self, value): """Set translation text from `value`.""" self._tran_text = value gaupol-1.11/aeidon/temp.py000066400000000000000000000035041422217132500155020ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 . """Creating and removing temporary files and directories.""" import aeidon import atexit import os import tempfile _paths = [] def create(suffix=""): """Create a new temporary file and return its path.""" handle, path = tempfile.mkstemp(suffix, "gaupol-") # Avoid PermissionErrors etc. on Windows by closing # the handle and returning only the path which will # be opened and closed separately. os.close(handle) _paths.append(path) return path def create_directory(suffix=""): """Create a new temporary directory and return its path.""" path = tempfile.mkdtemp(suffix, "gaupol-") _paths.append(path) return path def remove(path): """Remove temporary file or directory at `path`.""" if os.path.isfile(path): with aeidon.util.silent(OSError): os.remove(path) if os.path.isdir(path): for name in os.listdir(path): remove(os.path.join(path, name)) with aeidon.util.silent(OSError): os.rmdir(path) def remove_all(): """Remove all temporary files and directories.""" for path in _paths: remove(path) atexit.register(remove_all) gaupol-1.11/aeidon/test/000077500000000000000000000000001422217132500151405ustar00rootroot00000000000000gaupol-1.11/aeidon/test/__init__.py000066400000000000000000000000001422217132500172370ustar00rootroot00000000000000gaupol-1.11/aeidon/test/test_calculator.py000066400000000000000000000122661422217132500207110ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class TestCalculator(aeidon.TestCase): def setup_method(self, method): self.framerate = aeidon.framerates.FPS_23_976 self.calc = aeidon.Calculator(self.framerate) def test___new__(self): a = aeidon.Calculator(aeidon.framerates.FPS_23_976) b = aeidon.Calculator(aeidon.framerates.FPS_23_976) assert a is b def test___new____float(self): a = aeidon.Calculator(48.0) b = aeidon.Calculator(96.0) assert a is not b def test_add__frames(self): assert self.calc.add(10, 10) == 20 def test_add__seconds(self): assert self.calc.add(10.0, 10.0) == 20.0 def test_add__times(self): assert self.calc.add("00:00:10.000", "00:00:10.000") == "00:00:20.000" def test_frame_to_seconds(self): calc = aeidon.Calculator(aeidon.framerates.FPS_25_000) assert calc.frame_to_seconds(127) == 5.08 def test_frame_to_time(self): assert self.calc.frame_to_time(2658) == "00:01:50.861" def test_get_middle__frame(self): assert self.calc.get_middle(300, 400) == 350 def test_get_middle__seconds(self): assert self.calc.get_middle(300.0, 400.0) == 350.0 def test_get_middle__time(self): assert self.calc.get_middle("00:00:01.000", "00:00:02.000") == "00:00:01.500" def test_is_earlier__frame(self): assert self.calc.is_earlier(1, 2) assert not self.calc.is_earlier(2, 2) assert not self.calc.is_earlier(2, 1) def test_is_earlier__seconds(self): assert self.calc.is_earlier(1.0, 2.0) assert not self.calc.is_earlier(2.0, 2.0) assert not self.calc.is_earlier(2.0, 1.0) def test_is_earlier__time(self): assert self.calc.is_earlier("00:00:01.000", "00:00:02.000") assert not self.calc.is_earlier("00:00:01.000", "00:00:01.000") assert not self.calc.is_earlier("00:00:02.000", "00:00:01.000") def test_is_later__frame(self): assert self.calc.is_later(2, 1) assert not self.calc.is_later(2, 2) assert not self.calc.is_later(1, 2) def test_is_later__seconds(self): assert self.calc.is_later(2.0, 1.0) assert not self.calc.is_later(2.0, 2.0) assert not self.calc.is_later(1.0, 2.0) def test_is_later__time(self): assert self.calc.is_later("00:00:02.000", "00:00:01.000") assert not self.calc.is_later("00:00:02.000", "00:00:02.000") assert not self.calc.is_later("00:00:01.000", "00:00:02.000") def test_is_valid_time__false(self): assert not self.calc.is_valid_time("2:34:56.789") assert not self.calc.is_valid_time("12:60:56.789") def test_is_valid_time__true(self): assert self.calc.is_valid_time("12:34:56.789") assert self.calc.is_valid_time("-12:34:56.789") def test_normalize_time(self): assert self.calc.normalize_time("1:2:3.4") == "01:02:03.400" assert self.calc.normalize_time("-1:2:3,4") == "-01:02:03.400" assert self.calc.normalize_time("12:34.567") == "00:12:34.567" def test_round__frame(self): assert self.calc.round(13, -1) == 10 def test_round__seconds(self): assert self.calc.round(13.33, 0) == 13.0 def test_round__time(self): assert self.calc.round("12:34:56.789", 1) == "12:34:56.800" def test_seconds_to_frame(self): assert self.calc.seconds_to_frame(6552) == 157091 def test_seconds_to_time(self): assert self.calc.seconds_to_time(68951.15388) == "19:09:11.154" def test_time_to_frame(self): assert self.calc.time_to_frame("01:22:36.144") == 118829 def test_time_to_seconds(self): assert self.calc.time_to_seconds("03:45:22.117") == 13522.117 def test_to_frame(self): self.calc = aeidon.Calculator(aeidon.framerates.FPS_25_000) assert self.calc.to_frame("00:00:01.000") == 25 assert self.calc.to_frame(25) == 25 assert self.calc.to_frame(1.0) == 25 def test_to_seconds(self): self.calc = aeidon.Calculator(aeidon.framerates.FPS_25_000) assert self.calc.to_seconds("00:00:01.000") == 1.0 assert self.calc.to_seconds(25) == 1.0 assert self.calc.to_seconds(1.0) == 1.0 def test_to_time(self): self.calc = aeidon.Calculator(aeidon.framerates.FPS_25_000) assert self.calc.to_time("00:00:01.000") == "00:00:01.000" assert self.calc.to_time(25) == "00:00:01.000" assert self.calc.to_time(1.0) == "00:00:01.000" gaupol-1.11/aeidon/test/test_countries.py000066400000000000000000000021551422217132500205670ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon from aeidon.i18n import d_ class TestModule(aeidon.TestCase): def test_code_to_name(self): name = d_("iso_3166", "Ireland") assert aeidon.countries.code_to_name("IE") == name name = d_("iso_3166", "Yemen") assert aeidon.countries.code_to_name("YE") == name def test_is_valid(self): assert aeidon.countries.is_valid("RU") assert not aeidon.countries.is_valid("XX") gaupol-1.11/aeidon/test/test_deco.py000066400000000000000000000021371422217132500174660ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2006 Osmo Salomaa # # 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 aeidon class TestModule(aeidon.TestCase): def setup_method(self, method): self.project = self.new_project() def test_silent(self): function = lambda: 0 / 0 aeidon.deco.silent(ZeroDivisionError)(function)() aeidon.deco.silent(ZeroDivisionError, tb=True)(function)() aeidon.deco.silent(Exception)(function)() aeidon.deco.silent(Exception, tb=True)(function)() gaupol-1.11/aeidon/test/test_delegate.py000066400000000000000000000024551422217132500203310ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2006 Osmo Salomaa # # 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 aeidon class PuppetMaster: def __init__(self): self.name = "master" class TestDelegate(aeidon.TestCase): def setup_method(self, method): self.master = PuppetMaster() self.delegate = aeidon.Delegate(self.master) def test___getattr__(self): assert self.delegate.name == "master" def test___setattr____delegate(self): self.delegate.none = None assert "none" in self.delegate.__dict__ assert not "none" in self.master.__dict__ def test___setattr____master(self): self.delegate.name = "slave" assert self.master.name == "slave" gaupol-1.11/aeidon/test/test_encodings.py000066400000000000000000000153401422217132500205250ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon import codecs from aeidon.i18n import _ from unittest.mock import patch # https://docs.python.org/3.10/library/codecs.html#standard-encodings ENCODINGS = [ "ascii", "big5", "big5hkscs", "cp037", "cp273", "cp424", "cp437", "cp500", "cp720", "cp737", "cp775", "cp850", "cp852", "cp855", "cp856", "cp857", "cp858", "cp860", "cp861", "cp862", "cp863", "cp864", "cp865", "cp866", "cp869", "cp874", "cp875", "cp932", "cp949", "cp950", "cp1006", "cp1026", "cp1125", "cp1140", "cp1250", "cp1251", "cp1252", "cp1253", "cp1254", "cp1255", "cp1256", "cp1257", "cp1258", "euc_jp", "euc_jis_2004", "euc_jisx0213", "euc_kr", "gb2312", "gbk", "gb18030", "hz", "iso2022_jp", "iso2022_jp_1", "iso2022_jp_2", "iso2022_jp_2004", "iso2022_jp_3", "iso2022_jp_ext", "iso2022_kr", "latin_1", "iso8859_2", "iso8859_3", "iso8859_4", "iso8859_5", "iso8859_6", "iso8859_7", "iso8859_8", "iso8859_9", "iso8859_10", "iso8859_11", "iso8859_13", "iso8859_14", "iso8859_15", "iso8859_16", "johab", "koi8_r", "koi8_t", "koi8_u", "kz1048", "mac_cyrillic", "mac_greek", "mac_iceland", "mac_latin2", "mac_roman", "mac_turkish", "ptcp154", "shift_jis", "shift_jis_2004", "shift_jisx0213", "utf_32", "utf_32_be", "utf_32_le", "utf_16", "utf_16_be", "utf_16_le", "utf_7", "utf_8", "utf_8_sig", ] class TestModule(aeidon.TestCase): def test_all_found(self): for code in ENCODINGS: # Skip if code not included in the Python version # that we're currently running. if not aeidon.encodings.is_valid_code(code): continue code = aeidon.encodings.translate_code(code) assert aeidon.encodings.code_to_name(code) assert aeidon.encodings.code_to_description(code) def test_code_to_description(self): code_to_description = aeidon.encodings.code_to_description assert code_to_description("cp1006") == _("Urdu") assert code_to_description("hz") == _("Chinese simplified") assert code_to_description("shift_jis") == _("Japanese") def test_code_to_long_name(self): code, name, description = ("cp1140", "IBM1140", _("Western")) long_name = aeidon.encodings.code_to_long_name(code) assert long_name == _("{description} ({name})").format(**locals()) def test_code_to_name(self): code_to_name = aeidon.encodings.code_to_name assert code_to_name("big5hkscs") == "Big5-HKSCS" assert code_to_name("cp949") == "IBM949" assert code_to_name("mac_roman") == "MacRoman" def test_detect(self): name = aeidon.encodings.detect(self.new_subrip_file()) assert aeidon.encodings.is_valid_code(name) def test_detect_bom__none(self): path = self.new_subrip_file() encoding = aeidon.encodings.detect_bom(path) assert encoding is None @patch("aeidon.encodings.is_valid_code", lambda x: True) def test_detect_bom__utf_16_be(self): path = self.new_subrip_file() blob = open(path, "rb").read() open(path, "wb").write(codecs.BOM_UTF16_BE + blob) encoding = aeidon.encodings.detect_bom(path) assert encoding == "utf_16_be" @patch("aeidon.encodings.is_valid_code", lambda x: True) def test_detect_bom__utf_16_le(self): path = self.new_subrip_file() blob = open(path, "rb").read() open(path, "wb").write(codecs.BOM_UTF16_LE + blob) encoding = aeidon.encodings.detect_bom(path) assert encoding == "utf_16_le" @patch("aeidon.encodings.is_valid_code", lambda x: True) def test_detect_bom__utf_32_be(self): path = self.new_subrip_file() blob = open(path, "rb").read() open(path, "wb").write(codecs.BOM_UTF32_BE + blob) encoding = aeidon.encodings.detect_bom(path) assert encoding == "utf_32_be" @patch("aeidon.encodings.is_valid_code", lambda x: True) def test_detect_bom__utf_32_le(self): path = self.new_subrip_file() blob = open(path, "rb").read() open(path, "wb").write(codecs.BOM_UTF32_LE + blob) encoding = aeidon.encodings.detect_bom(path) assert encoding == "utf_32_le" @patch("aeidon.encodings.is_valid_code", lambda x: True) def test_detect_bom__utf_8_sig(self): path = self.new_subrip_file() blob = open(path, "rb").read() open(path, "wb").write(codecs.BOM_UTF8 + blob) encoding = aeidon.encodings.detect_bom(path) assert encoding == "utf_8_sig" def test_get_locale_code(self): code = aeidon.encodings.get_locale_code() assert aeidon.encodings.is_valid_code(code) def test_get_locale_long_name(self): long_name = aeidon.encodings.get_locale_long_name() code = aeidon.encodings.get_locale_code() name = aeidon.encodings.code_to_name(code) assert long_name == _("Current locale ({})").format(name) def test_get_valid(self): assert aeidon.encodings.get_valid() for item in aeidon.encodings.get_valid(): code, name, description = item assert aeidon.encodings.is_valid_code(code) def test_is_valid_code(self): assert aeidon.encodings.is_valid_code("gbk") assert aeidon.encodings.is_valid_code("utf_16_be") assert not aeidon.encodings.is_valid_code("xxxxx") def test_name_to_code(self): name_to_code = aeidon.encodings.name_to_code assert name_to_code("IBM037") == "cp037" assert name_to_code("GB2312") == "gb2312" assert name_to_code("PTCP154") == "ptcp154" def test_translate_code(self): translate_code = aeidon.encodings.translate_code assert translate_code("johab") == "johab" assert translate_code("UTF-8") == "utf_8" assert translate_code("ISO-8859-1") == "latin_1" gaupol-1.11/aeidon/test/test_enum.py000066400000000000000000000050131422217132500175140ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class TestEnumerationItem(aeidon.TestCase): def setup_method(self, method): self.parent = object() self.item_0 = aeidon.EnumerationItem(0, "a", self.parent) self.item_1 = aeidon.EnumerationItem(1, "b", self.parent) self.item_2 = aeidon.EnumerationItem(2, "c", self.parent) def test___bool__(self): assert self.item_0 assert self.item_1 assert self.item_2 def test___eq__(self): assert self.item_0 == self.item_0 assert self.item_0 == 0 def test___ne__(self): assert self.item_0 != self.item_1 assert self.item_0 != 1 def test___str__(self): assert str(self.item_0) == "a" assert str(self.item_1) == "b" assert str(self.item_2) == "c" class TestEnumeration(aeidon.TestCase): def setup_method(self, method): self.fruits = aeidon.Enumeration() self.fruits.APPLE = aeidon.EnumerationItem() self.fruits.MANGO = aeidon.EnumerationItem() self.fruits.APPLE.size = 10 self.fruits.MANGO.size = 20 def test___contains__(self): assert self.fruits.APPLE in self.fruits assert self.fruits.MANGO in self.fruits def test___delattr__(self): value = self.fruits.MANGO delattr(self.fruits, "MANGO") assert not hasattr(self.fruits, "MANGO") assert not value in self.fruits def test_find_item(self): assert self.fruits.find_item("size", 10) == self.fruits.APPLE assert self.fruits.find_item("size", 20) == self.fruits.MANGO def test___setattr__(self): assert self.fruits.APPLE == 0 assert self.fruits.MANGO == 1 assert self.fruits.APPLE.name == "APPLE" assert self.fruits.MANGO.name == "MANGO" assert self.fruits.APPLE.size == 10 assert self.fruits.MANGO.size == 20 gaupol-1.11/aeidon/test/test_file.py000066400000000000000000000046201422217132500174720ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon import codecs class PuppetSubtitleFile(aeidon.SubtitleFile): format = aeidon.formats.SUBVIEWER2 mode = aeidon.modes.TIME class TestSubtitleFile(aeidon.TestCase): def setup_method(self, method): path = self.new_temp_file(PuppetSubtitleFile.format) newline = aeidon.newlines.UNIX self.file = PuppetSubtitleFile(path, "ascii", newline) def test_read__utf_16(self): path = self.new_subrip_file() with open(path, "r") as f: text = f.read() with open(path, "w", encoding="utf_16") as f: f.write(text) file = aeidon.files.new(aeidon.formats.SUBRIP, path, "utf_16") file.read() def test_read__utf_16_be(self): path = self.new_subrip_file() with open(path, "r") as f: text = f.read() with open(path, "w", encoding="utf_16_be") as f: f.write(str(codecs.BOM_UTF16_BE, "utf_16_be")) f.write(text) file = aeidon.files.new(aeidon.formats.SUBRIP, path, "utf_16_be") file.read() def test_read__utf_16_le(self): path = self.new_subrip_file() with open(path, "r") as f: text = f.read() with open(path, "w", encoding="utf_16_le") as f: f.write(str(codecs.BOM_UTF16_LE, "utf_16_le")) f.write(text) file = aeidon.files.new(aeidon.formats.SUBRIP, path, "utf_16_le") file.read() def test_read__utf_8_sig(self): path = self.new_subrip_file() with open(path, "r") as f: text = f.read() with open(path, "w", encoding="utf_8_sig") as f: f.write(text) file = aeidon.files.new(aeidon.formats.SUBRIP, path, "utf_8") file.read() gaupol-1.11/aeidon/test/test_finder.py000066400000000000000000000160521422217132500200240ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class TestFinder(aeidon.TestCase): ####### 00000000001111111111222222 222233333333334444444444555555 ####### 01234567890123456789012345 678901234567890123456789012345 text = "One only risks it, because\none's survival depends on it." def find_indices(self, next): advance = self.finder.next if next else self.finder.previous pos = [] while True: try: advance() except StopIteration: break pos.append(self.finder.pos) return pos def setup_method(self, method): self.finder = aeidon.Finder() self.finder.set_text(self.text) def test_next__regex(self): self.finder.set_regex(r"^") pos = self.find_indices(next=True) assert pos == [0, 27] def test_next__regex_ignore_case(self): self.finder.ignore_case = True self.finder.set_regex(r"O") pos = self.find_indices(next=True) assert pos == [1, 5, 28, 51] def test_next__string(self): self.finder.pattern = "it" pos = self.find_indices(next=True) assert pos == [17, 55] def test_next__string_ignore_case(self): self.finder.ignore_case = True self.finder.pattern = "o" pos = self.find_indices(next=True) assert pos == [1, 5, 28, 51] def test_previous__regex(self): self.finder.set_regex(r"\s") pos = self.find_indices(next=False) assert pos == [52, 49, 41, 32, 26, 18, 14, 8, 3] def test_previous__regex_ignore_case(self): self.finder.ignore_case = True self.finder.set_regex(r"O") pos = self.find_indices(next=False) assert pos == [50, 27, 4, 0] def test_previous__string(self): self.finder.pattern = "it" pos = self.find_indices(next=False) assert pos == [53, 15] def test_previous__string_ignore_case(self): self.finder.ignore_case = True self.finder.pattern = "o" pos = self.find_indices(next=False) assert pos == [50, 27, 4, 0] def test_replace__equal_length_next(self): self.finder.pattern = "ne" self.finder.replacement = "--" self.finder.next() self.finder.replace() assert self.finder.text == ( "O-- only risks it, because\n" "one's survival depends on it.") assert self.finder.pos == 3 self.finder.next() self.finder.replace() assert self.finder.text == ( "O-- only risks it, because\n" "o--'s survival depends on it.") assert self.finder.pos == 30 self.assert_raises(StopIteration, self.finder.next) def test_replace__equal_length_previous(self): self.finder.pattern = "ne" self.finder.replacement = "--" self.finder.previous() self.finder.replace(next=False) assert self.finder.text == ( "One only risks it, because\n" "o--'s survival depends on it.") assert self.finder.pos == 28 self.finder.previous() self.finder.replace(next=False) assert self.finder.text == ( "O-- only risks it, because\n" "o--'s survival depends on it.") assert self.finder.pos == 1 self.assert_raises(StopIteration, self.finder.previous) def test_replace__lengthen_next(self): self.finder.set_regex(r"$") self.finder.replacement = "--" self.finder.next() self.finder.replace() assert self.finder.text == ( "One only risks it, because--\n" "one's survival depends on it.") assert self.finder.pos == 28 self.finder.next() self.finder.replace() assert self.finder.text == ( "One only risks it, because--\n" "one's survival depends on it.--") assert self.finder.pos == 60 self.assert_raises(StopIteration, self.finder.next) def test_replace__lengthen_previous(self): self.finder.set_regex(r"$") self.finder.replacement = "--" self.finder.previous() self.finder.replace(next=False) assert self.finder.text == ( "One only risks it, because\n" "one's survival depends on it.--") assert self.finder.pos == 56 self.finder.previous() self.finder.replace(next=False) assert self.finder.text == ( "One only risks it, because--\n" "one's survival depends on it.--") assert self.finder.pos == 26 self.assert_raises(StopIteration, self.finder.previous) def test_replace__shorten_next(self): self.finder.set_regex(r"[.,]") self.finder.replacement = "" self.finder.next() self.finder.replace() assert self.finder.text == ( "One only risks it because\n" "one's survival depends on it.") assert self.finder.pos == 17 self.finder.next() self.finder.replace() assert self.finder.text == ( "One only risks it because\n" "one's survival depends on it") assert self.finder.pos == 54 self.assert_raises(StopIteration, self.finder.next) def test_replace__shorten_previous(self): self.finder.set_regex(r"[.,]") self.finder.replacement = "" self.finder.previous() self.finder.replace(next=False) assert self.finder.text == ( "One only risks it, because\n" "one's survival depends on it") assert self.finder.pos == 55 self.finder.previous() self.finder.replace(next=False) assert self.finder.text == ( "One only risks it because\n" "one's survival depends on it") assert self.finder.pos == 17 self.assert_raises(StopIteration, self.finder.previous) def test_replace_all__regex(self): self.finder.set_regex(r"\s") self.finder.replacement = "" count = self.finder.replace_all() assert count == 9 assert self.finder.text == ( "Oneonlyrisksit,because" "one'ssurvivaldependsonit.") def test_replace_all__string(self): self.finder.pattern = "i" self.finder.replacement = "-" count = self.finder.replace_all() assert count == 4 assert self.finder.text == ( "One only r-sks -t, because\n" "one's surv-val depends on -t.") gaupol-1.11/aeidon/test/test_languages.py000066400000000000000000000021521422217132500205170ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon from aeidon.i18n import d_ class TestModule(aeidon.TestCase): def test_code_to_name(self): name = d_("iso_639", "Nauru") assert aeidon.languages.code_to_name("na") == name name = d_("iso_639", "Sindhi") assert aeidon.languages.code_to_name("sd") == name def test_is_valid(self): assert aeidon.languages.is_valid("sv") assert not aeidon.languages.is_valid("xx") gaupol-1.11/aeidon/test/test_liner.py000066400000000000000000000061721422217132500176700ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2011 Osmo Salomaa # # 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 aeidon import re class TestLiner(aeidon.TestCase): def setup_method(self, method): self.liner = aeidon.Liner(re.compile(r"<.+?>")) self.liner.set_penalties(( dict(pattern=r"( )- ", flags=re.DOTALL|re.MULTILINE, group=1, value=-1000), dict(pattern=r"[,.;:!?]( )", flags=re.DOTALL|re.MULTILINE, group=1, value=-100), dict(pattern=r"\b(by|the|into|a)( )", flags=re.DOTALL|re.MULTILINE, group=2, value=1000))) def test_break_lines__1(self): text = "Hello." self.liner.set_text(text) assert self.liner.break_lines() == "Hello." def test_break_lines__2(self): text = ("- Isn't he off on Saturdays? " "- Didn't he tell you?") self.liner.set_text(text) assert self.liner.break_lines() == ( "- Isn't he off on Saturdays?\n" "- Didn't he tell you?") def test_break_lines__3(self): text = ("Close by the king's castle " "lay a great dark forest.") self.liner.set_text(text) assert self.liner.break_lines() == ( "Close by the king's castle\n" "lay a great dark forest.") def test_break_lines__4(self): text = ("The king's child went out " "into the forest and sat down " "by the side of the cool fountain.") self.liner.set_text(text) assert self.liner.break_lines() == ( "The king's child went out\n" "into the forest and sat down\n" "by the side of the cool fountain.") def test_break_lines__5(self): text = ("The king's child went out " "into the forest and sat down by the side " "of the cool fountain; and when " "she was bored she took a golden ball, " "and threw it up high and caught it; " "and this ball was her favorite plaything.") self.liner.set_text(text) assert self.liner.break_lines() == ( "The king's child went out\n" "into the forest and sat down by the side\n" "of the cool fountain; and when she\n" "was bored she took a golden ball,\n" "and threw it up high and caught it; and\n" "this ball was her favorite plaything.") gaupol-1.11/aeidon/test/test_locales.py000066400000000000000000000037641422217132500202050ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon import imp from aeidon.i18n import _, d_ from unittest.mock import patch class TestModule(aeidon.TestCase): def test_code_to_country(self): country = d_("iso_3166", "South Africa") assert aeidon.locales.code_to_country("af_ZA") == country assert aeidon.locales.code_to_country("af") is None def test_code_to_language(self): language = d_("iso_639", "Icelandic") assert aeidon.locales.code_to_language("is_IS") == language assert aeidon.locales.code_to_language("is") == language def test_code_to_name(self): language = d_("iso_639", "Mongolian") country = d_("iso_3166", "Mongolia") name = _("{language} ({country})").format(**locals()) assert aeidon.locales.code_to_name("mn_MN") == name assert aeidon.locales.code_to_name("mn") == language def test_get_system_code(self): assert aeidon.locales.get_system_code() @patch.dict("os.environ", dict(LANGUAGE="sr@Latn")) def test_get_system_modifier__latn(self): imp.reload(aeidon.locales) assert aeidon.locales.get_system_modifier() == "Latn" @patch.dict("os.environ", dict(LANGUAGE="en")) def test_get_system_modifier__none(self): imp.reload(aeidon.locales) assert aeidon.locales.get_system_modifier() is None gaupol-1.11/aeidon/test/test_markup.py000066400000000000000000000041041422217132500200470ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class TestMarkup(aeidon.TestCase): text = "All things weird are normal\nin this whore of cities." def setup_method(self, method): self.markup = aeidon.Markup() def test_clean(self): text = self.markup.clean(self.text) assert text == self.text def test_decode(self): text = self.markup.decode(self.text) assert text == self.text def test_encode__b(self): text = "All things weird are normal\nin this whore of cities." assert self.markup.encode(text) == self.text def test_encode__color(self): text = "All things weird are normal\nin this whore of cities." assert self.markup.encode(text) == self.text def test_encode__font(self): text = "All things weird are normal\nin this whore of cities." assert self.markup.encode(text) == self.text def test_encode__i(self): text = "All things weird are normal\nin this whore of cities." assert self.markup.encode(text) == self.text def test_encode__size(self): text = "All things weird are normal\nin this whore of cities." assert self.markup.encode(text) == self.text def test_encode__u(self): text = "All things weird are normal\nin this whore of cities." assert self.markup.encode(text) == self.text gaupol-1.11/aeidon/test/test_metadata.py000066400000000000000000000057431422217132500203420ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 aeidon from unittest.mock import patch class TestMetadataItem(aeidon.TestCase): def assert_name_in_locale(self, code, modifier): with patch("aeidon.locales.get_system_code", lambda: code): with patch("aeidon.locales.get_system_modifier", lambda: modifier): self.item.set_field("Name", "system") key = "{}@{}".format(code, modifier) if modifier else code self.item.set_field("Name[{}]".format(key), "local") assert self.item.get_name(localize=True) == "local" def setup_method(self, method): self.item = aeidon.MetadataItem() def test_get_description(self): self.item.set_field("Description", "test") assert self.item.get_description(localize=False) == "test" assert self.item.get_description(localize=True) == "test" def test_get_field(self): assert self.item.get_field("Test") is None self.item.set_field("Test", "test") assert self.item.get_field("Test") == "test" def test_get_field_boolean(self): assert self.item.get_field("Test") is None self.item.set_field("Test", "True") assert self.item.get_field_boolean("Test") is True def test_get_field_list(self): assert self.item.get_field("Test") is None self.item.set_field("Test", "Yee;Haw;") assert self.item.get_field_list("Test") == ["Yee", "Haw"] def test_get_name(self): self.item.set_field("Name", "test") assert self.item.get_name(localize=False) == "test" assert self.item.get_name(localize=True) == "test" def test_get_name__localize(self): self.assert_name_in_locale("en_US", "Latn") self.assert_name_in_locale("en_US", None) self.assert_name_in_locale("en", "Latn") self.assert_name_in_locale("en", None) @patch("aeidon.locales.get_system_code", lambda: None) def test_get_name__no_locale(self): self.item.set_field("Name", "system") assert self.item.get_name() == "system" def test_has_field(self): assert not self.item.has_field("Test") self.item.set_field("Test", "test") assert self.item.has_field("Test") def test_set_field(self): self.item.set_field("Test", "test") assert self.item.get_field("Test") == "test" gaupol-1.11/aeidon/test/test_mutables.py000066400000000000000000000103531422217132500203670ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2006 Osmo Salomaa # # 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 aeidon import copy class PuppetMaster: def __init__(self): self.count = 0 def notify(self, name): self.count += 1 class _TestObservable(aeidon.TestCase): def edit_obs(self): raise NotImplementedError def setup_method(self, method): self.master = PuppetMaster() self.obs = None def teardown_method(self, method): if method.__name__ in self.__class__.__dict__: assert self.master.count == 1 def test___copy__(self): obs_copy = copy.copy(self.obs) assert obs_copy == self.obs assert obs_copy.master is self.obs.master self.edit_obs() assert obs_copy != self.obs assert obs_copy.master is self.obs.master def test___deepcopy__(self): obs_copy = copy.deepcopy(self.obs) assert obs_copy == self.obs assert obs_copy.master is self.obs.master self.edit_obs() assert obs_copy != self.obs assert obs_copy.master is self.obs.master class TestObservableDict(_TestObservable): def edit_obs(self): del self.obs[1] def setup_method(self, method): _TestObservable.setup_method(self, method) self.obs = aeidon.ObservableDict({1:1, 2:2}, self.master, "") def test___delitem__(self): del self.obs[1] def test___setitem__(self): self.obs[1] = 2 def test_clear(self): self.obs.clear() def test_pop(self): self.obs.pop(1) def test_popitem(self): self.obs.popitem() def test_setdefault(self): self.obs.setdefault(1, 2) def test_update(self): self.obs.update({1:2, 3:3}) class TestObservableList(_TestObservable): def edit_obs(self): self.obs.pop() def setup_method(self, method): _TestObservable.setup_method(self, method) self.obs = aeidon.ObservableList((1, 2, 3), self.master, "") def test___delitem__(self): del self.obs[0] def test___iadd__(self): self.obs += (4, 5) def test___imul__(self): self.obs *= 2 def test___setitem__(self): self.obs[0] = 2 def test_append(self): self.obs.append(4) def test_extend(self): self.obs.extend((4, 5)) def test_insert(self): self.obs.insert(0, 0) def test_pop(self): self.obs.pop() def test_remove(self): self.obs.remove(1) def test_reverse(self): self.obs.reverse() def test_sort(self): self.obs.sort() class TestObservableSet(_TestObservable): def edit_obs(self): self.obs.pop() def setup_method(self, method): _TestObservable.setup_method(self, method) self.obs = aeidon.ObservableSet((1, 2, 3), self.master, "") def test___iand__(self): self.obs &= set((1, 2)) def test___ior__(self): self.obs |= set((1, 2)) def test___isub__(self): self.obs -= set((1, 2)) def test___ixor__(self): self.obs ^= set((1, 2)) def test_add(self): self.obs.add(4) def test_clear(self): self.obs.clear() def test_difference_update(self): self.obs.difference_update(set((1, 2))) def test_discard(self): self.obs.discard(1) def test_intersection_update(self): self.obs.intersection_update(set((1, 2))) def test_pop(self): self.obs.pop() def test_remove(self): self.obs.remove(1) def test_symmetric_difference_update(self): self.obs.symmetric_difference_update(set((1, 2))) def test_update(self): self.obs.update(set((4, 5))) gaupol-1.11/aeidon/test/test_observable.py000066400000000000000000000065531422217132500207060ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon class PuppetObservable(aeidon.Observable): signals = ("do",) def __init__(self): aeidon.Observable.__init__(self) self.x = 0 class TestObservable(aeidon.TestCase): def on_do(self, obj): assert obj is self.obs self.do_count += 1 def on_notify_x(self, obj, value): assert obj is self.obs assert value == self.obs.x self.notify_count += 1 def setup_method(self, method): self.obs = PuppetObservable() self.do_count = 0 self.notify_count = 0 self.obs.connect("do", self.on_do) self.obs.connect("notify::x", self.on_notify_x) def test_block(self): assert self.obs.block("do") assert not self.obs.block("do") self.obs.emit("do") assert self.do_count == 0 def test_block_all__emit(self): assert self.obs.block_all() assert not self.obs.block_all() self.obs.emit("do") assert self.do_count == 0 def test_block_all__notify(self): assert self.obs.block_all() assert not self.obs.block_all() self.obs.notify("x") assert self.notify_count == 0 def test_connect(self): self.obs.connect("do", lambda *args: None) self.obs.connect("notify::x", lambda *args: None) def test_disconnect(self): self.obs.disconnect("do", self.on_do) self.obs.emit("do") assert self.do_count == 0 def test_emit(self): self.obs.x = 1 assert self.notify_count == 1 self.obs.emit("do") assert self.do_count == 1 def test_freeze_notify(self): assert self.obs.freeze_notify() assert not self.obs.freeze_notify() self.obs.x = 1 assert self.notify_count == 0 def test_notify(self): self.obs.notify("x") assert self.notify_count == 1 def test_thaw_notify(self): self.obs.freeze_notify() self.obs.x = 1 self.obs.x = 2 assert self.obs.thaw_notify() assert not self.obs.thaw_notify() assert self.notify_count == 1 def test_unblock(self): self.obs.block("do") assert self.obs.unblock("do") assert not self.obs.unblock("do") self.obs.emit("do") assert self.do_count == 1 def test_unblock_all__emit(self): self.obs.block_all() assert self.obs.unblock_all() assert not self.obs.unblock_all() self.obs.emit("do") assert self.do_count == 1 def test_unblock_all__notify(self): self.obs.block_all() assert self.obs.unblock_all() assert not self.obs.unblock_all() self.obs.notify("x") assert self.notify_count == 1 gaupol-1.11/aeidon/test/test_parser.py000066400000000000000000000054711422217132500200540ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon import re class TestParser(aeidon.TestCase): def setup_method(self, method): self.parser = aeidon.Parser(re.compile(r"<.+?>"), lambda x: x.strip()) def test_get_text__margins(self): text = ("You will find allies there,\n" "and they will pay more.") self.parser.set_text(text) assert self.parser.get_text() == text def test_get_text__tags(self): text = ("You will find allies there,\n" "and they will pay more.") self.parser.set_text(text) assert self.parser.get_text() == text def test_replace_all__regex(self): text = ("One only risks it, because\n" "one's survival depends on it.") self.parser.set_text(text) self.parser.set_regex(r"\b") self.parser.replacement = "-" self.parser.replace_all() assert self.parser.get_text() == ( "-One- -only- -risks- -it-, -because-\n" "-one-'-s- -survival- -depends- -on- -it-.") def test_replace_all__string(self): text = ("One only risks it, because\n" "one's survival depends on it.") self.parser.set_text(text) self.parser.pattern = "e" self.parser.replacement = "" self.parser.replace_all() assert self.parser.get_text() == ( "On only risks it, bcaus\n" "on's survival dpnds on it.") def test_set_text__margins(self): text = ("One only risks it, because\n" "one's survival depends on it.") self.parser.set_text(text) assert self.parser.text == ( "One only risks it, because\n" "one's survival depends on it.") def test_set_text__tags(self): text = ("One only risks it, because\n" "one's survival depends on it.") self.parser.set_text(text) assert self.parser.text == ( "One only risks it, because\n" "one's survival depends on it.") gaupol-1.11/aeidon/test/test_scripts.py000066400000000000000000000021561422217132500202440ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 aeidon from aeidon.i18n import d_ class TestModule(aeidon.TestCase): def test_code_to_name(self): name = d_("iso_15924", "Arabic") assert aeidon.scripts.code_to_name("Arab") == name name = d_("iso_15924", "Latin") assert aeidon.scripts.code_to_name("Latn") == name def test_is_valid(self): assert aeidon.scripts.is_valid("Latn") assert not aeidon.scripts.is_valid("Xxxx") gaupol-1.11/aeidon/test/test_singleton.py000066400000000000000000000015641422217132500205610ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2008 Osmo Salomaa # # 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 aeidon class PuppetSingleton(aeidon.Singleton): pass class TestSingleton(aeidon.TestCase): def test___new__(self): assert PuppetSingleton() is PuppetSingleton() gaupol-1.11/aeidon/test/test_spell.py000066400000000000000000000111211422217132500176640ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2019 Osmo Salomaa # # 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 aeidon class TestSpellChecker(aeidon.TestCase): def setup_method(self, method): language = self.get_spell_check_language("en") self.checker = aeidon.SpellChecker(language) def test_add_replacement(self): self.checker.add_replacement("abc", "xyz") suggestions = self.checker.suggest("abc") assert suggestions and suggestions[0] == "xyz" def test_add_to_session(self): assert not self.checker.check("asdf") self.checker.add_to_session("asdf") assert self.checker.check("asdf") def test_available(self): assert aeidon.SpellChecker.available() def test_check(self): assert self.checker.check("subtitle") assert not self.checker.check("substitle") def test_list_languages(self): assert aeidon.SpellChecker.list_languages() def test_suggest(self): assert self.checker.suggest("substitle") class TestSpellCheckNavigator(aeidon.TestCase): def setup_method(self, method): language = self.get_spell_check_language("en") self.navigator = aeidon.SpellCheckNavigator(language) self.navigator.text = "She knows the fighting\ntechniques of Panzr Kunst." def test_ignore(self): error = next(self.navigator) assert error == (37, "Panzr") self.navigator.ignore() error = next(self.navigator) assert error == (43, "Kunst") self.navigator.ignore() self.assert_raises(StopIteration, self.navigator.__next__) def test_ignore_all(self): error = next(self.navigator) assert error == (37, "Panzr") self.navigator.ignore_all() self.navigator.reset(self.navigator.text) error = next(self.navigator) assert error == (43, "Kunst") def test_join_with_next(self): error = next(self.navigator) assert error == (37, "Panzr") self.navigator.join_with_next() error = next(self.navigator) assert error == (37, "PanzrKunst") def test_join_with_previous(self): error = next(self.navigator) assert error == (37, "Panzr") self.navigator.ignore() error = next(self.navigator) assert error == (43, "Kunst") self.navigator.join_with_previous() error = next(self.navigator) assert error == (37, "PanzrKunst") def test_leading_context(self): error = next(self.navigator) assert error == (37, "Panzr") assert self.navigator.leading_context(3) == "of " def test_replace(self): text = self.navigator.text text = text.replace("Panzr", "Test") error = next(self.navigator) assert error == (37, "Panzr") self.navigator.replace("Test") assert self.navigator.text == text def test_replace_all(self): self.navigator.reset("abc abc abc") error = next(self.navigator) self.navigator.replace_all("xyz") for error in self.navigator: pass assert self.navigator.text == "xyz xyz xyz" def test_reset(self): error = next(self.navigator) self.navigator.reset(self.navigator.text) assert next(self.navigator) == error def test_suggest(self): error = next(self.navigator) assert error == (37, "Panzr") assert self.navigator.suggest() def test_trailing_context(self): error = next(self.navigator) assert error == (37, "Panzr") assert self.navigator.trailing_context(3) == " Ku" class TestSpellCheckTokenizer(aeidon.TestCase): def setup_method(self, method): text = "- This is an URM ship?\n- Uh-huh." self.tokenizer = aeidon.SpellCheckTokenizer(text) def test_tokenize(self): assert list(self.tokenizer.tokenize()) == [ ( 2, "This"), ( 7, "is"), (10, "an"), (13, "URM"), (17, "ship"), (25, "Uh"), (28, "huh"), ] gaupol-1.11/aeidon/test/test_subtitle.py000066400000000000000000000230701422217132500204060ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 aeidon MAIN = aeidon.documents.MAIN TRAN = aeidon.documents.TRAN FRAME = aeidon.modes.FRAME TIME = aeidon.modes.TIME class TestSubtitle(aeidon.TestCase): def setup_method(self, method): self.tsub = aeidon.Subtitle() self.tsub.mode = TIME self.tsub.framerate = aeidon.framerates.FPS_25_000 self.tsub.start = "00:00:01.000" self.tsub.end = "00:00:03.000" self.tsub.main_text = "main" self.tsub.tran_text = "translation" self.fsub = aeidon.Subtitle() self.fsub.mode = FRAME self.fsub.framerate = aeidon.framerates.FPS_25_000 self.fsub.start = 100 self.fsub.end = 300 self.fsub.main_text = "main" self.fsub.tran_text = "translation" def test_convert_framerate__frame(self): self.fsub.start = 100 self.fsub.end = 200 framerate = aeidon.framerates.FPS_23_976 self.fsub.convert_framerate(framerate) assert self.fsub.framerate == framerate assert self.fsub.start == 96 assert self.fsub.end == 192 def test_convert_framerate__time(self): self.tsub.start = "00:00:01.000" self.tsub.end = "00:00:02.000" framerate = aeidon.framerates.FPS_23_976 self.tsub.convert_framerate(framerate) assert self.tsub.framerate == framerate assert self.tsub.start == "00:00:01.043" assert self.tsub.end == "00:00:02.085" def test_duration__get(self): assert self.tsub.duration == "00:00:02.000" assert self.fsub.duration == 200 def test_duration__set_frame(self): self.fsub.duration = 500 assert self.fsub.end_frame == 600 self.fsub.duration = "00:00:10.000" assert self.fsub.end_frame == 350 self.fsub.duration = 5.0 assert self.fsub.end_frame == 225 def test_duration__set_time(self): self.tsub.duration = "00:00:10.000" assert self.tsub.end_time == "00:00:11.000" self.tsub.duration = 500 assert self.tsub.end_time == "00:00:21.000" self.tsub.duration = 10.0 assert self.tsub.end_time == "00:00:11.000" def test_duration_frame__get(self): assert self.tsub.duration_frame == 50 assert self.fsub.duration_frame == 200 def test_duration_frame__set(self): self.fsub.duration_frame = 500 assert self.fsub.end_frame == 600 def test_duration_seconds__get(self): assert self.tsub.duration_seconds == 2.0 assert self.fsub.duration_seconds == 8.0 def test_duration_seconds__set(self): self.tsub.duration_seconds = 3.0 assert self.tsub.end_seconds == 4.0 def test_duration_time__get(self): assert self.tsub.duration_time == "00:00:02.000" assert self.fsub.duration_time == "00:00:08.000" def test_duration_time__set(self): self.tsub.duration_time = "00:00:03.000" assert self.tsub.end_time == "00:00:04.000" def test_end__get(self): assert self.tsub.end == "00:00:03.000" assert self.fsub.end == 300 def test_end__set_frame(self): self.fsub.end = 500 assert self.fsub.end_frame == 500 self.fsub.end = "00:00:10.000" assert self.fsub.end_frame == 250 self.fsub.end = 5.0 assert self.fsub.end_frame == 125 def test_end__set_time(self): self.tsub.end = "00:00:10.000" assert self.tsub.end_time == "00:00:10.000" self.tsub.end = 500 assert self.tsub.end_time == "00:00:20.000" self.tsub.end = 5.0 assert self.tsub.end_time == "00:00:05.000" def test_end_frame__get(self): assert self.tsub.end_frame == 75 assert self.fsub.end_frame == 300 def test_end_frame__set(self): self.fsub.end_frame = 300 assert self.fsub.end_frame == 300 def test_end_seconds__get(self): assert self.tsub.end_seconds == 3.0 assert self.fsub.end_seconds == 12.0 def test_end_seconds__set(self): self.tsub.end_seconds = 4.0 assert self.tsub.end_seconds == 4.0 def test_end_time__get(self): assert self.tsub.end_time == "00:00:03.000" assert self.fsub.end_time == "00:00:12.000" def test_end_time__set(self): self.tsub.end_time = "00:00:04.000" assert self.tsub.end_time == "00:00:04.000" def test_framerate__get(self): assert self.tsub.framerate == aeidon.framerates.FPS_25_000 assert self.fsub.framerate == aeidon.framerates.FPS_25_000 def test_framerate__set(self): self.tsub.framerate = aeidon.framerates.FPS_29_970 assert self.tsub.framerate == aeidon.framerates.FPS_29_970 def test_get_duration(self): assert self.tsub.get_duration(TIME) == "00:00:02.000" assert self.tsub.get_duration(FRAME) == 50 assert self.fsub.get_duration(TIME) == "00:00:08.000" assert self.fsub.get_duration(FRAME) == 200 def test_get_end(self): assert self.tsub.get_end(TIME) == "00:00:03.000" assert self.tsub.get_end(FRAME) == 75 assert self.fsub.get_end(TIME) == "00:00:12.000" assert self.fsub.get_end(FRAME) == 300 def test_get_start(self): assert self.tsub.get_start(TIME) == "00:00:01.000" assert self.tsub.get_start(FRAME) == 25 assert self.fsub.get_start(TIME) == "00:00:04.000" assert self.fsub.get_start(FRAME) == 100 def test_get_text(self): assert self.tsub.get_text(MAIN) == "main" assert self.tsub.get_text(TRAN) == "translation" def test_main_text__get(self): assert self.tsub.main_text == "main" assert self.fsub.main_text == "main" def test_main_text__set(self): self.tsub.main_text = "test" assert self.tsub.main_text == "test" def test_mode__get(self): assert self.tsub.mode == TIME assert self.fsub.mode == FRAME def test_mode__set_frame(self): self.fsub.mode = FRAME self.fsub.mode = TIME assert self.fsub._start == "00:00:04.000" assert self.fsub._end == "00:00:12.000" def test_mode__set_time(self): self.tsub.mode = TIME self.tsub.mode = FRAME assert self.tsub._start == 25 assert self.tsub._end == 75 def test_scale_positions__frame(self): self.fsub.scale_positions(2.0) assert self.fsub.start == 200 assert self.fsub.end == 600 def test_scale_positions__time(self): self.tsub.scale_positions(2.0) assert self.tsub.start == "00:00:02.000" assert self.tsub.end == "00:00:06.000" def test_set_text(self): self.tsub.set_text(MAIN, "") assert self.tsub.main_text == "" self.tsub.set_text(TRAN, "") assert self.tsub.tran_text == "" def test_shift_positions__frame(self): self.fsub.shift_positions(-10) assert self.fsub._start == 90 assert self.fsub._end == 290 def test_shift_positions__seconds(self): self.tsub.shift_positions(1.0) assert self.tsub._start == "00:00:02.000" assert self.tsub._end == "00:00:04.000" def test_shift_positions__time(self): self.tsub.shift_positions("00:00:01.000") assert self.tsub._start == "00:00:02.000" assert self.tsub._end == "00:00:04.000" def test_start__get(self): assert self.tsub.start == "00:00:01.000" assert self.fsub.start == 100 def test_start__set_frame(self): self.fsub.start = 500 assert self.fsub.start_frame == 500 self.fsub.start = "00:00:10.000" assert self.fsub.start_frame == 250 self.fsub.start = 5.0 assert self.fsub.start_frame == 125 def test_start__set_time(self): self.tsub.start = "00:00:10.000" assert self.tsub.start_time == "00:00:10.000" self.tsub.start = 500 assert self.tsub.start_time == "00:00:20.000" self.tsub.start = 5.0 assert self.tsub.start_time == "00:00:05.000" def test_start_frame__get(self): assert self.tsub.start_frame == 25 assert self.fsub.start_frame == 100 def test_start_frame__set(self): self.fsub.start_frame = 25 assert self.fsub.start_frame == 25 def test_start_seconds__get(self): assert self.tsub.start_seconds == 1.0 assert self.fsub.start_seconds == 4.0 def test_start_seconds__set(self): self.tsub.start_seconds = 0.1 assert self.tsub.start_seconds == 0.1 def test_start_time__get(self): assert self.tsub.start_time == "00:00:01.000" assert self.fsub.start_time == "00:00:04.000" def test_start_time__set(self): self.tsub.start_time = "00:00:00.100" assert self.tsub.start_time == "00:00:00.100" def test_tran_text__get(self): assert self.tsub.tran_text == "translation" assert self.fsub.tran_text == "translation" def test_tran_text_set(self): self.tsub.tran_text = "test" assert self.tsub.tran_text == "test" gaupol-1.11/aeidon/test/test_temp.py000066400000000000000000000032611422217132500175200ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 aeidon import os class TestModule(aeidon.TestCase): def test_create(self): path = aeidon.temp.create() aeidon.temp.remove(path) def test_create_directory(self): path = aeidon.temp.create_directory() aeidon.temp.remove(path) def test_remove__directory(self): path = aeidon.temp.create_directory() open(os.path.join(path, "a"), "w").write("a") open(os.path.join(path, "b"), "w").write("b") os.makedirs(os.path.join(path, "c")) aeidon.temp.remove(path) assert not os.path.isdir(path) aeidon.temp.remove(path) def test_remove__file(self): path = aeidon.temp.create() aeidon.temp.remove(path) assert not os.path.isfile(path) aeidon.temp.remove(path) def test_remove_all(self): path_1 = aeidon.temp.create() path_2 = aeidon.temp.create() aeidon.temp.remove_all() assert not os.path.isfile(path_1) assert not os.path.isfile(path_2) gaupol-1.11/aeidon/test/test_util.py000066400000000000000000000122031422217132500175240ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2006 Osmo Salomaa # # 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 aeidon class TestModule(aeidon.TestCase): def test_atomic_open__existing_file(self): path = self.new_subrip_file() with aeidon.util.atomic_open(path, "w") as f: f.write("test\n") text = open(path, "r").read() assert text == "test\n" def test_atomic_open__no_existing_file(self): path = aeidon.temp.create() with aeidon.util.atomic_open(path, "w") as f: f.write("test\n") text = open(path, "r").read() assert text == "test\n" def test_compare_versions(self): assert aeidon.util.compare_versions("0.1.1", "0.1" ) == 1 assert aeidon.util.compare_versions("0.2" , "0.1" ) == 1 assert aeidon.util.compare_versions("0.3" , "0.3" ) == 0 assert aeidon.util.compare_versions("0.4" , "0.4.1") == -1 assert aeidon.util.compare_versions("0.4" , "0.5" ) == -1 def test_detect_format(self): for format in aeidon.formats: path = self.new_temp_file(format) assert aeidon.util.detect_format(path, "ascii") == format def test_detect_newlines__mac(self): path = aeidon.temp.create() open(path, "w", newline="").write("a\rb\rc\r") newlines = aeidon.util.detect_newlines(path) assert newlines == aeidon.newlines.MAC def test_detect_newlines__unix(self): path = aeidon.temp.create() open(path, "w", newline="").write("a\nb\nc\n") newlines = aeidon.util.detect_newlines(path) assert newlines == aeidon.newlines.UNIX def test_detect_newlines__windows(self): path = aeidon.temp.create() open(path, "w", newline="").write("a\r\nb\r\nc\r\n") newlines = aeidon.util.detect_newlines(path) assert newlines == aeidon.newlines.WINDOWS def test_flatten(self): lst = [1, 2, [3, 4, [5, 6, [7]], 8], 9] lst = aeidon.util.flatten(lst) assert lst == [1, 2, 3, 4, 5, 6, 7, 8, 9] def test_get_default_encoding(self): assert aeidon.util.get_default_encoding() def test_get_default_newline(self): assert aeidon.util.get_default_newline() def test_get_encoding_alias(self): assert aeidon.util.get_encoding_alias("utf8") == "utf_8" assert aeidon.util.get_encoding_alias("johab") == "johab" def test_get_ranges(self): lst = [0, 0, 4, 5, 3, 7, 8, 2, 7] lst = aeidon.util.get_ranges(lst) assert lst == [[0], [2, 3, 4, 5], [7, 8]] def test_get_unique__first(self): lst = [4, 1, 5, 5, 1, 1, 3, 6, 4, 4] lst = aeidon.util.get_unique(lst) assert lst == [4, 1, 5, 3, 6] def test_get_unique__last(self): lst = [4, 1, 5, 5, 1, 1, 3, 6, 4, 4] lst = aeidon.util.get_unique(lst, keep_last=True) assert lst == [5, 1, 3, 6, 4] def test_read__basic(self): path = self.new_subrip_file() text = open(path, "r", encoding="ascii").read().strip() assert aeidon.util.read(path) == text def test_read__fallback(self): path = self.new_subrip_file() open(path, "w", encoding="utf_8").write("\xc3\xb6\n") assert aeidon.util.read(path, "ascii") == "\xc3\xb6" def test_readlines__basic(self): path = self.new_subrip_file() lines = [x.rstrip() for x in open(path, "r").readlines()] assert aeidon.util.readlines(path) == lines def test_readlines__fallback(self): path = self.new_subrip_file() open(path, "w", encoding="utf_8").write("\xc3\xb6\n") assert aeidon.util.readlines(path, "ascii") == ["\xc3\xb6"] def test_write__basic(self): text = "test\ntest\n" path = self.new_subrip_file() aeidon.util.write(path, text) f = open(path, "r", encoding="ascii") assert f.read() == text def test_write__fallback(self): text = "\xc3\xb6\n" path = self.new_subrip_file() aeidon.util.write(path, text, "ascii") f = open(path, "r", encoding="utf_8") assert f.read() == text def test_writelines__basic(self): lines = ("test", "test") path = self.new_subrip_file() aeidon.util.writelines(path, lines) f = open(path, "r", encoding="ascii") assert f.read() == "test\ntest\n" def test_writelines__fallback(self): text = "\xc3\xb6" path = self.new_subrip_file() aeidon.util.writelines(path, (text,), "ascii") f = open(path, "r", encoding="utf_8") assert f.read() == text + "\n" gaupol-1.11/aeidon/unittest.py000066400000000000000000000071121422217132500164130ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Base class for unit test cases.""" import aeidon import os __all__ = ("TestCase",) class TestCase: """Base class for unit test cases.""" def assert_raises(self, exception, function, *args, **kwargs): """Assert that calling `function` raises `exception`.""" try: function(*args, **kwargs) except exception: return raise AssertionError( "{!r} failed to raise {!r}" .format(function, exception)) def get_sample_text(self, format, name=None): """ Return sample text for subtitle file `format`. `name` can be specified if different from ``format.name.lower()``. This is useful for variants of a format, e.g. "subrip-extended". """ name = name or format.name.lower() basename = "".join((name, format.extension)) path = os.path.join(aeidon.DATA_DIR, "samples", basename) with open(path, "r", encoding="ascii") as f: return f.read().strip() def get_spell_check_language(self, language): """Return spell-check language to use in unit tests.""" # Allow any close-enough variant as different systems will have # different spell-check engines and dictionaries installed. for candidate in aeidon.SpellChecker.list_languages(): if candidate.startswith(language): return candidate raise Exception("Spell-check dictionary {}* not found".format(language)) def new_microdvd_file(self): """Return path to a new temporary MicroDVD file.""" return self.new_temp_file(aeidon.formats.MICRODVD) def new_project(self): """Return a new project with both main and translation files.""" project = aeidon.Project() project.open_main(self.new_subrip_file(), "ascii") project.open_translation(self.new_microdvd_file(), "ascii") return project def new_subrip_file(self): """Return path to a new temporary SubRip file.""" return self.new_temp_file(aeidon.formats.SUBRIP) def new_temp_file(self, format, name=None): """Return path to a new temporary subtitle file.""" text = self.get_sample_text(format, name) path = aeidon.temp.create(format.extension) with open(path, "w", encoding="ascii") as f: f.write(text) return path def setUp(self): """Compatibility alias for :meth:`setup_method`.""" self.setup_method(None) def setup_method(self, method): """Set state for executing tests in `method`.""" pass def tearDown(self): """Compatibility alias for :meth:`teardown_method`.""" self.teardown_method(None) def teardown_method(self, method): """Remove state set for executing tests in `method`.""" pass def test___init__(self): """Make sure that :meth:`setup_method` is always run.""" pass gaupol-1.11/aeidon/util.py000066400000000000000000000406451422217132500155210ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2006 Osmo Salomaa # # 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 . """Miscellaneous functions.""" import aeidon import collections import contextlib import inspect import locale import mimetypes import os import random import re import shutil import stat import subprocess import sys import traceback import urllib.parse VIDEO_FILE_EXTENSIONS = [ ".avi", ".flv", ".m2ts", ".mkv", ".mov", ".mp4", ".ogg", ".ogv", ".vob", ".webm", ] def affirm(value): """Raise :exc:`aeidon.AffirmationError` if value evaluates to ``False``.""" if not value: raise aeidon.AffirmationError("Not True: {!r}".format(value)) @contextlib.contextmanager def atomic_open(path, mode="w", *args, **kwargs): """ A context manager for atomically writing a file. The file is written to a temporary file on the same filesystem, flushed and fsynced and then renamed to replace the existing file. This should (probably) be atomic on any Unix system. On Windows, it should (probably) be atomic if using Python 3.3 or greater. """ path = os.path.realpath(path) chars = list("abcdefghijklmnopqrstuvwxyz0123456789") directory = os.path.dirname(path) basename = os.path.basename(path) while True: # Let's use a hidden temporary file to avoid a file # flickering in a possibly open file browser window. suffix = "".join(random.sample(chars, 8)) temp_basename = ".{}.tmp{}".format(basename, suffix) temp_path = os.path.join(directory, temp_basename) if not os.path.isfile(temp_path): break try: if os.path.isfile(path): # If the file exists, use the same permissions. # Note that all other file metadata, including # owner and group, is not preserved. with open(temp_path, "w") as f: pass st = os.stat(path) os.chmod(temp_path, stat.S_IMODE(st.st_mode)) with open(temp_path, mode, *args, **kwargs) as f: yield f f.flush() os.fsync(f.fileno()) try: if hasattr(os, "replace"): # os.replace was added in Python 3.3. # This should be atomic on Windows too. os.replace(temp_path, path) else: # os.rename is atomic on Unix, but fails # on Windows if the file exists. os.rename(temp_path, path) # os.rename and os.replace will fail if path # and temp_path are not on the same device, # for instance they can be on two separate # branches of a union mount. Atomicity is not # possible in this case. except OSError: # Fall back to a non-atomic operation using # shutil.move. On Windows this requires that # the destination file does not exist. if sys.platform == "win32": if os.path.isfile(path): os.remove(path) shutil.move(temp_path, path) finally: with silent(Exception): os.remove(temp_path) @aeidon.deco.once def chardet_available(): """Return ``True`` if :mod:`chardet` module is available.""" try: import chardet # noqa return True except Exception: return False def compare_versions(x, y): """ Compare version strings `x` and `y`. Used version number formats are ``MAJOR.MINOR``, ``MAJOR.MINOR.PATCH`` and ``MAJOR.MINOR.PATCH.DATE/REVISION``, where all items are integers. Return 1 if `x` newer, 0 if equal or -1 if `y` newer. """ compare = lambda a, b: (a > b) - (a < b) return compare(list(map(int, x.split("."))), list(map(int, y.split(".")))) def connect(observer, observable, signal, *args): """ Connect `observable`'s `signal` to `observer`'s callback method. If `observable` is a string, it should be an attribute of `observer`. If `observable` is not a string it should be the same as `observer`. """ method_name = signal.replace("-", "_").replace("::", "_") if observer is not observable: method_name = "_".join((observable, method_name)) method_name = "_on_{}".format(method_name).replace("__", "_") if not hasattr(observer, method_name): method_name = method_name[1:] method = getattr(observer, method_name) if observer is not observable: observable = getattr(observer, observable) return observable.connect(signal, method, *args) def detect_format(path, encoding): """ Detect and return format of subtitle file at `path`. Raise :exc:`IOError` if reading fails. Raise :exc:`UnicodeError` if decoding fails. Raise :exc:`aeidon.FormatError` if unable to detect format. Return an :attr:`aeidon.formats` enumeration item. """ re_ids = [(x, re.compile(x.identifier)) for x in aeidon.formats] with open(path, "r", encoding=encoding) as f: for line in f: for format, re_id in re_ids: if re_id.search(line) is not None: return format raise aeidon.FormatError("Failed to detect format of file {!r}" .format(path)) def detect_newlines(path): """Detect and return the newline type of file at `path` or ``None``.""" try: with open(path, "r", newline="") as f: f.read() chars = f.newlines except Exception: return None if chars is None: return None if isinstance(chars, str): return aeidon.newlines.find_item("value", chars) if isinstance(chars, tuple): if len(chars) == 1: return aeidon.newlines.find_item("value", chars[0]) # This is not actually correct. If both CR and LF are detected, # it could mean a mixture of Mac and Unix newlines on separate # lines or one Windows newline in a mostly something else file. # We could count the frequencies, but it's probably not worth # the effort. return aeidon.newlines.WINDOWS return None def flatten(lst): """ Return a shallow version of `lst`. >>> aeidon.util.flatten([1, 2, 3, [4, 5, [6]]]) [1, 2, 3, 4, 5, 6] """ flat_lst = [] for item in lst: if isinstance(item, list): flat_lst.extend(flatten(item)) else: # Non-list item. flat_lst.append(item) return flat_lst def get_chardet_version(): """Return :mod:`chardet` version number as string or ``None``.""" try: import chardet return chardet.__version__ except Exception: return None @aeidon.deco.once def get_default_encoding(fallback="utf_8"): """Return the locale encoding or `fallback`.""" encoding = locale.getpreferredencoding() encoding = encoding or fallback re_illegal = re.compile(r"[^a-z0-9_]") encoding = re_illegal.sub("_", encoding.lower()) encoding = get_encoding_alias(encoding) return encoding @aeidon.deco.once def get_default_newline(): """Return system default newline as :attr:`aeidon.newlines` item.""" return aeidon.newlines.find_item("value", os.linesep) def get_encoding_alias(encoding): """Return proper Python alias for `encoding`.""" from encodings.aliases import aliases with silent(LookupError): return aliases[encoding] return encoding def get_ranges(lst): """ Return a list of ranges in list of integers. >>> aeidon.util.get_ranges([1, 2, 3, 5, 6, 7, 9, 11, 12]) [[1, 2, 3], [5, 6, 7], [9], [11, 12]] """ if not lst: return [] lst = sorted(get_unique(lst)) ranges = [[lst.pop(0)]] for item in lst: if item == ranges[-1][-1] + 1: ranges[-1].append(item) else: ranges.append([item]) return ranges def get_template_header(format): """ Read and return the template header for `format`. Raise :exc:`IOError` if reading global header file fails. Raise :exc:`UnicodeError` if decoding global header file fails. """ directory = os.path.join(aeidon.DATA_HOME_DIR, "headers") path = os.path.join(directory, format.name.lower()) with silent(Exception): header = read(path, encoding=None, quiet=True).rstrip() return normalize_newlines(header) directory = os.path.join(aeidon.DATA_DIR, "headers") path = os.path.join(directory, format.name.lower()) header = read(path, "ascii").rstrip() return normalize_newlines(header) def get_unique(lst, keep_last=False): """Return `lst` with duplicates removed.""" if keep_last: return list(reversed(get_unique(list(reversed(lst))))) # https://stackoverflow.com/a/7961425 return list(collections.OrderedDict.fromkeys(lst)) def install_module(name, obj): """ Install `obj`'s module into the :mod:`aeidon` namespace. Typical call is of form:: aeidon.util.install_module("foo", lambda: None) """ aeidon.__dict__[name] = inspect.getmodule(obj) def is_video_file(path): """Return ``True`` if `path` is a video file.""" if not os.path.isfile(path): return False # The mimetypes module doesn't work well on Windows, # fall back on a custom list of video file extensions. type, encoding = mimetypes.guess_type(path) return ((type and type.startswith("video/")) or path.lower().endswith(tuple(VIDEO_FILE_EXTENSIONS))) def last(iterator): """Return the last value from `iterator` or ``None``.""" value = None for value in iterator: pass return value def makedirs(directory): """ Recursively make `directory` if it does not exist. Raise :exc:`OSError` if unsuccessful. """ directory = os.path.abspath(directory) if os.path.isdir(directory): return directory try: os.makedirs(directory) except OSError as error: print("Failed to create directory {!r}: {!s}" .format(directory, error), file=sys.stderr) raise # OSError return directory def normalize_newlines(text): """Convert all newlines in `text` to "\\n".""" re_newline_char = re.compile(r"\r\n?") return re_newline_char.sub("\n", text) def path_to_uri(path): """Convert local filepath to URI.""" if sys.platform == "win32": path = "/{}".format(path.replace("\\", "/")) return "file://{}".format(urllib.parse.quote(path)) def print_read_io(exc_info, path): """Print :exc:`IOError` message to standard error.""" print("Failed to read file '{}': {}" .format(path, exc_info[1].args[1]), file=sys.stderr) def print_read_unicode(exc_info, path, encoding): """Print :exc:`UnicodeError` message to standard error.""" encoding = encoding or get_default_encoding() print("Failed to decode file '{}' with codec '{}'" .format(path, encoding), file=sys.stderr) def print_write_io(exc_info, path): """Print :exc:`IOError` message to standard error.""" print("Failed to write file '{}': {}" .format(path, exc_info[1].args[1]), file=sys.stderr) def print_write_unicode(exc_info, path, encoding): """Print :exc:`UnicodeError` message to standard error.""" encoding = encoding or get_default_encoding() print("Failed to encode file '{}' with codec '{}'" .format(path, encoding), file=sys.stderr) def read(path, encoding=None, fallback="utf_8", quiet=False): """ Read file at `path` and return text. `fallback` should be ``None`` to try only `encoding`. Raise :exc:`IOError` if reading fails. Raise :exc:`UnicodeError` if decoding fails. """ encoding = encoding or get_default_encoding() try: with open(path, "r", encoding=encoding) as f: return f.read().strip() except IOError: if not quiet: print_read_io(sys.exc_info(), path) raise # IOError except UnicodeError: if not fallback in (encoding, None, ""): return read(path, fallback, None, quiet) if not quiet: print_read_unicode(sys.exc_info(), path, encoding) raise # UnicodeError def readlines(path, encoding=None, fallback="utf_8", quiet=False): """ Read file at `path` and return lines. `fallback` should be ``None`` to try only `encoding`. Raise :exc:`IOError` if reading fails. Raise :exc:`UnicodeError` if decoding fails. """ text = read(path, encoding, fallback, quiet) text = normalize_newlines(text) return text.split("\n") def replace_extension(path, format): """Replace possible extension in `path` with that of `format`.""" extensions = [x.extension for x in aeidon.formats] if path.endswith(tuple(extensions)): path = path[:path.rfind(".")] return "".join((path, format.extension)) def shell_quote(path): """Quote and escape `path` for shell use.""" if sys.platform != "win32": # Windows filenames can contain backslashes only as # directory separators and cannot contain double quotes. path = path.replace("\\", "\\\\") path = path.replace('"', '\\"') return '"{}"'.format(path) @contextlib.contextmanager def silent(*exceptions, tb=False): """Try to execute body, ignoring `exceptions`.""" try: yield except exceptions: if tb: traceback.print_exc() def start_process(command, **kwargs): """ Start `command` as a new background subprocess. `command` and `kwargs` are passed to :class:`subprocess.Popen`. Raise :exc:`aeidon.ProcessError` if something goes wrong. Return :class:`subprocess.Popen` instance. """ # Use no environment on Windows due to a subprocess bug. # https://bugzilla.gnome.org/show_bug.cgi?id=605805 env = os.environ.copy() if sys.platform != "win32" else None try: return subprocess.Popen(command, shell=(sys.platform != "win32"), cwd=os.getcwd(), env=env, universal_newlines=True, **kwargs) except OSError as error: raise aeidon.ProcessError(str(error.args)) def title_to_lower_case(title_name): """Convert title case name to lower case with underscores.""" lower_name = "" for char in title_name: if char.isupper() and lower_name: lower_name += "_" lower_name += char.lower() return lower_name def uri_to_path(uri): """Convert `uri` to local filepath.""" uri = urllib.parse.unquote(uri) if sys.platform == "win32": path = urllib.parse.urlsplit(uri)[2] while path.startswith("/"): path = path[1:] return path.replace("/", "\\") return urllib.parse.urlsplit(uri)[2] def write(path, text, encoding=None, fallback="utf_8", quiet=False): """ Write `text` to file at `path`. `fallback` should be ``None`` to try only `encoding`. Raise :exc:`IOError` if writing fails. Raise :exc:`UnicodeError` if encoding fails. """ if not os.path.isdir(os.path.dirname(path)): makedirs(os.path.dirname(path)) encoding = encoding or get_default_encoding() try: with open(path, "w", encoding=encoding) as f: return f.write(text) except IOError: if not quiet: print_write_io(sys.exc_info(), path) raise # IOError except UnicodeError: if not fallback in (encoding, None, ""): return write(path, text, fallback, None, quiet) if not quiet: print_write_unicode(sys.exc_info(), path, encoding) raise # UnicodeError def writelines(path, lines, encoding=None, fallback="utf_8", quiet=False): """ Write `lines` of text to file at `path`. `fallback` should be ``None`` to try only `encoding`. Raise :exc:`IOError` if writing fails. Raise :exc:`UnicodeError` if encoding fails. """ text = "\n".join(lines) + "\n" return write(path, text, encoding, fallback, quiet) gaupol-1.11/bin/000077500000000000000000000000001422217132500134725ustar00rootroot00000000000000gaupol-1.11/bin/gaupol000077500000000000000000000010231422217132500147030ustar00rootroot00000000000000#!/usr/bin/env python3 import os import sys def prepare_paths(): # If running from source, add root directory to sys.path. # '__file__' attribute missing implies a frozen installation. if not "__file__" in globals(): return bindir = os.path.dirname(os.path.abspath(__file__)) if not os.path.isfile(os.path.join( bindir, "..", "data", "io.otsaloma.gaupol.desktop.in")): return sys.path.insert(0, os.path.abspath(os.path.join(bindir, ".."))) prepare_paths() import gaupol gaupol.main(sys.argv[1:]) gaupol-1.11/data/000077500000000000000000000000001422217132500136335ustar00rootroot00000000000000gaupol-1.11/data/extensions/000077500000000000000000000000001422217132500160325ustar00rootroot00000000000000gaupol-1.11/data/extensions/custom-framerates/000077500000000000000000000000001422217132500214735ustar00rootroot00000000000000gaupol-1.11/data/extensions/custom-framerates/add-framerate-dialog.ui000066400000000000000000000074301422217132500257670ustar00rootroot00000000000000 9999 0.1 1 False 12 Add Framerate False True dialog 1 True False vertical 12 False False False 0 True False 12 True False _Framerate: True spin_button False True 0 True True 1 adjustment1 6 True False True 1 True False fps False True 2 False True 1 gaupol-1.11/data/extensions/custom-framerates/custom-framerates.extension.in000066400000000000000000000004231422217132500274760ustar00rootroot00000000000000# -*- conf -*- [Extension] GaupolVersion=1.11 Module=custom-framerates Name=Custom Framerates Description=Allow use of non-standard framerates Version=1.10 Authors=Osmo Salomaa ; Copyright=Copyright © 2011 Osmo Salomaa; Website=https://otsaloma.io/gaupol/ gaupol-1.11/data/extensions/custom-framerates/custom-framerates.py000066400000000000000000000217541422217132500255170ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2011 Osmo Salomaa # # 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 . """Allow use of non-standard framerates.""" import aeidon import gaupol import os from aeidon.i18n import _ from gi.repository import Gtk class AddFramerateDialog(gaupol.BuilderDialog): """Dialog for entering a custom framerate value.""" _widgets = ["spin_button"] def __init__(self, parent): """Initialize an :class:`AddFramerateDialog` instance.""" directory = os.path.abspath(os.path.dirname(__file__)) ui_file_path = os.path.join(directory, "add-framerate-dialog.ui") gaupol.BuilderDialog.__init__(self, ui_file_path) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_Add"), Gtk.ResponseType.OK) self.set_default_response(Gtk.ResponseType.OK) self.set_transient_for(parent) self.set_modal(True) def _on_response(self, *args): """Update spin button before dispatching response.""" self._spin_button.update() def get_framerate(self): """Return framerate entered in the spin button.""" return float(self._spin_button.get_value()) class PreferencesDialog(gaupol.BuilderDialog): """Dialog for editing a list of custom framerates.""" _widgets = ["add_button", "remove_button", "toolbar", "tree_view"] def __init__(self, framerates, parent): """Initialize a :class:`PreferencesDialog` instance.""" directory = os.path.abspath(os.path.dirname(__file__)) ui_file_path = os.path.join(directory, "preferences-dialog.ui") gaupol.BuilderDialog.__init__(self, ui_file_path) self.set_default_response(Gtk.ResponseType.CLOSE) self.set_transient_for(parent) self.set_modal(True) self._init_toolbar() self._init_tree_view(framerates) self._remove_button.set_sensitive(False) gaupol.util.scale_to_content(self._tree_view, min_nchar=30, max_nchar=60, min_nlines=8, max_nlines=16) def get_framerates(self): """Return the defined custom framerates.""" framerates = [] store = self._tree_view.get_model() for i in range(len(store)): framerates.append(store[i][0]) return sorted(framerates) def _get_selected_rows(self): """Return a sequence of the selected rows.""" selection = self._tree_view.get_selection() paths = selection.get_selected_rows()[1] return list(map(gaupol.util.tree_path_to_row, paths)) def _init_toolbar(self): """Initialize the tree view inline toolbar.""" self._toolbar.set_icon_size(Gtk.IconSize.MENU) style = self._toolbar.get_style_context() style.add_class(Gtk.STYLE_CLASS_INLINE_TOOLBAR) theme = Gtk.IconTheme.get_default() # Tool buttons in the UI file are specified as symbolic icons # by name, found in adwaita-icon-theme, if missing in another # theme fall back to non-symbolic icons. if not all((theme.has_icon(self._add_button.get_icon_name()), theme.has_icon(self._remove_button.get_icon_name()))): self._add_button.set_icon_name("list-add") self._remove_button.set_icon_name("list-remove") def _init_tree_view(self, framerates): """Initialize the tree view.""" selection = self._tree_view.get_selection() selection.set_mode(Gtk.SelectionMode.MULTIPLE) selection.connect("changed", self._on_tree_view_selection_changed) store = Gtk.ListStore(float) for framerate in framerates: store.append((framerate,)) store.set_sort_column_id(0, Gtk.SortType.ASCENDING) self._tree_view.set_model(store) renderer = Gtk.CellRendererText() renderer.props.xalign = 1 column = Gtk.TreeViewColumn("", renderer, text=0) column.set_sort_column_id(0) def format_framerate(column, renderer, store, itr, data): renderer.props.text = "{:.6f}".format(store.get_value(itr, 0)) column.set_cell_data_func(renderer, format_framerate) self._tree_view.append_column(column) def _on_add_button_clicked(self, *args): """Add a new framerate.""" dialog = AddFramerateDialog(self._dialog) response = gaupol.util.run_dialog(dialog) framerate = dialog.get_framerate() dialog.destroy() if response != Gtk.ResponseType.OK: return store = self._tree_view.get_model() store.append((framerate,)) def _on_remove_button_clicked(self, *args): """Remove the selected framerate.""" rows = self._get_selected_rows() store = self._tree_view.get_model() for row in reversed(sorted(rows)): path = gaupol.util.tree_row_to_path(row) store.remove(store.get_iter(path)) if len(store) <= 0: return self._tree_view.set_cursor(max(row-1, 0)) def _on_tree_view_selection_changed(self, *args): """Set the remove button sensitivity.""" selection = self._tree_view.get_selection() n = selection.count_selected_rows() self._remove_button.set_sensitive(n > 0) class CustomFrameratesExtension(gaupol.Extension): """Allow use of non-standard framerates.""" def __init__(self): """Initialize a :class:`CustomFrameratesExtension` instance.""" self.application = None self.conf = None self.framerates = [] def _add_framerates(self): """Add custom framerates and corresponding UI elements.""" self.framerates = [] menu = self.application.get_menubar_section( "custom-framerates-placeholder") for value in sorted(self.conf.framerates): name = "FPS_{:.3f}".format(value).replace(".", "_") if hasattr(aeidon.framerates, name): continue setattr(aeidon.framerates, name, aeidon.EnumerationItem()) framerate = getattr(aeidon.framerates, name) framerate.label = _("{:.3f} fps").format(value) framerate.value = float(value) self.framerates.append(framerate) with aeidon.util.silent(AttributeError): # Menubar not available when running unit tests. action = "win.set-framerate::{}".format(name) menu.append(framerate.label, action) def _remove_framerates(self): """Remove custom framerates and corresponding UI elements.""" fallback = aeidon.framerates.FPS_23_976 if gaupol.conf.editor.framerate in self.framerates: gaupol.conf.editor.framerate = fallback # Go through all application's pages and reset those set # to a custom framerate back to the default framerate. orig_page = self.application.get_current_page() for page in self.application.pages: if not page.project.framerate in self.framerates: continue self.application.set_current_page(page) action = self.application.get_action("set-framerate") action.activate(str(fallback)) self.application.set_current_page(orig_page) for framerate in self.framerates: delattr(aeidon.framerates, str(framerate)) with aeidon.util.silent(AttributeError): # Menubar not available when running unit tests. self.application.get_menubar_section( "custom-framerates-placeholder").remove_all() def setup(self, application): """Setup extension for use with `application`.""" options = dict(framerates=[48.0]) gaupol.conf.register_extension("custom_framerates", options) self.conf = gaupol.conf.extensions.custom_framerates self.application = application self.framerates = [] self._add_framerates() def show_preferences_dialog(self, parent): """Show a dialog to edit list of custom framerates.""" dialog = PreferencesDialog(self.conf.framerates, parent) gaupol.util.run_dialog(dialog) self.conf.framerates = list(dialog.get_framerates()) dialog.destroy() self._remove_framerates() self._add_framerates() def teardown(self, application): """End use of extension with `application`.""" self._remove_framerates() self.application = None self.conf = None self.framerates = [] gaupol-1.11/data/extensions/custom-framerates/preferences-dialog.ui000066400000000000000000000112311422217132500255660ustar00rootroot00000000000000 False 12 Framerates True dialog 1 True False vertical 12 False False False 0 True False vertical True True etched-in True True False True True True 0 True False True False Add True list-add-symbolic False True True False Remove True list-remove-symbolic False True False True 1 True True 1 gaupol-1.11/data/extensions/custom-framerates/test/000077500000000000000000000000001422217132500224525ustar00rootroot00000000000000gaupol-1.11/data/extensions/custom-framerates/test/test_custom-framerates.py000066400000000000000000000072411422217132500275300ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2011 Osmo Salomaa # # 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 os import sys sys.path.insert(0, os.path.abspath(os.path.join( os.path.dirname(__file__), ".."))) sys.path.insert(1, os.path.abspath(os.path.join( os.path.dirname(__file__), "..", "..", "..", ".."))) import aeidon import gaupol from gi.repository import Gtk from unittest.mock import patch class TestAddFramerateDialog(gaupol.TestCase): def run_dialog(self): self.dialog.run() self.dialog.destroy() def setup_method(self, method): module = __import__("custom-framerates", {}, {}, []) self.dialog = module.AddFramerateDialog(Gtk.Window()) self.dialog.show() def test_get_framerate(self): assert self.dialog.get_framerate() == 0.0 class TestPreferencesDialog(gaupol.TestCase): def run_dialog(self): self.dialog.run() self.dialog.destroy() def setup_method(self, method): module = __import__("custom-framerates", {}, {}, []) self.framerates = [20.0, 21.0, 22.0, 23.0] self.dialog = module.PreferencesDialog(self.framerates, Gtk.Window()) self.dialog.show() @patch("gaupol.util.run_dialog", lambda *args: Gtk.ResponseType.OK) def test__on_add_button_clicked(self): orig_framerates = self.dialog.get_framerates() self.dialog._add_button.emit("clicked") framerates = self.dialog.get_framerates() assert len(framerates) == len(orig_framerates) + 1 assert 0.0 in framerates def test__on_remove_button_clicked(self): orig_framerates = self.dialog.get_framerates() selection = self.dialog._tree_view.get_selection() selection.unselect_all() path = gaupol.util.tree_row_to_path(0) selection.select_path(path) self.dialog._remove_button.emit("clicked") framerates = self.dialog.get_framerates() assert len(framerates) == len(orig_framerates) - 1 def test_get_framerates(self): framerates = self.dialog.get_framerates() assert framerates == self.framerates class TestCustomFrameratesExtension(gaupol.TestCase): def setup_method(self, method): module = __import__("custom-framerates", {}, {}, []) self.extension = module.CustomFrameratesExtension() self.application = self.new_application() self.extension.setup(self.application) assert hasattr(aeidon.framerates, "FPS_48_000") def teardown_method(self, method): self.extension.teardown(self.application) assert not hasattr(aeidon.framerates, "FPS_48_000") gaupol.TestCase.teardown_method(self, self.application) @patch("gaupol.util.run_dialog", lambda *args: Gtk.ResponseType.CLOSE) def test_show_preferences_dialog(self): self.extension.show_preferences_dialog(self.application.window) def test_teardown__custom(self): page = self.application.get_current_page() page.project.set_framerate(aeidon.framerates.FPS_48_000) self.extension.teardown(self.application) self.extension.setup(self.application) gaupol-1.11/data/gaupol.1000066400000000000000000000027321422217132500152100ustar00rootroot00000000000000.TH GAUPOL 1 "May 23, 2014" .SH NAME gaupol \- editor for text\-based subtitle files .SH SYNOPSIS .B gaupol [\fIOPTION...\fR] [\fIFILE...\fR] [+[\fINUM\fR]] .SH DESCRIPTION .PP .B gaupol is an editor for text-based subtitle files. It supports multiple subtitle file formats and provides means of creating subtitles, editing texts and timing subtitles to match video. .SH OPTIONS .TP \fB\-h\fR, \fB\-\-help\fR Show command line options. .TP \fB\-\-version\fR Show version number. .TP \fB\-e\fR, \fB\-\-encoding\fR=\fIENCODING\fR Set the character encoding to use for opening files. .TP \fB\-\-list\-encodings\fR List possible character encodings to use with \fB\-\-encoding\fR. .TP \fB\+[NUM]\fR Go to subtitle number NUM in the opened file. If NUM is missing go to the last subtitle. .TP \fB\-t\fR, \fB\-\-translation\-file\fR=\fIFILE\fR Open translation file. .TP \fB\-a\fR, \fB\-\-align\-method\fR=\fIMETHOD\fR Method used to align translation file's subtitle texts with main document's subtitles. Possible values are 'number' and 'position'. The default is 'position', which compares the positions in the main document and the translation file and inserts the translation texts so that those positions match. Existing subtitles are skipped and new ones inserted as needed. 'number' discards position information and inserts the N translation texts into the first N subtitles. .TP \fB\-v\fR, \fB\-\-video\-file\fR=\fIFILE\fR Load video file. .SH AUTHOR Written by Osmo Salomaa . gaupol-1.11/data/headers/000077500000000000000000000000001422217132500152465ustar00rootroot00000000000000gaupol-1.11/data/headers/ass000066400000000000000000000011561422217132500157620ustar00rootroot00000000000000[Script Info] Title: Original Script: Original Translation: Original Editing: Original Timing: Synch Point: Script Updated By: Update Details: ScriptType: v4.00+ Collisions: Normal PlayResY: PlayResX: PlayDepth: Timer: 100.0000 WrapStyle: [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding Style: Default, Sans, 18, &H00FFFFFF, &H00FFFF00, &H00000000, &H00000000, 0, 0, 0, 0, 100, 100, 0, 0.00, 1, 2, 2, 2, 30, 30, 30, 0 gaupol-1.11/data/headers/lrc000066400000000000000000000000001422217132500157370ustar00rootroot00000000000000gaupol-1.11/data/headers/microdvd000066400000000000000000000000001422217132500167660ustar00rootroot00000000000000gaupol-1.11/data/headers/ssa000066400000000000000000000010111422217132500157500ustar00rootroot00000000000000[Script Info] Title: Original Script: Original Translation: Original Editing: Original Timing: Synch Point: Script Updated By: Update Details: ScriptType: v4.00 Collisions: Normal PlayResY: PlayResX: PlayDepth: Timer: 100.0000 [V4 Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding Style: Default,Sans,18,&HFFFFFF,&HFFFF00,&H000000,&H000000,0,0,1,2,2,2,30,30,30,0,0 gaupol-1.11/data/headers/subviewer2000066400000000000000000000002421422217132500172640ustar00rootroot00000000000000[INFORMATION] [TITLE] [AUTHOR] [SOURCE] [PRG] [FILEPATH] [DELAY]0 [CD TRACK]0 [COMMENT] [END INFORMATION] [SUBTITLE] [COLF]&HFFFFFF,[STYLE]bd,[SIZE]18,[FONT]Sans gaupol-1.11/data/headers/webvtt000066400000000000000000000000071422217132500165010ustar00rootroot00000000000000WEBVTT gaupol-1.11/data/icons/000077500000000000000000000000001422217132500147465ustar00rootroot00000000000000gaupol-1.11/data/icons/io.otsaloma.gaupol-symbolic.svg000066400000000000000000000022421422217132500230210ustar00rootroot00000000000000 image/svg+xml gaupol-1.11/data/icons/io.otsaloma.gaupol.ico000066400000000000000000000476061422217132500211720ustar00rootroot00000000000000 F00 %  v: hKPNG  IHDR\rfOIDATxytTLX2 VA$ Pwj]֊b^۪պT`ժ=Z}Ey]Uq $ $a Y& If2@ ̽(};w*>}*&C!0* @Cd /`x F톊 ~b^Cf1 u':iۀzt}a,?8fp1'w\L/Hd+> ՜Ků4t`\X `D,~)"j_+_ @YaVnsH-(*]Ka>w~YR2ԕ/E# `?]3;+nՈ9"k VtY0ԓOd.y+lG+eLx¡ܰe>PacVV Qq%o?0pzLVQ10{VuA g"(1XD}ˊ|DH4{| HD:wǃnt $'!9s=we [7@.ѹ;w0)]vx<]v'ɀn7>: <$HG>iH!OoIOZZ,iQ@fiiixըBeE**PUEEy%*+(SQ@+\.2g`ȐA2t0 !C!_:MGפ#ƍD앂R0hݦ&W`OYKQ\JP\\];ˠwڒWeߊMM~FlV;Ve <19㲑TݑH W%;uGj Nu|Nǫ=IT,xL;LQ:̖pŗaHD<'0麣t `,<ԃHp$C;O=0OlUfbO}v3uGi“sFJOko?%ꨞR0lm^w1v\DG= W_{E;QD{mE̞sA5+fr_}3qA.W\5}3uh3y֟lSN .v1 t YW\"40yi[w ;&;Q.ӧ@O)ۓ-gy@V(_:Ad)==Jw#[9ٺ#"'G,x/9ĘѺ#p\%wDcN \uYf"9"g-U" `Ĉa#*p, fq2i0hЀB$Ȑ!tGh]TDٟ"7D g'Mm GJ>r!-P}y'gJ-9 'ɩR9hĖ$2Cj* Mݻw/oWI$,!qW~@M$"3$y@Ra<͓ gm+-Idѭ7O"2[ s.#YKy۶HL.5r |AHH qW[ m)9Sm[\H~"Q4ܜ͝ % &$$"3$`$p:r(;QwÈ+!.)\.yoF#_.$"WDe@M76l9 gO @FF:re0ab8Ә -d'X2o)`LQ>3Ba7tlT(*-4uI1a˙Oh>&ouAXj XQ(/~{*Oh>)7`DB擅+Hz}_QG+;?&e`ݥ'cFsg|Bq`''`⩹SOq&utT~ճ?ҳ~'<Ӊ+4RzgzJ+>;ژOyG7y`!1'w_SƵw'nQg|N&ymnU+˱&ee0d닱9Yq4䎏~pӛ/---8؎شu:udv,"횛8q!, pq șn #r#YBM\H\IDf8W GL!۶גDfm+'J qW--IDf tG ľ}mq7@d ϯ;aDdcW>y+ mq(% qt+$Γ(hm~Nș$n ;%| Fw"Kxmq୒P0 @J"2J޶-j[(pյcF\47D6%Q4*cF\ΝuG 2Νe#JdbHݦE#dY[7@d?lU" `˖uG 25kg&:ݻx0bp 7Ad^" ?Pw"S_;-#"?_, ֮Cm^1rb  (*_|ފ-X#Ee'+tG8*b7CՊou8* d{cuKſ^t7y%pm_{*֛W$O-|c T&M|_D/@wآjuދcEdɳ-mQڂϓ{E7^[;FlSp BԪښuGm v؍u q ~3^:[_{~H_BZ;Jٮ`w#ҫ^,Q:Ė_|5nVۜm%zqsl}ϊm VZ~oY; řkqyWb5DފG>?,W_߀Gk7پ_;p37``¥:b7 竾1^AYڟ~g_.BΝt!knE/ee㠨}֑_ݻwù3ƕW]Ǐld[Q1,z55rOӧ̳t!n)}AwVL0``&N;}"ƍqcлwHAUyy[|v CY'b\̜u8d~~ ߴ66x{XfvuBo/A`c@{*{WK}[ o+Eqq)vvX?;>[w:D GC5jԢ{*UU*X?;~"44" --hjC0}}޻kh@8PW__~>5O3xyOuG!X? Ƽ/ߨ;ifE-ZaW?nݦ; uL bGua.'jϺ=2/uWJ=aMa`şa_{7Fбjێ[2nN`0-Xg^;w~ 6OVvBF<1 pW?=c]'( ,^mWAi=Z)NtFƍfX2yV;Q~c<) de 0!F$uKx+ UJ€RjEc˷vlH[覔 XwV0պ9@4IwCp;+oDgoaToRl((kR)~ BSI?{Ktx= c,0O?zV)&{1:ALt$8Ϩp-Ia"I@+a0:"i,(ru~DtkR)?P6dx /ZY1 ! ȎL?CF)RODQPJ-hKx^K+QJ'H)/TDd6Ɏ0Uَ0_Jם,vO%'p3P=aBDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\~IENDB`(0` $Lc 4^`($$$0%o0%1#1#1#1#RDH:(-1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#0%0%o$$$2$1$1$1$1$1$1$1$l_c1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$/$+1$1$1$1$1$1$1$1$¼I9>1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$*0 $@1$1$1$1$1$1$1$1$|}rucUY?.31$1$1$1$1$1$1$1$0 $@0 $@1$1$1$1$1$<+0<+01$1$1$1$1$0 $@0 $@1$1$1$1$YJNYJN1$1$1$1$0 $@0 $@1$1$1$>-2=,11$1$1$0 $@0 $@1$1$1$1$1$1$0 $@0 $@1$1$1$1$1$1$0 $@0 $@1$1$2 %2 %1$1$0 $@0 $@1$1$?.3=,11$1$0 $@0 $@1$1$N?CM>B1$1$0 $@0 $@1$1$]NR\NR1$1$0 $@0 $@1$1$aSW_QU1$1$0 $@0 $@1$1$bUX¼|qt½¼|qt½aSW1$1$0 $@0 $@1$1$dVZ6$)1$7%*1$1$6$)1$7%*bUX1$1$0 $@0 $@1$1$dVZ6$)1$6$)1$1$6$)1$6$)dVZ1$1$0 $@0 $@1$1$cUY|qt¼|qt¼bUX1$1$0 $@0 $@1$1$aTX`RV1$1$0 $@0 $@1$1$`RV^PT1$1$0 $@0 $@1$1$ZLPYKO1$1$0 $@0 $@1$1$L<@J:?1$1$0 $@0 $@1$1$;*/:)-1$1$0 $@0 $@1$1$1$1$1$1$0 $@0 $@1$1$1$1$1$1$0 $@0 $@1$1$1$tw~rv1$1$1$0 $@0 $@1$1$1$4#'3"'1$1$1$0 $@0 $@1$1$1$1$@04¼@/31$1$1$1$0 $@0 $@1$1$1$1$1$1$]OS]NR1$1$1$1$1$1$0 $@0 $@1$1$1$1$1$1$1$1$1$5#(I9>ZLPj]aznqy|y|znqj]aYKOI9>5#(1$1$1$1$1$1$1$1$1$0 $@.$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$/&0%1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1#3$21%n1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w1%n3$2( @ `E/!&62#{1 $1 $]OSRBE1 $1 $1 $1 $1 $1 $1 $1 $1 $1 $1 $1 $1 $2#{0"51 $?1$1$1$1$1$3"'1$1$1$1$1$1$1$1$1$1$1$1$1$1 $?1$~1$1$1$1$1$uxqdh`RV;*.1$1$1$1$1$1$~2 $1$1$2 %vknvkn2 %1$1$2 $2 $1$1$1$1$2 $2 $1$9(-9(-1$2 $2 $1$j\`j\`1$2 $2 $1$wzux1$2 $2 $1$1$2 $2 $1$1$2 $2 $1$G7;G7;G7;G7;G7;G7;1$2 $2 $1$F6:F6:F6:F6:F6:F6:1$2 $2 $1$1$2 $2 $1$1$2 $2 $1$1$2 $2 $1$ympymp1$2 $2 $1$QAEO?D1$2 $2 $1$1$1$1$2 $2 $1$1$TEITEI1$1$2 $2 $1$1$1$3"'ocfocf3"'1$1$1$2 $2 $p1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$0%o7$$0$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$0$7$$(  Lc@ 1 $?xms[ٕj1&D1&D1&D1&D1&D1&D1 $?@ 0%1$1$`RVYKOL=A@/31$1$0%1$I9>H8=1$1$1$1$1$1$1$1$1$1$1$1$1$1$aTXaTX1$1%1$A15rfjy|y|rfjA151$1#.#,0%u1$w1$w1$w1$w1$w1$w1$w1$w1$w1$w0%u/$+gaupol-1.11/data/icons/io.otsaloma.gaupol.svg000066400000000000000000000145551422217132500212140ustar00rootroot00000000000000 image/svg+xml gaupol-1.11/data/icons/svg2ico000077500000000000000000000005211422217132500162460ustar00rootroot00000000000000#!/bin/sh cd "$(dirname "$0")" || exit 1 # https://docs.microsoft.com/en-us/windows/win32/uxguide/vis-icons#size-requirements for SIZE in 256 48 32 16; do inkscape -o $SIZE.png -C -w $SIZE io.otsaloma.gaupol.svg; done convert 256.png 48.png 32.png 16.png -background transparent io.otsaloma.gaupol.ico rm -f 256.png 48.png 32.png 16.png gaupol-1.11/data/io.otsaloma.gaupol.appdata.xml.in000066400000000000000000000035651422217132500221170ustar00rootroot00000000000000 io.otsaloma.gaupol.desktop CC0-1.0 Gaupol Editor for text-based subtitles

Gaupol is an editor for text-based subtitle files. It supports multiple subtitle file formats and provides means of creating subtitles, editing texts and timing subtitles to match video.

AudioVideo Video GTK https://otsaloma.io/gaupol/ https://github.com/otsaloma/gaupol/tree/master/doc https://github.com/otsaloma/gaupol/issues https://www.transifex.com/otsaloma/gaupol/ io.otsaloma.gaupol.desktop application/x-subrip text/vtt text/x-microdvd text/x-ssa text/x-subviewer GPL-3.0+ Osmo Salomaa https://otsaloma.io/gaupol/screenshot-appdata.png Main window otsaloma@iki.fi gaupol
gaupol-1.11/data/io.otsaloma.gaupol.desktop.in000066400000000000000000000007031422217132500213460ustar00rootroot00000000000000[Desktop Entry] Type=Application Name=Gaupol GenericName=Subtitle Editor Comment=Edit subtitle files Icon=io.otsaloma.gaupol Exec=gaupol %F MimeType=text/x-microdvd;text/x-ssa;application/x-subrip;text/x-subviewer;text/vtt; Categories=AudioVideo;Video;GTK; # TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! Keywords=video;subtitles;captions; StartupNotify=true gaupol-1.11/data/iso-codes/000077500000000000000000000000001422217132500155205ustar00rootroot00000000000000gaupol-1.11/data/iso-codes/README.md000066400000000000000000000003461422217132500170020ustar00rootroot00000000000000iso-codes JSON files are written by various authors and are copied unmodified from [iso-codes][1]. The files are released under the GNU Lesser General Public License (LGPL). [1]: https://salsa.debian.org/iso-codes-team/iso-codes gaupol-1.11/data/iso-codes/iso_15924.json000066400000000000000000000413111422217132500177510ustar00rootroot00000000000000{ "15924": [ { "alpha_4": "Adlm", "name": "Adlam", "numeric": "166" }, { "alpha_4": "Afak", "name": "Afaka", "numeric": "439" }, { "alpha_4": "Aghb", "name": "Caucasian Albanian", "numeric": "239" }, { "alpha_4": "Ahom", "name": "Ahom, Tai Ahom", "numeric": "338" }, { "alpha_4": "Arab", "name": "Arabic", "numeric": "160" }, { "alpha_4": "Aran", "name": "Arabic (Nastaliq variant)", "numeric": "161" }, { "alpha_4": "Armi", "name": "Imperial Aramaic", "numeric": "124" }, { "alpha_4": "Armn", "name": "Armenian", "numeric": "230" }, { "alpha_4": "Avst", "name": "Avestan", "numeric": "134" }, { "alpha_4": "Bali", "name": "Balinese", "numeric": "360" }, { "alpha_4": "Bamu", "name": "Bamum", "numeric": "435" }, { "alpha_4": "Bass", "name": "Bassa Vah", "numeric": "259" }, { "alpha_4": "Batk", "name": "Batak", "numeric": "365" }, { "alpha_4": "Beng", "name": "Bengali", "numeric": "325" }, { "alpha_4": "Bhks", "name": "Bhaiksuki", "numeric": "334" }, { "alpha_4": "Blis", "name": "Blissymbols", "numeric": "550" }, { "alpha_4": "Bopo", "name": "Bopomofo", "numeric": "285" }, { "alpha_4": "Brah", "name": "Brahmi", "numeric": "300" }, { "alpha_4": "Brai", "name": "Braille", "numeric": "570" }, { "alpha_4": "Bugi", "name": "Buginese", "numeric": "367" }, { "alpha_4": "Buhd", "name": "Buhid", "numeric": "372" }, { "alpha_4": "Cakm", "name": "Chakma", "numeric": "349" }, { "alpha_4": "Cans", "name": "Unified Canadian Aboriginal Syllabics", "numeric": "440" }, { "alpha_4": "Cari", "name": "Carian", "numeric": "201" }, { "alpha_4": "Cham", "name": "Cham", "numeric": "358" }, { "alpha_4": "Cher", "name": "Cherokee", "numeric": "445" }, { "alpha_4": "Cirt", "name": "Cirth", "numeric": "291" }, { "alpha_4": "Copt", "name": "Coptic", "numeric": "204" }, { "alpha_4": "Cprt", "name": "Cypriot", "numeric": "403" }, { "alpha_4": "Cyrl", "name": "Cyrillic", "numeric": "220" }, { "alpha_4": "Cyrs", "name": "Cyrillic (Old Church Slavonic variant)", "numeric": "221" }, { "alpha_4": "Deva", "name": "Devanagari (Nagari)", "numeric": "315" }, { "alpha_4": "Dsrt", "name": "Deseret (Mormon)", "numeric": "250" }, { "alpha_4": "Dupl", "name": "Duployan shorthand, Duployan stenography", "numeric": "755" }, { "alpha_4": "Egyd", "name": "Egyptian demotic", "numeric": "070" }, { "alpha_4": "Egyh", "name": "Egyptian hieratic", "numeric": "060" }, { "alpha_4": "Egyp", "name": "Egyptian hieroglyphs", "numeric": "050" }, { "alpha_4": "Elba", "name": "Elbasan", "numeric": "226" }, { "alpha_4": "Ethi", "name": "Ethiopic (Geʻez)", "numeric": "430" }, { "alpha_4": "Geok", "name": "Khutsuri (Asomtavruli and Nuskhuri)", "numeric": "241" }, { "alpha_4": "Geor", "name": "Georgian (Mkhedruli)", "numeric": "240" }, { "alpha_4": "Glag", "name": "Glagolitic", "numeric": "225" }, { "alpha_4": "Goth", "name": "Gothic", "numeric": "206" }, { "alpha_4": "Gran", "name": "Grantha", "numeric": "343" }, { "alpha_4": "Grek", "name": "Greek", "numeric": "200" }, { "alpha_4": "Gujr", "name": "Gujarati", "numeric": "320" }, { "alpha_4": "Guru", "name": "Gurmukhi", "numeric": "310" }, { "alpha_4": "Hanb", "name": "Han with Bopomofo (alias for Han + Bopomofo)", "numeric": "503" }, { "alpha_4": "Hang", "name": "Hangul (Hangŭl, Hangeul)", "numeric": "286" }, { "alpha_4": "Hani", "name": "Han (Hanzi, Kanji, Hanja)", "numeric": "500" }, { "alpha_4": "Hano", "name": "Hanunoo (Hanunóo)", "numeric": "371" }, { "alpha_4": "Hans", "name": "Han (Simplified variant)", "numeric": "501" }, { "alpha_4": "Hant", "name": "Han (Traditional variant)", "numeric": "502" }, { "alpha_4": "Hatr", "name": "Hatran", "numeric": "127" }, { "alpha_4": "Hebr", "name": "Hebrew", "numeric": "125" }, { "alpha_4": "Hira", "name": "Hiragana", "numeric": "410" }, { "alpha_4": "Hluw", "name": "Anatolian Hieroglyphs (Luwian Hieroglyphs, Hittite Hieroglyphs)", "numeric": "080" }, { "alpha_4": "Hmng", "name": "Pahawh Hmong", "numeric": "450" }, { "alpha_4": "Hrkt", "name": "Japanese syllabaries (alias for Hiragana + Katakana)", "numeric": "412" }, { "alpha_4": "Hung", "name": "Old Hungarian (Hungarian Runic)", "numeric": "176" }, { "alpha_4": "Inds", "name": "Indus (Harappan)", "numeric": "610" }, { "alpha_4": "Ital", "name": "Old Italic (Etruscan, Oscan, etc.)", "numeric": "210" }, { "alpha_4": "Jamo", "name": "Jamo (alias for Jamo subset of Hangul)", "numeric": "284" }, { "alpha_4": "Java", "name": "Javanese", "numeric": "361" }, { "alpha_4": "Jpan", "name": "Japanese (alias for Han + Hiragana + Katakana)", "numeric": "413" }, { "alpha_4": "Jurc", "name": "Jurchen", "numeric": "510" }, { "alpha_4": "Kali", "name": "Kayah Li", "numeric": "357" }, { "alpha_4": "Kana", "name": "Katakana", "numeric": "411" }, { "alpha_4": "Khar", "name": "Kharoshthi", "numeric": "305" }, { "alpha_4": "Khmr", "name": "Khmer", "numeric": "355" }, { "alpha_4": "Khoj", "name": "Khojki", "numeric": "322" }, { "alpha_4": "Kitl", "name": "Khitan large script", "numeric": "505" }, { "alpha_4": "Kits", "name": "Khitan small script", "numeric": "288" }, { "alpha_4": "Knda", "name": "Kannada", "numeric": "345" }, { "alpha_4": "Kore", "name": "Korean (alias for Hangul + Han)", "numeric": "287" }, { "alpha_4": "Kpel", "name": "Kpelle", "numeric": "436" }, { "alpha_4": "Kthi", "name": "Kaithi", "numeric": "317" }, { "alpha_4": "Lana", "name": "Tai Tham (Lanna)", "numeric": "351" }, { "alpha_4": "Laoo", "name": "Lao", "numeric": "356" }, { "alpha_4": "Latf", "name": "Latin (Fraktur variant)", "numeric": "217" }, { "alpha_4": "Latg", "name": "Latin (Gaelic variant)", "numeric": "216" }, { "alpha_4": "Latn", "name": "Latin", "numeric": "215" }, { "alpha_4": "Leke", "name": "Leke", "numeric": "364" }, { "alpha_4": "Lepc", "name": "Lepcha (Róng)", "numeric": "335" }, { "alpha_4": "Limb", "name": "Limbu", "numeric": "336" }, { "alpha_4": "Lina", "name": "Linear A", "numeric": "400" }, { "alpha_4": "Linb", "name": "Linear B", "numeric": "401" }, { "alpha_4": "Lisu", "name": "Lisu (Fraser)", "numeric": "399" }, { "alpha_4": "Loma", "name": "Loma", "numeric": "437" }, { "alpha_4": "Lyci", "name": "Lycian", "numeric": "202" }, { "alpha_4": "Lydi", "name": "Lydian", "numeric": "116" }, { "alpha_4": "Mahj", "name": "Mahajani", "numeric": "314" }, { "alpha_4": "Mand", "name": "Mandaic, Mandaean", "numeric": "140" }, { "alpha_4": "Mani", "name": "Manichaean", "numeric": "139" }, { "alpha_4": "Marc", "name": "Marchen", "numeric": "332" }, { "alpha_4": "Maya", "name": "Mayan hieroglyphs", "numeric": "090" }, { "alpha_4": "Mend", "name": "Mende Kikakui", "numeric": "438" }, { "alpha_4": "Merc", "name": "Meroitic Cursive", "numeric": "101" }, { "alpha_4": "Mero", "name": "Meroitic Hieroglyphs", "numeric": "100" }, { "alpha_4": "Mlym", "name": "Malayalam", "numeric": "347" }, { "alpha_4": "Modi", "name": "Modi, Moḍī", "numeric": "324" }, { "alpha_4": "Mong", "name": "Mongolian", "numeric": "145" }, { "alpha_4": "Moon", "name": "Moon (Moon code, Moon script, Moon type)", "numeric": "218" }, { "alpha_4": "Mroo", "name": "Mro, Mru", "numeric": "199" }, { "alpha_4": "Mtei", "name": "Meitei Mayek (Meithei, Meetei)", "numeric": "337" }, { "alpha_4": "Mult", "name": "Multani", "numeric": "323" }, { "alpha_4": "Mymr", "name": "Myanmar (Burmese)", "numeric": "350" }, { "alpha_4": "Narb", "name": "Old North Arabian (Ancient North Arabian)", "numeric": "106" }, { "alpha_4": "Nbat", "name": "Nabataean", "numeric": "159" }, { "alpha_4": "Newa", "name": "Newa, Newar, Newari, Nepāla lipi", "numeric": "333" }, { "alpha_4": "Nkgb", "name": "Nakhi Geba ('Na-'Khi ²Ggŏ-¹baw, Naxi Geba)", "numeric": "420" }, { "alpha_4": "Nkoo", "name": "N’Ko", "numeric": "165" }, { "alpha_4": "Nshu", "name": "Nüshu", "numeric": "499" }, { "alpha_4": "Ogam", "name": "Ogham", "numeric": "212" }, { "alpha_4": "Olck", "name": "Ol Chiki (Ol Cemet’, Ol, Santali)", "numeric": "261" }, { "alpha_4": "Orkh", "name": "Old Turkic, Orkhon Runic", "numeric": "175" }, { "alpha_4": "Orya", "name": "Oriya", "numeric": "327" }, { "alpha_4": "Osge", "name": "Osage", "numeric": "219" }, { "alpha_4": "Osma", "name": "Osmanya", "numeric": "260" }, { "alpha_4": "Palm", "name": "Palmyrene", "numeric": "126" }, { "alpha_4": "Pauc", "name": "Pau Cin Hau", "numeric": "263" }, { "alpha_4": "Perm", "name": "Old Permic", "numeric": "227" }, { "alpha_4": "Phag", "name": "Phags-pa", "numeric": "331" }, { "alpha_4": "Phli", "name": "Inscriptional Pahlavi", "numeric": "131" }, { "alpha_4": "Phlp", "name": "Psalter Pahlavi", "numeric": "132" }, { "alpha_4": "Phlv", "name": "Book Pahlavi", "numeric": "133" }, { "alpha_4": "Phnx", "name": "Phoenician", "numeric": "115" }, { "alpha_4": "Piqd", "name": "Klingon (KLI pIqaD)", "numeric": "293" }, { "alpha_4": "Plrd", "name": "Miao (Pollard)", "numeric": "282" }, { "alpha_4": "Prti", "name": "Inscriptional Parthian", "numeric": "130" }, { "alpha_4": "Qaaa", "name": "Reserved for private use (start)", "numeric": "900" }, { "alpha_4": "Qabx", "name": "Reserved for private use (end)", "numeric": "949" }, { "alpha_4": "Rjng", "name": "Rejang (Redjang, Kaganga)", "numeric": "363" }, { "alpha_4": "Roro", "name": "Rongorongo", "numeric": "620" }, { "alpha_4": "Runr", "name": "Runic", "numeric": "211" }, { "alpha_4": "Samr", "name": "Samaritan", "numeric": "123" }, { "alpha_4": "Sara", "name": "Sarati", "numeric": "292" }, { "alpha_4": "Sarb", "name": "Old South Arabian", "numeric": "105" }, { "alpha_4": "Saur", "name": "Saurashtra", "numeric": "344" }, { "alpha_4": "Sgnw", "name": "SignWriting", "numeric": "095" }, { "alpha_4": "Shaw", "name": "Shavian (Shaw)", "numeric": "281" }, { "alpha_4": "Shrd", "name": "Sharada, Śāradā", "numeric": "319" }, { "alpha_4": "Sidd", "name": "Siddham, Siddhaṃ, Siddhamātṛkā", "numeric": "302" }, { "alpha_4": "Sind", "name": "Khudawadi, Sindhi", "numeric": "318" }, { "alpha_4": "Sinh", "name": "Sinhala", "numeric": "348" }, { "alpha_4": "Sora", "name": "Sora Sompeng", "numeric": "398" }, { "alpha_4": "Sund", "name": "Sundanese", "numeric": "362" }, { "alpha_4": "Sylo", "name": "Syloti Nagri", "numeric": "316" }, { "alpha_4": "Syrc", "name": "Syriac", "numeric": "135" }, { "alpha_4": "Syre", "name": "Syriac (Estrangelo variant)", "numeric": "138" }, { "alpha_4": "Syrj", "name": "Syriac (Western variant)", "numeric": "137" }, { "alpha_4": "Syrn", "name": "Syriac (Eastern variant)", "numeric": "136" }, { "alpha_4": "Tagb", "name": "Tagbanwa", "numeric": "373" }, { "alpha_4": "Takr", "name": "Takri, Ṭākrī, Ṭāṅkrī", "numeric": "321" }, { "alpha_4": "Tale", "name": "Tai Le", "numeric": "353" }, { "alpha_4": "Talu", "name": "New Tai Lue", "numeric": "354" }, { "alpha_4": "Taml", "name": "Tamil", "numeric": "346" }, { "alpha_4": "Tang", "name": "Tangut", "numeric": "520" }, { "alpha_4": "Tavt", "name": "Tai Viet", "numeric": "359" }, { "alpha_4": "Telu", "name": "Telugu", "numeric": "340" }, { "alpha_4": "Teng", "name": "Tengwar", "numeric": "290" }, { "alpha_4": "Tfng", "name": "Tifinagh (Berber)", "numeric": "120" }, { "alpha_4": "Tglg", "name": "Tagalog (Baybayin, Alibata)", "numeric": "370" }, { "alpha_4": "Thaa", "name": "Thaana", "numeric": "170" }, { "alpha_4": "Thai", "name": "Thai", "numeric": "352" }, { "alpha_4": "Tibt", "name": "Tibetan", "numeric": "330" }, { "alpha_4": "Tirh", "name": "Tirhuta", "numeric": "326" }, { "alpha_4": "Ugar", "name": "Ugaritic", "numeric": "040" }, { "alpha_4": "Vaii", "name": "Vai", "numeric": "470" }, { "alpha_4": "Visp", "name": "Visible Speech", "numeric": "280" }, { "alpha_4": "Wara", "name": "Warang Citi (Varang Kshiti)", "numeric": "262" }, { "alpha_4": "Wole", "name": "Woleai", "numeric": "480" }, { "alpha_4": "Xpeo", "name": "Old Persian", "numeric": "030" }, { "alpha_4": "Xsux", "name": "Cuneiform, Sumero-Akkadian", "numeric": "020" }, { "alpha_4": "Yiii", "name": "Yi", "numeric": "460" }, { "alpha_4": "Zinh", "name": "Code for inherited script", "numeric": "994" }, { "alpha_4": "Zmth", "name": "Mathematical notation", "numeric": "995" }, { "alpha_4": "Zsye", "name": "Symbols (Emoji variant)", "numeric": "993" }, { "alpha_4": "Zsym", "name": "Symbols", "numeric": "996" }, { "alpha_4": "Zxxx", "name": "Code for unwritten documents", "numeric": "997" }, { "alpha_4": "Zyyy", "name": "Code for undetermined script", "numeric": "998" }, { "alpha_4": "Zzzz", "name": "Code for uncoded script", "numeric": "999" } ] } gaupol-1.11/data/iso-codes/iso_3166-1.json000066400000000000000000001242701422217132500200300ustar00rootroot00000000000000{ "3166-1": [ { "alpha_2": "AW", "alpha_3": "ABW", "flag": "🇦🇼", "name": "Aruba", "numeric": "533" }, { "alpha_2": "AF", "alpha_3": "AFG", "flag": "🇦🇫", "name": "Afghanistan", "numeric": "004", "official_name": "Islamic Republic of Afghanistan" }, { "alpha_2": "AO", "alpha_3": "AGO", "flag": "🇦🇴", "name": "Angola", "numeric": "024", "official_name": "Republic of Angola" }, { "alpha_2": "AI", "alpha_3": "AIA", "flag": "🇦🇮", "name": "Anguilla", "numeric": "660" }, { "alpha_2": "AX", "alpha_3": "ALA", "flag": "🇦🇽", "name": "Åland Islands", "numeric": "248" }, { "alpha_2": "AL", "alpha_3": "ALB", "flag": "🇦🇱", "name": "Albania", "numeric": "008", "official_name": "Republic of Albania" }, { "alpha_2": "AD", "alpha_3": "AND", "flag": "🇦🇩", "name": "Andorra", "numeric": "020", "official_name": "Principality of Andorra" }, { "alpha_2": "AE", "alpha_3": "ARE", "flag": "🇦🇪", "name": "United Arab Emirates", "numeric": "784" }, { "alpha_2": "AR", "alpha_3": "ARG", "flag": "🇦🇷", "name": "Argentina", "numeric": "032", "official_name": "Argentine Republic" }, { "alpha_2": "AM", "alpha_3": "ARM", "flag": "🇦🇲", "name": "Armenia", "numeric": "051", "official_name": "Republic of Armenia" }, { "alpha_2": "AS", "alpha_3": "ASM", "flag": "🇦🇸", "name": "American Samoa", "numeric": "016" }, { "alpha_2": "AQ", "alpha_3": "ATA", "flag": "🇦🇶", "name": "Antarctica", "numeric": "010" }, { "alpha_2": "TF", "alpha_3": "ATF", "flag": "🇹🇫", "name": "French Southern Territories", "numeric": "260" }, { "alpha_2": "AG", "alpha_3": "ATG", "flag": "🇦🇬", "name": "Antigua and Barbuda", "numeric": "028" }, { "alpha_2": "AU", "alpha_3": "AUS", "flag": "🇦🇺", "name": "Australia", "numeric": "036" }, { "alpha_2": "AT", "alpha_3": "AUT", "flag": "🇦🇹", "name": "Austria", "numeric": "040", "official_name": "Republic of Austria" }, { "alpha_2": "AZ", "alpha_3": "AZE", "flag": "🇦🇿", "name": "Azerbaijan", "numeric": "031", "official_name": "Republic of Azerbaijan" }, { "alpha_2": "BI", "alpha_3": "BDI", "flag": "🇧🇮", "name": "Burundi", "numeric": "108", "official_name": "Republic of Burundi" }, { "alpha_2": "BE", "alpha_3": "BEL", "flag": "🇧🇪", "name": "Belgium", "numeric": "056", "official_name": "Kingdom of Belgium" }, { "alpha_2": "BJ", "alpha_3": "BEN", "flag": "🇧🇯", "name": "Benin", "numeric": "204", "official_name": "Republic of Benin" }, { "alpha_2": "BQ", "alpha_3": "BES", "flag": "🇧🇶", "name": "Bonaire, Sint Eustatius and Saba", "numeric": "535", "official_name": "Bonaire, Sint Eustatius and Saba" }, { "alpha_2": "BF", "alpha_3": "BFA", "flag": "🇧🇫", "name": "Burkina Faso", "numeric": "854" }, { "alpha_2": "BD", "alpha_3": "BGD", "flag": "🇧🇩", "name": "Bangladesh", "numeric": "050", "official_name": "People's Republic of Bangladesh" }, { "alpha_2": "BG", "alpha_3": "BGR", "flag": "🇧🇬", "name": "Bulgaria", "numeric": "100", "official_name": "Republic of Bulgaria" }, { "alpha_2": "BH", "alpha_3": "BHR", "flag": "🇧🇭", "name": "Bahrain", "numeric": "048", "official_name": "Kingdom of Bahrain" }, { "alpha_2": "BS", "alpha_3": "BHS", "flag": "🇧🇸", "name": "Bahamas", "numeric": "044", "official_name": "Commonwealth of the Bahamas" }, { "alpha_2": "BA", "alpha_3": "BIH", "flag": "🇧🇦", "name": "Bosnia and Herzegovina", "numeric": "070", "official_name": "Republic of Bosnia and Herzegovina" }, { "alpha_2": "BL", "alpha_3": "BLM", "flag": "🇧🇱", "name": "Saint Barthélemy", "numeric": "652" }, { "alpha_2": "BY", "alpha_3": "BLR", "flag": "🇧🇾", "name": "Belarus", "numeric": "112", "official_name": "Republic of Belarus" }, { "alpha_2": "BZ", "alpha_3": "BLZ", "flag": "🇧🇿", "name": "Belize", "numeric": "084" }, { "alpha_2": "BM", "alpha_3": "BMU", "flag": "🇧🇲", "name": "Bermuda", "numeric": "060" }, { "alpha_2": "BO", "alpha_3": "BOL", "common_name": "Bolivia", "flag": "🇧🇴", "name": "Bolivia, Plurinational State of", "numeric": "068", "official_name": "Plurinational State of Bolivia" }, { "alpha_2": "BR", "alpha_3": "BRA", "flag": "🇧🇷", "name": "Brazil", "numeric": "076", "official_name": "Federative Republic of Brazil" }, { "alpha_2": "BB", "alpha_3": "BRB", "flag": "🇧🇧", "name": "Barbados", "numeric": "052" }, { "alpha_2": "BN", "alpha_3": "BRN", "flag": "🇧🇳", "name": "Brunei Darussalam", "numeric": "096" }, { "alpha_2": "BT", "alpha_3": "BTN", "flag": "🇧🇹", "name": "Bhutan", "numeric": "064", "official_name": "Kingdom of Bhutan" }, { "alpha_2": "BV", "alpha_3": "BVT", "flag": "🇧🇻", "name": "Bouvet Island", "numeric": "074" }, { "alpha_2": "BW", "alpha_3": "BWA", "flag": "🇧🇼", "name": "Botswana", "numeric": "072", "official_name": "Republic of Botswana" }, { "alpha_2": "CF", "alpha_3": "CAF", "flag": "🇨🇫", "name": "Central African Republic", "numeric": "140" }, { "alpha_2": "CA", "alpha_3": "CAN", "flag": "🇨🇦", "name": "Canada", "numeric": "124" }, { "alpha_2": "CC", "alpha_3": "CCK", "flag": "🇨🇨", "name": "Cocos (Keeling) Islands", "numeric": "166" }, { "alpha_2": "CH", "alpha_3": "CHE", "flag": "🇨🇭", "name": "Switzerland", "numeric": "756", "official_name": "Swiss Confederation" }, { "alpha_2": "CL", "alpha_3": "CHL", "flag": "🇨🇱", "name": "Chile", "numeric": "152", "official_name": "Republic of Chile" }, { "alpha_2": "CN", "alpha_3": "CHN", "flag": "🇨🇳", "name": "China", "numeric": "156", "official_name": "People's Republic of China" }, { "alpha_2": "CI", "alpha_3": "CIV", "flag": "🇨🇮", "name": "Côte d'Ivoire", "numeric": "384", "official_name": "Republic of Côte d'Ivoire" }, { "alpha_2": "CM", "alpha_3": "CMR", "flag": "🇨🇲", "name": "Cameroon", "numeric": "120", "official_name": "Republic of Cameroon" }, { "alpha_2": "CD", "alpha_3": "COD", "flag": "🇨🇩", "name": "Congo, The Democratic Republic of the", "numeric": "180" }, { "alpha_2": "CG", "alpha_3": "COG", "flag": "🇨🇬", "name": "Congo", "numeric": "178", "official_name": "Republic of the Congo" }, { "alpha_2": "CK", "alpha_3": "COK", "flag": "🇨🇰", "name": "Cook Islands", "numeric": "184" }, { "alpha_2": "CO", "alpha_3": "COL", "flag": "🇨🇴", "name": "Colombia", "numeric": "170", "official_name": "Republic of Colombia" }, { "alpha_2": "KM", "alpha_3": "COM", "flag": "🇰🇲", "name": "Comoros", "numeric": "174", "official_name": "Union of the Comoros" }, { "alpha_2": "CV", "alpha_3": "CPV", "flag": "🇨🇻", "name": "Cabo Verde", "numeric": "132", "official_name": "Republic of Cabo Verde" }, { "alpha_2": "CR", "alpha_3": "CRI", "flag": "🇨🇷", "name": "Costa Rica", "numeric": "188", "official_name": "Republic of Costa Rica" }, { "alpha_2": "CU", "alpha_3": "CUB", "flag": "🇨🇺", "name": "Cuba", "numeric": "192", "official_name": "Republic of Cuba" }, { "alpha_2": "CW", "alpha_3": "CUW", "flag": "🇨🇼", "name": "Curaçao", "numeric": "531", "official_name": "Curaçao" }, { "alpha_2": "CX", "alpha_3": "CXR", "flag": "🇨🇽", "name": "Christmas Island", "numeric": "162" }, { "alpha_2": "KY", "alpha_3": "CYM", "flag": "🇰🇾", "name": "Cayman Islands", "numeric": "136" }, { "alpha_2": "CY", "alpha_3": "CYP", "flag": "🇨🇾", "name": "Cyprus", "numeric": "196", "official_name": "Republic of Cyprus" }, { "alpha_2": "CZ", "alpha_3": "CZE", "flag": "🇨🇿", "name": "Czechia", "numeric": "203", "official_name": "Czech Republic" }, { "alpha_2": "DE", "alpha_3": "DEU", "flag": "🇩🇪", "name": "Germany", "numeric": "276", "official_name": "Federal Republic of Germany" }, { "alpha_2": "DJ", "alpha_3": "DJI", "flag": "🇩🇯", "name": "Djibouti", "numeric": "262", "official_name": "Republic of Djibouti" }, { "alpha_2": "DM", "alpha_3": "DMA", "flag": "🇩🇲", "name": "Dominica", "numeric": "212", "official_name": "Commonwealth of Dominica" }, { "alpha_2": "DK", "alpha_3": "DNK", "flag": "🇩🇰", "name": "Denmark", "numeric": "208", "official_name": "Kingdom of Denmark" }, { "alpha_2": "DO", "alpha_3": "DOM", "flag": "🇩🇴", "name": "Dominican Republic", "numeric": "214" }, { "alpha_2": "DZ", "alpha_3": "DZA", "flag": "🇩🇿", "name": "Algeria", "numeric": "012", "official_name": "People's Democratic Republic of Algeria" }, { "alpha_2": "EC", "alpha_3": "ECU", "flag": "🇪🇨", "name": "Ecuador", "numeric": "218", "official_name": "Republic of Ecuador" }, { "alpha_2": "EG", "alpha_3": "EGY", "flag": "🇪🇬", "name": "Egypt", "numeric": "818", "official_name": "Arab Republic of Egypt" }, { "alpha_2": "ER", "alpha_3": "ERI", "flag": "🇪🇷", "name": "Eritrea", "numeric": "232", "official_name": "the State of Eritrea" }, { "alpha_2": "EH", "alpha_3": "ESH", "flag": "🇪🇭", "name": "Western Sahara", "numeric": "732" }, { "alpha_2": "ES", "alpha_3": "ESP", "flag": "🇪🇸", "name": "Spain", "numeric": "724", "official_name": "Kingdom of Spain" }, { "alpha_2": "EE", "alpha_3": "EST", "flag": "🇪🇪", "name": "Estonia", "numeric": "233", "official_name": "Republic of Estonia" }, { "alpha_2": "ET", "alpha_3": "ETH", "flag": "🇪🇹", "name": "Ethiopia", "numeric": "231", "official_name": "Federal Democratic Republic of Ethiopia" }, { "alpha_2": "FI", "alpha_3": "FIN", "flag": "🇫🇮", "name": "Finland", "numeric": "246", "official_name": "Republic of Finland" }, { "alpha_2": "FJ", "alpha_3": "FJI", "flag": "🇫🇯", "name": "Fiji", "numeric": "242", "official_name": "Republic of Fiji" }, { "alpha_2": "FK", "alpha_3": "FLK", "flag": "🇫🇰", "name": "Falkland Islands (Malvinas)", "numeric": "238" }, { "alpha_2": "FR", "alpha_3": "FRA", "flag": "🇫🇷", "name": "France", "numeric": "250", "official_name": "French Republic" }, { "alpha_2": "FO", "alpha_3": "FRO", "flag": "🇫🇴", "name": "Faroe Islands", "numeric": "234" }, { "alpha_2": "FM", "alpha_3": "FSM", "flag": "🇫🇲", "name": "Micronesia, Federated States of", "numeric": "583", "official_name": "Federated States of Micronesia" }, { "alpha_2": "GA", "alpha_3": "GAB", "flag": "🇬🇦", "name": "Gabon", "numeric": "266", "official_name": "Gabonese Republic" }, { "alpha_2": "GB", "alpha_3": "GBR", "flag": "🇬🇧", "name": "United Kingdom", "numeric": "826", "official_name": "United Kingdom of Great Britain and Northern Ireland" }, { "alpha_2": "GE", "alpha_3": "GEO", "flag": "🇬🇪", "name": "Georgia", "numeric": "268" }, { "alpha_2": "GG", "alpha_3": "GGY", "flag": "🇬🇬", "name": "Guernsey", "numeric": "831" }, { "alpha_2": "GH", "alpha_3": "GHA", "flag": "🇬🇭", "name": "Ghana", "numeric": "288", "official_name": "Republic of Ghana" }, { "alpha_2": "GI", "alpha_3": "GIB", "flag": "🇬🇮", "name": "Gibraltar", "numeric": "292" }, { "alpha_2": "GN", "alpha_3": "GIN", "flag": "🇬🇳", "name": "Guinea", "numeric": "324", "official_name": "Republic of Guinea" }, { "alpha_2": "GP", "alpha_3": "GLP", "flag": "🇬🇵", "name": "Guadeloupe", "numeric": "312" }, { "alpha_2": "GM", "alpha_3": "GMB", "flag": "🇬🇲", "name": "Gambia", "numeric": "270", "official_name": "Republic of the Gambia" }, { "alpha_2": "GW", "alpha_3": "GNB", "flag": "🇬🇼", "name": "Guinea-Bissau", "numeric": "624", "official_name": "Republic of Guinea-Bissau" }, { "alpha_2": "GQ", "alpha_3": "GNQ", "flag": "🇬🇶", "name": "Equatorial Guinea", "numeric": "226", "official_name": "Republic of Equatorial Guinea" }, { "alpha_2": "GR", "alpha_3": "GRC", "flag": "🇬🇷", "name": "Greece", "numeric": "300", "official_name": "Hellenic Republic" }, { "alpha_2": "GD", "alpha_3": "GRD", "flag": "🇬🇩", "name": "Grenada", "numeric": "308" }, { "alpha_2": "GL", "alpha_3": "GRL", "flag": "🇬🇱", "name": "Greenland", "numeric": "304" }, { "alpha_2": "GT", "alpha_3": "GTM", "flag": "🇬🇹", "name": "Guatemala", "numeric": "320", "official_name": "Republic of Guatemala" }, { "alpha_2": "GF", "alpha_3": "GUF", "flag": "🇬🇫", "name": "French Guiana", "numeric": "254" }, { "alpha_2": "GU", "alpha_3": "GUM", "flag": "🇬🇺", "name": "Guam", "numeric": "316" }, { "alpha_2": "GY", "alpha_3": "GUY", "flag": "🇬🇾", "name": "Guyana", "numeric": "328", "official_name": "Republic of Guyana" }, { "alpha_2": "HK", "alpha_3": "HKG", "flag": "🇭🇰", "name": "Hong Kong", "numeric": "344", "official_name": "Hong Kong Special Administrative Region of China" }, { "alpha_2": "HM", "alpha_3": "HMD", "flag": "🇭🇲", "name": "Heard Island and McDonald Islands", "numeric": "334" }, { "alpha_2": "HN", "alpha_3": "HND", "flag": "🇭🇳", "name": "Honduras", "numeric": "340", "official_name": "Republic of Honduras" }, { "alpha_2": "HR", "alpha_3": "HRV", "flag": "🇭🇷", "name": "Croatia", "numeric": "191", "official_name": "Republic of Croatia" }, { "alpha_2": "HT", "alpha_3": "HTI", "flag": "🇭🇹", "name": "Haiti", "numeric": "332", "official_name": "Republic of Haiti" }, { "alpha_2": "HU", "alpha_3": "HUN", "flag": "🇭🇺", "name": "Hungary", "numeric": "348", "official_name": "Hungary" }, { "alpha_2": "ID", "alpha_3": "IDN", "flag": "🇮🇩", "name": "Indonesia", "numeric": "360", "official_name": "Republic of Indonesia" }, { "alpha_2": "IM", "alpha_3": "IMN", "flag": "🇮🇲", "name": "Isle of Man", "numeric": "833" }, { "alpha_2": "IN", "alpha_3": "IND", "flag": "🇮🇳", "name": "India", "numeric": "356", "official_name": "Republic of India" }, { "alpha_2": "IO", "alpha_3": "IOT", "flag": "🇮🇴", "name": "British Indian Ocean Territory", "numeric": "086" }, { "alpha_2": "IE", "alpha_3": "IRL", "flag": "🇮🇪", "name": "Ireland", "numeric": "372" }, { "alpha_2": "IR", "alpha_3": "IRN", "flag": "🇮🇷", "name": "Iran, Islamic Republic of", "numeric": "364", "official_name": "Islamic Republic of Iran" }, { "alpha_2": "IQ", "alpha_3": "IRQ", "flag": "🇮🇶", "name": "Iraq", "numeric": "368", "official_name": "Republic of Iraq" }, { "alpha_2": "IS", "alpha_3": "ISL", "flag": "🇮🇸", "name": "Iceland", "numeric": "352", "official_name": "Republic of Iceland" }, { "alpha_2": "IL", "alpha_3": "ISR", "flag": "🇮🇱", "name": "Israel", "numeric": "376", "official_name": "State of Israel" }, { "alpha_2": "IT", "alpha_3": "ITA", "flag": "🇮🇹", "name": "Italy", "numeric": "380", "official_name": "Italian Republic" }, { "alpha_2": "JM", "alpha_3": "JAM", "flag": "🇯🇲", "name": "Jamaica", "numeric": "388" }, { "alpha_2": "JE", "alpha_3": "JEY", "flag": "🇯🇪", "name": "Jersey", "numeric": "832" }, { "alpha_2": "JO", "alpha_3": "JOR", "flag": "🇯🇴", "name": "Jordan", "numeric": "400", "official_name": "Hashemite Kingdom of Jordan" }, { "alpha_2": "JP", "alpha_3": "JPN", "flag": "🇯🇵", "name": "Japan", "numeric": "392" }, { "alpha_2": "KZ", "alpha_3": "KAZ", "flag": "🇰🇿", "name": "Kazakhstan", "numeric": "398", "official_name": "Republic of Kazakhstan" }, { "alpha_2": "KE", "alpha_3": "KEN", "flag": "🇰🇪", "name": "Kenya", "numeric": "404", "official_name": "Republic of Kenya" }, { "alpha_2": "KG", "alpha_3": "KGZ", "flag": "🇰🇬", "name": "Kyrgyzstan", "numeric": "417", "official_name": "Kyrgyz Republic" }, { "alpha_2": "KH", "alpha_3": "KHM", "flag": "🇰🇭", "name": "Cambodia", "numeric": "116", "official_name": "Kingdom of Cambodia" }, { "alpha_2": "KI", "alpha_3": "KIR", "flag": "🇰🇮", "name": "Kiribati", "numeric": "296", "official_name": "Republic of Kiribati" }, { "alpha_2": "KN", "alpha_3": "KNA", "flag": "🇰🇳", "name": "Saint Kitts and Nevis", "numeric": "659" }, { "alpha_2": "KR", "alpha_3": "KOR", "common_name": "South Korea", "flag": "🇰🇷", "name": "Korea, Republic of", "numeric": "410" }, { "alpha_2": "KW", "alpha_3": "KWT", "flag": "🇰🇼", "name": "Kuwait", "numeric": "414", "official_name": "State of Kuwait" }, { "alpha_2": "LA", "alpha_3": "LAO", "flag": "🇱🇦", "name": "Lao People's Democratic Republic", "numeric": "418" }, { "alpha_2": "LB", "alpha_3": "LBN", "flag": "🇱🇧", "name": "Lebanon", "numeric": "422", "official_name": "Lebanese Republic" }, { "alpha_2": "LR", "alpha_3": "LBR", "flag": "🇱🇷", "name": "Liberia", "numeric": "430", "official_name": "Republic of Liberia" }, { "alpha_2": "LY", "alpha_3": "LBY", "flag": "🇱🇾", "name": "Libya", "numeric": "434", "official_name": "Libya" }, { "alpha_2": "LC", "alpha_3": "LCA", "flag": "🇱🇨", "name": "Saint Lucia", "numeric": "662" }, { "alpha_2": "LI", "alpha_3": "LIE", "flag": "🇱🇮", "name": "Liechtenstein", "numeric": "438", "official_name": "Principality of Liechtenstein" }, { "alpha_2": "LK", "alpha_3": "LKA", "flag": "🇱🇰", "name": "Sri Lanka", "numeric": "144", "official_name": "Democratic Socialist Republic of Sri Lanka" }, { "alpha_2": "LS", "alpha_3": "LSO", "flag": "🇱🇸", "name": "Lesotho", "numeric": "426", "official_name": "Kingdom of Lesotho" }, { "alpha_2": "LT", "alpha_3": "LTU", "flag": "🇱🇹", "name": "Lithuania", "numeric": "440", "official_name": "Republic of Lithuania" }, { "alpha_2": "LU", "alpha_3": "LUX", "flag": "🇱🇺", "name": "Luxembourg", "numeric": "442", "official_name": "Grand Duchy of Luxembourg" }, { "alpha_2": "LV", "alpha_3": "LVA", "flag": "🇱🇻", "name": "Latvia", "numeric": "428", "official_name": "Republic of Latvia" }, { "alpha_2": "MO", "alpha_3": "MAC", "flag": "🇲🇴", "name": "Macao", "numeric": "446", "official_name": "Macao Special Administrative Region of China" }, { "alpha_2": "MF", "alpha_3": "MAF", "flag": "🇲🇫", "name": "Saint Martin (French part)", "numeric": "663" }, { "alpha_2": "MA", "alpha_3": "MAR", "flag": "🇲🇦", "name": "Morocco", "numeric": "504", "official_name": "Kingdom of Morocco" }, { "alpha_2": "MC", "alpha_3": "MCO", "flag": "🇲🇨", "name": "Monaco", "numeric": "492", "official_name": "Principality of Monaco" }, { "alpha_2": "MD", "alpha_3": "MDA", "common_name": "Moldova", "flag": "🇲🇩", "name": "Moldova, Republic of", "numeric": "498", "official_name": "Republic of Moldova" }, { "alpha_2": "MG", "alpha_3": "MDG", "flag": "🇲🇬", "name": "Madagascar", "numeric": "450", "official_name": "Republic of Madagascar" }, { "alpha_2": "MV", "alpha_3": "MDV", "flag": "🇲🇻", "name": "Maldives", "numeric": "462", "official_name": "Republic of Maldives" }, { "alpha_2": "MX", "alpha_3": "MEX", "flag": "🇲🇽", "name": "Mexico", "numeric": "484", "official_name": "United Mexican States" }, { "alpha_2": "MH", "alpha_3": "MHL", "flag": "🇲🇭", "name": "Marshall Islands", "numeric": "584", "official_name": "Republic of the Marshall Islands" }, { "alpha_2": "MK", "alpha_3": "MKD", "flag": "🇲🇰", "name": "North Macedonia", "numeric": "807", "official_name": "Republic of North Macedonia" }, { "alpha_2": "ML", "alpha_3": "MLI", "flag": "🇲🇱", "name": "Mali", "numeric": "466", "official_name": "Republic of Mali" }, { "alpha_2": "MT", "alpha_3": "MLT", "flag": "🇲🇹", "name": "Malta", "numeric": "470", "official_name": "Republic of Malta" }, { "alpha_2": "MM", "alpha_3": "MMR", "flag": "🇲🇲", "name": "Myanmar", "numeric": "104", "official_name": "Republic of Myanmar" }, { "alpha_2": "ME", "alpha_3": "MNE", "flag": "🇲🇪", "name": "Montenegro", "numeric": "499", "official_name": "Montenegro" }, { "alpha_2": "MN", "alpha_3": "MNG", "flag": "🇲🇳", "name": "Mongolia", "numeric": "496" }, { "alpha_2": "MP", "alpha_3": "MNP", "flag": "🇲🇵", "name": "Northern Mariana Islands", "numeric": "580", "official_name": "Commonwealth of the Northern Mariana Islands" }, { "alpha_2": "MZ", "alpha_3": "MOZ", "flag": "🇲🇿", "name": "Mozambique", "numeric": "508", "official_name": "Republic of Mozambique" }, { "alpha_2": "MR", "alpha_3": "MRT", "flag": "🇲🇷", "name": "Mauritania", "numeric": "478", "official_name": "Islamic Republic of Mauritania" }, { "alpha_2": "MS", "alpha_3": "MSR", "flag": "🇲🇸", "name": "Montserrat", "numeric": "500" }, { "alpha_2": "MQ", "alpha_3": "MTQ", "flag": "🇲🇶", "name": "Martinique", "numeric": "474" }, { "alpha_2": "MU", "alpha_3": "MUS", "flag": "🇲🇺", "name": "Mauritius", "numeric": "480", "official_name": "Republic of Mauritius" }, { "alpha_2": "MW", "alpha_3": "MWI", "flag": "🇲🇼", "name": "Malawi", "numeric": "454", "official_name": "Republic of Malawi" }, { "alpha_2": "MY", "alpha_3": "MYS", "flag": "🇲🇾", "name": "Malaysia", "numeric": "458" }, { "alpha_2": "YT", "alpha_3": "MYT", "flag": "🇾🇹", "name": "Mayotte", "numeric": "175" }, { "alpha_2": "NA", "alpha_3": "NAM", "flag": "🇳🇦", "name": "Namibia", "numeric": "516", "official_name": "Republic of Namibia" }, { "alpha_2": "NC", "alpha_3": "NCL", "flag": "🇳🇨", "name": "New Caledonia", "numeric": "540" }, { "alpha_2": "NE", "alpha_3": "NER", "flag": "🇳🇪", "name": "Niger", "numeric": "562", "official_name": "Republic of the Niger" }, { "alpha_2": "NF", "alpha_3": "NFK", "flag": "🇳🇫", "name": "Norfolk Island", "numeric": "574" }, { "alpha_2": "NG", "alpha_3": "NGA", "flag": "🇳🇬", "name": "Nigeria", "numeric": "566", "official_name": "Federal Republic of Nigeria" }, { "alpha_2": "NI", "alpha_3": "NIC", "flag": "🇳🇮", "name": "Nicaragua", "numeric": "558", "official_name": "Republic of Nicaragua" }, { "alpha_2": "NU", "alpha_3": "NIU", "flag": "🇳🇺", "name": "Niue", "numeric": "570", "official_name": "Niue" }, { "alpha_2": "NL", "alpha_3": "NLD", "flag": "🇳🇱", "name": "Netherlands", "numeric": "528", "official_name": "Kingdom of the Netherlands" }, { "alpha_2": "NO", "alpha_3": "NOR", "flag": "🇳🇴", "name": "Norway", "numeric": "578", "official_name": "Kingdom of Norway" }, { "alpha_2": "NP", "alpha_3": "NPL", "flag": "🇳🇵", "name": "Nepal", "numeric": "524", "official_name": "Federal Democratic Republic of Nepal" }, { "alpha_2": "NR", "alpha_3": "NRU", "flag": "🇳🇷", "name": "Nauru", "numeric": "520", "official_name": "Republic of Nauru" }, { "alpha_2": "NZ", "alpha_3": "NZL", "flag": "🇳🇿", "name": "New Zealand", "numeric": "554" }, { "alpha_2": "OM", "alpha_3": "OMN", "flag": "🇴🇲", "name": "Oman", "numeric": "512", "official_name": "Sultanate of Oman" }, { "alpha_2": "PK", "alpha_3": "PAK", "flag": "🇵🇰", "name": "Pakistan", "numeric": "586", "official_name": "Islamic Republic of Pakistan" }, { "alpha_2": "PA", "alpha_3": "PAN", "flag": "🇵🇦", "name": "Panama", "numeric": "591", "official_name": "Republic of Panama" }, { "alpha_2": "PN", "alpha_3": "PCN", "flag": "🇵🇳", "name": "Pitcairn", "numeric": "612" }, { "alpha_2": "PE", "alpha_3": "PER", "flag": "🇵🇪", "name": "Peru", "numeric": "604", "official_name": "Republic of Peru" }, { "alpha_2": "PH", "alpha_3": "PHL", "flag": "🇵🇭", "name": "Philippines", "numeric": "608", "official_name": "Republic of the Philippines" }, { "alpha_2": "PW", "alpha_3": "PLW", "flag": "🇵🇼", "name": "Palau", "numeric": "585", "official_name": "Republic of Palau" }, { "alpha_2": "PG", "alpha_3": "PNG", "flag": "🇵🇬", "name": "Papua New Guinea", "numeric": "598", "official_name": "Independent State of Papua New Guinea" }, { "alpha_2": "PL", "alpha_3": "POL", "flag": "🇵🇱", "name": "Poland", "numeric": "616", "official_name": "Republic of Poland" }, { "alpha_2": "PR", "alpha_3": "PRI", "flag": "🇵🇷", "name": "Puerto Rico", "numeric": "630" }, { "alpha_2": "KP", "alpha_3": "PRK", "common_name": "North Korea", "flag": "🇰🇵", "name": "Korea, Democratic People's Republic of", "numeric": "408", "official_name": "Democratic People's Republic of Korea" }, { "alpha_2": "PT", "alpha_3": "PRT", "flag": "🇵🇹", "name": "Portugal", "numeric": "620", "official_name": "Portuguese Republic" }, { "alpha_2": "PY", "alpha_3": "PRY", "flag": "🇵🇾", "name": "Paraguay", "numeric": "600", "official_name": "Republic of Paraguay" }, { "alpha_2": "PS", "alpha_3": "PSE", "flag": "🇵🇸", "name": "Palestine, State of", "numeric": "275", "official_name": "the State of Palestine" }, { "alpha_2": "PF", "alpha_3": "PYF", "flag": "🇵🇫", "name": "French Polynesia", "numeric": "258" }, { "alpha_2": "QA", "alpha_3": "QAT", "flag": "🇶🇦", "name": "Qatar", "numeric": "634", "official_name": "State of Qatar" }, { "alpha_2": "RE", "alpha_3": "REU", "flag": "🇷🇪", "name": "Réunion", "numeric": "638" }, { "alpha_2": "RO", "alpha_3": "ROU", "flag": "🇷🇴", "name": "Romania", "numeric": "642" }, { "alpha_2": "RU", "alpha_3": "RUS", "flag": "🇷🇺", "name": "Russian Federation", "numeric": "643" }, { "alpha_2": "RW", "alpha_3": "RWA", "flag": "🇷🇼", "name": "Rwanda", "numeric": "646", "official_name": "Rwandese Republic" }, { "alpha_2": "SA", "alpha_3": "SAU", "flag": "🇸🇦", "name": "Saudi Arabia", "numeric": "682", "official_name": "Kingdom of Saudi Arabia" }, { "alpha_2": "SD", "alpha_3": "SDN", "flag": "🇸🇩", "name": "Sudan", "numeric": "729", "official_name": "Republic of the Sudan" }, { "alpha_2": "SN", "alpha_3": "SEN", "flag": "🇸🇳", "name": "Senegal", "numeric": "686", "official_name": "Republic of Senegal" }, { "alpha_2": "SG", "alpha_3": "SGP", "flag": "🇸🇬", "name": "Singapore", "numeric": "702", "official_name": "Republic of Singapore" }, { "alpha_2": "GS", "alpha_3": "SGS", "flag": "🇬🇸", "name": "South Georgia and the South Sandwich Islands", "numeric": "239" }, { "alpha_2": "SH", "alpha_3": "SHN", "flag": "🇸🇭", "name": "Saint Helena, Ascension and Tristan da Cunha", "numeric": "654" }, { "alpha_2": "SJ", "alpha_3": "SJM", "flag": "🇸🇯", "name": "Svalbard and Jan Mayen", "numeric": "744" }, { "alpha_2": "SB", "alpha_3": "SLB", "flag": "🇸🇧", "name": "Solomon Islands", "numeric": "090" }, { "alpha_2": "SL", "alpha_3": "SLE", "flag": "🇸🇱", "name": "Sierra Leone", "numeric": "694", "official_name": "Republic of Sierra Leone" }, { "alpha_2": "SV", "alpha_3": "SLV", "flag": "🇸🇻", "name": "El Salvador", "numeric": "222", "official_name": "Republic of El Salvador" }, { "alpha_2": "SM", "alpha_3": "SMR", "flag": "🇸🇲", "name": "San Marino", "numeric": "674", "official_name": "Republic of San Marino" }, { "alpha_2": "SO", "alpha_3": "SOM", "flag": "🇸🇴", "name": "Somalia", "numeric": "706", "official_name": "Federal Republic of Somalia" }, { "alpha_2": "PM", "alpha_3": "SPM", "flag": "🇵🇲", "name": "Saint Pierre and Miquelon", "numeric": "666" }, { "alpha_2": "RS", "alpha_3": "SRB", "flag": "🇷🇸", "name": "Serbia", "numeric": "688", "official_name": "Republic of Serbia" }, { "alpha_2": "SS", "alpha_3": "SSD", "flag": "🇸🇸", "name": "South Sudan", "numeric": "728", "official_name": "Republic of South Sudan" }, { "alpha_2": "ST", "alpha_3": "STP", "flag": "🇸🇹", "name": "Sao Tome and Principe", "numeric": "678", "official_name": "Democratic Republic of Sao Tome and Principe" }, { "alpha_2": "SR", "alpha_3": "SUR", "flag": "🇸🇷", "name": "Suriname", "numeric": "740", "official_name": "Republic of Suriname" }, { "alpha_2": "SK", "alpha_3": "SVK", "flag": "🇸🇰", "name": "Slovakia", "numeric": "703", "official_name": "Slovak Republic" }, { "alpha_2": "SI", "alpha_3": "SVN", "flag": "🇸🇮", "name": "Slovenia", "numeric": "705", "official_name": "Republic of Slovenia" }, { "alpha_2": "SE", "alpha_3": "SWE", "flag": "🇸🇪", "name": "Sweden", "numeric": "752", "official_name": "Kingdom of Sweden" }, { "alpha_2": "SZ", "alpha_3": "SWZ", "flag": "🇸🇿", "name": "Eswatini", "numeric": "748", "official_name": "Kingdom of Eswatini" }, { "alpha_2": "SX", "alpha_3": "SXM", "flag": "🇸🇽", "name": "Sint Maarten (Dutch part)", "numeric": "534", "official_name": "Sint Maarten (Dutch part)" }, { "alpha_2": "SC", "alpha_3": "SYC", "flag": "🇸🇨", "name": "Seychelles", "numeric": "690", "official_name": "Republic of Seychelles" }, { "alpha_2": "SY", "alpha_3": "SYR", "flag": "🇸🇾", "name": "Syrian Arab Republic", "numeric": "760" }, { "alpha_2": "TC", "alpha_3": "TCA", "flag": "🇹🇨", "name": "Turks and Caicos Islands", "numeric": "796" }, { "alpha_2": "TD", "alpha_3": "TCD", "flag": "🇹🇩", "name": "Chad", "numeric": "148", "official_name": "Republic of Chad" }, { "alpha_2": "TG", "alpha_3": "TGO", "flag": "🇹🇬", "name": "Togo", "numeric": "768", "official_name": "Togolese Republic" }, { "alpha_2": "TH", "alpha_3": "THA", "flag": "🇹🇭", "name": "Thailand", "numeric": "764", "official_name": "Kingdom of Thailand" }, { "alpha_2": "TJ", "alpha_3": "TJK", "flag": "🇹🇯", "name": "Tajikistan", "numeric": "762", "official_name": "Republic of Tajikistan" }, { "alpha_2": "TK", "alpha_3": "TKL", "flag": "🇹🇰", "name": "Tokelau", "numeric": "772" }, { "alpha_2": "TM", "alpha_3": "TKM", "flag": "🇹🇲", "name": "Turkmenistan", "numeric": "795" }, { "alpha_2": "TL", "alpha_3": "TLS", "flag": "🇹🇱", "name": "Timor-Leste", "numeric": "626", "official_name": "Democratic Republic of Timor-Leste" }, { "alpha_2": "TO", "alpha_3": "TON", "flag": "🇹🇴", "name": "Tonga", "numeric": "776", "official_name": "Kingdom of Tonga" }, { "alpha_2": "TT", "alpha_3": "TTO", "flag": "🇹🇹", "name": "Trinidad and Tobago", "numeric": "780", "official_name": "Republic of Trinidad and Tobago" }, { "alpha_2": "TN", "alpha_3": "TUN", "flag": "🇹🇳", "name": "Tunisia", "numeric": "788", "official_name": "Republic of Tunisia" }, { "alpha_2": "TR", "alpha_3": "TUR", "flag": "🇹🇷", "name": "Turkey", "numeric": "792", "official_name": "Republic of Turkey" }, { "alpha_2": "TV", "alpha_3": "TUV", "flag": "🇹🇻", "name": "Tuvalu", "numeric": "798" }, { "alpha_2": "TW", "alpha_3": "TWN", "common_name": "Taiwan", "flag": "🇹🇼", "name": "Taiwan, Province of China", "numeric": "158", "official_name": "Taiwan, Province of China" }, { "alpha_2": "TZ", "alpha_3": "TZA", "common_name": "Tanzania", "flag": "🇹🇿", "name": "Tanzania, United Republic of", "numeric": "834", "official_name": "United Republic of Tanzania" }, { "alpha_2": "UG", "alpha_3": "UGA", "flag": "🇺🇬", "name": "Uganda", "numeric": "800", "official_name": "Republic of Uganda" }, { "alpha_2": "UA", "alpha_3": "UKR", "flag": "🇺🇦", "name": "Ukraine", "numeric": "804" }, { "alpha_2": "UM", "alpha_3": "UMI", "flag": "🇺🇲", "name": "United States Minor Outlying Islands", "numeric": "581" }, { "alpha_2": "UY", "alpha_3": "URY", "flag": "🇺🇾", "name": "Uruguay", "numeric": "858", "official_name": "Eastern Republic of Uruguay" }, { "alpha_2": "US", "alpha_3": "USA", "flag": "🇺🇸", "name": "United States", "numeric": "840", "official_name": "United States of America" }, { "alpha_2": "UZ", "alpha_3": "UZB", "flag": "🇺🇿", "name": "Uzbekistan", "numeric": "860", "official_name": "Republic of Uzbekistan" }, { "alpha_2": "VA", "alpha_3": "VAT", "flag": "🇻🇦", "name": "Holy See (Vatican City State)", "numeric": "336" }, { "alpha_2": "VC", "alpha_3": "VCT", "flag": "🇻🇨", "name": "Saint Vincent and the Grenadines", "numeric": "670" }, { "alpha_2": "VE", "alpha_3": "VEN", "common_name": "Venezuela", "flag": "🇻🇪", "name": "Venezuela, Bolivarian Republic of", "numeric": "862", "official_name": "Bolivarian Republic of Venezuela" }, { "alpha_2": "VG", "alpha_3": "VGB", "flag": "🇻🇬", "name": "Virgin Islands, British", "numeric": "092", "official_name": "British Virgin Islands" }, { "alpha_2": "VI", "alpha_3": "VIR", "flag": "🇻🇮", "name": "Virgin Islands, U.S.", "numeric": "850", "official_name": "Virgin Islands of the United States" }, { "alpha_2": "VN", "alpha_3": "VNM", "common_name": "Vietnam", "flag": "🇻🇳", "name": "Viet Nam", "numeric": "704", "official_name": "Socialist Republic of Viet Nam" }, { "alpha_2": "VU", "alpha_3": "VUT", "flag": "🇻🇺", "name": "Vanuatu", "numeric": "548", "official_name": "Republic of Vanuatu" }, { "alpha_2": "WF", "alpha_3": "WLF", "flag": "🇼🇫", "name": "Wallis and Futuna", "numeric": "876" }, { "alpha_2": "WS", "alpha_3": "WSM", "flag": "🇼🇸", "name": "Samoa", "numeric": "882", "official_name": "Independent State of Samoa" }, { "alpha_2": "YE", "alpha_3": "YEM", "flag": "🇾🇪", "name": "Yemen", "numeric": "887", "official_name": "Republic of Yemen" }, { "alpha_2": "ZA", "alpha_3": "ZAF", "flag": "🇿🇦", "name": "South Africa", "numeric": "710", "official_name": "Republic of South Africa" }, { "alpha_2": "ZM", "alpha_3": "ZMB", "flag": "🇿🇲", "name": "Zambia", "numeric": "894", "official_name": "Republic of Zambia" }, { "alpha_2": "ZW", "alpha_3": "ZWE", "flag": "🇿🇼", "name": "Zimbabwe", "numeric": "716", "official_name": "Republic of Zimbabwe" } ] } gaupol-1.11/data/iso-codes/iso_639-2.json000066400000000000000000001076631422217132500177620ustar00rootroot00000000000000{ "639-2": [ { "alpha_2": "aa", "alpha_3": "aar", "name": "Afar" }, { "alpha_2": "ab", "alpha_3": "abk", "name": "Abkhazian" }, { "alpha_3": "ace", "name": "Achinese" }, { "alpha_3": "ach", "name": "Acoli" }, { "alpha_3": "ada", "name": "Adangme" }, { "alpha_3": "ady", "name": "Adyghe; Adygei" }, { "alpha_3": "afa", "name": "Afro-Asiatic languages" }, { "alpha_3": "afh", "name": "Afrihili" }, { "alpha_2": "af", "alpha_3": "afr", "name": "Afrikaans" }, { "alpha_3": "ain", "name": "Ainu" }, { "alpha_2": "ak", "alpha_3": "aka", "name": "Akan" }, { "alpha_3": "akk", "name": "Akkadian" }, { "alpha_3": "ale", "name": "Aleut" }, { "alpha_3": "alg", "name": "Algonquian languages" }, { "alpha_3": "alt", "name": "Southern Altai" }, { "alpha_2": "am", "alpha_3": "amh", "name": "Amharic" }, { "alpha_3": "ang", "name": "English, Old (ca. 450-1100)" }, { "alpha_3": "anp", "name": "Angika" }, { "alpha_3": "apa", "name": "Apache languages" }, { "alpha_2": "ar", "alpha_3": "ara", "name": "Arabic" }, { "alpha_3": "arc", "name": "Official Aramaic (700-300 BCE); Imperial Aramaic (700-300 BCE)" }, { "alpha_2": "an", "alpha_3": "arg", "name": "Aragonese" }, { "alpha_3": "arn", "name": "Mapudungun; Mapuche" }, { "alpha_3": "arp", "name": "Arapaho" }, { "alpha_3": "art", "name": "Artificial languages" }, { "alpha_3": "arw", "name": "Arawak" }, { "alpha_2": "as", "alpha_3": "asm", "name": "Assamese" }, { "alpha_3": "ast", "name": "Asturian; Bable; Leonese; Asturleonese" }, { "alpha_3": "ath", "name": "Athapascan languages" }, { "alpha_3": "aus", "name": "Australian languages" }, { "alpha_2": "av", "alpha_3": "ava", "name": "Avaric" }, { "alpha_2": "ae", "alpha_3": "ave", "name": "Avestan" }, { "alpha_3": "awa", "name": "Awadhi" }, { "alpha_2": "ay", "alpha_3": "aym", "name": "Aymara" }, { "alpha_2": "az", "alpha_3": "aze", "name": "Azerbaijani" }, { "alpha_3": "bad", "name": "Banda languages" }, { "alpha_3": "bai", "name": "Bamileke languages" }, { "alpha_2": "ba", "alpha_3": "bak", "name": "Bashkir" }, { "alpha_3": "bal", "name": "Baluchi" }, { "alpha_2": "bm", "alpha_3": "bam", "name": "Bambara" }, { "alpha_3": "ban", "name": "Balinese" }, { "alpha_3": "bas", "name": "Basa" }, { "alpha_3": "bat", "name": "Baltic languages" }, { "alpha_3": "bej", "name": "Beja; Bedawiyet" }, { "alpha_2": "be", "alpha_3": "bel", "name": "Belarusian" }, { "alpha_3": "bem", "name": "Bemba" }, { "alpha_2": "bn", "alpha_3": "ben", "common_name": "Bangla", "name": "Bengali" }, { "alpha_3": "ber", "name": "Berber languages" }, { "alpha_3": "bho", "name": "Bhojpuri" }, { "alpha_2": "bh", "alpha_3": "bih", "name": "Bihari languages" }, { "alpha_3": "bik", "name": "Bikol" }, { "alpha_3": "bin", "name": "Bini; Edo" }, { "alpha_2": "bi", "alpha_3": "bis", "name": "Bislama" }, { "alpha_3": "bla", "name": "Siksika" }, { "alpha_3": "bnt", "name": "Bantu (Other)" }, { "alpha_2": "bo", "alpha_3": "bod", "bibliographic": "tib", "name": "Tibetan" }, { "alpha_2": "bs", "alpha_3": "bos", "name": "Bosnian" }, { "alpha_3": "bra", "name": "Braj" }, { "alpha_2": "br", "alpha_3": "bre", "name": "Breton" }, { "alpha_3": "btk", "name": "Batak languages" }, { "alpha_3": "bua", "name": "Buriat" }, { "alpha_3": "bug", "name": "Buginese" }, { "alpha_2": "bg", "alpha_3": "bul", "name": "Bulgarian" }, { "alpha_3": "byn", "name": "Blin; Bilin" }, { "alpha_3": "cad", "name": "Caddo" }, { "alpha_3": "cai", "name": "Central American Indian languages" }, { "alpha_3": "car", "name": "Galibi Carib" }, { "alpha_2": "ca", "alpha_3": "cat", "name": "Catalan; Valencian" }, { "alpha_3": "cau", "name": "Caucasian languages" }, { "alpha_3": "ceb", "name": "Cebuano" }, { "alpha_3": "cel", "name": "Celtic languages" }, { "alpha_2": "cs", "alpha_3": "ces", "bibliographic": "cze", "name": "Czech" }, { "alpha_2": "ch", "alpha_3": "cha", "name": "Chamorro" }, { "alpha_3": "chb", "name": "Chibcha" }, { "alpha_2": "ce", "alpha_3": "che", "name": "Chechen" }, { "alpha_3": "chg", "name": "Chagatai" }, { "alpha_3": "chk", "name": "Chuukese" }, { "alpha_3": "chm", "name": "Mari" }, { "alpha_3": "chn", "name": "Chinook jargon" }, { "alpha_3": "cho", "name": "Choctaw" }, { "alpha_3": "chp", "name": "Chipewyan; Dene Suline" }, { "alpha_3": "chr", "name": "Cherokee" }, { "alpha_2": "cu", "alpha_3": "chu", "name": "Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic" }, { "alpha_2": "cv", "alpha_3": "chv", "name": "Chuvash" }, { "alpha_3": "chy", "name": "Cheyenne" }, { "alpha_3": "cmc", "name": "Chamic languages" }, { "alpha_3": "cop", "name": "Coptic" }, { "alpha_2": "kw", "alpha_3": "cor", "name": "Cornish" }, { "alpha_2": "co", "alpha_3": "cos", "name": "Corsican" }, { "alpha_3": "cpe", "name": "Creoles and pidgins, English based" }, { "alpha_3": "cpf", "name": "Creoles and pidgins, French-based" }, { "alpha_3": "cpp", "name": "Creoles and pidgins, Portuguese-based" }, { "alpha_2": "cr", "alpha_3": "cre", "name": "Cree" }, { "alpha_3": "crh", "name": "Crimean Tatar; Crimean Turkish" }, { "alpha_3": "crp", "name": "Creoles and pidgins" }, { "alpha_3": "csb", "name": "Kashubian" }, { "alpha_3": "cus", "name": "Cushitic languages" }, { "alpha_2": "cy", "alpha_3": "cym", "bibliographic": "wel", "name": "Welsh" }, { "alpha_3": "dak", "name": "Dakota" }, { "alpha_2": "da", "alpha_3": "dan", "name": "Danish" }, { "alpha_3": "dar", "name": "Dargwa" }, { "alpha_3": "day", "name": "Land Dayak languages" }, { "alpha_3": "del", "name": "Delaware" }, { "alpha_3": "den", "name": "Slave (Athapascan)" }, { "alpha_2": "de", "alpha_3": "deu", "bibliographic": "ger", "name": "German" }, { "alpha_3": "dgr", "name": "Dogrib" }, { "alpha_3": "din", "name": "Dinka" }, { "alpha_2": "dv", "alpha_3": "div", "name": "Divehi; Dhivehi; Maldivian" }, { "alpha_3": "doi", "name": "Dogri" }, { "alpha_3": "dra", "name": "Dravidian languages" }, { "alpha_3": "dsb", "name": "Lower Sorbian" }, { "alpha_3": "dua", "name": "Duala" }, { "alpha_3": "dum", "name": "Dutch, Middle (ca. 1050-1350)" }, { "alpha_3": "dyu", "name": "Dyula" }, { "alpha_2": "dz", "alpha_3": "dzo", "name": "Dzongkha" }, { "alpha_3": "efi", "name": "Efik" }, { "alpha_3": "egy", "name": "Egyptian (Ancient)" }, { "alpha_3": "eka", "name": "Ekajuk" }, { "alpha_2": "el", "alpha_3": "ell", "bibliographic": "gre", "name": "Greek, Modern (1453-)" }, { "alpha_3": "elx", "name": "Elamite" }, { "alpha_2": "en", "alpha_3": "eng", "name": "English" }, { "alpha_3": "enm", "name": "English, Middle (1100-1500)" }, { "alpha_2": "eo", "alpha_3": "epo", "name": "Esperanto" }, { "alpha_2": "et", "alpha_3": "est", "name": "Estonian" }, { "alpha_2": "eu", "alpha_3": "eus", "bibliographic": "baq", "name": "Basque" }, { "alpha_2": "ee", "alpha_3": "ewe", "name": "Ewe" }, { "alpha_3": "ewo", "name": "Ewondo" }, { "alpha_3": "fan", "name": "Fang" }, { "alpha_2": "fo", "alpha_3": "fao", "name": "Faroese" }, { "alpha_2": "fa", "alpha_3": "fas", "bibliographic": "per", "name": "Persian" }, { "alpha_3": "fat", "name": "Fanti" }, { "alpha_2": "fj", "alpha_3": "fij", "name": "Fijian" }, { "alpha_3": "fil", "name": "Filipino; Pilipino" }, { "alpha_2": "fi", "alpha_3": "fin", "name": "Finnish" }, { "alpha_3": "fiu", "name": "Finno-Ugrian languages" }, { "alpha_3": "fon", "name": "Fon" }, { "alpha_2": "fr", "alpha_3": "fra", "bibliographic": "fre", "name": "French" }, { "alpha_3": "frm", "name": "French, Middle (ca. 1400-1600)" }, { "alpha_3": "fro", "name": "French, Old (842-ca. 1400)" }, { "alpha_3": "frr", "name": "Northern Frisian" }, { "alpha_3": "frs", "name": "Eastern Frisian" }, { "alpha_2": "fy", "alpha_3": "fry", "name": "Western Frisian" }, { "alpha_2": "ff", "alpha_3": "ful", "name": "Fulah" }, { "alpha_3": "fur", "name": "Friulian" }, { "alpha_3": "gaa", "name": "Ga" }, { "alpha_3": "gay", "name": "Gayo" }, { "alpha_3": "gba", "name": "Gbaya" }, { "alpha_3": "gem", "name": "Germanic languages" }, { "alpha_3": "gez", "name": "Geez" }, { "alpha_3": "gil", "name": "Gilbertese" }, { "alpha_2": "gd", "alpha_3": "gla", "name": "Gaelic; Scottish Gaelic" }, { "alpha_2": "ga", "alpha_3": "gle", "name": "Irish" }, { "alpha_2": "gl", "alpha_3": "glg", "name": "Galician" }, { "alpha_2": "gv", "alpha_3": "glv", "name": "Manx" }, { "alpha_3": "gmh", "name": "German, Middle High (ca. 1050-1500)" }, { "alpha_3": "goh", "name": "German, Old High (ca. 750-1050)" }, { "alpha_3": "gon", "name": "Gondi" }, { "alpha_3": "gor", "name": "Gorontalo" }, { "alpha_3": "got", "name": "Gothic" }, { "alpha_3": "grb", "name": "Grebo" }, { "alpha_3": "grc", "name": "Greek, Ancient (to 1453)" }, { "alpha_2": "gn", "alpha_3": "grn", "name": "Guarani" }, { "alpha_3": "gsw", "name": "Swiss German; Alemannic; Alsatian" }, { "alpha_2": "gu", "alpha_3": "guj", "name": "Gujarati" }, { "alpha_3": "gwi", "name": "Gwich'in" }, { "alpha_3": "hai", "name": "Haida" }, { "alpha_2": "ht", "alpha_3": "hat", "name": "Haitian; Haitian Creole" }, { "alpha_2": "ha", "alpha_3": "hau", "name": "Hausa" }, { "alpha_3": "haw", "name": "Hawaiian" }, { "alpha_2": "he", "alpha_3": "heb", "name": "Hebrew" }, { "alpha_2": "hz", "alpha_3": "her", "name": "Herero" }, { "alpha_3": "hil", "name": "Hiligaynon" }, { "alpha_3": "him", "name": "Himachali languages; Western Pahari languages" }, { "alpha_2": "hi", "alpha_3": "hin", "name": "Hindi" }, { "alpha_3": "hit", "name": "Hittite" }, { "alpha_3": "hmn", "name": "Hmong; Mong" }, { "alpha_2": "ho", "alpha_3": "hmo", "name": "Hiri Motu" }, { "alpha_2": "hr", "alpha_3": "hrv", "name": "Croatian" }, { "alpha_3": "hsb", "name": "Upper Sorbian" }, { "alpha_2": "hu", "alpha_3": "hun", "name": "Hungarian" }, { "alpha_3": "hup", "name": "Hupa" }, { "alpha_2": "hy", "alpha_3": "hye", "bibliographic": "arm", "name": "Armenian" }, { "alpha_3": "iba", "name": "Iban" }, { "alpha_2": "ig", "alpha_3": "ibo", "name": "Igbo" }, { "alpha_2": "io", "alpha_3": "ido", "name": "Ido" }, { "alpha_2": "ii", "alpha_3": "iii", "name": "Sichuan Yi; Nuosu" }, { "alpha_3": "ijo", "name": "Ijo languages" }, { "alpha_2": "iu", "alpha_3": "iku", "name": "Inuktitut" }, { "alpha_2": "ie", "alpha_3": "ile", "name": "Interlingue; Occidental" }, { "alpha_3": "ilo", "name": "Iloko" }, { "alpha_2": "ia", "alpha_3": "ina", "name": "Interlingua (International Auxiliary Language Association)" }, { "alpha_3": "inc", "name": "Indic languages" }, { "alpha_2": "id", "alpha_3": "ind", "name": "Indonesian" }, { "alpha_3": "ine", "name": "Indo-European languages" }, { "alpha_3": "inh", "name": "Ingush" }, { "alpha_2": "ik", "alpha_3": "ipk", "name": "Inupiaq" }, { "alpha_3": "ira", "name": "Iranian languages" }, { "alpha_3": "iro", "name": "Iroquoian languages" }, { "alpha_2": "is", "alpha_3": "isl", "bibliographic": "ice", "name": "Icelandic" }, { "alpha_2": "it", "alpha_3": "ita", "name": "Italian" }, { "alpha_2": "jv", "alpha_3": "jav", "name": "Javanese" }, { "alpha_3": "jbo", "name": "Lojban" }, { "alpha_2": "ja", "alpha_3": "jpn", "name": "Japanese" }, { "alpha_3": "jpr", "name": "Judeo-Persian" }, { "alpha_3": "jrb", "name": "Judeo-Arabic" }, { "alpha_3": "kaa", "name": "Kara-Kalpak" }, { "alpha_3": "kab", "name": "Kabyle" }, { "alpha_3": "kac", "name": "Kachin; Jingpho" }, { "alpha_2": "kl", "alpha_3": "kal", "name": "Kalaallisut; Greenlandic" }, { "alpha_3": "kam", "name": "Kamba" }, { "alpha_2": "kn", "alpha_3": "kan", "name": "Kannada" }, { "alpha_3": "kar", "name": "Karen languages" }, { "alpha_2": "ks", "alpha_3": "kas", "name": "Kashmiri" }, { "alpha_2": "ka", "alpha_3": "kat", "bibliographic": "geo", "name": "Georgian" }, { "alpha_2": "kr", "alpha_3": "kau", "name": "Kanuri" }, { "alpha_3": "kaw", "name": "Kawi" }, { "alpha_2": "kk", "alpha_3": "kaz", "name": "Kazakh" }, { "alpha_3": "kbd", "name": "Kabardian" }, { "alpha_3": "kha", "name": "Khasi" }, { "alpha_3": "khi", "name": "Khoisan languages" }, { "alpha_2": "km", "alpha_3": "khm", "name": "Central Khmer" }, { "alpha_3": "kho", "name": "Khotanese; Sakan" }, { "alpha_2": "ki", "alpha_3": "kik", "name": "Kikuyu; Gikuyu" }, { "alpha_2": "rw", "alpha_3": "kin", "name": "Kinyarwanda" }, { "alpha_2": "ky", "alpha_3": "kir", "name": "Kirghiz; Kyrgyz" }, { "alpha_3": "kmb", "name": "Kimbundu" }, { "alpha_3": "kok", "name": "Konkani" }, { "alpha_2": "kv", "alpha_3": "kom", "name": "Komi" }, { "alpha_2": "kg", "alpha_3": "kon", "name": "Kongo" }, { "alpha_2": "ko", "alpha_3": "kor", "name": "Korean" }, { "alpha_3": "kos", "name": "Kosraean" }, { "alpha_3": "kpe", "name": "Kpelle" }, { "alpha_3": "krc", "name": "Karachay-Balkar" }, { "alpha_3": "krl", "name": "Karelian" }, { "alpha_3": "kro", "name": "Kru languages" }, { "alpha_3": "kru", "name": "Kurukh" }, { "alpha_2": "kj", "alpha_3": "kua", "name": "Kuanyama; Kwanyama" }, { "alpha_3": "kum", "name": "Kumyk" }, { "alpha_2": "ku", "alpha_3": "kur", "name": "Kurdish" }, { "alpha_3": "kut", "name": "Kutenai" }, { "alpha_3": "lad", "name": "Ladino" }, { "alpha_3": "lah", "name": "Lahnda" }, { "alpha_3": "lam", "name": "Lamba" }, { "alpha_2": "lo", "alpha_3": "lao", "name": "Lao" }, { "alpha_2": "la", "alpha_3": "lat", "name": "Latin" }, { "alpha_2": "lv", "alpha_3": "lav", "name": "Latvian" }, { "alpha_3": "lez", "name": "Lezghian" }, { "alpha_2": "li", "alpha_3": "lim", "name": "Limburgan; Limburger; Limburgish" }, { "alpha_2": "ln", "alpha_3": "lin", "name": "Lingala" }, { "alpha_2": "lt", "alpha_3": "lit", "name": "Lithuanian" }, { "alpha_3": "lol", "name": "Mongo" }, { "alpha_3": "loz", "name": "Lozi" }, { "alpha_2": "lb", "alpha_3": "ltz", "name": "Luxembourgish; Letzeburgesch" }, { "alpha_3": "lua", "name": "Luba-Lulua" }, { "alpha_2": "lu", "alpha_3": "lub", "name": "Luba-Katanga" }, { "alpha_2": "lg", "alpha_3": "lug", "name": "Ganda" }, { "alpha_3": "lui", "name": "Luiseno" }, { "alpha_3": "lun", "name": "Lunda" }, { "alpha_3": "luo", "name": "Luo (Kenya and Tanzania)" }, { "alpha_3": "lus", "name": "Lushai" }, { "alpha_3": "mad", "name": "Madurese" }, { "alpha_3": "mag", "name": "Magahi" }, { "alpha_2": "mh", "alpha_3": "mah", "name": "Marshallese" }, { "alpha_3": "mai", "name": "Maithili" }, { "alpha_3": "mak", "name": "Makasar" }, { "alpha_2": "ml", "alpha_3": "mal", "name": "Malayalam" }, { "alpha_3": "man", "name": "Mandingo" }, { "alpha_3": "map", "name": "Austronesian languages" }, { "alpha_2": "mr", "alpha_3": "mar", "name": "Marathi" }, { "alpha_3": "mas", "name": "Masai" }, { "alpha_3": "mdf", "name": "Moksha" }, { "alpha_3": "mdr", "name": "Mandar" }, { "alpha_3": "men", "name": "Mende" }, { "alpha_3": "mga", "name": "Irish, Middle (900-1200)" }, { "alpha_3": "mic", "name": "Mi'kmaq; Micmac" }, { "alpha_3": "min", "name": "Minangkabau" }, { "alpha_3": "mis", "name": "Uncoded languages" }, { "alpha_2": "mk", "alpha_3": "mkd", "bibliographic": "mac", "name": "Macedonian" }, { "alpha_3": "mkh", "name": "Mon-Khmer languages" }, { "alpha_2": "mg", "alpha_3": "mlg", "name": "Malagasy" }, { "alpha_2": "mt", "alpha_3": "mlt", "name": "Maltese" }, { "alpha_3": "mnc", "name": "Manchu" }, { "alpha_3": "mni", "name": "Manipuri" }, { "alpha_3": "mno", "name": "Manobo languages" }, { "alpha_3": "moh", "name": "Mohawk" }, { "alpha_2": "mn", "alpha_3": "mon", "name": "Mongolian" }, { "alpha_3": "mos", "name": "Mossi" }, { "alpha_2": "mi", "alpha_3": "mri", "bibliographic": "mao", "name": "Maori" }, { "alpha_2": "ms", "alpha_3": "msa", "bibliographic": "may", "name": "Malay" }, { "alpha_3": "mul", "name": "Multiple languages" }, { "alpha_3": "mun", "name": "Munda languages" }, { "alpha_3": "mus", "name": "Creek" }, { "alpha_3": "mwl", "name": "Mirandese" }, { "alpha_3": "mwr", "name": "Marwari" }, { "alpha_2": "my", "alpha_3": "mya", "bibliographic": "bur", "name": "Burmese" }, { "alpha_3": "myn", "name": "Mayan languages" }, { "alpha_3": "myv", "name": "Erzya" }, { "alpha_3": "nah", "name": "Nahuatl languages" }, { "alpha_3": "nai", "name": "North American Indian languages" }, { "alpha_3": "nap", "name": "Neapolitan" }, { "alpha_2": "na", "alpha_3": "nau", "name": "Nauru" }, { "alpha_2": "nv", "alpha_3": "nav", "name": "Navajo; Navaho" }, { "alpha_2": "nr", "alpha_3": "nbl", "name": "Ndebele, South; South Ndebele" }, { "alpha_2": "nd", "alpha_3": "nde", "name": "Ndebele, North; North Ndebele" }, { "alpha_2": "ng", "alpha_3": "ndo", "name": "Ndonga" }, { "alpha_3": "nds", "name": "Low German; Low Saxon; German, Low; Saxon, Low" }, { "alpha_2": "ne", "alpha_3": "nep", "name": "Nepali" }, { "alpha_3": "new", "name": "Nepal Bhasa; Newari" }, { "alpha_3": "nia", "name": "Nias" }, { "alpha_3": "nic", "name": "Niger-Kordofanian languages" }, { "alpha_3": "niu", "name": "Niuean" }, { "alpha_2": "nl", "alpha_3": "nld", "bibliographic": "dut", "name": "Dutch; Flemish" }, { "alpha_2": "nn", "alpha_3": "nno", "name": "Norwegian Nynorsk; Nynorsk, Norwegian" }, { "alpha_2": "nb", "alpha_3": "nob", "name": "Bokmål, Norwegian; Norwegian Bokmål" }, { "alpha_3": "nog", "name": "Nogai" }, { "alpha_3": "non", "name": "Norse, Old" }, { "alpha_2": "no", "alpha_3": "nor", "name": "Norwegian" }, { "alpha_3": "nqo", "name": "N'Ko" }, { "alpha_3": "nso", "name": "Pedi; Sepedi; Northern Sotho" }, { "alpha_3": "nub", "name": "Nubian languages" }, { "alpha_3": "nwc", "name": "Classical Newari; Old Newari; Classical Nepal Bhasa" }, { "alpha_2": "ny", "alpha_3": "nya", "name": "Chichewa; Chewa; Nyanja" }, { "alpha_3": "nym", "name": "Nyamwezi" }, { "alpha_3": "nyn", "name": "Nyankole" }, { "alpha_3": "nyo", "name": "Nyoro" }, { "alpha_3": "nzi", "name": "Nzima" }, { "alpha_2": "oc", "alpha_3": "oci", "name": "Occitan (post 1500); Provençal" }, { "alpha_2": "oj", "alpha_3": "oji", "name": "Ojibwa" }, { "alpha_2": "or", "alpha_3": "ori", "name": "Oriya" }, { "alpha_2": "om", "alpha_3": "orm", "name": "Oromo" }, { "alpha_3": "osa", "name": "Osage" }, { "alpha_2": "os", "alpha_3": "oss", "name": "Ossetian; Ossetic" }, { "alpha_3": "ota", "name": "Turkish, Ottoman (1500-1928)" }, { "alpha_3": "oto", "name": "Otomian languages" }, { "alpha_3": "paa", "name": "Papuan languages" }, { "alpha_3": "pag", "name": "Pangasinan" }, { "alpha_3": "pal", "name": "Pahlavi" }, { "alpha_3": "pam", "name": "Pampanga; Kapampangan" }, { "alpha_2": "pa", "alpha_3": "pan", "name": "Panjabi; Punjabi" }, { "alpha_3": "pap", "name": "Papiamento" }, { "alpha_3": "pau", "name": "Palauan" }, { "alpha_3": "peo", "name": "Persian, Old (ca. 600-400 B.C.)" }, { "alpha_3": "phi", "name": "Philippine languages" }, { "alpha_3": "phn", "name": "Phoenician" }, { "alpha_2": "pi", "alpha_3": "pli", "name": "Pali" }, { "alpha_2": "pl", "alpha_3": "pol", "name": "Polish" }, { "alpha_3": "pon", "name": "Pohnpeian" }, { "alpha_2": "pt", "alpha_3": "por", "name": "Portuguese" }, { "alpha_3": "pra", "name": "Prakrit languages" }, { "alpha_3": "pro", "name": "Provençal, Old (to 1500)" }, { "alpha_2": "ps", "alpha_3": "pus", "name": "Pushto; Pashto" }, { "alpha_3": "qaa-qtz", "name": "Reserved for local use" }, { "alpha_2": "qu", "alpha_3": "que", "name": "Quechua" }, { "alpha_3": "raj", "name": "Rajasthani" }, { "alpha_3": "rap", "name": "Rapanui" }, { "alpha_3": "rar", "name": "Rarotongan; Cook Islands Maori" }, { "alpha_3": "roa", "name": "Romance languages" }, { "alpha_2": "rm", "alpha_3": "roh", "name": "Romansh" }, { "alpha_3": "rom", "name": "Romany" }, { "alpha_2": "ro", "alpha_3": "ron", "bibliographic": "rum", "name": "Romanian; Moldavian; Moldovan" }, { "alpha_2": "rn", "alpha_3": "run", "name": "Rundi" }, { "alpha_3": "rup", "name": "Aromanian; Arumanian; Macedo-Romanian" }, { "alpha_2": "ru", "alpha_3": "rus", "name": "Russian" }, { "alpha_3": "sad", "name": "Sandawe" }, { "alpha_2": "sg", "alpha_3": "sag", "name": "Sango" }, { "alpha_3": "sah", "name": "Yakut" }, { "alpha_3": "sai", "name": "South American Indian (Other)" }, { "alpha_3": "sal", "name": "Salishan languages" }, { "alpha_3": "sam", "name": "Samaritan Aramaic" }, { "alpha_2": "sa", "alpha_3": "san", "name": "Sanskrit" }, { "alpha_3": "sas", "name": "Sasak" }, { "alpha_3": "sat", "name": "Santali" }, { "alpha_3": "scn", "name": "Sicilian" }, { "alpha_3": "sco", "name": "Scots" }, { "alpha_3": "sel", "name": "Selkup" }, { "alpha_3": "sem", "name": "Semitic languages" }, { "alpha_3": "sga", "name": "Irish, Old (to 900)" }, { "alpha_3": "sgn", "name": "Sign Languages" }, { "alpha_3": "shn", "name": "Shan" }, { "alpha_3": "sid", "name": "Sidamo" }, { "alpha_2": "si", "alpha_3": "sin", "name": "Sinhala; Sinhalese" }, { "alpha_3": "sio", "name": "Siouan languages" }, { "alpha_3": "sit", "name": "Sino-Tibetan languages" }, { "alpha_3": "sla", "name": "Slavic languages" }, { "alpha_2": "sk", "alpha_3": "slk", "bibliographic": "slo", "name": "Slovak" }, { "alpha_2": "sl", "alpha_3": "slv", "name": "Slovenian" }, { "alpha_3": "sma", "name": "Southern Sami" }, { "alpha_2": "se", "alpha_3": "sme", "name": "Northern Sami" }, { "alpha_3": "smi", "name": "Sami languages" }, { "alpha_3": "smj", "name": "Lule Sami" }, { "alpha_3": "smn", "name": "Inari Sami" }, { "alpha_2": "sm", "alpha_3": "smo", "name": "Samoan" }, { "alpha_3": "sms", "name": "Skolt Sami" }, { "alpha_2": "sn", "alpha_3": "sna", "name": "Shona" }, { "alpha_2": "sd", "alpha_3": "snd", "name": "Sindhi" }, { "alpha_3": "snk", "name": "Soninke" }, { "alpha_3": "sog", "name": "Sogdian" }, { "alpha_2": "so", "alpha_3": "som", "name": "Somali" }, { "alpha_3": "son", "name": "Songhai languages" }, { "alpha_2": "st", "alpha_3": "sot", "name": "Sotho, Southern" }, { "alpha_2": "es", "alpha_3": "spa", "name": "Spanish; Castilian" }, { "alpha_2": "sq", "alpha_3": "sqi", "bibliographic": "alb", "name": "Albanian" }, { "alpha_2": "sc", "alpha_3": "srd", "name": "Sardinian" }, { "alpha_3": "srn", "name": "Sranan Tongo" }, { "alpha_2": "sr", "alpha_3": "srp", "name": "Serbian" }, { "alpha_3": "srr", "name": "Serer" }, { "alpha_3": "ssa", "name": "Nilo-Saharan languages" }, { "alpha_2": "ss", "alpha_3": "ssw", "name": "Swati" }, { "alpha_3": "suk", "name": "Sukuma" }, { "alpha_2": "su", "alpha_3": "sun", "name": "Sundanese" }, { "alpha_3": "sus", "name": "Susu" }, { "alpha_3": "sux", "name": "Sumerian" }, { "alpha_2": "sw", "alpha_3": "swa", "name": "Swahili" }, { "alpha_2": "sv", "alpha_3": "swe", "name": "Swedish" }, { "alpha_3": "syc", "name": "Classical Syriac" }, { "alpha_3": "syr", "name": "Syriac" }, { "alpha_2": "ty", "alpha_3": "tah", "name": "Tahitian" }, { "alpha_3": "tai", "name": "Tai languages" }, { "alpha_2": "ta", "alpha_3": "tam", "name": "Tamil" }, { "alpha_2": "tt", "alpha_3": "tat", "name": "Tatar" }, { "alpha_2": "te", "alpha_3": "tel", "name": "Telugu" }, { "alpha_3": "tem", "name": "Timne" }, { "alpha_3": "ter", "name": "Tereno" }, { "alpha_3": "tet", "name": "Tetum" }, { "alpha_2": "tg", "alpha_3": "tgk", "name": "Tajik" }, { "alpha_2": "tl", "alpha_3": "tgl", "name": "Tagalog" }, { "alpha_2": "th", "alpha_3": "tha", "name": "Thai" }, { "alpha_3": "tig", "name": "Tigre" }, { "alpha_2": "ti", "alpha_3": "tir", "name": "Tigrinya" }, { "alpha_3": "tiv", "name": "Tiv" }, { "alpha_3": "tkl", "name": "Tokelau" }, { "alpha_3": "tlh", "name": "Klingon; tlhIngan-Hol" }, { "alpha_3": "tli", "name": "Tlingit" }, { "alpha_3": "tmh", "name": "Tamashek" }, { "alpha_3": "tog", "name": "Tonga (Nyasa)" }, { "alpha_2": "to", "alpha_3": "ton", "name": "Tonga (Tonga Islands)" }, { "alpha_3": "tpi", "name": "Tok Pisin" }, { "alpha_3": "tsi", "name": "Tsimshian" }, { "alpha_2": "tn", "alpha_3": "tsn", "name": "Tswana" }, { "alpha_2": "ts", "alpha_3": "tso", "name": "Tsonga" }, { "alpha_2": "tk", "alpha_3": "tuk", "name": "Turkmen" }, { "alpha_3": "tum", "name": "Tumbuka" }, { "alpha_3": "tup", "name": "Tupi languages" }, { "alpha_2": "tr", "alpha_3": "tur", "name": "Turkish" }, { "alpha_3": "tut", "name": "Altaic languages" }, { "alpha_3": "tvl", "name": "Tuvalu" }, { "alpha_2": "tw", "alpha_3": "twi", "name": "Twi" }, { "alpha_3": "tyv", "name": "Tuvinian" }, { "alpha_3": "udm", "name": "Udmurt" }, { "alpha_3": "uga", "name": "Ugaritic" }, { "alpha_2": "ug", "alpha_3": "uig", "name": "Uighur; Uyghur" }, { "alpha_2": "uk", "alpha_3": "ukr", "name": "Ukrainian" }, { "alpha_3": "umb", "name": "Umbundu" }, { "alpha_3": "und", "name": "Undetermined" }, { "alpha_2": "ur", "alpha_3": "urd", "name": "Urdu" }, { "alpha_2": "uz", "alpha_3": "uzb", "name": "Uzbek" }, { "alpha_3": "vai", "name": "Vai" }, { "alpha_2": "ve", "alpha_3": "ven", "name": "Venda" }, { "alpha_2": "vi", "alpha_3": "vie", "name": "Vietnamese" }, { "alpha_2": "vo", "alpha_3": "vol", "name": "Volapük" }, { "alpha_3": "vot", "name": "Votic" }, { "alpha_3": "wak", "name": "Wakashan languages" }, { "alpha_3": "wal", "name": "Walamo" }, { "alpha_3": "war", "name": "Waray" }, { "alpha_3": "was", "name": "Washo" }, { "alpha_3": "wen", "name": "Sorbian languages" }, { "alpha_2": "wa", "alpha_3": "wln", "name": "Walloon" }, { "alpha_2": "wo", "alpha_3": "wol", "name": "Wolof" }, { "alpha_3": "xal", "name": "Kalmyk; Oirat" }, { "alpha_2": "xh", "alpha_3": "xho", "name": "Xhosa" }, { "alpha_3": "yao", "name": "Yao" }, { "alpha_3": "yap", "name": "Yapese" }, { "alpha_2": "yi", "alpha_3": "yid", "name": "Yiddish" }, { "alpha_2": "yo", "alpha_3": "yor", "name": "Yoruba" }, { "alpha_3": "ypk", "name": "Yupik languages" }, { "alpha_3": "zap", "name": "Zapotec" }, { "alpha_3": "zbl", "name": "Blissymbols; Blissymbolics; Bliss" }, { "alpha_3": "zen", "name": "Zenaga" }, { "alpha_3": "zgh", "name": "Standard Moroccan Tamazight" }, { "alpha_2": "za", "alpha_3": "zha", "name": "Zhuang; Chuang" }, { "alpha_2": "zh", "alpha_3": "zho", "bibliographic": "chi", "name": "Chinese" }, { "alpha_3": "znd", "name": "Zande languages" }, { "alpha_2": "zu", "alpha_3": "zul", "name": "Zulu" }, { "alpha_3": "zun", "name": "Zuni" }, { "alpha_3": "zxx", "name": "No linguistic content; Not applicable" }, { "alpha_3": "zza", "name": "Zaza; Dimili; Dimli; Kirdki; Kirmanjki; Zazaki" } ] } gaupol-1.11/data/patterns/000077500000000000000000000000001422217132500154735ustar00rootroot00000000000000gaupol-1.11/data/patterns/Latn-en-US.common-error.conf000066400000000000000000000001641422217132500226040ustar00rootroot00000000000000 gaupol-1.11/data/patterns/Latn-en-US.common-error.in000066400000000000000000000003621422217132500222650ustar00rootroot00000000000000# -*- conf -*- [Common Error Pattern] Name=Period after title Description=Add period after a shortened title, such as "Mr" and "Dr" Classes=Human; Pattern=\b(Dr|Jr|Mr|Mrs|Ms|Sr|St)( |$) Flags=DOTALL;MULTILINE; Replacement=\1.\2 Repeat=False gaupol-1.11/data/patterns/Latn-en.capitalization.conf000066400000000000000000000001661422217132500226550ustar00rootroot00000000000000 gaupol-1.11/data/patterns/Latn-en.capitalization.in000066400000000000000000000002561422217132500223360ustar00rootroot00000000000000# -*- conf -*- [Capitalization Pattern] Name=First person pronoun Description=Capitalize the first person pronoun "I" Capitalize=Start Pattern=\bi\b Flags=DOTALL;MULTILINE; gaupol-1.11/data/patterns/Latn-en.common-error.conf000066400000000000000000000006771422217132500222700ustar00rootroot00000000000000 gaupol-1.11/data/patterns/Latn-en.common-error.in000066400000000000000000000060161422217132500217420ustar00rootroot00000000000000# -*- conf -*- [Common Error Pattern] Name=Letter "I" in a lower case word Description=Replace letter "I" with letter "l" in a lower case word Classes=OCR; Pattern=(?<=[a-z])I Flags=DOTALL;MULTILINE; Replacement=l Repeat=True [Common Error Pattern] Name=Letter "I" in a lower case word Description=Replace letter "I" with letter "l" in a lower case word Classes=OCR; Pattern=(?<=\b[A-Z])I(?=[a-z]) Flags=DOTALL;MULTILINE; Replacement=l Repeat=True [Common Error Pattern] Name=Letter "I" in a lower case word Description=Replace letter "I" with letter "l" in a lower case word Classes=OCR; Pattern='[Il][Il]\b Flags=DOTALL;MULTILINE; Replacement='ll Repeat=False [Common Error Pattern] Name=Letter "l" in an upper case word Description=Replace letter "l" with letter "I" in an upper case word Classes=OCR; Pattern=(?<=[A-Z][A-Z])l Flags=DOTALL;MULTILINE; Replacement=I Repeat=True [Common Error Pattern] Name=Letter "l" in an upper case word Description=Replace letter "l" with letter "I" in an upper case word Classes=OCR; Pattern=l(?=[A-Z]) Flags=DOTALL;MULTILINE; Replacement=I Repeat=True [Common Error Pattern] Name=Letter "l" in an upper case word Description=Replace letter "l" with letter "I" in an upper case word Classes=OCR; # Handle the case of the first person pronoun "I". # Disallow dashes for the case of spelling out a word, but allow them # for the case of stuttering. Pattern=(? gaupol-1.11/data/patterns/Latn-en.hearing-impaired.in000066400000000000000000000004541422217132500225300ustar00rootroot00000000000000# -*- conf -*- [Hearing Impaired Pattern] Name=Uppercase speaker before a colon Description=Replace the uppercase name of the speaker before a colon with a dialogue dash # Allow lower case "c" for McNAMES. Pattern=^[\-\–\—]?\s*?[A-Z\[][A-Zc\d#&'.\-\[\] ]+?:\s Flags=MULTILINE; Replacement=-\040 gaupol-1.11/data/patterns/Latn-en.line-break.conf000066400000000000000000000003721422217132500216520ustar00rootroot00000000000000 gaupol-1.11/data/patterns/Latn-en.line-break.in000066400000000000000000000026401422217132500213330ustar00rootroot00000000000000# -*- conf -*- [Line Break Pattern] Name=Title Description=Do not break after a title, e.g. " Dr." Pattern=\b(Dr|Jr|Mr|Mrs|Ms|Sr|St)\.?( ) Flags=DOTALL;MULTILINE; Group=2 Penalty=1000000 [Line Break Pattern] Name=Article Description=Do not break after an article Pattern=\b(a|an|the)( ) Flags=DOTALL;MULTILINE; Group=2 Penalty=1000000 [Line Break Pattern] Name=Preposition Description=Do not break after a preposition # http://en.wikipedia.org/wiki/List_of_English_prepositions Pattern=\b(abaft|aboard|about|above|absent|across|afore|after|against|along|alongside|amid|amidst|among|amongst|apropos|around|as|aside|astride|at|athwart|atop|barring|before|behind|below|beneath|beside|besides|between|betwixt|beyond|but|by|circa|concerning|despite|down|during|except|excluding|failing|following|for|from|given|in|including|inside|into|lest|like|mid|midst|minus|modulo|near|next|notwithstanding|of|off|on|onto|opposite|out|outside|over|pace|past|per|plus|pro|qua|regarding|round|sans|save|since|than|though|throughout|till|times|to|toward|towards|under|underneath|unlike|until|unto|up|upon|versus|via|vice|with|within|without|worth)( ) Flags=DOTALL;MULTILINE; Group=2 Penalty=100 [Line Break Pattern] Name=Possessive determiner Description=Do not break after a possessive determiner, e.g. "my" # http://en.wikipedia.org/wiki/Possessive_determiner Pattern=\b(my|your|his|her|its|our|your|their)( ) Flags=DOTALL;MULTILINE; Group=2 Penalty=100 gaupol-1.11/data/patterns/Latn-fi.common-error.conf000066400000000000000000000001771422217132500222570ustar00rootroot00000000000000 gaupol-1.11/data/patterns/Latn-fi.common-error.in000066400000000000000000000006301422217132500217320ustar00rootroot00000000000000# -*- conf -*- [Common Error Pattern] Name=Space after punctuation marks Description=Add space after various punctuation marks Classes=Human;OCR; # Same as the Latin pattern, except no space after colon # to accommodate Finnish suffixes, e.g. "TV:ssä". Pattern=((\w|^|['‘’"“”«»])[,;?!])(?!['‘’"“”«»])([^\W\d][\w\s]) Flags=DOTALL;MULTILINE; Replacement=\1 \3 Repeat=False Policy=Replace gaupol-1.11/data/patterns/Latn-fr.common-error.conf000066400000000000000000000002741422217132500222660ustar00rootroot00000000000000 gaupol-1.11/data/patterns/Latn-fr.common-error.in000066400000000000000000000024511422217132500217460ustar00rootroot00000000000000# -*- conf -*- [Common Error Pattern] Name=Spaces around guillemets Description=Add spaces around guillemets Classes=Human;OCR; Pattern=(\S)(«) Flags=DOTALL;MULTILINE; Replacement=\1 \2 Repeat=False [Common Error Pattern] Name=Spaces around guillemets Description=Add spaces around guillemets Classes=Human;OCR; Pattern=(»)(\w) Flags=DOTALL;MULTILINE; Replacement=\1 \2 Repeat=False [Common Error Pattern] Name=Spaces around guillemets Description=Add spaces around guillemets Classes=Human;OCR; Pattern=(«)(\S) Flags=DOTALL;MULTILINE; Replacement=\1 \2 Repeat=False [Common Error Pattern] Name=Spaces around guillemets Description=Add spaces around guillemets Classes=Human;OCR; Pattern=(\S)(») Flags=DOTALL;MULTILINE; Replacement=\1 \2 Repeat=False [Common Error Pattern] Name=Space before punctuation marks Description=Add or remove space before various punctuation marks Classes=Human;OCR; # Same as the Latin pattern, except keep space before [?!;:]. Pattern=\0 +(['‘’"“”«»]?(?!\.\.)([,.])(?!\d)) Flags=DOTALL;MULTILINE; Replacement=\1 Repeat=False Policy=Replace [Common Error Pattern] Name=Space before punctuation marks Description=Add or remove space before various punctuation marks Classes=Human;OCR; Pattern=([^\s?!;:])([?!;:])(?!\d) Flags=DOTALL;MULTILINE; Replacement=\1 \2 Repeat=False gaupol-1.11/data/patterns/Latn.capitalization.conf000066400000000000000000000002271422217132500222530ustar00rootroot00000000000000 gaupol-1.11/data/patterns/Latn.capitalization.in000066400000000000000000000005611422217132500217350ustar00rootroot00000000000000# -*- conf -*- [Capitalization Pattern] Name=Sentence Description=Capitalize the first word of a sentence Capitalize=After Pattern=((? gaupol-1.11/data/patterns/Latn.common-error.in000066400000000000000000000200721422217132500213400ustar00rootroot00000000000000# -*- conf -*- [Common Error Pattern] # Some OCR software seem to infest subtitles with ligature characters, # causing a multitude of problems all the way to playback. # https://en.wikipedia.org/wiki/Typographic_ligature#Ligatures_in_Unicode_(Latin_alphabets) Name=Ligatures Description=Unpack ligatures to individual characters Classes=OCR; Pattern=\ufb00 Flags=DOTALL;MULTILINE; Replacement=ff Repeat=False [Common Error Pattern] Name=Ligatures Description=Unpack ligatures to individual characters Classes=OCR; Pattern=\ufb01 Flags=DOTALL;MULTILINE; Replacement=fi Repeat=False [Common Error Pattern] Name=Ligatures Description=Unpack ligatures to individual characters Classes=OCR; Pattern=\ufb02 Flags=DOTALL;MULTILINE; Replacement=fl Repeat=False [Common Error Pattern] Name=Ligatures Description=Unpack ligatures to individual characters Classes=OCR; Pattern=\ufb03 Flags=DOTALL;MULTILINE; Replacement=ffi Repeat=False [Common Error Pattern] Name=Ligatures Description=Unpack ligatures to individual characters Classes=OCR; Pattern=\ufb04 Flags=DOTALL;MULTILINE; Replacement=ffl Repeat=False [Common Error Pattern] Name=Ligatures Description=Unpack ligatures to individual characters Classes=OCR; Pattern=\ufb05 Flags=DOTALL;MULTILINE; Replacement=ft Repeat=False [Common Error Pattern] Name=Ligatures Description=Unpack ligatures to individual characters Classes=OCR; Pattern=\ufb06 Flags=DOTALL;MULTILINE; Replacement=st Repeat=False [Common Error Pattern] Name=Spelling of a.m. and p.m. Description=Change the various spellings of 12-hour periods to "a.m." and "p.m." Classes=Human;OCR; Pattern=(\d)(\s*a\.? ?m\.?)(\W|$) Flags=DOTALL;MULTILINE;IGNORECASE; Replacement=\1 a.m.\3 Repeat=False [Common Error Pattern] Name=Spelling of a.m. and p.m. Description=Change the various spellings of 12-hour periods to "a.m." and "p.m." Classes=Human;OCR; Pattern=(\d)(\s*p\.? ?m\.?)(\W|$) Flags=DOTALL;MULTILINE;IGNORECASE; Replacement=\1 p.m.\3 Repeat=False [Common Error Pattern] Name=Letter "O" in a number Description=Replace letter "O" with a zero in a number Classes=OCR; Pattern=((? gaupol-1.11/data/patterns/Latn.hearing-impaired.in000066400000000000000000000021451422217132500221270ustar00rootroot00000000000000# -*- conf -*- [Hearing Impaired Pattern] Name=Sound in brackets Description=Remove description of a sound between square brackets Pattern=\[.*?\] Flags=DOTALL;MULTILINE; Replacement=\0 [Hearing Impaired Pattern] Name=Sound in parantheses Description=Remove description of a sound between parantheses Pattern=\(.*?\) Flags=DOTALL;MULTILINE; Replacement=\0 [Hearing Impaired Pattern] Name=Song lyrics between number signs Description=Remove song lyrics starting with or between number signs # Remove up to the end of the subtitle if no terminating number sign. Pattern=#+.+?(#+|\Z) Flags=DOTALL;MULTILINE; Replacement=\0 [Hearing Impaired Pattern] Name=One-line song lyrics between number signs Description=Remove one-line song lyrics starting with or between number signs # Remove up to the end of the line if no terminating number sign. Pattern=#+.+?(#+|$) Flags=DOTALL;MULTILINE; Replacement=\0 [Hearing Impaired Pattern] Name=Speaker before a colon Description=Replace the name of the speaker before a colon with a dialogue dash Pattern=^[\-\–\—]?\s*?[\w\[][\w#&'.\-\[\] ]+?:\s Flags=MULTILINE; Replacement=-\040 gaupol-1.11/data/patterns/Latn.line-break.conf000066400000000000000000000003071422217132500212500ustar00rootroot00000000000000 gaupol-1.11/data/patterns/Latn.line-break.in000066400000000000000000000017371422217132500207410ustar00rootroot00000000000000# -*- conf -*- [Line Break Pattern] Name=Dialogue Description=Break according to dialogue separated by dashes Pattern=( )([\-\–\—] ) Flags=DOTALL;MULTILINE; Group=1 Penalty=-1000 [Line Break Pattern] Name=Dialogue Description=Break according to dialogue separated by dashes Pattern=( [\-\–\—])( ) Flags=DOTALL;MULTILINE; Group=2 Penalty=1000000 [Line Break Pattern] Name=Clause Description=Break according to clauses terminated by a punctuation mark # Disallow abbreviations and ellipses preceding a period. Pattern=((? gaupol-1.11/data/patterns/Zyyy.common-error.in000066400000000000000000000042721422217132500214320ustar00rootroot00000000000000# -*- conf -*- [Common Error Pattern] Name=Leading and trailing spaces Description=Remove spaces from the beginning and end of lines Classes=Human;OCR; Pattern=^ + Flags=DOTALL;MULTILINE; Replacement=\0 Repeat=False [Common Error Pattern] Name=Leading and trailing spaces Description=Remove spaces from the beginning and end of lines Classes=Human;OCR; Pattern=\0 +$ Flags=DOTALL;MULTILINE; Replacement=\0 Repeat=False [Common Error Pattern] Name=Multiple consecutive spaces Description=Replace multiple consecutive spaces with only one Classes=Human;OCR; Pattern=\0 {2,} Flags=DOTALL;MULTILINE; Replacement=\040 Repeat=False [Common Error Pattern] Name=Space between digits Description=Remove space between digits of a number Classes=OCR; # Do not remove space if it's followed by exactly three digits, # implying that the space being used as a thousand separator. # Do not allow a trailing slash which might be used # to spell out a fraction, e.g. "2 1/2". Pattern=(\b\d+) +(?!\d\d\d\b)(\d+)(?!/) Flags=DOTALL;MULTILINE; Replacement=\1\2 Repeat=True [Common Error Pattern] Name=Space between digits Description=Remove space between digits of a number Classes=OCR; # Remove spaces around thousand, decimal and time separators. Pattern=(\b\d+) +([,.:])(\d+) Flags=DOTALL;MULTILINE; Replacement=\1\2\3 Repeat=False [Common Error Pattern] Name=Space between digits Description=Remove space between digits of a number Classes=OCR; # Remove spaces around time separators. Pattern=(\b\d+)([:]) +(\d+) Flags=DOTALL;MULTILINE; Replacement=\1\2\3 Repeat=False [Common Error Pattern] Name=Space between digits Description=Remove space between digits of a number Classes=OCR; # Don't leave thousand separators for four-digit numbers. Pattern=(\b\d) +(\d\d\d\b)(?!.\d) Flags=DOTALL;MULTILINE; Replacement=\1\2 Repeat=True SkipIn=Latn-fr; [Common Error Pattern] # Many subtitle fonts don't support Unicode note characters and many # video players by default use fonts with a poor coverage and have no # system of fallback fonts to provide missing characters. Name=Musical notes Description=Replace Unicode musical note characters with number signs Classes=Human; Pattern=[♩♪♫♬]+ Flags=DOTALL;MULTILINE; Replacement=# Repeat=False gaupol-1.11/data/samples/000077500000000000000000000000001422217132500152775ustar00rootroot00000000000000gaupol-1.11/data/samples/ass.ass000066400000000000000000000033031422217132500165740ustar00rootroot00000000000000[Script Info] Title: Original Script: Original Translation: Original Editing: Original Timing: Synch Point: Script Updated By: Update Details: ScriptType: v4.00+ Collisions: Normal PlayResY: PlayResX: PlayDepth: Timer: 100.0000 WrapStyle: [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding Style: Default, Sans, 18, &H00FFFFFF, &H00FFFF00, &H00000000, &H00000000, 0, 0, 0, 0, 100, 100, 0, 0.00, 1, 2, 2, 2, 30, 30, 30, 0 [Events] Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text Dialogue: 0,-0:00:06.84,-0:00:02.85,Default,,0000,0000,0000,,I always wanted to leave my country\Nand go somewhere else. Dialogue: 0,-0:00:01.47,0:00:00.95,Default,,0000,0000,0000,,I always wanted to come to France. Dialogue: 0,0:00:00.95,0:00:03.36,Default,,0000,0000,0000,,So, one day when I was 17, I left. Dialogue: 0,0:00:04.64,0:00:06.63,Default,,0000,0000,0000,,There I was in Paris. Dialogue: 0,0:00:09.61,0:00:13.74,Default,,0000,0000,0000,,Since I was a bit naive, Dialogue: 0,0:00:14.45,0:00:18.54,Default,,0000,0000,0000,,everyone seemed beautiful\Nand fabulous. Dialogue: 0,0:00:18.98,0:00:23.18,Default,,0000,0000,0000,,{\i1}I couldn't tell cruelty from kindness.{\i0} Dialogue: 0,0:00:23.39,0:00:27.65,Default,,0000,0000,0000,,{\i1}For me, people were{\i0}\N{\i1}the way they were.{\i0} Dialogue: 0,0:00:28.06,0:00:31.62,Default,,0000,0000,0000,,{\i1}You just worked with them{\i0}\N{\i1}or talked with them.{\i0} Dialogue: 0,0:00:32.56,0:00:35.90,Default,,0000,0000,0000,,Obviously, it was a big shock. gaupol-1.11/data/samples/lrc.lrc000066400000000000000000000007321422217132500165630ustar00rootroot00000000000000[-00:06.84]I always wanted to leave my country and go somewhere else. [-00:01.47]I always wanted to come to France. [00:00.95]So, one day when I was 17, I left. [00:04.64]There I was in Paris. [00:09.61]Since I was a bit naive, [00:14.45]everyone seemed beautiful and fabulous. [00:18.98]I couldn't tell cruelty from kindness. [00:23.39]For me, people were the way they were. [00:28.06]You just worked with them or talked with them. [00:32.56]Obviously, it was a big shock. gaupol-1.11/data/samples/microdvd.sub000066400000000000000000000007571422217132500176320ustar00rootroot00000000000000{-164}{-68}I always wanted to leave my country|and go somewhere else. {-35}{23}I always wanted to come to France. {23}{81}So, one day when I was 17, I left. {111}{159}There I was in Paris. {230}{329}Since I was a bit naive, {346}{445}everyone seemed beautiful|and fabulous. {455}{556}{Y:i}I couldn't tell cruelty from kindness. {561}{663}{y:i}For me, people were|{y:i}the way they were. {673}{758}{y:i}You just worked with them|{y:i}or talked with them. {781}{861}Obviously, it was a big shock. gaupol-1.11/data/samples/mpl2.txt000066400000000000000000000007251422217132500167160ustar00rootroot00000000000000[-68][-28]I always wanted to leave my country|and go somewhere else. [-15][9]I always wanted to come to France. [9][34]So, one day when I was 17, I left. [46][66]There I was in Paris. [96][137]Since I was a bit naive, [144][185]everyone seemed beautiful|and fabulous. [190][232]/I couldn't tell cruelty from kindness. [234][277]/For me, people were|/the way they were. [281][316]/You just worked with them|/or talked with them. [326][359]Obviously, it was a big shock. gaupol-1.11/data/samples/ssa.ssa000066400000000000000000000032451422217132500166010ustar00rootroot00000000000000[Script Info] Title: Original Script: Original Translation: Original Editing: Original Timing: Synch Point: Script Updated By: Update Details: ScriptType: v4.00 Collisions: Normal PlayResY: PlayResX: PlayDepth: Timer: 100.0000 [V4 Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding Style: Default,Sans,18,&HFFFFFF,&HFFFF00,&H000000,&H000000,0,0,1,2,2,2,30,30,30,0,0 [Events] Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text Dialogue: Marked=0,-0:00:06.84,-0:00:02.85,Default,,0000,0000,0000,,I always wanted to leave my country\Nand go somewhere else. Dialogue: Marked=0,-0:00:01.47,0:00:00.95,Default,,0000,0000,0000,,I always wanted to come to France. Dialogue: Marked=0,0:00:00.95,0:00:03.36,Default,,0000,0000,0000,,So, one day when I was 17, I left. Dialogue: Marked=0,0:00:04.64,0:00:06.63,Default,,0000,0000,0000,,There I was in Paris. Dialogue: Marked=0,0:00:09.61,0:00:13.74,Default,,0000,0000,0000,,Since I was a bit naive, Dialogue: Marked=0,0:00:14.45,0:00:18.54,Default,,0000,0000,0000,,everyone seemed beautiful\Nand fabulous. Dialogue: Marked=0,0:00:18.98,0:00:23.18,Default,,0000,0000,0000,,{\i1}I couldn't tell cruelty from kindness.{\i0} Dialogue: Marked=0,0:00:23.39,0:00:27.65,Default,,0000,0000,0000,,{\i1}For me, people were{\i0}\N{\i1}the way they were.{\i0} Dialogue: Marked=0,0:00:28.06,0:00:31.62,Default,,0000,0000,0000,,{\i1}You just worked with them{\i0}\N{\i1}or talked with them.{\i0} Dialogue: Marked=0,0:00:32.56,0:00:35.90,Default,,0000,0000,0000,,Obviously, it was a big shock. gaupol-1.11/data/samples/subrip-extended.srt000066400000000000000000000020061422217132500211310ustar00rootroot000000000000001 -00:00:06,843 --> -00:00:02,850 X1:010 X2:710 Y1:400 Y2:460 I always wanted to leave my country and go somewhere else. 2 -00:00:01,471 --> 00:00:00,946 X1:010 X2:710 Y1:400 Y2:460 I always wanted to come to France. 3 00:00:00,946 --> 00:00:03,364 X1:010 X2:710 Y1:400 Y2:460 So, one day when I was 17, I left. 4 00:00:04,635 --> 00:00:06,626 X1:010 X2:710 Y1:400 Y2:460 There I was in Paris. 5 00:00:09,606 --> 00:00:13,736 X1:010 X2:710 Y1:400 Y2:460 Since I was a bit naive, 6 00:00:14,445 --> 00:00:18,541 X1:010 X2:710 Y1:400 Y2:460 everyone seemed beautiful and fabulous. 7 00:00:18,982 --> 00:00:23,180 X1:010 X2:710 Y1:400 Y2:460 I couldn't tell cruelty from kindness. 8 00:00:23,387 --> 00:00:27,653 X1:010 X2:710 Y1:400 Y2:460 For me, people were the way they were. 9 00:00:28,058 --> 00:00:31,619 X1:010 X2:710 Y1:400 Y2:460 You just worked with them or talked with them. 10 00:00:32,563 --> 00:00:35,896 X1:010 X2:710 Y1:400 Y2:460 Obviously, it was a big shock. gaupol-1.11/data/samples/subrip.srt000066400000000000000000000013441422217132500173370ustar00rootroot000000000000001 -00:00:06,843 --> -00:00:02,850 I always wanted to leave my country and go somewhere else. 2 -00:00:01,471 --> 00:00:00,946 I always wanted to come to France. 3 00:00:00,946 --> 00:00:03,364 So, one day when I was 17, I left. 4 00:00:04,635 --> 00:00:06,626 There I was in Paris. 5 00:00:09,606 --> 00:00:13,736 Since I was a bit naive, 6 00:00:14,445 --> 00:00:18,541 everyone seemed beautiful and fabulous. 7 00:00:18,982 --> 00:00:23,180 I couldn't tell cruelty from kindness. 8 00:00:23,387 --> 00:00:27,653 For me, people were the way they were. 9 00:00:28,058 --> 00:00:31,619 You just worked with them or talked with them. 10 00:00:32,563 --> 00:00:35,896 Obviously, it was a big shock. gaupol-1.11/data/samples/subviewer2.sub000066400000000000000000000015021422217132500201050ustar00rootroot00000000000000[INFORMATION] [TITLE] [AUTHOR] [SOURCE] [PRG] [FILEPATH] [DELAY]0 [CD TRACK]0 [COMMENT] [END INFORMATION] [SUBTITLE] [COLF]&HFFFFFF,[STYLE]bd,[SIZE]18,[FONT]Sans -00:00:06.84,-00:00:02.85 I always wanted to leave my country[br]and go somewhere else. -00:00:01.47,00:00:00.95 I always wanted to come to France. 00:00:00.95,00:00:03.36 So, one day when I was 17, I left. 00:00:04.64,00:00:06.63 There I was in Paris. 00:00:09.61,00:00:13.74 Since I was a bit naive, 00:00:14.45,00:00:18.54 everyone seemed beautiful[br]and fabulous. 00:00:18.98,00:00:23.18 I couldn't tell cruelty from kindness. 00:00:23.39,00:00:27.65 For me, people were[br]the way they were. 00:00:28.06,00:00:31.62 You just worked with them[br]or talked with them. 00:00:32.56,00:00:35.90 Obviously, it was a big shock. gaupol-1.11/data/samples/tmplayer-1.txt000066400000000000000000000007061422217132500200360ustar00rootroot00000000000000-0:00:07:I always wanted to leave my country|and go somewhere else. -0:00:01:I always wanted to come to France. 0:00:01:So, one day when I was 17, I left. 0:00:05:There I was in Paris. 0:00:10:Since I was a bit naive, 0:00:14:everyone seemed beautiful|and fabulous. 0:00:19:I couldn't tell cruelty from kindness. 0:00:23:For me, people were|the way they were. 0:00:28:You just worked with them|or talked with them. 0:00:33:Obviously, it was a big shock. gaupol-1.11/data/samples/tmplayer-2.txt000066400000000000000000000007201422217132500200330ustar00rootroot00000000000000-00:00:07:I always wanted to leave my country|and go somewhere else. -00:00:01:I always wanted to come to France. 00:00:01:So, one day when I was 17, I left. 00:00:05:There I was in Paris. 00:00:10:Since I was a bit naive, 00:00:14:everyone seemed beautiful|and fabulous. 00:00:19:I couldn't tell cruelty from kindness. 00:00:23:For me, people were|the way they were. 00:00:28:You just worked with them|or talked with them. 00:00:33:Obviously, it was a big shock. gaupol-1.11/data/samples/tmplayer.txt000066400000000000000000000007201422217132500176740ustar00rootroot00000000000000-00:00:07:I always wanted to leave my country|and go somewhere else. -00:00:01:I always wanted to come to France. 00:00:01:So, one day when I was 17, I left. 00:00:05:There I was in Paris. 00:00:10:Since I was a bit naive, 00:00:14:everyone seemed beautiful|and fabulous. 00:00:19:I couldn't tell cruelty from kindness. 00:00:23:For me, people were|the way they were. 00:00:28:You just worked with them|or talked with them. 00:00:33:Obviously, it was a big shock. gaupol-1.11/data/samples/webvtt.vtt000066400000000000000000000015051422217132500173520ustar00rootroot00000000000000WEBVTT - Title STYLE ::cue { background-color: yellow; } NOTE First comment 00:00.946 --> 00:03.364 So, one day when I was 17, I left. NOTE Second comment, which spans multiple lines 1 00:01.471 --> 00:04.635 I always wanted to come to France. Textual cue identifier 00:04.635 --> 00:06.626 There I was in Paris. 00:06.843 --> 00:09.606 position:10% I always wanted to leave my country and go somewhere else. 00:09.606 --> 00:13.736 position:90% Since I was a bit naive, 00:14.445 --> 00:18.541 everyone seemed beautiful and fabulous. 00:18.982 --> 00:23.180 I couldn't tell cruelty from kindness. 00:23.387 --> 00:27.653 For me, people were the way they were. 00:28.058 --> 00:31.619 You just worked with them or talked with them. 00:32.563 --> 00:35.896 Obviously, it was a big shock. gaupol-1.11/data/ui/000077500000000000000000000000001422217132500142505ustar00rootroot00000000000000gaupol-1.11/data/ui/columns-popup.ui000066400000000000000000000021741422217132500174340ustar00rootroot00000000000000
_No. win.toggle-number-column _Start win.toggle-start-column _End win.toggle-end-column _Duration win.toggle-duration-column _Text win.toggle-main-text-column T_ranslation win.toggle-translation-text-column
gaupol-1.11/data/ui/duration-adjust-dialog.ui000066400000000000000000000611411422217132500211640ustar00rootroot00000000000000 1 99 15 0.5 1 99 1 0.1 1 99 1 0.1 1 99 1 0.1 1 False 12 Adjust Durations False True center-on-parent dialog 1 True False vertical 12 False False False 0 True False vertical 12 True False vertical 6 True False start Theoretic Duration False False 0 True False 12 vertical 6 True False 12 True False start _Reading speed: True speed_spin False False 0 True True 15,0 adjustment1 1 1 True 15 False True 1 True False start characters per second False False 2 False True 0 _Lengthen duration to match reading speed True True False start True True False False 1 _Shorten duration to match reading speed True True False start True True False False 2 False True 1 False True 0 True False vertical 6 True False start Limits False False 0 True False 12 6 12 _Minimum duration: True True False start True True 0 0 Ma_ximum duration: True True False start True True 0 1 _Gap between subtitles: True True False start True True 0 2 True True 1,000 adjustment2 1 3 True 1 1 0 True False start s_econds True min_spin 2 0 True True 1,000 adjustment3 1 3 True 1 1 1 True False start seco_nds True max_spin 2 1 True True 1,000 adjustment4 1 3 True 1 1 2 True False start secon_ds True gap_spin 2 2 False True 1 False True 1 True False vertical 6 True False start Subtitles False False 0 True False 12 vertical 6 Adj_ust selected subtitles True True False start True True True False False 0 Adjus_t current project True True False start True True selected_radio False False 1 Adjust all _open projects True True False start True True selected_radio False False 2 False True 1 False True 2 False True 1 gaupol-1.11/data/ui/framerate-convert-dialog.ui000066400000000000000000000251551422217132500215000ustar00rootroot00000000000000 False 12 Convert Framerate False True center-on-parent dialog 1 True False vertical 12 False False False 0 True False vertical 12 True False vertical 6 True False start Framerate False False 0 True False 12 6 12 True False start _Input: True center input_combo 0 0 True False start _Output: True output_combo 0 1 True False True 1 0 True False True 1 1 False True 1 False True 0 True False vertical 6 True False start Subtitles False False 0 True False 12 vertical 6 Convert c_urrent project True True False start True True True False False 0 Convert _all open projects True True False start True True current_radio False False 1 False True 1 False True 1 False True 1 gaupol-1.11/data/ui/gaupol.css000066400000000000000000000005241422217132500162520ustar00rootroot00000000000000/* -*- coding: utf-8-unix -*- */ .gaupol-floating-label { background-color: @theme_fg_color; border-top-right-radius: 5px; color: @theme_bg_color; padding: 4px 9px 4px 4px; } .gaupol-tab-close-button { margin: 0; padding: 0; } .gaupol-video-background { background-color: black; } .monospace { font-family: monospace; } gaupol-1.11/data/ui/insert-dialog.ui000066400000000000000000000110521422217132500173470ustar00rootroot00000000000000 1 99999 1 1 10 False 12 Insert Subtitles False True dialog 1 True False vertical 12 False False False 0 True False 6 12 True False end _Amount: True amount_spin 0 0 True False end _Position: True position_combo 0 1 True True True True adjustment1 1 True 1 0 True False True 1 1 False True 0 gaupol-1.11/data/ui/language-dialog.ui000066400000000000000000000353421422217132500176360ustar00rootroot00000000000000 False 12 Configure Spell-Check center-on-parent dialog 1 True False vertical 12 False False False 0 True False vertical 12 True False 12 True False vertical 6 True False start Language False False 0 True True etched-in True True False True True True 1 True True 0 True False vertical 12 True False vertical 6 True False start Columns False False 0 True False 12 vertical 6 Check _text column True True False start True True True False False 0 Check t_ranslation column True True False start True True main_radio False False 1 False True 1 False False 0 True False vertical 6 True False start Subtitles False False 0 True False 12 vertical 6 Check c_urrent project True True False start True True True False False 0 Check _all open projects True True False start True True current_radio False False 1 False True 1 False False 1 False False 1 True True 0 True True 1 gaupol-1.11/data/ui/menubar.ui000066400000000000000000000523161422217132500162470ustar00rootroot00000000000000 _File
_New win.new-project _Open… win.open-main-files Open _Translation… win.open-translation-file
Open _Recent
Open R_ecent Translation
_Save win.save-main-document Save _As… win.save-main-document-as Save Trans_lation win.save-translation-document Save Translat_ion As… win.save-translation-document-as
_Close win.close-project _Quit win.quit
_Edit
_Undo win.undo-action _Redo win.redo-action
_Edit Cell win.edit-value Edit _Next Cell win.edit-next-value
Stretc_h
_Start Earlier win.start-earlier S_tart Later win.start-later
E_nd Earlier win.end-earlier En_d Later win.end-later
Set St_art From Video Position win.set-start-from-video-position Set En_d From Video Position win.set-end-from-video-position
_Split Subtitle win.split-subtitle _Merge Subtitles win.merge-subtitles
_Insert Subtitles… win.insert-subtitles Inser_t Subtitle At Video Position win.insert-subtitle-at-video-position Rem_ove Subtitles win.remove-subtitles
Sele_ction
Select _All win.select-all _Invert Selection win.invert-selection
Extend To _Beginning win.extend-selection-to-beginning Extend To _End win.extend-selection-to-end
_Previous From Video Position win.select-previous-from-video-position _Next From Video Position win.select-next-from-video-position
_Preferences win.edit-preferences
_View
Tool_bar win.toggle-main-toolbar _Video Player win.toggle-player
_Layout
_Horizontal win.set-layout HORIZONTAL _Vertical win.set-layout VERTICAL
_Times win.set-edit-mode TIME _Frames win.set-edit-mode FRAME
F_ramerate
2_3.976 fps win.set-framerate FPS_23_976 2_4.000 fps win.set-framerate FPS_24_000 2_5.000 fps win.set-framerate FPS_25_000 2_9.970 fps win.set-framerate FPS_29_970 30.000 fps win.set-framerate FPS_30_000 50.000 fps win.set-framerate FPS_50_000 59.940 fps win.set-framerate FPS_59_940 60.000 fps win.set-framerate FPS_60_000
_Columns
_No. win.toggle-number-column _Start win.toggle-start-column _End win.toggle-end-column _Duration win.toggle-duration-column _Text win.toggle-main-text-column T_ranslation win.toggle-translation-text-column
_Text
Cu_t win.cut-texts _Copy win.copy-texts _Paste win.paste-texts Cl_ear win.clear-texts
_Find And Replace… win.find-and-replace Find _Next win.find-next Find Pre_vious win.find-previous
_Italic win.toggle-italicization _Dialogue win.toggle-dialogue-dashes
Ca_se
_Title win.use-title-case _Sentence win.use-sentence-case _Upper win.use-upper-case _Lower win.use-lower-case
Vi_deo
_Load Video… win.load-video
_Play/Pause win.play-pause Play _Selection win.play-selection
Seek _Previous win.seek-previous Seek _Next win.seek-next
Seek _Backward win.seek-backward Seek _Forward win.seek-forward
S_eek Selection Start win.seek-selection-start See_k Selection End win.seek-selection-end
_Audio
_Language
Volume _Down win.volume-down Volume _Up win.volume-up
T_ools
_Preview win.preview Select _Video… win.select-video-file
_Check Spelling win.check-spelling Co_nfigure Spell-check… win.configure-spell-check C_orrect Texts… win.correct-texts
_Shift Positions… win.shift-positions _Transform Positions… win.transform-positions Adjust _Durations… win.adjust-durations Convert _Framerate… win.convert-framerate
_Append File… win.append-file Spli_t Project… win.split-project
_Projects
_Save All win.save-all-documents Save _All As… win.save-all-documents-as _Close All win.close-all-projects
_Previous win.activate-previous-project _Next win.activate-next-project
_Help
_Documentation win.browse-documentation _Report A Bug win.report-a-bug _About win.view-about-dialog
gaupol-1.11/data/ui/multi-save-dialog.ui000066400000000000000000000213521422217132500201350ustar00rootroot00000000000000 False 12 Save All As False center-on-parent dialog 1 True False vertical 12 False False False 0 True False vertical True False 6 12 True False end Save in _folder: True filechooser_button 0 0 True False end For_mat: True format_combo 0 1 True False end _Encoding: True encoding_combo 0 2 True False end Ne_wlines: True newline_combo 0 3 True False True select-folder Select A Folder 1 0 True False True 1 1 True False True 1 2 True False True 1 3 True False end F_ramerate: True framerate_combo 0 4 True False True 1 4 False True 0 False True 1 gaupol-1.11/data/ui/open-dialog.ui000066400000000000000000000066141422217132500170140ustar00rootroot00000000000000 False 12 True False vertical 6 True False 6 12 True False start _Encoding: True encoding_combo 0 0 True False start Align _method: True align_combo 0 1 True False True 1 0 True False True 1 1 False True 0 gaupol-1.11/data/ui/position-shift-dialog.ui000066400000000000000000000351621422217132500210320ustar00rootroot00000000000000 1000 1 1 10 False 12 Shift Positions False True center-on-parent dialog 1 True False vertical 12 False False False 0 True False vertical 12 True False vertical 6 True False start Shift False False 0 True False 12 vertical 6 True False 12 True False start _Amount: True amount_spin False False 0 True True 1 adjustment1 1 1 False False 1 True False start units False False 2 False True 0 True False start _Preview Changes True True False True False False 0 False True 1 False True 1 False True 0 True False vertical 6 True False start Subtitles False False 0 True False 12 vertical 6 Shift s_elected subtitles True True False start True True True False False 0 Shift su_btitles from selection to end True True False start True True selected_radio False False 1 Shift c_urrent project True True False start True True selected_radio False False 2 Shift all _open projects True True False start True True selected_radio False False 3 False True 1 False True 1 False True 1 gaupol-1.11/data/ui/position-transform-dialog.ui000066400000000000000000000660001422217132500217230ustar00rootroot00000000000000 1 99999 1 1 10 1 99999 1 1 10 False 12 Transform Positions False True center-on-parent dialog 1 True False vertical 12 False False False 0 True False vertical 12 True False vertical 6 True False start First Point False False 0 True False 12 vertical 6 True False 6 12 True False start _Subtitle: True subtitle_spin_1 0 0 True False start C_orrection: True 0 1 True False start 4 Text: 0 2 True True True 1 adjustment1 1 True 1 1 0 True False 12 True False True False False True 0 True False False True 1 1 1 True False True end True 3 1 2 False True 0 True False _Preview Changes True True False True False False 0 False False 1 False True 1 False True 0 True False vertical 6 True False start Second Point False False 0 True False 12 vertical 6 True False 6 12 True False start Su_btitle: True subtitle_spin_2 0 0 True False start Co_rrection: True 0 1 True False start 4 Text: 0 2 True True True 1 adjustment2 1 True 1 1 0 True False True end True 3 1 2 True False 12 True False True False False True 0 True False False True 1 1 1 False True 0 True False Pre_view Changes True True False True False False 0 False False 1 False True 1 False True 1 True False vertical 6 True False start Subtitles False False 0 True False 12 vertical 6 Transform se_lected subtitles True True False start True True True False False 0 Transform c_urrent project True True False start True True selected_radio False False 1 False True 1 False True 2 False True 1 gaupol-1.11/data/ui/preferences-dialog.ui000066400000000000000000002165211422217132500203540ustar00rootroot00000000000000 -9999 9999 0.5 1 9999 1 10 False Preferences center-on-parent True dialog 0 1 True False vertical 12 0 False False False 0 True True True True 0 False True False 12 True True 12 vertical 12 True False vertical 6 True False start Character Encodings False False 0 True False 12 vertical 6 True False start When opening files, try encodings in the following order: True False False 0 Curr_ent locale encoding True True False start True True False False 1 True False vertical 6 True False start _Fallback encodings: True file_tree_view False False 0 True False vertical 260 True True etched-in True True False True True True 0 True False icons False True False list-add-symbolic False True True False list-remove-symbolic False True True False go-up-symbolic False True True False go-down-symbolic False True False True 1 True True 1 True True 2 Aut_o-detection True True False start True True False False 3 True False start Encoding specified in the open dialog will always be tried first. True True False False 4 True True 1 True True 0 True False File False True False start 12 True True 12 vertical 12 True False vertical 6 True False start Font False False 0 True False 12 vertical 6 Use _default theme fixed width font True True False start True True False False 0 True False 12 True False _Editor font: True editor_font_button False False 0 True True False Sans 12 True True 1 True True 1 False True 1 False False 0 True False vertical 6 True False start Line Lengths False False 0 True False 12 vertical 6 _Show line lengths in list cells True True False start True True False False 0 S_how line lengths in editable text fields True True False start True True False False 1 True False 12 True False _Length unit: True editor_length_combo False False 0 True False True True 1 True True 2 False True 1 False False 1 True False vertical 6 True False start Spell-Check False False 0 True False 12 vertical 6 Chec_k spelling as you type True True False start True True False False 0 False True 1 False False 2 1 True False Editor 1 False True False 12 True True 12 vertical 12 True False vertical 6 True False start Fonts False True 0 True False 12 6 12 True False start _Subtitles: True video_subtitle_font_button 0 0 True True True True Sans 12 1 0 2 True False start _Time: True video_time_font_button 0 1 True True True True Sans 12 1 1 2 False True 1 False False 0 True False vertical 6 True False start Colors False True 0 True False 12 6 12 True False start Su_btitles: True video_subtitle_color_button 0 0 True True True start True 1 0 _Use a background behind text True True False start True True True 2 0 True False start Ti_me: True video_time_color_button 0 1 True True True start True 1 1 Us_e a background behind text True True False start True True True 2 1 False True 1 False False 1 True False vertical 6 True False start Seek False True 0 True False 12 12 True False _Length: True video_seek_spin False True 0 True True video_seek_adjustment True False True 1 True False seconds False True 2 False True 1 False False 2 2 True False Video 2 False True False start 12 True True 12 vertical 12 True False vertical 6 True False start Video Player False False 0 True False 12 6 12 True False start _Application: True preview_app_combo 0 0 True False start Co_mmand: True preview_command_entry 0 1 True False True 1 0 True True Fields: $MILLISECONDS $SECONDS $SUBFILE $VIDEOFILE True 1 1 Al_ways use UTF-8 character encoding True True False start True True True 0 2 2 False True 1 False True 0 True False vertical 6 True False start Start Position False False 0 True False 12 12 True False start _Offset: True preview_offset_spin False False 0 True True 0,0 adjustment1 1 1 True False True 1 True False seconds before selection False False 2 False True 1 False True 1 3 True False Preview 3 False True False True True 12 vertical 6 True False vertical True True etched-in True True False True True True 0 True False icons True False preferences-desktop False True True False help-contents False True True False help-about False True False True 1 True True 0 4 True False Extensions 4 False False True 1 gaupol-1.11/data/ui/save-dialog.ui000066400000000000000000000133151422217132500170050ustar00rootroot00000000000000 False 12 True False vertical 12 True False 6 12 True False start For_mat: True format_combo 0 0 True False start _Encoding: True encoding_combo 0 1 True False start Ne_wlines: True newline_combo 0 2 True False True 1 0 True False True 1 1 True False True 1 2 True False start F_ramerate: True framerate_combo 0 3 True False True 1 3 False True 0 gaupol-1.11/data/ui/search-dialog.ui000066400000000000000000000635071422217132500173240ustar00rootroot00000000000000 False 0 center-on-parent dialog 1 True False vertical 12 False False False 0 True False True False 12 vertical 6 True False 12 True False 6 12 True False True True True True in True True 6 6 False -1 0 0 2 True False start _Search for: True pattern_combo_entry 0 1 True False start Replace _with: True replacement_combo_entry 0 2 True False True True True 1 1 True False True True True 1 2 True True 0 True False vertical 6 start Find _Next True True False True False False 0 Find _Previous True True False True False False 1 _Replace True True False True False False 2 Replace _All True True False True False False 3 False True 1 True True 0 True False 12 R_egular expression True True False center True True False False 0 _Ignore case True True False center True True False False 1 False False 1 page0 Find True False 12 vertical 12 True False vertical 6 True False start Columns False False 0 True False 12 vertical 6 Find in _text column True True False start True True False False 0 Find in t_ranslation column True True False start True True False False 1 False True 1 False True 0 True False vertical 6 True False start Subtitles False False 0 True False 12 vertical 6 Find in c_urrent project True True False start True True True False False 0 Find in _all open projects True True False start True True current_radio False False 1 False True 1 False True 1 page1 Target 1 False True 0 True False True True False stack gaupol-1.11/data/ui/spell-check-dialog.ui000066400000000000000000000317341422217132500202460ustar00rootroot00000000000000 False 12 Check Spelling True center-on-parent dialog 1 True False vertical 12 False False False 0 True False True True 6 12 True False vertical 6 start Join _Back True True True True False False 0 Join _Forward True True True True False False 1 _Edit True True True True False False 2 _Ignore True True True True False False 3 Ig_nore All True True True True False False 4 _Replace True True True True False False 5 Rep_lace All True True True True False False 6 _Add True True True True False False 7 2 0 3 True False end start 2 _Suggestions: True tree_view 0 2 True False end Replace _with: True entry 0 1 True True etched-in True True False 6 6 False 0 0 2 True True 1 1 True True True True etched-in True True False True False 1 2 False True 0 gaupol-1.11/data/ui/split-dialog.ui000066400000000000000000000070451422217132500172050ustar00rootroot00000000000000 2 999999 2 1 10 False 12 Split Project False True center-on-parent dialog 1 True False vertical 12 False False False 0 True False 12 True False end _First subtitle of new project: True subtitle_spin False False 0 True True adjustment1 1 True False True 1 False True 1 gaupol-1.11/data/ui/tab-popup.ui000066400000000000000000000012161422217132500165160ustar00rootroot00000000000000
Move Tab _Left win.move-tab-left Move Tab _Right win.move-tab-right
_Close win.close-project
gaupol-1.11/data/ui/text-assistant/000077500000000000000000000000001422217132500172435ustar00rootroot00000000000000gaupol-1.11/data/ui/text-assistant/capitalization-page.ui000066400000000000000000000147511422217132500235370ustar00rootroot00000000000000 False False 12 True False True True vertical 6 True False start S_elect parts to capitalize: True tree_view False True 0 True True etched-in True True False True False True True 1 False 6 12 True False start _Script: True script_combo 0 0 True False start _Language: True language_combo 0 1 True False start Co_untry: True country_combo 0 2 True False True 1 0 True False True 1 1 True False True 1 2 False True 2 gaupol-1.11/data/ui/text-assistant/common-error-page.ui000066400000000000000000000224641422217132500231430ustar00rootroot00000000000000 False False 12 True False True True vertical 6 True False start S_elect errors to correct: True tree_view False True 0 True True etched-in True True False True False True True 1 False 6 12 True False start _Script: True script_combo 0 0 True False start _Language: True language_combo 0 1 True False start Co_untry: True country_combo 0 2 True False start Error types: 0 3 True False True 1 0 True False True 1 1 True False True 1 2 True False 12 _Human errors True True False start True True False True 0 _Image recognition errors True True False start True True False True 1 1 3 False True 2 gaupol-1.11/data/ui/text-assistant/confirmation-page.ui000066400000000000000000000151151422217132500232070ustar00rootroot00000000000000 False False 12 True False True True vertical 6 True False start Acc_ept, discard or edit changes: True tree_view False True 0 True True in True True True False True True 1 True False 12 False 6 start _Mark All True True True True False False 0 _Unmark All True True True True False False 1 _Preview True True False True False False 2 False True 0 _Remove all blank subtitles True True False center True True False True 1 False True 2 gaupol-1.11/data/ui/text-assistant/hearing-impaired-page.ui000066400000000000000000000150321422217132500237220ustar00rootroot00000000000000 False False 12 True False True True vertical 6 True False start S_elect parts to remove: True tree_view False True 0 True True etched-in True True False True False True True 1 True False 6 12 True False start _Script: True script_combo 0 0 True False start _Language: True language_combo 0 1 True False start Co_untry: True country_combo 0 2 True False True 1 2 True False True 1 0 True False True 1 1 False True 2 gaupol-1.11/data/ui/text-assistant/introduction-page.ui000066400000000000000000000136521422217132500232440ustar00rootroot00000000000000 False False 12 True False True True vertical 12 True False vertical 6 True False start _Select corrections to perform on texts: True tree_view False True 0 True True etched-in True True False True True True 1 True True 0 True False 6 12 True False start Colu_mns: True columns_combo 0 0 True False start S_ubtitles: True subtitles_combo 0 1 True False True 1 0 True False True 1 1 False True 1 gaupol-1.11/data/ui/text-assistant/join-split-page.ui000066400000000000000000000170441422217132500226120ustar00rootroot00000000000000 False False 12 True False True True vertical 12 True False vertical 6 True False start Spell-Check Dictionary False True 0 True False 12 12 True False _Language: True language_button False True 0 True True True False True 1 False True 1 False True 0 True False vertical 6 True False start Corrections False True 0 True False 12 vertical 6 _Join words not found in spell-check dictionary True True False start True True False True 0 _Split words not found in spell-check dictionary True True False start True True False True 1 False True 1 False True 1 gaupol-1.11/data/ui/text-assistant/line-break-options-page.ui000066400000000000000000000335151422217132500242250ustar00rootroot00000000000000 1 99 1 1 5 1 999 1 1 5 1 999 1 1 5 1 99 1 1 5 False False 12 True False True True vertical 12 True False vertical 6 True False start Limits False True 0 True False 12 6 12 True False start _Maximum line length: True max_length_spin 0 0 True False start _Preferred maximum amount of lines: True max_lines_spin 0 1 True False 2 1 True True 1 adjustment2 True 1 1 0 True True 1 adjustment1 True 1 1 1 True False 2 0 False True 1 False True 0 True False vertical 6 True False start Subtitles False True 0 True False 12 6 12 _Skip subtitles with maximum line length of: True True False start True True 0 0 S_kip subtitles with maximum line amount of: True True False start True True 0 1 True True 1 adjustment3 True 1 1 0 True True 1 adjustment4 True 1 1 1 True False 2 1 True False 2 0 False True 1 False True 1 gaupol-1.11/data/ui/text-assistant/line-break-page.ui000066400000000000000000000150461422217132500225330ustar00rootroot00000000000000 False False 12 True False True True vertical 6 True False start S_elect preferred line-break points: True tree_view False True 0 True True etched-in True True False True False True True 1 True False 6 12 True False start _Script: True script_combo 0 0 True False start _Language: True language_combo 0 1 True False start Co_untry: True country_combo 0 2 True False True 1 0 True False True 1 2 True False True 1 1 False True 2 gaupol-1.11/data/ui/text-assistant/progress-page.ui000066400000000000000000000065511422217132500223670ustar00rootroot00000000000000 False False 12 True False True True vertical 12 True False start True False True 0 True False False True 1 True False vertical 6 True False start True end False True 0 True False start True end False True 1 False True 2 gaupol-1.11/data/ui/view-popup.ui000066400000000000000000000026101422217132500167210ustar00rootroot00000000000000
_Split Subtitle win.split-subtitle _Merge Subtitles win.merge-subtitles
_Insert Subtitles… win.insert-subtitles Rem_ove Subtitles win.remove-subtitles
Play _Selection win.play-selection S_eek Selection Start win.seek-selection-start
_Preview win.preview
gaupol-1.11/doc/000077500000000000000000000000001422217132500134675ustar00rootroot00000000000000gaupol-1.11/doc/README.md000066400000000000000000000003111422217132500147410ustar00rootroot00000000000000Documentation ============= ## For Users * [Creating Subtitles](creating-subtitles.md) ## For Developers * [API documentation on the aeidon library](https://otsaloma.io/gaupol/doc/api/aeidon.html) gaupol-1.11/doc/creating-subtitles.md000066400000000000000000000062311422217132500176230ustar00rootroot00000000000000Creating Subtitles from Scratch =============================== Gaupol's built-in video player should allow you create subtitles from scratch for a given video and the various tools provided should help if some batch processing is needed. There are many possible work-flows for subtitling – here's one simple approach that can get you started. All the keys referred to below correspond to actions that you can find via the menubar as well, but using the keyboard is necessary to be productive. 1. Open Gaupol and create a blank document: File New. 1. Load the video file you wish to subtitle: Video Load Video. 1. Play the video from start to finish (or maybe a scene at a time, whichever feels more comfortable). Press J whenever someone starts speaking a new subtitle length piece. A new subtitle will be inserted with a three second duration and a placeholder text. 1. To correct for your reaction speed, hit H. If your reaction speed earlier has been e.g. half a second, shift all subtitles -0.5 seconds. If you're working a scene at a time, select the new subtitles and shift only those. 1. Go over the video one subtitle at a time. Press O over and over again to play video of the selected subtitle as you make changes to the subtitle in question. Note that you don't need to wait for the subtitle playback to finish – whenever you hit O again, playback will resume from right before the subtitle start. 1. Write down what is said. Hit S and M to split and merge subtitles where needed to avoid too long or short subtitles, or too long pauses within a subtitle. 1. Use keys Q and W to adjust the subtitle start time so that it matches the video. Keep your right hand on O and alternate between adjustment and play until the match looks good. 1. Play the subtitle with O. Hit K during playback to set the end time of the subtitle. Adjust if needed with keys E and R, similar to the start time. Note that the end time doesn't need to match when speaking ends, but should instead be visible long enough to be read, although limited by the next subtitle or scene change. 1. Once a scene or the whole video is subtitled, if you were not careful to avoid it, you'll notice that short subtitles disappear too fast. You can batch-fix that with Tools Adjust Durations. Set a minimum duration and gap and possibly lengthening to match reading speed to ensure that subtitles remain on screen long enough to be read. Note that automatic lengthening can have adverse effects such as pushing subtitles across a scene change, but for some videos, such as conference presentations, there should be no harm. 1. Done! Save your file! Share your work! The SubRip format is the most common and compatible subtitle file format and thus recommended for most uses, especially if you share your work for a wide audience. gaupol-1.11/flatpak/000077500000000000000000000000001422217132500143445ustar00rootroot00000000000000gaupol-1.11/flatpak/Makefile000066400000000000000000000005701422217132500160060ustar00rootroot00000000000000# -*- coding: utf-8-unix -*- clean: rm -rf build rm -rf .flatpak-builder install: $(MAKE) uninstall rm -rf build .flatpak-builder/build flatpak-builder --install --install-deps-from=flathub build io.otsaloma.gaupol.yml run: flatpak run io.otsaloma.gaupol uninstall: flatpak uninstall -y io.otsaloma.gaupol/x86_64/master || true .PHONY: clean install run uninstall gaupol-1.11/flatpak/io.otsaloma.gaupol.yml000066400000000000000000000073161422217132500206110ustar00rootroot00000000000000app-id: io.otsaloma.gaupol runtime: org.gnome.Platform runtime-version: "3.38" sdk: org.gnome.Sdk command: gaupol finish-args: - --device=dri - --env=GST_PLUGIN_PATH_1_0=/app/lib/gstreamer-1.0 - --filesystem=home - --filesystem=xdg-videos - --share=ipc - --socket=pulseaudio - --socket=wayland - --socket=x11 modules: # Internal video player codecs - name: gst-libav buildsystem: autotools config-opts: # Prefer upstream configuration over what happens to be in the runtime. # https://github.com/flathub/org.gnome.Totem/commit/0c8ed1e25bfad9745ff002b8b3efae3cdd3aebde - --with-system-libav=no sources: - type: archive url: https://gstreamer.freedesktop.org/src/gst-libav/gst-libav-1.16.1.tar.xz sha256: e8a5748ae9a4a7be9696512182ea9ffa6efe0be9b7976916548e9d4381ca61c4 - name: gst-plugins-ugly buildsystem: meson sources: - type: archive url: https://gstreamer.freedesktop.org/src/gst-plugins-ugly/gst-plugins-ugly-1.16.1.tar.xz sha256: 4bf913b2ca5195ac3b53b5e3ade2dc7c45d2258507552ddc850c5fa425968a1d # Spell-check - name: gspell buildsystem: autotools sources: - type: archive url: https://download.gnome.org/sources/gspell/1.9/gspell-1.9.1.tar.xz sha256: dcbb769dfdde8e3c0a8ed3102ce7e661abbf7ddf85df08b29915e92cd723abdd # Character encoding auto-detection - name: chardet buildsystem: simple build-commands: - python3 setup.py install --prefix=/app ensure-writable: - /lib/python3.*/site-packages/easy-install.pth sources: - type: archive url: https://files.pythonhosted.org/packages/fc/bb/a5768c230f9ddb03acc9ef3f0d4a3cf93462473795d18e9535498c8f929d/chardet-3.0.4.tar.gz sha256: 84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae # External video player: mpv - name: ffmpeg buildsystem: autotools sources: - type: archive url: https://ffmpeg.org/releases/ffmpeg-4.1.tar.xz sha256: a38ec4d026efb58506a99ad5cd23d5a9793b4bf415f2c4c2e9c1bb444acd1994 - name: fribidi buildsystem: autotools sources: - type: archive url: https://github.com/fribidi/fribidi/releases/download/v1.0.8/fribidi-1.0.8.tar.bz2 sha256: 94c7b68d86ad2a9613b4dcffe7bbeb03523d63b5b37918bdf2e4ef34195c1e6c - name: libass buildsystem: autotools sources: - type: archive url: https://github.com/libass/libass/releases/download/0.14.0/libass-0.14.0.tar.xz sha256: 881f2382af48aead75b7a0e02e65d88c5ebd369fe46bc77d9270a94aa8fd38a2 - name: uchardet buildsystem: cmake-ninja config-opts: - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_INSTALL_PREFIX=/app sources: - type: archive url: https://www.freedesktop.org/software/uchardet/releases/uchardet-0.0.6.tar.xz sha256: 8351328cdfbcb2432e63938721dd781eb8c11ebc56e3a89d0f84576b96002c61 - name: mpv buildsystem: simple build-commands: - python3 waf configure --prefix=/app - python3 waf build - python3 waf install sources: - type: archive url: https://github.com/mpv-player/mpv/archive/v0.31.0.tar.gz sha256: 805a3ac8cf51bfdea6087a6480c18835101da0355c8e469b6d488a1e290585a5 - type: file # Use the version of waf tested to work with mpv. # https://github.com/mpv-player/mpv/blob/master/bootstrap.py url: https://waf.io/waf-2.0.9 sha256: 2a8e0816f023995e557f79ea8940d322bec18f286917c8f9a6fa2dc3875dfa48 dest-filename: waf # Gaupol - name: gaupol buildsystem: simple build-commands: - python3 setup.py install --prefix=/app sources: - type: git url: https://github.com/otsaloma/gaupol.git gaupol-1.11/gaupol/000077500000000000000000000000001422217132500142115ustar00rootroot00000000000000gaupol-1.11/gaupol/__init__.py000066400000000000000000000077361422217132500163370ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """GTK user interface for the Gaupol subtitle editor.""" __version__ = "1.11" COMBO_SEPARATOR = "" import sys import warnings if hasattr(sys, "frozen"): # Avoid error trying to write to non-existent stderr. # https://stackoverflow.com/a/35773092 warnings.simplefilter("ignore") # Needed for the spell-check dialog, where the '_proceed' function call is # recursive. The recursion limit effectively defines the maximum allowed # amount of consecutive subtitles without spelling errors, which if exceeded # triggers a RecursionError. sys.setrecursionlimit(10000) import aeidon import gi import os # Disable gst-vaapi as it doesn't seem to work with gtksink. # https://github.com/otsaloma/gaupol/issues/79 os.environ["LIBVA_DRIVER_NAME"] = "null" os.environ["LIBVA_DRIVERS_PATH"] = "/dev/null" gi.require_version("Gdk", "3.0") gi.require_version("Gtk", "3.0") for module, version in { "Gst": "1.0", "GstPbutils": "1.0", "GstVideo": "1.0", "GstTag": "1.0", }.items(): with aeidon.util.silent(Exception): gi.require_version(module, version) with aeidon.util.silent(Exception): from gi.repository import Gst Gst.init(None) from gaupol.urls import * # noqa from gaupol import util # noqa from gaupol.enums import * # noqa from gaupol.errors import * # noqa from gaupol.attrdict import * # noqa from gaupol.config import ConfigurationStore # noqa conf = ConfigurationStore() from gaupol import style # noqa from gaupol import ruler # noqa from gaupol.entries import * # noqa from gaupol.renderers import * # noqa from gaupol.floatlabel import * # noqa from gaupol.spell import * # noqa from gaupol.view import * # noqa from gaupol.page import * # noqa from gaupol.player import * # noqa from gaupol.dialogs.builder import * # noqa from gaupol.dialogs.file import * # noqa from gaupol.dialogs.open import * # noqa from gaupol.dialogs.save import * # noqa from gaupol.dialogs.video import * # noqa from gaupol.dialogs.append import * # noqa from gaupol.dialogs.about import * # noqa from gaupol.dialogs.debug import * # noqa from gaupol.dialogs.duration_adjust import * # noqa from gaupol.dialogs.encoding import * # noqa from gaupol.dialogs.framerate_convert import * # noqa from gaupol.dialogs.insert import * # noqa from gaupol.dialogs.language import * # noqa from gaupol.dialogs.message import * # noqa from gaupol.dialogs.multi_close import * # noqa from gaupol.dialogs.multi_save import * # noqa from gaupol.dialogs.preferences import * # noqa from gaupol.dialogs.preview_error import * # noqa from gaupol.dialogs.search import * # noqa from gaupol.dialogs.position_shift import * # noqa from gaupol.dialogs.spell_check import * # noqa from gaupol.dialogs.split import * # noqa from gaupol.dialogs.text_edit import * # noqa from gaupol.dialogs.position_transform import * # noqa from gaupol.assistants import * # noqa from gaupol.action import * # noqa from gaupol import actions # noqa from gaupol.extension import * # noqa from gaupol.extensionman import * # noqa from gaupol import agents # noqa from gaupol.application import * # noqa from gaupol.applicationman import ApplicationManager # noqa from gaupol.unittest import * # noqa def main(args): """Initialize application.""" global appman aeidon.i18n.bind() appman = ApplicationManager(args) raise SystemExit(appman.run()) gaupol-1.11/gaupol/action.py000066400000000000000000000073061422217132500160460ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2015 Osmo Salomaa # # 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 . """Baseclasses for for user-activatable actions.""" import aeidon from gi.repository import Gio from gi.repository import GLib from gi.repository import GObject __all__ = ( "Action", "OpenRecentTranslationFileAction", "RadioAction", "ToggleAction", ) class Action(Gio.SimpleAction): """Baseclass for user-activatable actions.""" def __init__(self, name): """Initialize an :class:`Action` instance.""" GObject.GObject.__init__(self, name=name) self.accelerators = [] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): """Raise :exc:`gaupol.AffirmationError` if action cannot be done.""" pass def update_enabled(self, application, page, selected_rows): """Update the "enabled" property to match `application`.""" try: self._affirm_doable(application, page, selected_rows) self.set_enabled(True) except aeidon.AffirmationError: self.set_enabled(False) class OpenRecentTranslationFileAction(Action): """Baseclass for a dynamic menu of recent translation files to open.""" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(page.project.main_file is not None) class RadioAction(Action): """Baseclass for user-activatable radio actions.""" # Gio's abstraction makes radio action instantiation and # management of string state values look really stupid # in Python. For proper instantiation, subclasses need to # define __new__, call new and assign to __class__. def activate(self, parameter): """Activate action with `parameter`.""" return Gio.SimpleAction.activate(self, GLib.Variant("s", parameter)) @staticmethod def new(name, parameter_type=GLib.VariantType.new("s")): """Return a new radio action.""" return Gio.SimpleAction.new_stateful( name, parameter_type, GLib.Variant("s", "")) def get_state(self): """Return the current string state.""" return Action.get_state(self).get_string() def set_state(self, value): """Set a new string state.""" Action.set_state(self, GLib.Variant("s", value)) class ToggleAction(Action): """Baseclass for user-activatable toggle actions.""" # Gio's abstraction makes toggle action instantiation and # management of boolean state values look really stupid # in Python. For proper instantiation, subclasses need to # define __new__, call new and assign to __class__. @staticmethod def new(name, parameter_type=None): """Return a new toggle action.""" return Gio.SimpleAction.new_stateful( name, parameter_type, GLib.Variant("b", False)) def get_state(self): """Return the current boolean state.""" return Action.get_state(self).get_boolean() def set_state(self, value): """Set a new boolean state.""" Action.set_state(self, GLib.Variant("b", value)) gaupol-1.11/gaupol/actions/000077500000000000000000000000001422217132500156515ustar00rootroot00000000000000gaupol-1.11/gaupol/actions/__init__.py000066400000000000000000000023071422217132500177640ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 . """User-activatable actions for :class:`gaupol.Application`.""" from gaupol.actions.audio import * # noqa from gaupol.actions.edit import * # noqa from gaupol.actions.file import * # noqa from gaupol.actions.help import * # noqa from gaupol.actions.projects import * # noqa from gaupol.actions.text import * # noqa from gaupol.actions.tools import * # noqa from gaupol.actions.video import * # noqa from gaupol.actions.view import * # noqa __all__ = tuple(x for x in dir() if x.endswith("Action")) gaupol-1.11/gaupol/actions/audio.py000066400000000000000000000040741422217132500173310ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2013 Osmo Salomaa # # 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 . """Audio actions for :class:`gaupol.Application`.""" import aeidon import gaupol class SetAudioLanguageAction(gaupol.RadioAction): def __new__(cls): action = gaupol.RadioAction.new("set-audio-language") action.__class__ = cls return action def __init__(self): gaupol.RadioAction.__init__(self, "set-audio-language") self.set_state(str(0)) def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(application.player is not None) aeidon.util.affirm(application.player.ready) class VolumeDownAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "volume-down") self.accelerators = ["minus", "KP_Subtract"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(application.player is not None) aeidon.util.affirm(application.player.ready) class VolumeUpAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "volume-up") self.accelerators = ["plus", "KP_Add"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(application.player is not None) aeidon.util.affirm(application.player.ready) __all__ = tuple(x for x in dir() if x.endswith("Action")) gaupol-1.11/gaupol/actions/edit.py000066400000000000000000000237561422217132500171650ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Simple subtitle data editing actions for :class:`gaupol.Application`.""" import aeidon import gaupol from gi.repository import Gtk class EditPreferencesAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "edit-preferences") self.action_group = "safe" class EditNextValueAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "edit-next-value") self.accelerators = ["space"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) row, col = page.view.get_focus() aeidon.util.affirm(not None in (row, col)) aeidon.util.affirm(row < len(page.project.subtitles) - 1) column = page.view.get_column(col) renderer = column.get_cells()[0] aeidon.util.affirm(renderer.props.mode == Gtk.CellRendererMode.EDITABLE) class EditValueAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "edit-value") self.accelerators = ["Return"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) row, col = page.view.get_focus() aeidon.util.affirm(not None in (row, col)) column = page.view.get_column(col) renderer = column.get_cells()[0] aeidon.util.affirm(renderer.props.mode == Gtk.CellRendererMode.EDITABLE) class EndEarlierAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "end-earlier") self.accelerators = ["E"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(page.project.subtitles) aeidon.util.affirm(len(selected_rows) == 1) class EndLaterAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "end-later") self.accelerators = ["R"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(page.project.subtitles) aeidon.util.affirm(len(selected_rows) == 1) class ExtendSelectionToBeginningAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "extend-selection-to-beginning") self.accelerators = ["Home"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(page.project.subtitles) aeidon.util.affirm(selected_rows) class ExtendSelectionToEndAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "extend-selection-to-end") self.accelerators = ["End"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(page.project.subtitles) aeidon.util.affirm(selected_rows) class InsertSubtitleAtVideoPositionAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "insert-subtitle-at-video-position") self.accelerators = ["J"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(application.player is not None) aeidon.util.affirm(application.player.ready) class InsertSubtitlesAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "insert-subtitles") self.accelerators = ["I"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) if page.project.subtitles: aeidon.util.affirm(selected_rows) class InvertSelectionAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "invert-selection") self.accelerators = ["J"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(page.project.subtitles) class MergeSubtitlesAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "merge-subtitles") self.accelerators = ["M"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(len(selected_rows) > 1) block = list(range(selected_rows[0], selected_rows[-1] + 1)) aeidon.util.affirm(list(selected_rows) == block) class RedoActionAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "redo-action") self.accelerators = ["Z"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(page.project.can_redo()) class RemoveSubtitlesAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "remove-subtitles") self.accelerators = ["Delete"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(selected_rows) class SelectAllAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "select-all") self.accelerators = ["A"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(page.project.subtitles) class SelectNextFromVideoPositionAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "select-next-from-video-position") self.accelerators = ["U"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(page.project.subtitles) aeidon.util.affirm(application.player is not None) aeidon.util.affirm(application.player.ready) class SelectPreviousFromVideoPositionAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "select-previous-from-video-position") self.accelerators = ["Y"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(page.project.subtitles) aeidon.util.affirm(application.player is not None) aeidon.util.affirm(application.player.ready) class SetEndFromVideoPositionAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "set-end-from-video-position") self.accelerators = ["K"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(application.player is not None) aeidon.util.affirm(application.player.ready) aeidon.util.affirm(len(selected_rows) == 1) class SetStartFromVideoPositionAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "set-start-from-video-position") self.accelerators = ["U"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(application.player is not None) aeidon.util.affirm(application.player.ready) aeidon.util.affirm(len(selected_rows) == 1) class SplitSubtitleAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "split-subtitle") self.accelerators = ["S"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(len(selected_rows) == 1) class StartEarlierAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "start-earlier") self.accelerators = ["Q"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(page.project.subtitles) aeidon.util.affirm(len(selected_rows) == 1) class StartLaterAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "start-later") self.accelerators = ["W"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(page.project.subtitles) aeidon.util.affirm(len(selected_rows) == 1) class UndoActionAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "undo-action") self.accelerators = ["Z"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(page.project.can_undo()) __all__ = tuple(x for x in dir() if x.endswith("Action")) gaupol-1.11/gaupol/actions/file.py000066400000000000000000000064731422217132500171540ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """File and project actions for :class:`gaupol.Application`.""" import aeidon import gaupol class CloseProjectAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "close-project") self.accelerators = ["W"] self.action_group = "safe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) class NewProjectAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "new-project") self.accelerators = ["N"] self.action_group = "safe" class OpenMainFilesAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "open-main-files") self.accelerators = ["O"] self.action_group = "safe" class OpenTranslationFileAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "open-translation-file") self.action_group = "safe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(page.project.main_file is not None) class QuitAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "quit") self.accelerators = ["Q"] self.action_group = "safe" class SaveMainDocumentAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "save-main-document") self.accelerators = ["S"] self.action_group = "safe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) class SaveMainDocumentAsAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "save-main-document-as") self.accelerators = ["S"] self.action_group = "safe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) class SaveTranslationDocumentAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "save-translation-document") self.accelerators = ["T"] self.action_group = "safe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) class SaveTranslationDocumentAsAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "save-translation-document-as") self.accelerators = ["T"] self.action_group = "safe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) __all__ = tuple(x for x in dir() if x.endswith("Action")) gaupol-1.11/gaupol/actions/help.py000066400000000000000000000024271422217132500171600ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Help actions for :class:`gaupol.Application`.""" import gaupol class BrowseDocumentationAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "browse-documentation") self.action_group = "safe" class ReportABugAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "report-a-bug") self.action_group = "safe" class ViewAboutDialogAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "view-about-dialog") self.action_group = "safe" __all__ = tuple(x for x in dir() if x.endswith("Action")) gaupol-1.11/gaupol/actions/projects.py000066400000000000000000000073451422217132500200650ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """File and project actions for :class:`gaupol.Application`.""" import aeidon import gaupol class ActivateNextProjectAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "activate-next-project") self.accelerators = ["Page_Down"] self.action_group = "safe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) index = application.pages.index(page) + 1 aeidon.util.affirm(index in range(len(application.pages))) class ActivatePreviousProjectAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "activate-previous-project") self.accelerators = ["Page_Up"] self.action_group = "safe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(application.pages.index(page) > 0) class ActivateProjectAction(gaupol.RadioAction): def __new__(cls): action = gaupol.RadioAction.new("activate-project") action.__class__ = cls return action def __init__(self): gaupol.RadioAction.__init__(self, "activate-project") self.set_state(str(0)) def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(application.pages) class CloseAllProjectsAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "close-all-projects") self.accelerators = ["W"] self.action_group = "safe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(application.pages) class MoveTabLeftAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "move-tab-left") self.action_group = "safe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(application.pages.index(page) > 0) class MoveTabRightAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "move-tab-right") self.action_group = "safe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) index = application.pages.index(page) + 1 aeidon.util.affirm(index in range(len(application.pages))) class SaveAllDocumentsAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "save-all-documents") self.accelerators = ["L"] self.action_group = "safe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(application.pages) class SaveAllDocumentsAsAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "save-all-documents-as") self.action_group = "safe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm([x for x in application.pages if x.project.main_file is not None]) __all__ = tuple(x for x in dir() if x.endswith("Action")) gaupol-1.11/gaupol/actions/text.py000066400000000000000000000153331422217132500172140ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Text formatting actions for :class:`gaupol.Application`.""" import aeidon import gaupol class ClearTextsAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "clear-texts") self.accelerators = ["C"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(selected_rows) col = page.view.get_focus()[1] aeidon.util.affirm(col is not None) aeidon.util.affirm(page.view.is_text_column(col)) class CopyTextsAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "copy-texts") self.accelerators = ["C"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(selected_rows) col = page.view.get_focus()[1] aeidon.util.affirm(col is not None) aeidon.util.affirm(page.view.is_text_column(col)) class CutTextsAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "cut-texts") self.accelerators = ["X"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(selected_rows) col = page.view.get_focus()[1] aeidon.util.affirm(col is not None) aeidon.util.affirm(page.view.is_text_column(col)) class FindAndReplaceAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "find-and-replace") self.accelerators = ["F", "H"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) class FindNextAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "find-next") self.accelerators = ["G"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(application.pattern) class FindPreviousAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "find-previous") self.accelerators = ["G"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(application.pattern) class PasteTextsAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "paste-texts") self.accelerators = ["V"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): """Raise :exc:`aeidon.AffirmationError` if action cannot be done.""" aeidon.util.affirm(page is not None) aeidon.util.affirm(selected_rows) col = page.view.get_focus()[1] aeidon.util.affirm(col is not None) aeidon.util.affirm(page.view.is_text_column(col)) class ToggleDialogDashesAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "toggle-dialogue-dashes") self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(selected_rows) col = page.view.get_focus()[1] aeidon.util.affirm(col is not None) aeidon.util.affirm(page.view.is_text_column(col)) class ToggleItalicizationAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "toggle-italicization") self.accelerators = ["I"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(selected_rows) col = page.view.get_focus()[1] aeidon.util.affirm(col is not None) aeidon.util.affirm(page.view.is_text_column(col)) doc = page.text_column_to_document(col) markup = page.project.get_markup(doc) aeidon.util.affirm(markup is not None) aeidon.util.affirm(markup.italic_tag is not None) class UseLowerCaseAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "use-lower-case") self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(selected_rows) col = page.view.get_focus()[1] aeidon.util.affirm(col is not None) aeidon.util.affirm(page.view.is_text_column(col)) class UseSentenceCaseAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "use-sentence-case") self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(selected_rows) col = page.view.get_focus()[1] aeidon.util.affirm(col is not None) aeidon.util.affirm(page.view.is_text_column(col)) class UseTitleCaseAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "use-title-case") self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(selected_rows) col = page.view.get_focus()[1] aeidon.util.affirm(col is not None) aeidon.util.affirm(page.view.is_text_column(col)) class UseUpperCaseAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "use-upper-case") self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(selected_rows) col = page.view.get_focus()[1] aeidon.util.affirm(col is not None) aeidon.util.affirm(page.view.is_text_column(col)) __all__ = tuple(x for x in dir() if x.endswith("Action")) gaupol-1.11/gaupol/actions/tools.py000066400000000000000000000107201422217132500173630ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Tool actions for :class:`gaupol.Application`.""" import aeidon import gaupol class AdjustDurationsAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "adjust-durations") self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) class AppendFileAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "append-file") self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(len(page.project.subtitles) > 0) class CheckSpellingAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "check-spelling") self.accelerators = ["F7"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(aeidon.SpellChecker.available()) aeidon.util.affirm(gaupol.conf.spell_check.language) class ConfigureSpellCheckAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "configure-spell-check") self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(aeidon.SpellChecker.available()) class ConvertFramerateAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "convert-framerate") self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(page.project.main_file is not None) class CorrectTextsAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "correct-texts") self.accelerators = ["F8"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) class PreviewAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "preview") self.accelerators = ["F5"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(page.project.video_path is not None) if gaupol.conf.preview.use_custom_command: aeidon.util.affirm(gaupol.conf.preview.custom_command) class SelectVideoFileAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "select-video-file") self.action_group = "safe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(page.project.main_file is not None) class ShiftPositionsAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "shift-positions") self.accelerators = ["H"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) class SplitProjectAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "split-project") self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(len(page.project.subtitles) > 1) class TransformPositionsAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "transform-positions") self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(len(page.project.subtitles) > 1) __all__ = tuple(x for x in dir() if x.endswith("Action")) gaupol-1.11/gaupol/actions/video.py000066400000000000000000000103741422217132500173360ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2012 Osmo Salomaa # # 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 . """Video actions for :class:`gaupol.Application`.""" import aeidon import gaupol class LoadVideoAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "load-video") self.accelerators = ["L"] self.action_group = "safe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(gaupol.util.gst_available()) aeidon.util.affirm(page is not None) class PlayPauseAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "play-pause") self.accelerators = ["P"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(application.player is not None) aeidon.util.affirm(application.player.ready) class PlaySelectionAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "play-selection") self.accelerators = ["O"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(application.player is not None) aeidon.util.affirm(application.player.ready) aeidon.util.affirm(selected_rows) class SeekBackwardAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "seek-backward") self.accelerators = ["Left"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(application.player is not None) aeidon.util.affirm(application.player.ready) class SeekForwardAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "seek-forward") self.accelerators = ["Right"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(application.player is not None) aeidon.util.affirm(application.player.ready) class SeekNextAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "seek-next") self.accelerators = ["Right"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(application.player is not None) aeidon.util.affirm(application.player.ready) class SeekPreviousAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "seek-previous") self.accelerators = ["Left"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(application.player is not None) aeidon.util.affirm(application.player.ready) class SeekSelectionEndAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "seek-selection-end") self.accelerators = ["Down"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(application.player is not None) aeidon.util.affirm(application.player.ready) aeidon.util.affirm(selected_rows) class SeekSelectionStartAction(gaupol.Action): def __init__(self): gaupol.Action.__init__(self, "seek-selection-start") self.accelerators = ["Up"] self.action_group = "unsafe" def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(application.player is not None) aeidon.util.affirm(application.player.ready) aeidon.util.affirm(selected_rows) __all__ = tuple(x for x in dir() if x.endswith("Action")) gaupol-1.11/gaupol/actions/view.py000066400000000000000000000141671422217132500172060ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """View actions for :class:`gaupol.Application`.""" import aeidon import gaupol class SetEditModeAction(gaupol.RadioAction): def __new__(cls): action = gaupol.RadioAction.new("set-edit-mode") action.__class__ = cls return action def __init__(self): gaupol.RadioAction.__init__(self, "set-edit-mode") self.accelerators = ["T"] self.set_state(str(gaupol.conf.editor.mode)) def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) class SetFramerateAction(gaupol.RadioAction): def __new__(cls): action = gaupol.RadioAction.new("set-framerate") action.__class__ = cls return action def __init__(self): gaupol.RadioAction.__init__(self, "set-framerate") self.action_group = "unsafe" self.set_state(str(gaupol.conf.editor.framerate)) def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) aeidon.util.affirm(page.project.main_file is not None) class SetLayoutAction(gaupol.RadioAction): def __new__(cls): action = gaupol.RadioAction.new("set-layout") action.__class__ = cls return action def __init__(self): gaupol.RadioAction.__init__(self, "set-layout") self.action_group = "unsafe" self.set_state(str(gaupol.conf.application_window.layout)) def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(application.player is not None) class ToggleDurationColumnAction(gaupol.ToggleAction): def __new__(cls): action = gaupol.ToggleAction.new("toggle-duration-column") action.__class__ = cls return action def __init__(self): gaupol.ToggleAction.__init__(self, "toggle-duration-column") self.action_group = "unsafe" self.set_state(gaupol.fields.DURATION in gaupol.conf.editor.visible_fields) def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) class ToggleEndColumnAction(gaupol.ToggleAction): def __new__(cls): action = gaupol.ToggleAction.new("toggle-end-column") action.__class__ = cls return action def __init__(self): gaupol.ToggleAction.__init__(self, "toggle-end-column") self.action_group = "unsafe" self.set_state(gaupol.fields.END in gaupol.conf.editor.visible_fields) def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) class ToggleMainTextColumnAction(gaupol.ToggleAction): def __new__(cls): action = gaupol.ToggleAction.new("toggle-main-text-column") action.__class__ = cls return action def __init__(self): gaupol.ToggleAction.__init__(self, "toggle-main-text-column") self.action_group = "unsafe" self.set_state(gaupol.fields.MAIN_TEXT in gaupol.conf.editor.visible_fields) def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) class ToggleMainToolbarAction(gaupol.ToggleAction): def __new__(cls): action = gaupol.ToggleAction.new("toggle-main-toolbar") action.__class__ = cls return action def __init__(self): gaupol.ToggleAction.__init__(self, "toggle-main-toolbar") self.action_group = "safe" self.set_state(gaupol.conf.application_window.show_main_toolbar) class ToggleNumberColumnAction(gaupol.ToggleAction): def __new__(cls): action = gaupol.ToggleAction.new("toggle-number-column") action.__class__ = cls return action def __init__(self): gaupol.ToggleAction.__init__(self, "toggle-number-column") self.action_group = "unsafe" self.set_state(gaupol.fields.NUMBER in gaupol.conf.editor.visible_fields) def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) class TogglePlayerAction(gaupol.ToggleAction): def __new__(cls): action = gaupol.ToggleAction.new("toggle-player") action.__class__ = cls return action def __init__(self): gaupol.ToggleAction.__init__(self, "toggle-player") self.action_group = "safe" self.set_state(False) def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(application.player is not None) class ToggleStartColumnAction(gaupol.ToggleAction): def __new__(cls): action = gaupol.ToggleAction.new("toggle-start-column") action.__class__ = cls return action def __init__(self): gaupol.ToggleAction.__init__(self, "toggle-start-column") self.action_group = "unsafe" self.set_state(gaupol.fields.START in gaupol.conf.editor.visible_fields) def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) class ToggleTranslationTextColumnAction(gaupol.ToggleAction): def __new__(cls): action = gaupol.ToggleAction.new("toggle-translation-text-column") action.__class__ = cls return action def __init__(self): gaupol.ToggleAction.__init__(self, "toggle-translation-text-column") self.action_group = "unsafe" self.set_state(gaupol.fields.TRAN_TEXT in gaupol.conf.editor.visible_fields) def _affirm_doable(self, application, page, selected_rows): aeidon.util.affirm(page is not None) __all__ = tuple(x for x in dir() if x.endswith("Action")) gaupol-1.11/gaupol/agents/000077500000000000000000000000001422217132500154725ustar00rootroot00000000000000gaupol-1.11/gaupol/agents/__init__.py000066400000000000000000000025371422217132500176120ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 . """Extension delegates of of :class:`gaupol.Application`.""" from .close import CloseAgent # noqa from .edit import EditAgent # noqa from .format import FormatAgent # noqa from .help import HelpAgent # noqa from .menu import MenuAgent # noqa from .open import OpenAgent # noqa from .preview import PreviewAgent # noqa from .save import SaveAgent # noqa from .search import SearchAgent # noqa from .tools import ToolsAgent # noqa from .update import UpdateAgent # noqa from .util import UtilityAgent # noqa from .video import VideoAgent # noqa from .view import ViewAgent # noqa __all__ = tuple(x for x in dir() if x.endswith("Agent")) gaupol-1.11/gaupol/agents/close.py000066400000000000000000000133361422217132500171570ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Closing pages and quitting Gaupol.""" import aeidon import gaupol import os from aeidon.i18n import _ from gi.repository import Gtk class CloseAgent(aeidon.Delegate): """Closing pages and quitting Gaupol.""" @aeidon.deco.export def close(self, page, confirm=True): """Close `page` after asking to save its documents.""" if confirm: self._confirm_close(page) if not page in self.pages: return index = self.pages.index(page) if self.notebook.get_current_page() == index: self.notebook.next_page() self.notebook.remove_page(index) self.pages.remove(page) self.update_gui() self.emit("page-closed", page) @aeidon.deco.export def close_all(self, confirm=True): """Close all pages after asking to save their documents.""" if confirm and sum(len(self._need_confirmation( x)) for x in self.pages) > 1: return self._confirm_close_multiple(tuple(self.pages)) while self.pages: self.close(self.pages[-1], confirm=confirm) def _confirm_close(self, page): """Close `page` after asking to save its documents.""" docs = self._need_confirmation(page) if len(docs) == 0: return if len(docs) == 1: self._confirm_close_document(page, docs[0]) if len(docs) > 1: self._confirm_close_multiple((page,)) def _confirm_close_document(self, page, doc): """Close `page` after asking to save `doc`.""" title = _('Save changes to document "{}" before closing?') title = title.format(page.get_basename(doc)) message = _("If you don't save, changes will be permanently lost.") dialog = gaupol.WarningDialog(self.window, title, message) dialog.add_button(_("Close _Without Saving"), Gtk.ResponseType.NO) dialog.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) dialog.add_button(_("_Save"), Gtk.ResponseType.YES) dialog.set_default_response(Gtk.ResponseType.YES) response = gaupol.util.flash_dialog(dialog) gaupol.util.raise_default(not response in ( Gtk.ResponseType.YES, Gtk.ResponseType.NO)) if response == Gtk.ResponseType.YES: self.save(page, doc) def _confirm_close_multiple(self, pages): """Close `pages` after asking to save their documents.""" dialog = gaupol.MultiCloseDialog(self.window, self, pages) response = gaupol.util.flash_dialog(dialog) gaupol.util.raise_default(not response in ( Gtk.ResponseType.YES, Gtk.ResponseType.NO)) def _need_confirmation(self, page): """Return documents in `page` with unsaved changes.""" docs = [] if page.project.main_changed: docs.append(aeidon.documents.MAIN) elif page.project.main_file is not None: if not os.path.isfile(page.project.main_file.path): docs.append(aeidon.documents.MAIN) if page.project.tran_changed: docs.append(aeidon.documents.TRAN) elif page.project.tran_file is not None: if not os.path.isfile(page.project.tran_file.path): docs.append(aeidon.documents.TRAN) return tuple(docs) @aeidon.deco.export @aeidon.deco.silent(gaupol.Default) def _on_close_all_projects_activate(self, *args): """Close all open projects.""" self.close_all() @aeidon.deco.export @aeidon.deco.silent(gaupol.Default) def _on_close_project_activate(self, *args): """Close project.""" self.close(self.get_current_page()) @aeidon.deco.export @aeidon.deco.silent(gaupol.Default) def _on_page_close_request(self, page, *args): """Close project.""" self.close(page) @aeidon.deco.export @aeidon.deco.silent(gaupol.Default) def _on_quit_activate(self, *args): """Quit Gaupol.""" self.quit() @aeidon.deco.export def _on_window_delete_event(self, *args): """Quit Gaupol.""" try: self.quit() except gaupol.Default: pass # Let appman destroy the window if confirmation given # and once any events being processed have completed. # https://github.com/otsaloma/gaupol/issues/54 return True @aeidon.deco.export def quit(self, confirm=True): """Quit Gaupol.""" self.emit("quit") if confirm and sum(len(self._need_confirmation( x)) for x in self.pages) > 1: self._confirm_close_multiple(tuple(self.pages)) elif confirm: for page in self.pages: if self._need_confirmation(page): self._confirm_close(page) self.extension_manager.teardown_extensions() if not gaupol.conf.application_window.maximized: conf = gaupol.conf.application_window conf.size = list(self.window.get_size()) conf.position = list(self.window.get_position()) if hasattr(gaupol, "appman"): gaupol.appman.remove_window(self.window) gaupol-1.11/gaupol/agents/edit.py000066400000000000000000000451121422217132500167740ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Editing subtitle data.""" import aeidon import bisect import gaupol from aeidon.i18n import _, n_ class EditAgent(aeidon.Delegate): """Editing subtitle data.""" def __init__(self, master): """Initialize an :class:`EditAgent` instance.""" aeidon.Delegate.__init__(self, master) self._pref_dialog = None self._revert_in_progress = False @aeidon.deco.export def _on_clear_texts_activate(self, *args): """Clear the selected texts.""" page = self.get_current_page() rows = page.view.get_selected_rows() col = page.view.get_focus()[1] doc = page.text_column_to_document(col) page.project.clear_texts(rows, doc) @aeidon.deco.export def _on_copy_texts_activate(self, *args): """Copy the selected texts to the clipboard.""" page = self.get_current_page() rows = page.view.get_selected_rows() col = page.view.get_focus()[1] doc = page.text_column_to_document(col) page.project.copy_texts(rows, doc) self._sync_clipboards(page) @aeidon.deco.export def _on_cut_texts_activate(self, *args): """Cut the selected texts to the clipboard.""" page = self.get_current_page() rows = page.view.get_selected_rows() col = page.view.get_focus()[1] doc = page.text_column_to_document(col) page.project.cut_texts(rows, doc) self._sync_clipboards(page) @aeidon.deco.export def _on_edit_next_value_activate(self, *args): """Edit the focused column of the next subtitle.""" page = self.get_current_page() path, column = page.view.get_cursor() row = gaupol.util.tree_path_to_row(path) path = gaupol.util.tree_row_to_path(row + 1) page.view.set_cursor(path, column, True) @aeidon.deco.export def _on_edit_preferences_activate(self, *args): """Configure Gaupol.""" if self._pref_dialog is not None: return self._pref_dialog.present() self._pref_dialog = gaupol.PreferencesDialog(self.window, self) aeidon.util.connect(self, "_pref_dialog", "response") self._pref_dialog.show() @aeidon.deco.export def _on_edit_value_activate(self, *args): """Edit the focused cell.""" page = self.get_current_page() path, column = page.view.get_cursor() page.view.set_cursor(path, column, True) @aeidon.deco.export def _on_end_earlier_activate(self, *args): """End the selected subtitle earlier.""" page = self.get_current_page() row = page.view.get_selected_rows()[0] pos = page.project.subtitles[row].end_seconds length = gaupol.conf.editor.stretch_length value = ((pos-0.001) // length) * length page.project.set_end(row, value) register = aeidon.registers.DO description = _("Stretching end position") page.project.set_action_description(register, description) # Group repeated stretches as one action. if (len(page.project.undoables) > 1 and page.project.undoables[1].description == page.project.undoables[0].description): page.project.group_actions(register, 2, description) @aeidon.deco.export def _on_end_later_activate(self, *args): """End the selected subtitle later.""" page = self.get_current_page() row = page.view.get_selected_rows()[0] pos = page.project.subtitles[row].end_seconds length = gaupol.conf.editor.stretch_length value = (((pos + 0.001) // length) + 1) * length page.project.set_end(row, value) register = aeidon.registers.DO description = _("Stretching end position") page.project.set_action_description(register, description) # Group repeated stretches as one action. if (len(page.project.undoables) > 1 and page.project.undoables[1].description == page.project.undoables[0].description): page.project.group_actions(register, 2, description) @aeidon.deco.export def _on_extend_selection_to_beginning_activate(self, *args): """Extend the selection up to the first subtitle.""" page = self.get_current_page() row = page.view.get_selected_rows()[-1] rows = list(range(0, row + 1)) page.view.select_rows(rows) @aeidon.deco.export def _on_extend_selection_to_end_activate(self, *args): """Extend the selection up to the last subtitle.""" page = self.get_current_page() row = page.view.get_selected_rows()[0] rows = list(range(row, len(page.project.subtitles))) page.view.select_rows(rows) @aeidon.deco.export def _on_insert_subtitle_at_video_position_activate(self, *args): """Insert a new subtitle at video position.""" mode = aeidon.modes.SECONDS pos = self.player.get_position(mode) if pos is None: return page = self.get_current_page() starts = [x.start_seconds for x in page.project.subtitles] index = bisect.bisect_right(starts, pos) subtitle = page.project.new_subtitle() subtitle.start_seconds = pos subtitle.end_seconds = pos + 3.0 subtitle.main_text = "[{:d}]".format(index + 1) page.project.insert_subtitles((index,), (subtitle,)) @aeidon.deco.export def _on_insert_subtitles_activate(self, *args): """Insert subtitles.""" dialog = gaupol.InsertDialog(self.window, self) gaupol.util.flash_dialog(dialog) @aeidon.deco.export def _on_invert_selection_activate(self, *args): """Invert the current selection.""" page = self.get_current_page() rows = set(range(0, len(page.project.subtitles))) rows -= set(page.view.get_selected_rows()) page.view.select_rows(rows) @aeidon.deco.export def _on_merge_subtitles_activate(self, *args): """Merge the selected subtitles.""" page = self.get_current_page() rows = page.view.get_selected_rows() page.project.merge_subtitles(rows) @aeidon.deco.export def _on_paste_texts_activate(self, *args): """Paste texts from the clipboard.""" page = self.get_current_page() text = self.x_clipboard.wait_for_text() if text: # Update all clipboards in case text is being # copied from the external clipboard. page.project.clipboard.set_string(text) self._sync_clipboards(page) if page.project.clipboard.is_empty(): return rows = page.view.get_selected_rows() row, col = page.view.get_focus() doc = page.text_column_to_document(col) length = len(page.project.subtitles) # Ensure that even if new subtitles need to be inserted, # focus and scroll position are not moved to the end. rect = page.view.get_visible_rect() window = page.view.get_bin_window() window.freeze_updates() rows = page.project.paste_texts(rows[0], doc) rows = page.view.get_selected_rows() page.view.set_focus(row, col) page.view.select_rows(rows) page.view.scroll_to_point(rect.x, rect.y) window.thaw_updates() count = len(page.project.subtitles) - length if count <= 0: return self.flash_message(n_( "Inserted {:d} subtitle to fit clipboard contents", "Inserted {:d} subtitles to fit clipboard contents", count).format(count)) def _on_pref_dialog_response(self, *args): """Destroy the preferences dialog.""" self._pref_dialog.destroy() self._pref_dialog = None gaupol.conf.write_to_file() @aeidon.deco.export def _on_project_action_done(self, *args): """Update user interface and send a signal.""" page = self.get_current_page() self.update_gui() self.emit("page-changed", page) @aeidon.deco.export def _on_project_action_redone(self, *args): """Update user interface and send a signal.""" page = self.get_current_page() row = page.view.get_focus()[0] if row is not None: page.view.scroll_to_row(row) self.update_gui() self.emit("page-changed", page) @aeidon.deco.export def _on_project_action_undone(self, *args): """Update user interface and send a signal.""" page = self.get_current_page() row = page.view.get_focus()[0] if row is not None: page.view.scroll_to_row(row) self.update_gui() self.emit("page-changed", page) @aeidon.deco.export def _on_redo_action_activate(self, *args): """Redo the last undone action.""" self.redo() @aeidon.deco.export def _on_remove_subtitles_activate(self, *args): """Remove the selected subtitles.""" page = self.get_current_page() rows = page.view.get_selected_rows() page.project.remove_subtitles(rows) @aeidon.deco.export def _on_select_all_activate(self, *args): """Select all subtitles.""" page = self.get_current_page() selection = page.view.get_selection() selection.select_all() @aeidon.deco.export def _on_select_previous_from_video_position_activate(self, *args): """Select the previous subtitle from video position.""" mode = aeidon.modes.SECONDS pos = self.player.get_position(mode) if pos is None: return page = self.get_current_page() for i, subtitle in reversed(list(enumerate(page.project.subtitles))): if subtitle.start_seconds < pos: page.view.select_rows([i]) page.view.scroll_to_row([i]) return # Select the first subtitle, if nothing previous. page.view.select_rows([0]) page.view.scroll_to_row([0]) @aeidon.deco.export def _on_select_next_from_video_position_activate(self, *args): """Select the next subtitle from video position.""" mode = aeidon.modes.SECONDS pos = self.player.get_position(mode) if pos is None: return page = self.get_current_page() for i, subtitle in enumerate(page.project.subtitles): if subtitle.start_seconds > pos: page.view.select_rows([i]) page.view.scroll_to_row([i]) return # Select the last subtitle, if nothing next. last = len(page.project.subtitles) - 1 page.view.select_rows([last]) page.view.scroll_to_row([last]) @aeidon.deco.export def _on_set_end_from_video_position_activate(self, *args): """Set subtitle end from video position.""" page = self.get_current_page() mode = aeidon.modes.SECONDS row = page.view.get_selected_rows()[0] pos = self.player.get_position(mode) if pos is None: return page.project.set_end(row, pos) @aeidon.deco.export def _on_set_start_from_video_position_activate(self, *args): """Set subtitle start from video position.""" page = self.get_current_page() mode = aeidon.modes.SECONDS row = page.view.get_selected_rows()[0] pos = self.player.get_position(mode) if pos is None: return page.project.set_start(row, pos) @aeidon.deco.export def _on_split_subtitle_activate(self, *args): """Split the selected subtitle.""" page = self.get_current_page() row = page.view.get_selected_rows()[0] page.project.split_subtitle(row) @aeidon.deco.export def _on_start_earlier_activate(self, *args): """Start the selected subtitle earlier.""" page = self.get_current_page() row = page.view.get_selected_rows()[0] pos = page.project.subtitles[row].start_seconds length = gaupol.conf.editor.stretch_length value = ((pos-0.001) // length) * length page.project.set_start(row, value) register = aeidon.registers.DO description = _("Stretching start position") page.project.set_action_description(register, description) # Group repeated stretches as one action. if (len(page.project.undoables) > 1 and page.project.undoables[1].description == page.project.undoables[0].description): page.project.group_actions(register, 2, description) @aeidon.deco.export def _on_start_later_activate(self, *args): """Start the selected subtitle later.""" page = self.get_current_page() row = page.view.get_selected_rows()[0] pos = page.project.subtitles[row].start_seconds length = gaupol.conf.editor.stretch_length value = (((pos + 0.001) // length) + 1) * length page.project.set_start(row, value) register = aeidon.registers.DO description = _("Stretching start position") page.project.set_action_description(register, description) # Group repeated stretches as one action. if (len(page.project.undoables) > 1 and page.project.undoables[1].description == page.project.undoables[0].description): page.project.group_actions(register, 2, description) @aeidon.deco.export def _on_undo_action_activate(self, *args): """Undo the last action.""" self.undo() @aeidon.deco.export def _on_view_renderer_edited(self, renderer, path, value, column): """Save changes made while editing cell.""" self._set_unsafe_enabled(True) self.show_message(None) page = self.get_current_page() row = gaupol.util.tree_path_to_row(path) col = page.view.get_columns().index(column) if page.view.is_position_column(col): if not value: return if page.edit_mode == aeidon.modes.FRAME: with aeidon.util.silent(ValueError): value = aeidon.as_frame(value) if col == page.view.columns.START: return page.project.set_start(row, value) if col == page.view.columns.END: return page.project.set_end(row, value) if col == page.view.columns.DURATION: if page.edit_mode == aeidon.modes.TIME: value = value.replace(",", ".") with aeidon.util.silent(ValueError): value = aeidon.as_seconds(value) return page.project.set_duration(row, value) doc = page.text_column_to_document(col) page.project.set_text(row, doc, value) self.update_gui() @aeidon.deco.export def _on_view_renderer_editing_canceled(self, *args): """Unset state set for editing cell.""" self._set_unsafe_enabled(True) self.show_message(None) self.update_gui() @aeidon.deco.export def _on_view_renderer_editing_started(self, renderer, editor, path, column): """Set proper state for editing cell.""" self._set_unsafe_enabled(False) page = self.get_current_page() col = page.view.get_columns().index(column) if not page.view.is_text_column(col): return self._set_global_italicize(page, col) start, end = page.view.get_visible_range() end = gaupol.util.tree_path_to_row(end) if gaupol.util.tree_path_to_row(path) < end - 1: # Don't show help text if it would overlap with text being edited. self.show_message(_("Use Shift+Return for line-break")) @aeidon.deco.export def redo(self, count=1): """Redo `count` amount of actions.""" # Avoid problems if holding down Ctrl+Shift+Z. if self._revert_in_progress: return self._revert_in_progress = True try: gaupol.util.set_cursor_busy(self.window) page = self.get_current_page() # Make sure the UI is given time to update # after the previous redone action. gaupol.util.iterate_main() if page.project.can_redo(count): page.project.redo(count) gaupol.util.set_cursor_normal(self.window) finally: self._revert_in_progress = False def _set_global_italicize(self, page, col): """Set global function to italicize text.""" # MultilineCellRenderer's CellTextView needs to know how # to italicize text. Pass ugly via a global function. gaupol.italic_tag = None gaupol.italicize = None if col is None: return if not page.view.is_text_column(col): return doc = page.text_column_to_document(col) markup = page.project.get_markup(doc) if markup is None: return if markup.italic_tag is None: return gaupol.italic_tag = markup.italic_tag gaupol.italicize = markup.italicize def _set_unsafe_enabled(self, enabled): """Set enabled states of unsafe actions.""" for name in self.window.list_actions(): action = self.get_action(name) if action.action_group == "unsafe": action.set_enabled(enabled) def _sync_clipboards(self, page): """Synchronize all clipboards to match that of `page`.""" texts = page.project.clipboard.get_texts() self.clipboard.set_texts(texts) for item in self.pages: item.project.clipboard.set_texts(texts) text = page.project.clipboard.get_string() self.x_clipboard.set_text(text, -1) self.update_gui() @aeidon.deco.export def undo(self, count=1): """Undo `count` amount of actions.""" # Avoid problems if holding down Ctrl+Z. if self._revert_in_progress: return self._revert_in_progress = True try: gaupol.util.set_cursor_busy(self.window) page = self.get_current_page() # Make sure the UI is given time to update # after the previous undone action. gaupol.util.iterate_main() if page.project.can_undo(count): page.project.undo(count) gaupol.util.set_cursor_normal(self.window) finally: self._revert_in_progress = False gaupol-1.11/gaupol/agents/format.py000066400000000000000000000056251422217132500173440ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Formatting text.""" import aeidon class FormatAgent(aeidon.Delegate): """Formatting text.""" @aeidon.deco.export def _on_toggle_dialogue_dashes_activate(self, *args): """Add or remove dialogue dashes on the selected texts.""" page = self.get_current_page() rows = page.view.get_selected_rows() col = page.view.get_focus()[1] doc = page.text_column_to_document(col) page.project.toggle_dialogue_dashes(rows, doc) @aeidon.deco.export def _on_toggle_italicization_activate(self, *args): """Italicize or unitalicize the selected texts.""" page = self.get_current_page() rows = page.view.get_selected_rows() col = page.view.get_focus()[1] doc = page.text_column_to_document(col) page.project.toggle_italicization(rows, doc) @aeidon.deco.export def _on_use_lower_case_activate(self, *args): """Change the selected texts to lower case.""" page = self.get_current_page() rows = page.view.get_selected_rows() col = page.view.get_focus()[1] doc = page.text_column_to_document(col) page.project.change_case(rows, doc, "lower") @aeidon.deco.export def _on_use_sentence_case_activate(self, *args): """Change the selected texts to sentence case.""" page = self.get_current_page() rows = page.view.get_selected_rows() col = page.view.get_focus()[1] doc = page.text_column_to_document(col) page.project.change_case(rows, doc, "capitalize") @aeidon.deco.export def _on_use_title_case_activate(self, *args): """Change the selected texts to title case.""" page = self.get_current_page() rows = page.view.get_selected_rows() col = page.view.get_focus()[1] doc = page.text_column_to_document(col) page.project.change_case(rows, doc, "title") @aeidon.deco.export def _on_use_upper_case_activate(self, *args): """Change the selected texts to upper case.""" page = self.get_current_page() rows = page.view.get_selected_rows() col = page.view.get_focus()[1] doc = page.text_column_to_document(col) page.project.change_case(rows, doc, "upper") gaupol-1.11/gaupol/agents/help.py000066400000000000000000000025431422217132500170000ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Help and information.""" import aeidon import gaupol class HelpAgent(aeidon.Delegate): """Help and information.""" @aeidon.deco.export def _on_browse_documentation_activate(self, *args): """Open web browser to view documentation.""" gaupol.util.show_uri(gaupol.DOCUMENTATION_URL) @aeidon.deco.export def _on_report_a_bug_activate(self, *args): """Open web browser to submit a bug report.""" gaupol.util.show_uri(gaupol.BUG_REPORT_URL) @aeidon.deco.export def _on_view_about_dialog_activate(self, *args): """Show information about Gaupol.""" gaupol.util.flash_dialog(gaupol.AboutDialog(self.window)) gaupol-1.11/gaupol/agents/menu.py000066400000000000000000000340661422217132500170210ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Building and updating dynamic menus.""" import aeidon import gaupol import os import sys from aeidon.i18n import _ from gi.repository import Gtk class MenuAgent(aeidon.Delegate): """Building and updating dynamic menus.""" def __init__(self, master): """Initialize a :class:`MenuAgent` instance.""" aeidon.Delegate.__init__(self, master) self._columns_popup = None self._redo_menu_items = [] self._tab_popup = None self._undo_menu_items = [] self._view_popup = None self._init_signal_handlers() @aeidon.deco.once def _get_recent_chooser_menu(self): """Return a new recent chooser menu.""" menu = Gtk.RecentChooserMenu() menu.set_show_icons(sys.platform != "win32") # Can be really slow with network drives. # https://github.com/otsaloma/gaupol/issues/175 menu.set_show_not_found(gaupol.conf.recent.show_not_found) menu.set_show_numbers(False) menu.set_show_tips(True) menu.set_sort_type(Gtk.RecentSortType.MRU) menu.connect("item-activated", self._on_recent_menu_item_activated) def custom_filter(info, user_data=None): application = "gaupol" in info.applications mime_type = info.mime_type in [x.mime_type for x in aeidon.formats] return bool(application and mime_type) recent_filter = Gtk.RecentFilter() flags = Gtk.RecentFilterFlags.APPLICATION | Gtk.RecentFilterFlags.MIME_TYPE recent_filter.add_custom(flags, custom_filter) menu.add_filter(recent_filter) menu.set_filter(recent_filter) menu.set_limit(10) return menu def _init_signal_handlers(self): """Initialize signal handlers.""" self.connect("page-added", self._update_projects_menu) self.connect("page-closed", self._update_projects_menu) self.connect("page-saved", self._update_projects_menu) self.connect("page-switched", self._update_projects_menu) self.connect("pages-reordered", self._update_projects_menu) self.connect("init-done", self._update_recent_menus) self.connect("page-added", self._update_recent_menus) self.connect("page-saved", self._update_recent_menus) @aeidon.deco.export def _on_activate_project_activate(self, action, parameter): """Activate the requested page.""" index = int(parameter.get_string()) self.set_current_page(self.pages[index]) @aeidon.deco.export def _on_open_button_show_menu(self, *args): """Show a menu listing recent files to open.""" menu = self._get_recent_chooser_menu() self.open_button.set_menu(menu) @aeidon.deco.export def _on_open_recent_main_file_activate(self, action, *args): """Open recent file as main document.""" if not os.path.isfile(action.gaupol_path): return self.flash_message(_("File not found")) self.open_main(action.gaupol_path) def _on_recent_menu_item_activated(self, chooser, *args): """Open recent file as main document.""" uri = chooser.get_current_uri() path = aeidon.util.uri_to_path(uri) self.open_button.get_menu().deactivate() if not os.path.isfile(path): return self.flash_message(_("File not found")) self.open_main(path) @aeidon.deco.export def _on_open_recent_translation_file_activate(self, action, *args): """Open recent file as translation document.""" if not os.path.isfile(action.gaupol_path): return self.flash_message(_("File not found")) self.open_translation(action.gaupol_path) @aeidon.deco.export def _on_redo_button_show_menu(self, *args): """Show a menu listing all redoable actions.""" if not self.redo_button.get_menu(): self.redo_button.set_menu(Gtk.Menu()) menu = self.redo_button.get_menu() for item in menu.get_children(): menu.remove(item) self._redo_menu_items = [] redoables = [] with aeidon.util.silent(AttributeError): # XXX: Gtk.Actionable.set_action_name doesn't affect the dropdown # arrow making it clickable even when there's nothing to redo. page = self.get_current_page() redoables = page.project.redoables for i, action in enumerate(redoables): item = Gtk.MenuItem(label=action.description) item.gaupol_index = i item.connect("activate", self._on_redo_menu_item_activate) item.connect("enter-notify-event", self._on_redo_menu_item_enter_notify_event) item.connect("leave-notify-event", self._on_redo_menu_item_leave_notify_event) self._redo_menu_items.append(item) menu.append(item) menu.show_all() self.redo_button.set_menu(menu) def _on_redo_menu_item_activate(self, menu_item): """Redo the selected action and all those above it.""" self.redo(menu_item.gaupol_index + 1) self.redo_button.get_menu().deactivate() def _on_redo_menu_item_enter_notify_event(self, menu_item, event): """Select all actions above `menu_item`.""" index = menu_item.gaupol_index for item in self._redo_menu_items[:index]: item.set_state(Gtk.StateType.PRELIGHT) def _on_redo_menu_item_leave_notify_event(self, menu_item, event): """Unselect all actions above `menu_item`.""" index = menu_item.gaupol_index for item in self._redo_menu_items[:index]: item.set_state(Gtk.StateType.NORMAL) @aeidon.deco.export def _on_tab_widget_button_press_event(self, button, event, page): """Display a pop-up menu with tab-related actions.""" if event.button != 3: return if self._tab_popup is None: path = os.path.join(aeidon.DATA_DIR, "ui", "tab-popup.ui") builder = Gtk.Builder.new_from_file(path) self._tab_popup = builder.get_object("tab-popup") menu = Gtk.Menu.new_from_model(self._tab_popup) menu.attach_to_widget(self.notebook, None) menu.popup(parent_menu_shell=None, parent_menu_item=None, func=None, data=None, button=event.button, activate_time=event.time) return True @aeidon.deco.export def _on_undo_button_show_menu(self, *args): """Show a menu listing all undoable actions.""" if not self.undo_button.get_menu(): self.undo_button.set_menu(Gtk.Menu()) menu = self.undo_button.get_menu() for item in menu.get_children(): menu.remove(item) self._undo_menu_items = [] undoables = [] with aeidon.util.silent(AttributeError): # XXX: Gtk.Actionable.set_action_name doesn't affect the dropdown # arrow making it clickable even when there's nothing to undo. page = self.get_current_page() undoables = page.project.undoables for i, action in enumerate(undoables): item = Gtk.MenuItem(label=action.description) item.gaupol_index = i item.connect("activate", self._on_undo_menu_item_activate) item.connect("enter-notify-event", self._on_undo_menu_item_enter_notify_event) item.connect("leave-notify-event", self._on_undo_menu_item_leave_notify_event) self._undo_menu_items.append(item) menu.append(item) menu.show_all() self.undo_button.set_menu(menu) def _on_undo_menu_item_activate(self, menu_item): """Undo the selected action and all those above it.""" self.undo(menu_item.gaupol_index + 1) self.undo_button.get_menu().deactivate() def _on_undo_menu_item_enter_notify_event(self, menu_item, event): """Select all actions above `menu_item`.""" index = menu_item.gaupol_index for item in self._undo_menu_items[:index]: item.set_state(Gtk.StateType.PRELIGHT) def _on_undo_menu_item_leave_notify_event(self, menu_item, event): """Unselect all actions above `menu_item`.""" index = menu_item.gaupol_index for item in self._undo_menu_items[:index]: item.set_state(Gtk.StateType.NORMAL) @aeidon.deco.export def _on_view_button_press_event(self, view, event): """Display a right-click pop-up menu to edit data.""" if event.button != 3: return x = int(event.x) y = int(event.y) value = view.get_path_at_pos(x, y) if value is None: return path, column, x, y = value row = gaupol.util.tree_path_to_row(path) if not row in view.get_selected_rows(): view.set_cursor(path, column) view.update_headers() if self._view_popup is None: path = os.path.join(aeidon.DATA_DIR, "ui", "view-popup.ui") builder = Gtk.Builder.new_from_file(path) self._view_popup = builder.get_object("view-popup") menu = Gtk.Menu.new_from_model(self._view_popup) menu.attach_to_widget(view, None) menu.popup(parent_menu_shell=None, parent_menu_item=None, func=None, data=None, button=event.button, activate_time=event.time) return True @aeidon.deco.export def _on_view_header_button_press_event(self, button, event): """Display a column visibility pop-up menu.""" if event.button != 3: return if self._columns_popup is None: path = os.path.join(aeidon.DATA_DIR, "ui", "columns-popup.ui") builder = Gtk.Builder.new_from_file(path) self._columns_popup = builder.get_object("columns-popup") menu = Gtk.Menu.new_from_model(self._columns_popup) menu.attach_to_widget(self.get_current_page().view, None) menu.popup(parent_menu_shell=None, parent_menu_item=None, func=None, data=None, button=event.button, activate_time=event.time) return True def _update_projects_menu(self, *args): """Update the project menu list of projects.""" menu = self.get_menubar_section("projects-placeholder") # Menubar not available when running unit tests. if menu is None: return menu.remove_all() current = self.get_current_page() for i, page in enumerate(self.pages): label = page.get_main_basename() if len(label) > 100: label = label[:100] + "…" action = "win.activate-project::{:d}".format(i) menu.append(label, action) if page is current: action = self.get_action("activate-project") action.set_state(str(i)) def _update_recent_main_menu(self, *args): """Update the file menu list of recent main files.""" menu = self.get_menubar_section("open-recent-main-placeholder") # Menubar not available when running unit tests. if menu is None: return menu.remove_all() recent = self._get_recent_chooser_menu() for i, uri in enumerate(recent.get_uris()): path = aeidon.util.uri_to_path(uri) label = os.path.basename(path) if len(label) > 100: label = label[:100] + "…" action = "win.open-recent-main-file-{:d}".format(i) menu.append(label, action) action = action.replace("win.", "") if self.get_action(action): # If action i exists, update the file path. self.get_action(action).gaupol_path = path else: # Otherwise, create the action and add to self.window. # XXX: For some reason, this can sometimes fail. with aeidon.util.silent(Exception): ao = gaupol.Action(action) ao.gaupol_path = path callback = self._on_open_recent_main_file_activate ao.connect("activate", callback) self.window.add_action(ao) def _update_recent_menus(self, *args): """Update the file menu lists of recent files.""" self._update_recent_main_menu() self._update_recent_translation_menu() # Update enabled states of added actions. self.update_gui() def _update_recent_translation_menu(self, *args): """Update the file menu list of recent translation files.""" menu = self.get_menubar_section("open-recent-translation-placeholder") # Menubar not available when running unit tests. if menu is None: return menu.remove_all() recent = self._get_recent_chooser_menu() for i, uri in enumerate(recent.get_uris()): path = aeidon.util.uri_to_path(uri) label = os.path.basename(path) if len(label) > 100: label = label[:100] + "…" action = "win.open-recent-translation-file-{:d}".format(i) menu.append(label, action) action = action.replace("win.", "") if not self.get_action(action): ao = gaupol.OpenRecentTranslationFileAction(action) callback = self._on_open_recent_translation_file_activate ao.connect("activate", callback) self.window.add_action(ao) self.get_action(action).gaupol_path = path gaupol-1.11/gaupol/agents/open.py000066400000000000000000000457531422217132500170230ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Opening subtitle files and creating new projects.""" import aeidon import gaupol import os from aeidon.i18n import _ from gi.repository import Gtk class OpenAgent(aeidon.Delegate): """Opening subtitle files and creating new projects.""" @aeidon.deco.export def add_page(self, page): """Add `page` to the application.""" self.pages.append(page) page.connect("close-request", self._on_page_close_request) page.project.connect("action-done", self._on_project_action_done) page.project.connect("action-redone", self._on_project_action_redone) page.project.connect("action-undone", self._on_project_action_undone) callback = self._on_tab_widget_button_press_event page.tab_widget.connect("button-press-event", callback, page) self.connect_view_signals(page.view) page.project.clipboard.set_texts(self.clipboard.get_texts()) scroller = Gtk.ScrolledWindow() policy = Gtk.PolicyType.AUTOMATIC scroller.set_policy(policy, policy) scroller.add(page.view) self.notebook.append_page(scroller, page.tab_widget) self.notebook.set_tab_reorderable(scroller, True) self.notebook.child_set_property(scroller, "tab-expand", True) self.notebook.child_set_property(scroller, "tab-fill", True) self.notebook.show_all() self.set_current_page(page) self.emit("page-added", page) @aeidon.deco.export def add_to_recent_files(self, path, format, doc): """Add `path` to recent files managed by the recent manager.""" # XXX: The group field is not available for Python, # we cannot differentiate between main and translation files. # https://bugzilla.gnome.org/show_bug.cgi?id=695970 uri = aeidon.util.path_to_uri(path) recent = Gtk.RecentData() recent.mime_type = format.mime_type recent.app_name = "gaupol" recent.app_exec = "gaupol %F" self.recent_manager.add_full(uri, recent) @aeidon.deco.export def append_file(self, path, encoding=None): """Append subtitles from file at `path` to the current project.""" encodings = self._get_encodings(encoding) doc = aeidon.documents.MAIN temp = self._open_file(path, encodings, doc, check_open=False) gaupol.util.set_cursor_busy(self.window) current = self.get_current_page() offset = current.project.subtitles[-1].end temp.project.shift_positions(None, offset) rows = self._append_subtitles(current, temp.project.subtitles) amount = len(rows) current.view.set_focus(rows[0], None) current.view.select_rows(rows) current.view.scroll_to_row(rows[0]) basename = temp.get_main_basename() message = _('Appended {amount:d} subtitles from "{basename}"') self.flash_message(message.format(**locals())) gaupol.util.set_cursor_normal(self.window) def _append_subtitles(self, page, subtitles): """Append `subtitles` to `page` and return new indices.""" n = len(page.project.subtitles) indices = list(range(n, n + len(subtitles))) page.project.block("action-done") page.project.insert_subtitles(indices, subtitles) page.project.set_action_description( aeidon.registers.DO, _("Appending file")) page.project.unblock("action-done") return tuple(indices) def _check_file_exists(self, path): """Raise :exc:`gaupol.Default` if no file at `path`.""" gaupol.util.raise_default(not os.path.isfile(path)) def _check_file_not_open(self, path): """Raise :exc:`gaupol.Default` if file at `path` already open.""" for page in self.pages: files = [page.project.main_file, page.project.tran_file] paths = [x.path for x in files if x] if not path in paths: continue self.set_current_page(page) message = _('File "{}" is already open') self.flash_message(message.format(os.path.basename(path))) raise gaupol.Default def _check_file_size(self, path): """Raise :exc:`gaupol.Default` if size of file at `path` too large.""" size_mb = os.stat(path).st_size / 1048576 if size_mb <= 1: return basename = os.path.basename(path) self._show_size_warning_dialog(basename, size_mb) def _check_sort_count(self, path, sort_count): """Raise :exc:`gaupol.Default` if `sort_count` too large.""" if sort_count <= 0: return basename = os.path.basename(path) self._show_sort_warning_dialog(basename, sort_count) @aeidon.deco.export def connect_view_signals(self, view): """Connect to signals emitted by `view`.""" view.connect_selection_changed(self._on_view_selection_changed) view.connect_after("move-cursor", self._on_view_move_cursor) view.connect("button-press-event", self._on_view_button_press_event) for column in view.get_columns(): renderer = column.get_cells()[0] callback = self._on_view_renderer_edited renderer.connect("edited", callback, column) callback = self._on_view_renderer_editing_started renderer.connect("editing-started", callback, column) callback = self._on_view_renderer_editing_canceled renderer.connect("editing-canceled", callback, column) button = column.get_widget().get_ancestor(Gtk.Button) callback = self._on_view_header_button_press_event button.connect("button-press-event", callback) def _get_encodings(self, first=None): """Return a sequence of encodings to try when opening files.""" encodings = [first] if gaupol.conf.encoding.try_locale: encoding = aeidon.encodings.get_locale_code() encodings.append(encoding) encodings += gaupol.conf.encoding.fallback try_auto = gaupol.conf.encoding.try_auto if try_auto and aeidon.util.chardet_available(): encodings.append("auto") encodings = list(filter(None, encodings)) encodings = encodings or ["utf_8"] return tuple(aeidon.util.get_unique(encodings)) @aeidon.deco.export @aeidon.deco.silent(gaupol.Default) def _on_append_file_activate(self, *args): """Append subtitles from file to the current project.""" gaupol.util.set_cursor_busy(self.window) dialog = gaupol.AppendDialog(self.window) gaupol.util.set_cursor_normal(self.window) response = gaupol.util.run_dialog(dialog) paths = dialog.get_filenames() encoding = dialog.get_encoding() dialog.destroy() if response != Gtk.ResponseType.OK: return if not paths: return gaupol.util.iterate_main() self.append_file(paths[0], encoding) @aeidon.deco.export def _on_new_project_activate(self, *args): """Create a new project.""" if gaupol.fields.TRAN_TEXT in gaupol.conf.editor.visible_fields: gaupol.conf.editor.visible_fields.remove(gaupol.fields.TRAN_TEXT) page = gaupol.Page(next(self.counter)) page.project.insert_subtitles((0,), register=None) self.add_page(page) @aeidon.deco.export def _on_notebook_drag_data_received(self, notebook, context, x, y, selection_data, info, time): """Open main files from dragged URIs.""" uris = selection_data.get_uris() paths = list(map(aeidon.util.uri_to_path, uris)) videos = list(filter(aeidon.util.is_video_file, paths)) subtitles = list(set(paths) - set(videos)) self.open_main(subtitles) if self.get_current_page() and len(videos) == 1: self.load_video(videos[0]) @aeidon.deco.export @aeidon.deco.silent(gaupol.Default) def _on_open_main_files_activate(self, *args): """Open main files.""" doc = aeidon.documents.MAIN paths, encoding = self._select_files(_("Open"), doc) self.open_main(paths, encoding) @aeidon.deco.export @aeidon.deco.silent(gaupol.Default) def _on_open_translation_file_activate(self, *args): """Open a translation file.""" page = self.get_current_page() if page.project.tran_changed: self._show_translation_warning_dialog(page) doc = aeidon.documents.TRAN paths, encoding = self._select_files(_("Open Translation"), doc) self.open_translation(paths[0], encoding) @aeidon.deco.export def _on_select_video_file_activate(self, *args): """Select a video file.""" gaupol.util.set_cursor_busy(self.window) page = self.get_current_page() path = page.project.video_path title = _("Select Video") label = _("_Select") dialog = gaupol.VideoDialog(self.window, title, label) if page.project.main_file is not None: directory = os.path.dirname(page.project.main_file.path) dialog.set_current_folder(directory) if page.project.video_path is not None: dialog.set_filename(page.project.video_path) gaupol.util.set_cursor_normal(self.window) response = gaupol.util.run_dialog(dialog) path = dialog.get_filename() dialog.destroy() if response != Gtk.ResponseType.OK: return page.project.video_path = path self.update_gui() @aeidon.deco.export def _on_split_project_activate(self, *args): """Split the current project in two.""" gaupol.util.flash_dialog(gaupol.SplitDialog(self.window, self)) def _open_file(self, path, encodings, doc, check_open=True): """Open file at `path` and return corresponding page if successful.""" self._check_file_exists(path) if check_open: self._check_file_not_open(path) self._check_file_size(path) basename = os.path.basename(path) page = (gaupol.Page() if doc == aeidon.documents.MAIN else self.get_current_page()) for encoding in encodings: with aeidon.util.silent(UnicodeError): n = self._try_open_file(page, doc, path, encoding) self._check_sort_count(path, n) return page # Report if all codecs failed to decode file. self._show_encoding_error_dialog(basename) raise gaupol.Default @aeidon.deco.export @aeidon.deco.silent(gaupol.Default) def open_main(self, path, encoding=None): """Open file at `path` as a main file.""" if gaupol.fields.TRAN_TEXT in gaupol.conf.editor.visible_fields: gaupol.conf.editor.visible_fields.remove(gaupol.fields.TRAN_TEXT) encodings = self._get_encodings(encoding) gaupol.util.set_cursor_busy(self.window) for path in aeidon.util.flatten([path]): try: # Skip files that are already open, # but show a status message when that happens. self._check_file_not_open(path) except gaupol.Default: continue try: page = self._open_file(path, encodings, aeidon.documents.MAIN) except gaupol.Default: gaupol.util.set_cursor_normal(self.window) raise # gaupol.Default self.add_page(page) format = page.project.main_file.format self.add_to_recent_files(path, format, aeidon.documents.MAIN) # Refresh view to get row heights etc. correct. page.view.set_focus(0, page.view.columns.MAIN_TEXT) gaupol.util.set_cursor_normal(self.window) self.update_gui() @aeidon.deco.export @aeidon.deco.silent(gaupol.Default) def open_translation(self, path, encoding=None, align_method=None): """Open file at `path` as a translation file.""" if align_method is not None: gaupol.conf.file.align_method = align_method encodings = self._get_encodings(encoding) page = self._open_file(path, encodings, aeidon.documents.TRAN) gaupol.util.set_cursor_busy(self.window) col = page.view.columns.TRAN_TEXT if not page.view.get_column(col).get_visible(): self.get_column_action(gaupol.fields.TRAN_TEXT).activate() format = page.project.tran_file.format self.add_to_recent_files(path, format, aeidon.documents.TRAN) gaupol.util.set_cursor_normal(self.window) def _select_files(self, title, doc): """Show a :class:`gaupol.OpenDialog` to select files.""" gaupol.util.set_cursor_busy(self.window) dialog = gaupol.OpenDialog(self.window, title, doc) page = self.get_current_page() if page is not None and page.project.main_file is not None: directory = os.path.dirname(page.project.main_file.path) dialog.set_current_folder(directory) gaupol.util.set_cursor_normal(self.window) response = gaupol.util.run_dialog(dialog) paths = dialog.get_filenames() encoding = dialog.get_encoding() dialog.destroy() gaupol.util.raise_default(response != Gtk.ResponseType.OK) gaupol.util.iterate_main() return paths, encoding def _show_encoding_error_dialog(self, basename): """Show an error dialog after failing to decode file.""" title = _('Failed to decode file "{}" with all attempted codecs').format(basename) message = _("Please try to open the file with a different character encoding.") dialog = gaupol.ErrorDialog(self.window, title, message) dialog.add_button(_("_OK"), Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK) gaupol.util.flash_dialog(dialog) def _show_format_error_dialog(self, basename): """Show an error dialog after failing to recognize file format.""" title = _('Failed to recognize format of file "{}"').format(basename) message = _("Please check that the file you are trying to open is a subtitle file of a format supported by Gaupol.") dialog = gaupol.ErrorDialog(self.window, title, message) dialog.add_button(_("_OK"), Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK) gaupol.util.flash_dialog(dialog) def _show_io_error_dialog(self, basename, message): """Show an error dialog after failing to read file.""" title = _('Failed to open file "{}"').format(basename) dialog = gaupol.ErrorDialog(self.window, title, message) dialog.add_button(_("_OK"), Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK) gaupol.util.flash_dialog(dialog) def _show_parse_error_dialog(self, basename, format): """Show an error dialog after failing to parse file.""" title = _('Failed to parse file "{}"').format(basename) message = _("Please check that the file you are trying to open is a valid {} file.").format(format.label) dialog = gaupol.ErrorDialog(self.window, title, message) dialog.add_button(_("_OK"), Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK) gaupol.util.flash_dialog(dialog) def _show_size_warning_dialog(self, basename, size): """Show a warning dialog when trying to open a large file.""" title = _('Open abnormally large file "{}"?').format(basename) message = _("Size of the file is {:.1f} MB, which is abnormally large for a text-based subtitle file. Please, check that you are not trying to open a binary file.").format(size) dialog = gaupol.WarningDialog(self.window, title, message) dialog.add_button(_("_Cancel"), Gtk.ResponseType.NO) dialog.add_button(_("_Open"), Gtk.ResponseType.YES) dialog.set_default_response(Gtk.ResponseType.NO) response = gaupol.util.flash_dialog(dialog) gaupol.util.raise_default(response != Gtk.ResponseType.YES) def _show_sort_warning_dialog(self, basename, count): """Show a warning dialog when subtitles have been sorted.""" title = _('Open unsorted file "{}"?').format(basename) message = _("The order of {:d} subtitles needs to be changed. If {:d} sounds like a lot, the file may be erroneously composed.") message = message.format(count, count) dialog = gaupol.WarningDialog(self.window, title, message) dialog.add_button(_("_Cancel"), Gtk.ResponseType.NO) dialog.add_button(_("_Open"), Gtk.ResponseType.YES) dialog.set_default_response(Gtk.ResponseType.YES) response = gaupol.util.flash_dialog(dialog) gaupol.util.raise_default(response != Gtk.ResponseType.YES) def _show_translation_warning_dialog(self, page): """Show a warning dialog if opening a new translation file.""" title = _('Save changes to translation document "{}" before opening a new one?').format(page.get_translation_basename()) message = _("If you don't save, changes will be permanently lost.") dialog = gaupol.WarningDialog(self.window, title, message) dialog.add_button(_("Open _Without Saving"), Gtk.ResponseType.NO) dialog.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) dialog.add_button(_("_Save"), Gtk.ResponseType.YES) dialog.set_default_response(Gtk.ResponseType.YES) response = gaupol.util.flash_dialog(dialog) if response == Gtk.ResponseType.YES: return self.save_translation(page) gaupol.util.raise_default(response != Gtk.ResponseType.NO) def _try_open_file(self, page, doc, path, encoding, **kwargs): """Try to open file at `path` and return subtitle sort count.""" if encoding == "auto": encoding = aeidon.encodings.detect(path) if encoding is None: raise UnicodeError kwargs["align_method"] = gaupol.conf.file.align_method basename = os.path.basename(path) try: return page.project.open(doc, path, encoding, **kwargs) except aeidon.FormatError: self._show_format_error_dialog(basename) except IOError as error: self._show_io_error_dialog(basename, str(error)) except aeidon.ParseError: bom_encoding = aeidon.encodings.detect_bom(path) encoding = bom_encoding or encoding with aeidon.util.silent(Exception): format = aeidon.util.detect_format(path, encoding) self._show_parse_error_dialog(basename, format) raise gaupol.Default gaupol-1.11/gaupol/agents/preview.py000066400000000000000000000141171422217132500175310ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Previewing subtitles with a video player.""" import aeidon import gaupol import shutil import tempfile from aeidon.i18n import _ from gi.repository import GLib from gi.repository import Gtk class PreviewAgent(aeidon.Delegate): """Previewing subtitles with a video player.""" def _check_process_state(self, page, process, fout, command): """Check if `process` has terminated or not.""" if process.poll() is None: return True self._handle_output(process, fout, command) return False # to not check again. def _handle_output(self, process, fout, command): """Handle output of finished `process`.""" fout.close() with open(fout.name, "r", errors="replace") as f: output = f.read().splitlines() output = "\n".join(output[:100]) print("\nPREVIEW: {}\n{}".format(command, output)) aeidon.temp.remove(fout.name) if process.returncode == 0: return dialog = gaupol.PreviewErrorDialog(self.window, output) gaupol.util.flash_dialog(dialog) @aeidon.deco.export def _on_preview_activate(self, *args): """Preview from selected position with a video player.""" page = self.get_current_page() rows = page.view.get_selected_rows() row = rows[0] if rows else 0 position = page.project.subtitles[row].start col = page.view.get_focus()[1] if col == page.view.columns.TRAN_TEXT: doc = aeidon.documents.TRAN else: # Any other column previews the main file. doc = aeidon.documents.MAIN self.preview(page, position, doc) @aeidon.deco.export def preview(self, page, position, doc, temp=False): """Preview from `position` with a video player.""" if (not gaupol.conf.preview.use_custom_command and not shutil.which(gaupol.conf.preview.player.executable)): return self._show_player_not_found_error_dialog() command = gaupol.util.get_preview_command() offset = gaupol.conf.preview.offset encoding = "utf_8" if gaupol.conf.preview.force_utf_8 else None try: process, command, fout = page.project.preview( position, doc, command, offset, encoding, temp) except aeidon.ProcessError as error: return self._show_process_error_dialog(str(error)) except (IOError, OSError) as error: return self._show_io_error_dialog(str(error)) except UnicodeError: return self._show_encoding_error_dialog() # GLib.child_watch_add does not appear to work on Windows, # so let's watch the process by polling it at regular intervals. GLib.timeout_add(1000, self._check_process_state, page, process, fout, command) @aeidon.deco.export def preview_changes(self, page, row, doc, method, args=None, kwargs=None): """Preview changes caused by `method` with a video player.""" subtitles = [x.copy() for x in page.project.subtitles] framerate = page.project.framerate blocked = page.project.block_all() method(register=None, *(args or ()), **(kwargs or {})) position = page.project.subtitles[row].start page.project.unblock_all(blocked) self.preview(page, position, doc, temp=True) page.project.set_framerate(framerate, register=None) page.project.subtitles = subtitles def _show_encoding_error_dialog(self): """Show an error dialog after failing to encode file.""" title = _('Failed to encode subtitle file to temporary directory "{}"').format(tempfile.gettempdir()) message = _("Subtitle data could not be encoded to a temporary file for preview with the current character encoding. Please first save the subtitle file with a different character encoding.") dialog = gaupol.ErrorDialog(self.window, title, message) dialog.add_button(_("_OK"), Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK) gaupol.util.flash_dialog(dialog) def _show_io_error_dialog(self, message): """Show an error dialog after failing to write file.""" title = _('Failed to save subtitle file to temporary directory "{}"').format(tempfile.gettempdir()) dialog = gaupol.ErrorDialog(self.window, title, message) dialog.add_button(_("_OK"), Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK) gaupol.util.flash_dialog(dialog) def _show_player_not_found_error_dialog(self): """Show an error dialog if video player not found.""" title = _("Video player not found") message = _("Please install one of the supported video players: mpv (recommended), MPlayer or VLC. See the preferences dialog to choose the video player or to customize the command.") dialog = gaupol.ErrorDialog(self.window, title, message) dialog.add_button(_("_OK"), Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK) gaupol.util.flash_dialog(dialog) def _show_process_error_dialog(self, message): """Show an error dialog after failing to launch video player.""" title = _("Failed to launch video player") dialog = gaupol.ErrorDialog(self.window, title, message) dialog.add_button(_("_OK"), Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK) gaupol.util.flash_dialog(dialog) gaupol-1.11/gaupol/agents/save.py000066400000000000000000000203771422217132500170130ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Saving documents.""" import aeidon import gaupol import os from aeidon.i18n import _ from gi.repository import Gtk class SaveAgent(aeidon.Delegate): """Saving documents.""" @aeidon.deco.export def _on_save_all_documents_activate(self, *args): """Save all open documents.""" for page in self.pages: with aeidon.util.silent(gaupol.Default): self.save_main(page) if page.project.tran_changed is not None: with aeidon.util.silent(gaupol.Default): self.save_translation(page) self.update_gui() @aeidon.deco.export def _on_save_all_documents_as_activate(self, *args): """Save all open documents with different properties.""" modes = [] for page in self.pages: if page.project.main_file is not None: modes.append(page.project.main_file.mode) dialog = gaupol.MultiSaveDialog(self.window, self, modes) gaupol.util.flash_dialog(dialog) self.update_gui() @aeidon.deco.export @aeidon.deco.silent(gaupol.Default) def _on_save_main_document_activate(self, *args): """Save the current main document.""" page = self.get_current_page() self.save_main(page) self.update_gui() @aeidon.deco.export @aeidon.deco.silent(gaupol.Default) def _on_save_main_document_as_activate(self, *args): """Save the current main document with a different name.""" page = self.get_current_page() self.save_main_as(page) self.update_gui() @aeidon.deco.export @aeidon.deco.silent(gaupol.Default) def _on_save_translation_document_activate(self, *args): """Save the current translation document.""" page = self.get_current_page() self.save_translation(page) self.update_gui() @aeidon.deco.export @aeidon.deco.silent(gaupol.Default) def _on_save_translation_document_as_activate(self, *args): """Save the current translation document with a different name.""" page = self.get_current_page() self.save_translation_as(page) self.update_gui() @aeidon.deco.export def save(self, page, doc): """Save `doc` of `page` to file.""" if doc == aeidon.documents.MAIN: return self.save_main(page) if doc == aeidon.documents.TRAN: return self.save_translation(page) raise ValueError("Invalid document: {!r}" .format(doc)) def _save_document(self, page, doc, file=None): """Save document to `file` or raise :exc:`gaupol.Default`.""" try: file = file or page.project.get_file(doc) gaupol.util.set_cursor_busy(self.window) return page.project.save(doc, file) except IOError as error: gaupol.util.set_cursor_normal(self.window) basename = os.path.basename(file.path) self._show_io_error_dialog(basename, str(error)) except UnicodeError: gaupol.util.set_cursor_normal(self.window) basename = os.path.basename(file.path) self._show_encoding_error_dialog(basename, file.encoding) finally: gaupol.util.set_cursor_normal(self.window) raise gaupol.Default @aeidon.deco.export def save_main(self, page): """Save the main document of `page` to file.""" if (page.project.main_file is None or page.project.main_file.path is None or page.project.main_file.encoding is None): return self.save_main_as(page) self._save_document(page, aeidon.documents.MAIN) self.emit("page-saved", self, page) @aeidon.deco.export def save_main_as(self, page, file=None): """Save the main document of `page` to a selected file.""" if file is None: file = page.project.main_file file = self._select_file(_("Save As"), page, file) self._save_document(page, aeidon.documents.MAIN, file) self.emit("page-saved", self, page) path = page.project.main_file.path format = page.project.main_file.format self.add_to_recent_files(path, format, aeidon.documents.MAIN) self.flash_message(_('Saved main document as "{}"') .format(os.path.basename(path))) @aeidon.deco.export def save_translation(self, page): """Save the translation document of `page` to file.""" if (page.project.tran_file is None or page.project.tran_file.path is None or page.project.tran_file.encoding is None): return self.save_translation_as(page) self._save_document(page, aeidon.documents.TRAN) self.emit("page-saved", self, page) @aeidon.deco.export def save_translation_as(self, page, file=None): """Save the translation document of `page` to a selected file.""" if file is None: file = page.project.tran_file file = self._select_file(_("Save Translation As"), page, file) self._save_document(page, aeidon.documents.TRAN, file) self.emit("page-saved", self, page) path = page.project.tran_file.path format = page.project.tran_file.format self.add_to_recent_files(path, format, aeidon.documents.TRAN) self.flash_message(_('Saved translation document as "{}"') .format(os.path.basename(path))) def _select_file(self, title, page, file=None): """Select a file to save or raise :exc:`gaupol.Default`.""" gaupol.util.set_cursor_busy(self.window) mode = page.project.get_mode() dialog = gaupol.SaveDialog(self.window, title, mode) if file is not None: dialog.set_name(file.path) dialog.set_format(file.format) dialog.set_encoding(file.encoding) dialog.set_newline(file.newline) dialog.set_framerate(page.project.framerate) gaupol.util.set_cursor_normal(self.window) response = gaupol.util.run_dialog(dialog) format = dialog.get_format() path = dialog.get_filename() encoding = dialog.get_encoding() newline = dialog.get_newline() framerate = dialog.get_framerate() dialog.destroy() if response != Gtk.ResponseType.OK: raise gaupol.Default if format.mode != mode: # Set framerate to the selected one. self.set_current_page(page) action = self.get_action("set-framerate") action.activate(str(framerate)) gaupol.util.iterate_main() return aeidon.files.new(format, path, encoding, newline) def _show_encoding_error_dialog(self, basename, codec): """Show an error dialog after failing to encode file.""" codec = aeidon.encodings.code_to_name(codec) title = _('Failed to encode file "{basename}" with codec "{codec}"').format(**locals()) message = _("Please try to save the file with a different character encoding.") dialog = gaupol.ErrorDialog(self.window, title, message) dialog.add_button(_("_OK"), Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK) gaupol.util.flash_dialog(dialog) def _show_io_error_dialog(self, basename, message): """Show an error dialog after failing to write file.""" title = _('Failed to save file "{}"').format(basename) dialog = gaupol.ErrorDialog(self.window, title, message) dialog.add_button(_("_OK"), Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK) gaupol.util.flash_dialog(dialog) gaupol-1.11/gaupol/agents/search.py000066400000000000000000000036701422217132500173170ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Searching for and replacing text.""" import aeidon import gaupol class SearchAgent(aeidon.Delegate): """Searching for and replacing text.""" def __init__(self, master): """Initialize a :class:`SearchAgent` instance.""" aeidon.Delegate.__init__(self, master) self._search_dialog = None def _on_search_dialog_response(self, *args): """Hide the search dialog.""" self._search_dialog.hide() @aeidon.deco.export def _on_find_and_replace_activate(self, *args): """Search for and replace text.""" if self._search_dialog is not None: return self._search_dialog.present() self._search_dialog = gaupol.SearchDialog(self.window, self) aeidon.util.connect(self, "_search_dialog", "response") # Do not destroy the dialog, but rather hide based on response. self._search_dialog.connect("delete-event", lambda *args: True) self._search_dialog.show() @aeidon.deco.export def _on_find_next_activate(self, *args): """Search forwards for same text.""" self._search_dialog.next() @aeidon.deco.export def _on_find_previous_activate(self, *args): """Search backwards for same text.""" self._search_dialog.previous() gaupol-1.11/gaupol/agents/test/000077500000000000000000000000001422217132500164515ustar00rootroot00000000000000gaupol-1.11/gaupol/agents/test/__init__.py000066400000000000000000000000001422217132500205500ustar00rootroot00000000000000gaupol-1.11/gaupol/agents/test/test_close.py000066400000000000000000000042111422217132500211650ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon import gaupol from gi.repository import Gtk from unittest.mock import patch class TestCloseAgent(gaupol.TestCase): def run__confirm_close_both(self): page = self.application.get_current_page() page.project.remove_subtitles((0,)) with aeidon.util.silent(gaupol.Default): self.application.close(page) def run__confirm_close_main(self): page = self.application.get_current_page() page.project.set_text(0, aeidon.documents.MAIN, "") with aeidon.util.silent(gaupol.Default): self.application.close(page) def run__confirm_close_translation(self): page = self.application.get_current_page() page.project.set_text(0, aeidon.documents.TRAN, "") with aeidon.util.silent(gaupol.Default): self.application.close(page) def setup_method(self, method): self.application = self.new_application() @patch("gaupol.util.flash_dialog", lambda *args: Gtk.ResponseType.CANCEL) @aeidon.deco.silent(gaupol.Default) def test_close(self): self.application.pages[-1].project.remove_subtitles((0,)) self.application.close(self.application.pages[-1], confirm=True) @patch("gaupol.util.flash_dialog", lambda *args: Gtk.ResponseType.NO) @aeidon.deco.silent(gaupol.Default) def test_close_all(self): for page in self.application.pages: page.project.remove_subtitles((0,)) self.application.close_all() gaupol-1.11/gaupol/agents/test/test_edit.py000066400000000000000000000166511422217132500210200ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk from unittest.mock import patch class TestEditAgent(gaupol.TestCase): def setup_method(self, method): self.application = self.new_application() def test__on_clear_texts_activate(self): page = self.application.get_current_page() page.view.set_focus(0, page.view.columns.MAIN_TEXT) page.view.select_rows((0,1,2)) self.application.get_action("clear-texts").activate() def test__on_copy_texts_activate(self): page = self.application.get_current_page() page.view.set_focus(0, page.view.columns.MAIN_TEXT) page.view.select_rows((0,1,2)) self.application.get_action("copy-texts").activate() def test__on_cut_texts_activate(self): page = self.application.get_current_page() page.view.set_focus(0, page.view.columns.MAIN_TEXT) page.view.select_rows((0,1,2)) self.application.get_action("cut-texts").activate() assert page.project.subtitles[0].main_text == "" assert page.project.subtitles[1].main_text == "" assert page.project.subtitles[2].main_text == "" def test__on_edit_next_value_activate(self): page = self.application.get_current_page() page.view.set_focus(0, page.view.columns.MAIN_TEXT) self.application.get_action("edit-next-value").activate() def test__on_edit_preferences_activate(self): self.application.get_action("edit-preferences").activate() self.application.get_action("edit-preferences").activate() def test__on_edit_value_activate(self): page = self.application.get_current_page() page.view.set_focus(0, page.view.columns.MAIN_TEXT) self.application.get_action("edit-value").activate() def test__on_end_earlier_activate(self): self.application.get_action("end-earlier").activate() self.application.get_action("end-earlier").activate() self.application.get_action("end-earlier").activate() def test__on_end_later_activate(self): self.application.get_action("end-later").activate() self.application.get_action("end-later").activate() self.application.get_action("end-later").activate() def test__on_extend_selection_to_beginning_activate(self): page = self.application.get_current_page() page.view.select_rows((4,5)) self.application.get_action("extend-selection-to-beginning").activate() rows = page.view.get_selected_rows() assert rows == tuple(range(0, 6)) def test__on_extend_selection_to_end_activate(self): page = self.application.get_current_page() page.view.select_rows((4,5)) self.application.get_action("extend-selection-to-end").activate() rows = page.view.get_selected_rows() assert rows == tuple(range(4, len(page.project.subtitles))) @patch("gaupol.util.flash_dialog", lambda *args: Gtk.ResponseType.OK) def test__on_insert_subtitles_activate(self): page = self.application.get_current_page() page.view.set_focus(0, page.view.columns.MAIN_TEXT) self.application.get_action("insert-subtitles").activate() def test__on_invert_selection_activate(self): page = self.application.get_current_page() page.view.select_rows((0,1,2)) self.application.get_action("invert-selection").activate() rows = page.view.get_selected_rows() assert rows == tuple(range(3, len(page.project.subtitles))) self.application.get_action("invert-selection").activate() rows = page.view.get_selected_rows() assert rows == (0,1,2) def test__on_merge_subtitles_activate(self): page = self.application.get_current_page() n = len(page.project.subtitles) page.view.set_focus(0, page.view.columns.MAIN_TEXT) page.view.select_rows((0,1)) self.application.get_action("merge-subtitles").activate() assert len(page.project.subtitles) == n-1 def test__on_paste_texts_activate(self): page = self.application.get_current_page() page.view.set_focus(0, page.view.columns.MAIN_TEXT) page.view.select_rows((0,1,2)) self.application.get_action("copy-texts").activate() page.view.set_focus(0, page.view.columns.MAIN_TEXT) self.application.get_action("paste-texts").activate() def test__on_redo_action_activate(self): page = self.application.get_current_page() n = len(page.project.subtitles) page.project.remove_subtitles((0,)) self.application.get_action("undo-action").activate() self.application.get_action("redo-action").activate() assert len(page.project.subtitles) == n-1 def test__on_remove_subtitles_activate(self): page = self.application.get_current_page() n = len(page.project.subtitles) page.view.select_rows((0,1,2)) self.application.get_action("remove-subtitles").activate() assert len(page.project.subtitles) == n-3 def test__on_select_all_activate(self): page = self.application.get_current_page() self.application.get_action("select-all").activate() rows = page.view.get_selected_rows() assert rows == tuple(range(0, len(page.project.subtitles))) def test__on_split_subtitle_activate(self): page = self.application.get_current_page() n = len(page.project.subtitles) page.view.set_focus(0, page.view.columns.MAIN_TEXT) self.application.get_action("split-subtitle").activate() assert len(page.project.subtitles) == n + 1 def test__on_start_earlier_activate(self): self.application.get_action("start-earlier").activate() self.application.get_action("start-earlier").activate() self.application.get_action("start-earlier").activate() def test__on_start_later_activate(self): self.application.get_action("start-later").activate() self.application.get_action("start-later").activate() self.application.get_action("start-later").activate() def test__on_undo_action_activate(self): page = self.application.get_current_page() n = len(page.project.subtitles) page.project.remove_subtitles((0,)) self.application.get_action("undo-action").activate() assert len(page.project.subtitles) == n def test_redo(self): page = self.application.get_current_page() n = len(page.project.subtitles) page.project.remove_subtitles((0,)) self.application.undo() self.application.redo() assert len(page.project.subtitles) == n-1 def test_undo(self): page = self.application.get_current_page() n = len(page.project.subtitles) page.project.remove_subtitles((0,)) self.application.undo() assert len(page.project.subtitles) == n gaupol-1.11/gaupol/agents/test/test_format.py000066400000000000000000000032531422217132500213550ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol class TestFormatAgent(gaupol.TestCase): def setup_method(self, method): self.application = self.new_application() page = self.application.get_current_page() page.view.set_focus(0, page.view.columns.MAIN_TEXT) page.view.select_rows((0, 1, 2)) def test__on_toggle_dialogue_dashes_activate(self): self.application.get_action("toggle-dialogue-dashes").activate() def test__on_toggle_italicization_activate(self): self.application.get_action("toggle-italicization").activate() def test__on_use_lower_case_activate(self): self.application.get_action("use-lower-case").activate() def test__on_use_sentence_case_activate(self): self.application.get_action("use-sentence-case").activate() def test__on_use_title_case_activate(self): self.application.get_action("use-title-case").activate() def test__on_use_upper_case_activate(self): self.application.get_action("use-upper-case").activate() gaupol-1.11/gaupol/agents/test/test_help.py000066400000000000000000000024721422217132500210170ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk from unittest.mock import patch class TestHelpAgent(gaupol.TestCase): def setup_method(self, method): self.application = self.new_application() def test__on_browse_documentation_activate(self): self.application.get_action("browse-documentation").activate() def test__on_report_a_bug_activate(self): self.application.get_action("report-a-bug").activate() @patch("gaupol.util.flash_dialog", lambda *args: Gtk.ResponseType.DELETE_EVENT) def test__on_view_about_dialog_activate(self): self.application.get_action("view-about-dialog").activate() gaupol-1.11/gaupol/agents/test/test_open.py000066400000000000000000000061511422217132500210260ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon import gaupol from gi.repository import Gtk from unittest.mock import patch class TestOpenAgent(gaupol.TestCase): def run__show_encoding_error_dialog(self): self.delegate._show_encoding_error_dialog("test") def run__show_format_error_dialog(self): self.delegate._show_format_error_dialog("test") def run__show_io_error_dialog(self): self.delegate._show_io_error_dialog("test", "test") def run__show_parse_error_dialog(self): self.delegate._show_parse_error_dialog("test", aeidon.formats.SUBRIP) @aeidon.deco.silent(gaupol.Default) def run__show_size_warning_dialog(self): self.delegate._show_size_warning_dialog("test", 2) @aeidon.deco.silent(gaupol.Default) def run__show_sort_warning_dialog(self): self.delegate._show_sort_warning_dialog("test", 3) @aeidon.deco.silent(gaupol.Default) def run__show_translation_warning_dialog(self): page = self.application.get_current_page() self.delegate._show_translation_warning_dialog(page) def setup_method(self, method): self.application = self.new_application() self.delegate = self.application.open_main.__self__ def test_add_to_recent_files(self): self.application.add_to_recent_files(self.new_subrip_file(), aeidon.formats.SUBRIP, aeidon.documents.MAIN) def test_append_file(self): page = self.application.get_current_page() n = len(page.project.subtitles) self.application.append_file(self.new_subrip_file()) assert len(page.project.subtitles) > n def test__on_new_project_activate(self): n = len(self.application.pages) self.application.get_action("new-project").activate() assert len(self.application.pages) == n + 1 @patch("gaupol.util.flash_dialog", lambda *args: Gtk.ResponseType.OK) def test__on_split_project_activate(self): page = self.application.get_current_page() page.view.select_rows((3,)) self.application.get_action("split-project").activate() def test_open_main(self): n = len(self.application.pages) path = self.new_subrip_file() self.application.open_main(path) assert len(self.application.pages) == n + 1 def test_open_translation(self): path = self.new_subrip_file() self.application.open_translation(path) gaupol-1.11/gaupol/agents/test/test_preview.py000066400000000000000000000024361422217132500215500ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol class TestPreviewAgent(gaupol.TestCase): def run__show_encoding_error_dialog(self): self.delegate._show_encoding_error_dialog() def run__show_io_error_dialog(self): self.delegate._show_io_error_dialog("test") def run__show_player_not_found_error_dialog(self): self.delegate._show_player_not_found_error_dialog() def run__show_process_error_dialog(self): self.delegate._show_process_error_dialog("test") def setup_method(self, method): self.application = self.new_application() self.delegate = self.application.preview.__self__ gaupol-1.11/gaupol/agents/test/test_save.py000066400000000000000000000033231422217132500210210ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol class TestSaveAgent(gaupol.TestCase): def run__show_encoding_error_dialog(self): self.delegate._show_encoding_error_dialog("test", "ascii") def run__show_io_error_dialog(self): self.delegate._show_io_error_dialog("test", "test") def setup_method(self, method): self.application = self.new_application() self.delegate = self.application.save.__self__ def test__on_save_all_documents_activate(self): self.application.get_action("save-all-documents").activate() def test__on_save_main_document_activate(self): self.application.get_action("save-main-document").activate() def test__on_save_translation_document_activate(self): self.application.get_action("save-translation-document").activate() def test_save_main(self): page = self.application.get_current_page() self.application.save_main(page) def test_save_translation(self): page = self.application.get_current_page() self.application.save_translation(page) gaupol-1.11/gaupol/agents/test/test_search.py000066400000000000000000000035201422217132500213270ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class TestSearchAgent(gaupol.TestCase): def setup_method(self, method): self.application = self.new_application() self.delegate = self.application._on_find_next_activate.__self__ def test__on_find_and_replace_activate(self): self.application.get_action("find-and-replace").activate() self.application.get_action("find-and-replace").activate() def test__on_find_next_activate(self): self.application.get_action("find-and-replace").activate() self.delegate._search_dialog._pattern_entry.set_text("a") self.application.get_action("find-next").activate() self.delegate._search_dialog.response(Gtk.ResponseType.CLOSE) self.application.get_action("find-next").activate() def test__on_find_previous_activate(self): self.application.get_action("find-and-replace").activate() self.delegate._search_dialog._pattern_entry.set_text("a") self.application.get_action("find-previous").activate() self.delegate._search_dialog.response(Gtk.ResponseType.CLOSE) self.application.get_action("find-previous").activate() gaupol-1.11/gaupol/agents/test/test_tools.py000066400000000000000000000057031422217132500212270ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon import gaupol from gi.repository import Gtk from unittest.mock import patch OK = lambda *args: Gtk.ResponseType.OK CANCEL = lambda *args: Gtk.ResponseType.CANCEL class TestToolsAgent(gaupol.TestCase): def setup_method(self, method): self.application = self.new_application() @patch("gaupol.util.flash_dialog", CANCEL) def test__on_adjust_durations_activate(self): self.application.get_action("adjust-durations").activate() @patch("gaupol.util.flash_dialog", OK) def test__on_check_spelling_activate(self): language = self.get_spell_check_language("en") gaupol.conf.spell_check.language = language self.application.get_action("check-spelling").activate() @patch("gaupol.util.flash_dialog", OK) def test__on_configure_spell_check_activate(self): self.application.get_action("configure-spell-check").activate() @patch("gaupol.util.flash_dialog", CANCEL) def test__on_convert_framerate_activate(self): self.application.get_action("convert-framerate").activate() @patch("gaupol.TextAssistant.show", lambda *args: None) def test__on_correct_texts_activate(self): self.application.get_action("correct-texts").activate() @patch("gaupol.util.flash_dialog", CANCEL) def test__on_shift_positions_activate__frame(self): page = self.application.get_current_page() page.edit_mode = aeidon.modes.FRAME self.application.get_action("shift-positions").activate() @patch("gaupol.util.flash_dialog", CANCEL) def test__on_shift_positions_activate__time(self): page = self.application.get_current_page() page.edit_mode = aeidon.modes.TIME self.application.get_action("shift-positions").activate() @patch("gaupol.util.flash_dialog", CANCEL) def test__on_transform_positions_activate__frame(self): page = self.application.get_current_page() page.edit_mode = aeidon.modes.FRAME self.application.get_action("transform-positions").activate() @patch("gaupol.util.flash_dialog", CANCEL) def test__on_transform_positions_activate__time(self): page = self.application.get_current_page() page.edit_mode = aeidon.modes.TIME self.application.get_action("transform-positions").activate() gaupol-1.11/gaupol/agents/test/test_update.py000066400000000000000000000037001422217132500213440ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol class TestUpdateAgent(gaupol.TestCase): def setup_method(self, method): self.application = self.new_application() self.application.add_page(self.new_page()) def test_flash_message(self): self.application.flash_message("") self.application.flash_message(None) def test__on_activate_next_project_activate(self): self.application.notebook.set_current_page(0) self.application.get_action("activate-next-project").activate() def test__on_activate_previous_project_activate(self): self.application.notebook.set_current_page(-1) self.application.get_action("activate-previous-project").activate() def test__on_move_tab_left_activate(self): self.application.notebook.set_current_page(-1) self.application.get_action("move-tab-left").activate() def test__on_move_tab_right_activate(self): self.application.notebook.set_current_page(0) self.application.get_action("move-tab-right").activate() def test_show_message(self): self.application.show_message("") self.application.show_message(None) def test_update_gui(self): self.application.update_gui() self.application.close_all() self.application.update_gui() gaupol-1.11/gaupol/agents/test/test_view.py000066400000000000000000000043011422217132500210320ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol class TestViewAgent(gaupol.TestCase): def setup_method(self, method): self.application = self.new_application() def test__on_toggle_duration_column_toggled(self): name = "toggle-duration-column" self.application.get_action(name).activate() self.application.get_action(name).activate() def test__on_toggle_end_column_toggled(self): name = "toggle-end-column" self.application.get_action(name).activate() self.application.get_action(name).activate() def test__on_toggle_main_text_column_toggled(self): name = "toggle-main-text-column" self.application.get_action(name).activate() self.application.get_action(name).activate() def test__on_toggle_main_toolbar_toggled(self): name = "toggle-main-toolbar" self.application.get_action(name).activate() self.application.get_action(name).activate() def test__on_toggle_number_column_toggled(self): name = "toggle-number-column" self.application.get_action(name).activate() self.application.get_action(name).activate() def test__on_toggle_start_column_toggled(self): name = "toggle-start-column" self.application.get_action(name).activate() self.application.get_action(name).activate() def test__on_toggle_translation_text_column_toggled(self): name = "toggle-translation-text-column" self.application.get_action(name).activate() self.application.get_action(name).activate() gaupol-1.11/gaupol/agents/tools.py000066400000000000000000000071731422217132500172140ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Tools to edit positions and texts.""" import aeidon import gaupol from aeidon.i18n import _ from gi.repository import Gtk class ToolsAgent(aeidon.Delegate): """Tools to edit positions and texts.""" @aeidon.deco.export def _on_adjust_durations_activate(self, *args): """Lengthen or shorten durations.""" dialog = gaupol.DurationAdjustDialog(self.window, self) gaupol.util.flash_dialog(dialog) @aeidon.deco.export def _on_check_spelling_activate(self, *args): """Check for incorrect spelling.""" gaupol.util.set_cursor_busy(self.window) try: dialog = gaupol.SpellCheckDialog(self.window, self) except Exception as error: gaupol.util.set_cursor_normal(self.window) title = _('Failed to load dictionary for language "{}"') title = title.format(gaupol.conf.spell_check.language) dialog = gaupol.ErrorDialog(self.window, title, str(error)) dialog.add_button(_("_OK"), Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK) return gaupol.util.flash_dialog(dialog) gaupol.util.set_cursor_normal(self.window) gaupol.util.flash_dialog(dialog) @aeidon.deco.export def _on_configure_spell_check_activate(self, *args): """Set language and spell-check targets.""" gaupol.util.set_cursor_busy(self.window) dialog = gaupol.LanguageDialog(self.window) gaupol.util.set_cursor_normal(self.window) gaupol.util.flash_dialog(dialog) self.update_gui() @aeidon.deco.export def _on_convert_framerate_activate(self, *args): """Convert framerate.""" dialog = gaupol.FramerateConvertDialog(self.window, self) gaupol.util.flash_dialog(dialog) @aeidon.deco.export def _on_correct_texts_activate(self, *args): """Find and correct errors in texts.""" gaupol.util.set_cursor_busy(self.window) assistant = gaupol.TextAssistant(self.window, self) gaupol.util.set_cursor_normal(self.window) assistant.show() @aeidon.deco.export def _on_shift_positions_activate(self, *args): """Make subtitles appear earlier or later.""" page = self.get_current_page() if page.edit_mode == aeidon.modes.TIME: dialog = gaupol.TimeShiftDialog(self.window, self) if page.edit_mode == aeidon.modes.FRAME: dialog = gaupol.FrameShiftDialog(self.window, self) gaupol.util.flash_dialog(dialog) @aeidon.deco.export def _on_transform_positions_activate(self, *args): """Change positions by linear two-point correction.""" page = self.get_current_page() if page.edit_mode == aeidon.modes.TIME: dialog = gaupol.TimeTransformDialog(self.window, self) if page.edit_mode == aeidon.modes.FRAME: dialog = gaupol.FrameTransformDialog(self.window, self) gaupol.util.flash_dialog(dialog) gaupol-1.11/gaupol/agents/update.py000066400000000000000000000134531422217132500173340ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Updating the application GUI.""" import aeidon import gaupol from gi.repository import Gdk class UpdateAgent(aeidon.Delegate): """Updating the application GUI.""" def _disable_widgets(self): """Make widgets insensitive and blank.""" self.window.set_title("Gaupol") self.show_message(None) @aeidon.deco.export def flash_message(self, message, duration=6): """Show `message` in statuslabel for `duration` seconds.""" self.statuslabel.flash_text(message, duration=duration) self.statuslabel.register_hide_event(self.window, "button-press-event") self.statuslabel.register_hide_event(self.window, "key-press-event") self.statuslabel.register_hide_event(self.window, "scroll-event") with aeidon.util.silent(AttributeError): self.statuslabel.register_hide_event( self.get_current_page().view, "button-press-event") @aeidon.deco.export def _on_activate_next_project_activate(self, *args): """Activate the project in the next tab.""" self.notebook.next_page() @aeidon.deco.export def _on_activate_previous_project_activate(self, *args): """Activate the project in the previous tab.""" self.notebook.prev_page() @aeidon.deco.export def _on_conf_application_window_notify_toolbar_style(self, *args): """Change the style of the main toolbar.""" style = gaupol.conf.application_window.toolbar_style self.main_toolbar.set_style(style.value) @aeidon.deco.export def _on_move_tab_left_activate(self, *args): """Move the current tab to the left.""" page = self.get_current_page() scroller = page.view.get_parent() index = self.pages.index(page) self.notebook.reorder_child(scroller, index-1) @aeidon.deco.export def _on_move_tab_right_activate(self, *args): """Move the current tab to the right.""" page = self.get_current_page() scroller = page.view.get_parent() index = self.pages.index(page) self.notebook.reorder_child(scroller, index + 1) @aeidon.deco.export def _on_notebook_page_reordered(self, notebook, scroller, index): """Update the list of pages to match the new order.""" view = scroller.get_child() page = [x for x in self.pages if x.view is view][0] self.pages.remove(page) self.pages.insert(index, page) self.update_gui() self.emit("pages-reordered", page, index) @aeidon.deco.export def _on_notebook_switch_page(self, notebook, pointer, index): """Update GUI for the page switched to.""" if not self.pages: return self.update_gui() page = self.pages[index] page.view.grab_focus() self.emit("page-switched", page) @aeidon.deco.export def _on_view_move_cursor(self, *args): """Update GUI after moving cursor in the view.""" self.update_gui() @aeidon.deco.export def _on_view_selection_changed(self, *args): """Update GUI after changing selection in the view.""" self.update_gui() @aeidon.deco.export def _on_window_window_state_event(self, window, event): """Save window maximization.""" state = event.new_window_state maximized = bool(state & Gdk.WindowState.MAXIMIZED) gaupol.conf.application_window.maximized = maximized @aeidon.deco.export def show_message(self, message): """Show `message` in the statuslabel or hide label with `None`.""" self.statuslabel.set_text(message) def _update_actions(self, page): """Update sensitivities of all actions for page.""" rows = [] with aeidon.util.silent(AttributeError): rows = page.view.get_selected_rows() for name in self.window.list_actions(): action = self.get_action(name) action.update_enabled(self, page, rows) @aeidon.deco.export def update_gui(self): """Update widget sensitivities and states for the current page.""" page = self.get_current_page() self._update_actions(page) self._update_widgets(page) self.extension_manager.update_extensions(page) def _update_widgets(self, page): """Update states of all widgets for `page`.""" if page is None: return self._disable_widgets() self.window.set_title(page.tab_label.get_text()) self.notebook.set_menu_label_text( page.view.get_parent(), page.tab_label.get_text()) tabs = len(self.pages) > 1 and not self.player_box.get_visible() self.notebook.set_show_tabs(tabs) self.get_action("set-edit-mode").set_state(str(page.edit_mode)) self.get_action("set-framerate").set_state(str(page.project.framerate)) if self.player is not None: layout = gaupol.conf.application_window.layout self.get_action("set-layout").set_state(str(layout)) for field in gaupol.fields: col = getattr(page.view.columns, field.name) visible = page.view.get_column(col).get_visible() self.get_column_action(field).set_state(visible) gaupol-1.11/gaupol/agents/util.py000066400000000000000000000066721422217132500170340ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Miscellaneous helper methods.""" import aeidon import gaupol class UtilityAgent(aeidon.Delegate): """Miscellaneous helper methods.""" @aeidon.deco.export def get_action(self, name): """Return user-activatable action by `name`.""" return self.window.lookup_action(name) @aeidon.deco.export def get_column_action(self, field): """Return action to hide or show column.""" return self.get_action({ gaupol.fields.NUMBER: "toggle-number-column", gaupol.fields.START: "toggle-start-column", gaupol.fields.END: "toggle-end-column", gaupol.fields.DURATION: "toggle-duration-column", gaupol.fields.MAIN_TEXT: "toggle-main-text-column", gaupol.fields.TRAN_TEXT: "toggle-translation-text-column", }[field]) @aeidon.deco.export def get_current_page(self): """Return the currently active page or ``None``.""" index = self.notebook.get_current_page() if index < 0: return None return self.pages[index] @aeidon.deco.export def get_menubar_section(self, id): """Return menubar section by its `id` attribute.""" if not hasattr(gaupol, "appman"): return None return gaupol.appman.menubar_builder.get_object(id) @aeidon.deco.export def get_target_pages(self, target): """Return a sequence of pages corresponding to `target`.""" if target == gaupol.targets.SELECTED: return (self.get_current_page(),) if target == gaupol.targets.SELECTED_TO_END: return (self.get_current_page(),) if target == gaupol.targets.CURRENT: return (self.get_current_page(),) if target == gaupol.targets.ALL: return tuple(self.pages) raise ValueError("Invalid target: {!r}" .format(target)) @aeidon.deco.export def get_target_rows(self, target): """Return rows corresponding to `target` or ``None`` for all.""" if target == gaupol.targets.SELECTED: page = self.get_current_page() return page.view.get_selected_rows() if target == gaupol.targets.SELECTED_TO_END: page = self.get_current_page() rows = page.view.get_selected_rows() return list(range(min(rows), len(page.project.subtitles))) if target == gaupol.targets.CURRENT: return None if target == gaupol.targets.ALL: return None raise ValueError("Invalid target: {!r}" .format(target)) @aeidon.deco.export def set_current_page(self, page): """Set the currently active page.""" if page is None: return index = self.pages.index(page) self.notebook.set_current_page(index) gaupol-1.11/gaupol/agents/video.py000066400000000000000000000363731422217132500171660ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2012 Osmo Salomaa # # 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 . """Loading and interacting with video.""" import aeidon import gaupol import os import sys from aeidon.i18n import _ from gi.repository import GLib from gi.repository import Gtk with aeidon.util.silent(Exception): from gi.repository import Gst from gi.repository import GstTag class VideoAgent(aeidon.Delegate): """Loading and interacting with video.""" def __init__(self, master): """Initialize an :class:`VideoAgent` instance.""" aeidon.Delegate.__init__(self, master) # Maintain an up-to-date cache of subtitle positions in seconds and # subtitle texts in order to allow fast polled updates in video player. # This cache must be updated when page or subtitle data changes. self._cache = [] self._update_handlers = [] def _clear_subtitle_cache(self): """Clear subtitle position and text cache.""" self._cache = [] def _init_cache_updates(self): """Initialize cache updates on application signals.""" self.connect("page-added", self._update_subtitle_cache) self.connect("page-changed", self._update_subtitle_cache) self.connect("page-closed", self._update_subtitle_cache) self.connect("page-switched", self._update_subtitle_cache) def _init_player_toolbar(self): """Initialize the video player toolbar.""" self.player_toolbar = Gtk.Toolbar() self.player_toolbar.set_style(Gtk.ToolbarStyle.ICONS) if sys.platform == "win32": self.player_toolbar.set_icon_size(Gtk.IconSize.MENU) # win.play-pause button = Gtk.ToolButton( label=_("_Play/Pause"), icon_name="media-playback-start") button.set_action_name("win.play-pause") button.set_tooltip_text(_("Play or pause video")) self.player_toolbar.insert(button, -1) self.player_toolbar.insert(Gtk.SeparatorToolItem(), -1) self.play_button = button # win.seek-previous button = Gtk.ToolButton( label=_("Seek _Previous"), icon_name="media-skip-backward") button.set_action_name("win.seek-previous") button.set_tooltip_text(_("Seek to the start of the previous subtitle")) self.player_toolbar.insert(button, -1) # win.seek-next button = Gtk.ToolButton( label=_("Seek _Next"), icon_name="media-skip-forward") button.set_action_name("win.seek-next") button.set_tooltip_text(_("Seek to the start of the next subtitle")) self.player_toolbar.insert(button, -1) self.player_toolbar.insert(Gtk.SeparatorToolItem(), -1) # win.seek-backward button = Gtk.ToolButton( label=_("Seek _Backward"), icon_name="media-seek-backward") button.set_action_name("win.seek-backward") button.set_tooltip_text(_("Seek backward")) self.player_toolbar.insert(button, -1) # win.seek-forward button = Gtk.ToolButton( label=_("Seek _Forward"), icon_name="media-seek-forward") button.set_action_name("win.seek-forward") button.set_tooltip_text(_("Seek forward")) self.player_toolbar.insert(button, -1) self.player_toolbar.insert(Gtk.SeparatorToolItem(), -1) # Volume button self.volume_button = Gtk.VolumeButton() self.volume_button.props.use_symbolic = False adjustment = self.volume_button.get_adjustment() adjustment.set_lower(0) adjustment.set_upper(1) adjustment.set_value(self.player.volume) aeidon.util.connect(self, "volume_button", "value-changed") item = Gtk.ToolItem() item.add(self.volume_button) item.set_tooltip_text(_("Volume")) self.player_toolbar.insert(item, -1) # Seekbar self.seekbar = Gtk.Scale( orientation=Gtk.Orientation.HORIZONTAL, adjustment=Gtk.Adjustment(value=0, lower=0, upper=1, step_increment=0.01, page_increment=0.05, page_size=0.05)) self.seekbar.set_draw_value(False) self.seekbar.connect("change-value", self._on_seekbar_change_value) item = Gtk.ToolItem() item.set_expand(True) item.add(self.seekbar) self.player_toolbar.insert(item, -1) def _init_player_widgets(self): """Initialize the video player and related widgets.""" vbox = gaupol.util.new_vbox(spacing=0) self.player = gaupol.VideoPlayer() aeidon.util.connect(self, "player", "state-changed") gaupol.util.pack_start_expand(vbox, self.player.widget) self._init_player_toolbar() gaupol.util.pack_start_fill(vbox, self.player_toolbar) gaupol.util.pack_start_expand(self.player_box, vbox) self.player_box.show_all() self.paned.add1(self.player_box) orientation = self.paned.get_orientation() size = ( self.notebook.get_window().get_width() if orientation == Gtk.Orientation.HORIZONTAL else self.notebook.get_window().get_height()) self.paned.set_position(int(size / 2)) self.get_action("toggle-player").set_state(True) def _init_update_handlers(self): """Initialize timed updates of widgets.""" while self._update_handlers: GLib.source_remove(self._update_handlers.pop()) self._update_handlers = [ GLib.timeout_add( 10, self._on_player_update_subtitle), GLib.timeout_add( 50, self._on_player_update_seekbar), GLib.timeout_add(100, self._on_player_update_volume), ] @aeidon.deco.export def load_video(self, path): """Load a video file.""" page = self.get_current_page() page.project.video_path = path if self.player is None: self._init_player_widgets() self._init_cache_updates() self._init_update_handlers() self._update_subtitle_cache() else: # Player exists if self.player.is_playing(): self.get_action("play-pause").activate() adjustment = self.seekbar.get_adjustment() adjustment.set_value(0) self.player.stop() self.player.set_path(path) # Playback initialization can fail, e.g. due to missing codecs, # in which case the player itself has shown an error dialog. if not self.player.ready: return self._update_languages_menu() self.update_gui() self.player.play() if not gaupol.conf.video_player.autoplay: self.player.pause() @aeidon.deco.export def _on_load_video_activate(self, *args): """Load a video file.""" gaupol.util.set_cursor_busy(self.window) page = self.get_current_page() dialog = gaupol.VideoDialog( self.window, title=_("Load Video"), button_label=_("_Load")) if page.project.main_file is not None: directory = os.path.dirname(page.project.main_file.path) dialog.set_current_folder(directory) if page.project.video_path is not None: dialog.set_filename(page.project.video_path) gaupol.util.set_cursor_normal(self.window) response = gaupol.util.run_dialog(dialog) path = dialog.get_filename() dialog.destroy() if response != Gtk.ResponseType.OK: return self.load_video(path) @aeidon.deco.export def _on_play_pause_activate(self, *args): """Play or pause video.""" if self.player.is_playing(): self.player.pause() else: # Not playing. self.player.play() @aeidon.deco.export def _on_play_selection_activate(self, *args): """Play the selected subtitles.""" page = self.get_current_page() rows = page.view.get_selected_rows() offset = gaupol.conf.video_player.context_length start = page.project.subtitles[rows[0]].start_seconds - offset end = page.project.subtitles[rows[-1]].end_seconds + offset self.player.play_segment(start, end) def _on_player_state_changed(self, player, state): """Update UI to match `state` of `player`.""" self.play_button.set_icon_name( "media-playback-pause" if state == Gst.State.PLAYING else "media-playback-start") def _on_player_update_seekbar(self, data=None): """Update seekbar from video position.""" if not self.player.ready: return True # to be called again. duration = self.player.get_duration(mode=None) position = self.player.get_position(mode=None) if duration is not None and position is not None: adjustment = self.seekbar.get_adjustment() adjustment.set_value(position/duration) return True # to be called again. def _on_player_update_subtitle(self, data=None): """Update subtitle overlay from video position.""" if not self.player.ready: return True # to be called again. pos = self.player.get_position(aeidon.modes.SECONDS) if pos is None: return True # to be called again. subtitles = list(filter(lambda x: x[0] <= pos <= x[1], self._cache)) if subtitles: text = subtitles[-1][2] if text != self.player.subtitle_text_raw: self.player.subtitle_text = text else: if self.player.subtitle_text: self.player.subtitle_text = "" return True # to be called again. def _on_player_update_volume(self, data=None): """Update volume from player.""" if not self.player.ready: return True # to be called again. self.volume_button.set_value(self.player.volume) return True # to be called again. @aeidon.deco.export def _on_seek_backward_activate(self, *args): """Seek backward.""" pos = self.player.get_position(aeidon.modes.SECONDS) if pos is None: return pos = pos - gaupol.conf.video_player.seek_length pos = max(pos, 0) self.player.seek(pos) @aeidon.deco.export def _on_seek_forward_activate(self, *args): """Seek forward.""" position = self.player.get_position(aeidon.modes.SECONDS) duration = self.player.get_duration(aeidon.modes.SECONDS) if position is None: return if duration is None: return position = position + gaupol.conf.video_player.seek_length position = min(position, duration) self.player.seek(position) @aeidon.deco.export def _on_seek_next_activate(self, *args): """Seek to the start of the next subtitle.""" pos = self.player.get_position(aeidon.modes.SECONDS) if pos is None: return subtitles = list(filter(lambda x: x[0] > pos + 0.001, self._cache)) if not subtitles: return self.player.seek(subtitles[0][0]) @aeidon.deco.export def _on_seek_previous_activate(self, *args): """Seek to the start of the previous subtitle.""" pos = self.player.get_position(aeidon.modes.SECONDS) if pos is None: return subtitles = list(filter(lambda x: x[1] < pos - 0.001, self._cache)) if not subtitles: return self.player.seek(subtitles[-1][0]) @aeidon.deco.export def _on_seek_selection_end_activate(self, *args): """Seek to the end of selection.""" page = self.get_current_page() rows = page.view.get_selected_rows() pos = page.project.subtitles[rows[-1]].end_seconds offset = gaupol.conf.video_player.context_length self.player.seek(max(pos - offset, 0)) @aeidon.deco.export def _on_seek_selection_start_activate(self, *args): """Seek to the start of selection.""" page = self.get_current_page() rows = page.view.get_selected_rows() pos = page.project.subtitles[rows[0]].start_seconds offset = gaupol.conf.video_player.context_length self.player.seek(max(pos - offset, 0)) def _on_seekbar_change_value(self, seekbar, scroll, value, data=None): """Seek to specified position in video.""" self.player.subtitle_text = "" duration = self.player.get_duration(aeidon.modes.SECONDS) if duration is None: return self.player.seek(value * duration) @aeidon.deco.export def _on_set_audio_language_activate(self, action, parameter): """Set the audio language to use.""" # Avoid freeze by pausing prior and playing after. # https://github.com/otsaloma/gaupol/issues/58 self.player.pause() index = int(parameter.get_string()) self.player.audio_track = index self._update_languages_menu() self.player.play() def _on_volume_button_value_changed(self, button, value): """Update video player volume.""" self.player.volume = value self.update_gui() @aeidon.deco.export def _on_volume_down_activate(self, *args): """Decrease volume.""" self.player.volume = self.player.volume - 0.05 self.volume_button.set_value(self.player.volume) self.update_gui() @aeidon.deco.export def _on_volume_up_activate(self, *args): """Increase volume.""" self.player.volume = self.player.volume + 0.05 self.volume_button.set_value(self.player.volume) self.update_gui() def _update_languages_menu(self): """Update the audio language selection menu.""" menu = self.get_menubar_section("audio-languages-placeholder") menu.remove_all() tracks = self.player.get_audio_infos() for i, track in enumerate(tracks): title = track.title or _("Track {:d}").format(i + 1) lang = None if track.language_code is not None: lang = GstTag.tag_get_language_name(track.language_code) if lang is None: lang = track.language_name name = title if lang is None else "{} - [{}]".format(title, lang.title()) action = "win.set-audio-language::{:d}".format(i) menu.append(name, action) if i == self.player.audio_track: action = self.get_action("set-audio-language") action.set_state(str(i)) def _update_subtitle_cache(self, *args, **kwargs): """Update subtitle position and text cache.""" page = self.get_current_page() if self.player is None or page is None: return self._clear_subtitle_cache() self._cache = [(x.start_seconds, x.end_seconds, x.main_text) for x in page.project.subtitles] gaupol-1.11/gaupol/agents/view.py000066400000000000000000000137501422217132500170240ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Changing the visual appearance of application and its documents.""" import aeidon import gaupol class ViewAgent(aeidon.Delegate): """Changing the visual appearance of application and its documents.""" @aeidon.deco.export def _on_set_edit_mode_activate(self, action, parameter): """Change the units in which positions are shown.""" page = self.get_current_page() edit_mode = getattr(aeidon.modes, parameter.get_string()) if edit_mode == page.edit_mode: return gaupol.util.set_cursor_busy(self.window) page.edit_mode = edit_mode gaupol.conf.editor.mode = edit_mode has_focus = page.view.has_focus() focus_row, focus_col = page.view.get_focus() selected_rows = page.view.get_selected_rows() scroller = page.view.get_parent() scroller.remove(page.view) page.view = gaupol.View(edit_mode) self.connect_view_signals(page.view) scroller.add(page.view) scroller.show_all() page.reload_view_all() if focus_row is not None: page.view.set_focus(focus_row, focus_col) page.view.scroll_to_row(focus_row) page.view.select_rows(selected_rows) page.view.props.has_focus = has_focus self.update_gui() gaupol.util.set_cursor_normal(self.window) page.emit("view-created", page.view) @aeidon.deco.export def _on_set_framerate_activate(self, action, parameter): """Change the framerate to use.""" page = self.get_current_page() framerate = getattr(aeidon.framerates, parameter.get_string()) if framerate == page.project.framerate: return gaupol.util.set_cursor_busy(self.window) page.project.set_framerate(framerate, register=None) gaupol.conf.editor.framerate = framerate if page.edit_mode != page.project.main_file.mode: rows = list(range(len(page.project.subtitles))) fields = [x for x in gaupol.fields if x.is_position] page.reload_view(rows, fields) self.update_gui() gaupol.util.set_cursor_normal(self.window) @aeidon.deco.export def _on_set_layout_activate(self, action, parameter): """Change the application window layout direction to use.""" orientation = getattr(gaupol.orientation, parameter.get_string()) if orientation == gaupol.orientation.HORIZONTAL: self.paned.set_orientation(gaupol.orientation.HORIZONTAL) self.player_box.orientation = gaupol.orientation.VERTICAL if orientation == gaupol.orientation.VERTICAL: self.paned.set_orientation(gaupol.orientation.VERTICAL) self.player_box.orientation = gaupol.orientation.HORIZONTAL gaupol.conf.application_window.layout = orientation self.update_gui() @aeidon.deco.export def _on_toggle_duration_column_activate(self, *args): """Show or hide the duration column.""" self._toggle_column(gaupol.fields.DURATION) @aeidon.deco.export def _on_toggle_end_column_activate(self, *args): """Show or hide the end column.""" self._toggle_column(gaupol.fields.END) @aeidon.deco.export def _on_toggle_main_text_column_activate(self, *args): """Show or hide the main text column.""" self._toggle_column(gaupol.fields.MAIN_TEXT) @aeidon.deco.export def _on_toggle_main_toolbar_activate(self, *args): """Show or hide the main toolbar.""" visible = self.main_toolbar.get_visible() self.main_toolbar.set_visible(not visible) self.notebook_separator.set_visible(not visible) gaupol.conf.application_window.show_main_toolbar = not visible self.get_action("toggle-main-toolbar").set_state(not visible) @aeidon.deco.export def _on_toggle_number_column_activate(self, *args): """Show or hide the number column.""" self._toggle_column(gaupol.fields.NUMBER) @aeidon.deco.export def _on_toggle_player_activate(self, *args): """Show or hide the video player.""" visible = self.player_box.get_visible() self.player_box.set_visible(not visible) self.get_action("toggle-player").set_state(not visible) self.update_gui() @aeidon.deco.export def _on_toggle_start_column_activate(self, *args): """Show or hide the start column.""" self._toggle_column(gaupol.fields.START) @aeidon.deco.export def _on_toggle_translation_text_column_activate(self, *args): """Show or hide the translation text column.""" self._toggle_column(gaupol.fields.TRAN_TEXT) def _toggle_column(self, field): """Show or hide column corresponding to `field`.""" page = self.get_current_page() col = getattr(page.view.columns, field.name) column = page.view.get_column(col) visible = column.get_visible() gaupol.util.set_cursor_busy(self.window) column.set_visible(not visible) visible_fields = [] for field in gaupol.fields: col = getattr(page.view.columns, field.name) if page.view.get_column(col).get_visible(): visible_fields.append(field) gaupol.conf.editor.visible_fields = visible_fields self.update_gui() page.view.columns_autosize() gaupol.util.set_cursor_normal(self.window) gaupol-1.11/gaupol/application.py000066400000000000000000000354271422217132500171010ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """GTK user interface controller for :class:`aeidon.Project`.""" import aeidon import gaupol import itertools import sys from aeidon.i18n import _ from gi.repository import Gdk from gi.repository import Gtk __all__ = ("Application",) class ApplicationMeta(type): """ Application metaclass with delegated methods added. Public methods are added to the class dictionary during :meth:`__new__` in order to fool Sphinx (and perhaps other API documentation generators) into thinking that the resulting instantiated class actually contains those methods, which it does not since the methods are removed during :meth:`Application.__init__`. """ def __new__(meta, class_name, bases, dic): new_dict = dic.copy() for agent_class_name in gaupol.agents.__all__: agent_class = getattr(gaupol.agents, agent_class_name) def is_delegate_method(name): value = getattr(agent_class, name) return (callable(value) and hasattr(value, "export") and value.export is True) attr_names = list(filter(is_delegate_method, dir(agent_class))) for attr_name in attr_names: new_dict[attr_name] = getattr(agent_class, attr_name) return type.__new__(meta, class_name, bases, new_dict) class Application(aeidon.Observable, metaclass=ApplicationMeta): """ GTK user interface controller for :class:`aeidon.Project`. :ivar clipboard: Instance of :class:`aeidon.Clipboard` used :ivar counter: Iterator used for naming unsaved documents :ivar _delegations: Dictionary mapping method names to agent methods :ivar extension_manager: Instance of :class:`gaupol.ExtensionManager` used :ivar main_toolbar: A :class:`Gtk.Toolbar` shown below the menubar :ivar notebook: A :class:`Gtk.Notebook` used to hold multiple projects :ivar notebook_separator: A :class:`Gtk.Separator` above the notebook :ivar open_button: The open button on the main toolbar :ivar pages: List of :class:`gaupol.Page` currently open :ivar paned: A :class:`Gtk.Paned` to hold player and subtitles :ivar pattern: Last used search pattern or blank if not used :ivar play_button: The play/pause button on the video player toolbar :ivar player: A :class:`gaupol.VideoPlayer` instance or ``None`` :ivar player_box: Box containing video player etc. :ivar player_toolbar: A :class:`Gtk.Toolbar` for video player actions :ivar recent_manager: Instance of :class:`Gtk.RecentManager` used :ivar redo_button: The redo button on the main toolbar :ivar replacement: Last used search replacement or blank if not used :ivar seekbar: Video player seekbar (a :class:`Gtk.Scale` instance) :ivar statuslabel: Instance of :class:`gaupol.FloatingLabel` used :ivar undo_button: The undo button on the main toolbar :ivar volume_button: A :class:`Gtk.VolumeButton` in the player toolbar :ivar window: A :class:`Gtk.ApplicationWindow` used to hold all the widgets :ivar x_clipboard: A :class:`Gtk.Clipboard` used for desktop-wide copying Signals and their arguments for callback functions: * ``init-done``: application * ``page-added``: application, page * ``page-changed``: application, page * ``page-closed``: application, page * ``page-saved``: application, page * ``page-switched``: application, page * ``pages-reordered``: application, page, number * ``quit``: application """ signals = ( "init-done", "page-added", "page-changed", "page-closed", "page-saved", "page-switched", "pages-reordered", "quit", ) def __init__(self): """Initialize an :class:`Application` instance.""" aeidon.Observable.__init__(self) self.clipboard = aeidon.Clipboard() self.counter = itertools.count(1) self._delegations = {} self.extension_manager = gaupol.ExtensionManager(self) self.main_toolbar = None self.notebook = None self.notebook_separator = None self.open_button = None self.pages = [] self.pattern = "" self.play_button = None self.player = None self.player_box = None self.player_toolbar = None self.recent_manager = Gtk.RecentManager.get_default() self.redo_button = None self.replacement = "" self.seekbar = None self.statuslabel = None self.undo_button = None self.volume_button = None self.window = None self.x_clipboard = None self._init_delegations() self._init_gui() self.extension_manager.find_extensions() self.extension_manager.setup_extensions() self.update_gui() self.window.show() self.emit("init-done") def __getattr__(self, name): """Return method delegated to an agent.""" try: return self._delegations[name] except KeyError: raise AttributeError def __setattr__(self, name, value): """Set value of attribute `name`.""" return aeidon.Observable.__setattr__(self, name, value) def _init_actions(self): """Initialize user-activatable actions.""" for name in gaupol.actions.__all__: action = getattr(gaupol.actions, name)() name = "win.{}".format(action.props.name) if hasattr(gaupol, "appman"): gaupol.appman.set_accels_for_action( name, action.accelerators) callback = "_on_{}_activate".format( action.props.name.replace("-", "_")) action.connect("activate", getattr(self, callback)) self.window.add_action(action) def _init_delegations(self): """Initialize the delegation mappings.""" for agent_class_name in gaupol.agents.__all__: agent = getattr(gaupol.agents, agent_class_name)(self) def is_delegate_method(name): value = getattr(agent, name) return (callable(value) and hasattr(value, "export") and value.export is True) attr_names = list(filter(is_delegate_method, dir(agent))) for attr_name in attr_names: attr_value = getattr(agent, attr_name) if attr_name in self._delegations: raise ValueError("Multiple definitions of {!r}" .format(attr_name)) self._delegations[attr_name] = attr_value # Remove class-level function added by ApplicationMeta. if hasattr(self.__class__, attr_name): delattr(self.__class__, attr_name) def _init_gui(self): """Initialize the user interface.""" vbox = gaupol.util.new_vbox(spacing=0) self._init_x_clipboard() self._init_window() self._init_actions() self._init_main_toolbar(vbox) self._init_paned(vbox) self._init_player_box(self.paned) self._init_notebook(self.paned) self.window.add(vbox) vbox.show_all() self._init_visibilities() def _init_main_toolbar(self, vbox): """Initialize the main toolbar.""" self.main_toolbar = Gtk.Toolbar() style = self.main_toolbar.get_style_context() style.add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR) toolbar_style = gaupol.conf.application_window.toolbar_style self.main_toolbar.set_style(toolbar_style.value) if sys.platform == "win32": self.main_toolbar.set_icon_size(Gtk.IconSize.MENU) gaupol.conf.connect_notify("application_window", "toolbar_style", self) gaupol.util.pack_start(vbox, self.main_toolbar) # win.open-main-files button = Gtk.MenuToolButton( label=_("Open"), icon_name="document-open") button.set_menu(Gtk.Menu()) button.set_is_important(True) button.set_action_name("win.open-main-files") button.set_tooltip_text(_("Open main files")) callback = self._on_open_button_show_menu button.connect("show-menu", callback) self.main_toolbar.insert(button, -1) self.open_button = button # win.save-main-document button = Gtk.ToolButton( label=_("Save"), icon_name="document-save") button.set_is_important(True) button.set_action_name("win.save-main-document") button.set_tooltip_text(_("Save the current main document")) self.main_toolbar.insert(button, -1) self.main_toolbar.insert(Gtk.SeparatorToolItem(), -1) # win.undo-action button = Gtk.MenuToolButton( label=_("Undo"), icon_name="edit-undo") button.set_menu(Gtk.Menu()) button.set_is_important(True) button.set_action_name("win.undo-action") button.set_tooltip_text(_("Undo the last action")) callback = self._on_undo_button_show_menu button.connect("show-menu", callback) self.main_toolbar.insert(button, -1) self.undo_button = button # win.redo-action button = Gtk.MenuToolButton( label=_("Redo"), icon_name="edit-redo") button.set_menu(Gtk.Menu()) button.set_action_name("win.redo-action") button.set_tooltip_text(_("Redo the last undone action")) callback = self._on_redo_button_show_menu button.connect("show-menu", callback) self.main_toolbar.insert(button, -1) self.redo_button = button self.main_toolbar.insert(Gtk.SeparatorToolItem(), -1) # win.insert-subtitles button = Gtk.ToolButton( label=_("Insert"), icon_name="list-add") button.set_action_name("win.insert-subtitles") button.set_tooltip_text(_("Insert new subtitles")) self.main_toolbar.insert(button, -1) # win.remove-subtitles button = Gtk.ToolButton( label=_("Remove"), icon_name="list-remove") button.set_action_name("win.remove-subtitles") button.set_tooltip_text(_("Remove the selected subtitles")) self.main_toolbar.insert(button, -1) self.main_toolbar.insert(Gtk.SeparatorToolItem(), -1) # win.find-and-replace button = Gtk.ToolButton( label=_("Find"), icon_name="edit-find") button.set_action_name("win.find-and-replace") button.set_tooltip_text(_("Search for and replace text")) self.main_toolbar.insert(button, -1) # win.toggle-player button = Gtk.ToggleToolButton( label=_("Video"), icon_name="video-x-generic") button.set_action_name("win.toggle-player") button.set_tooltip_text(_("Show or hide the video player")) self.main_toolbar.insert(button, -1) # win.preview button = Gtk.ToolButton( label=_("Preview"), icon_name="media-playback-start") button.set_action_name("win.preview") button.set_tooltip_text(_("Preview from selected position with a video player")) self.main_toolbar.insert(button, -1) def _init_notebook(self, paned): """Initialize the notebook.""" self.notebook = Gtk.Notebook() self.notebook.set_scrollable(True) self.notebook.set_show_border(False) self.notebook.set_show_tabs(False) self.notebook.drag_dest_set(flags=Gtk.DestDefaults.ALL, targets=None, actions=Gdk.DragAction.COPY) self.notebook.drag_dest_add_uri_targets() aeidon.util.connect(self, "notebook", "drag-data-received") aeidon.util.connect(self, "notebook", "page-reordered") callback = self._on_notebook_switch_page self.notebook.connect_after("switch-page", callback) orientation = Gtk.Orientation.HORIZONTAL self.notebook_separator = Gtk.Separator(orientation=orientation) vbox = gaupol.util.new_vbox(spacing=0) gaupol.util.pack_start(vbox, self.notebook_separator) overlay = Gtk.Overlay() overlay.add(self.notebook) self.statuslabel = gaupol.FloatingLabel() overlay.add_overlay(self.statuslabel) gaupol.util.pack_start_expand(vbox, overlay) paned.add2(vbox) def _init_paned(self, vbox): """Intialize the paned layout.""" orientation = gaupol.conf.application_window.layout self.paned = Gtk.Paned(orientation=orientation) gaupol.util.pack_start_expand(vbox, self.paned) def _init_player_box(self, paned): """Initialize the video player horizontal box.""" # This will actually be added to paned once a video is loaded. layout = gaupol.conf.application_window.layout if layout == Gtk.Orientation.HORIZONTAL: self.player_box = gaupol.util.new_vbox(spacing=0) if layout == Gtk.Orientation.VERTICAL: self.player_box = gaupol.util.new_hbox(spacing=0) def _init_visibilities(self): """Initialize visibilities of hideable widgets.""" conf = gaupol.conf.application_window self.main_toolbar.set_visible(conf.show_main_toolbar) self.notebook_separator.set_visible(conf.show_main_toolbar) self.show_message(None) def _init_window(self): """Initialize the main window.""" self.window = Gtk.ApplicationWindow( application=getattr(gaupol, "appman", None)) self.window.set_show_menubar(True) self.window.set_icon_name("io.otsaloma.gaupol") Gtk.Window.set_default_icon_name("io.otsaloma.gaupol") self.window.set_default_size(*gaupol.conf.application_window.size) self.window.move(*gaupol.conf.application_window.position) if gaupol.conf.application_window.maximized: self.window.maximize() aeidon.util.connect(self, "window", "delete-event") aeidon.util.connect(self, "window", "window-state-event") gaupol.style.load_css(self.window) def _init_x_clipboard(self): """Initialize the desktop-wide, persistent clipboard.""" atom = Gdk.atom_intern("CLIPBOARD", True) self.x_clipboard = Gtk.Clipboard.get(atom) self.x_clipboard.set_can_store(None) gaupol-1.11/gaupol/applicationman.py000066400000000000000000000144151422217132500175670ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2015 Osmo Salomaa # # 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 . """Initializing and managing Gaupol windows.""" # For historical reasons gaupol.Application has been effectively # a Gtk.Window. So, the later introduced Gtk.Application is for # us a gaupol.ApplicationManager and it doesn't actually manage # much, but is more of a main function in the form of a class. import aeidon import argparse import gaupol import os import re import sys from aeidon.i18n import _ from gi.repository import Gio from gi.repository import GObject from gi.repository import Gtk __all__ = ("ApplicationManager",) class ApplicationManager(Gtk.Application): """Initializing and managing Gaupol windows.""" def __init__(self, args): """Initialize an :class:`ApplicationManager` instance.""" GObject.GObject.__init__(self) self.menubar_builder = None self.set_application_id("io.otsaloma.gaupol") self.set_flags(Gio.ApplicationFlags.NON_UNIQUE) self.connect("activate", self._on_activate, args) self.connect("shutdown", self._on_shutdown) def _init_application(self, opts, args): """Initialize application and open files from `args`.""" application = gaupol.Application() paths = list(map(os.path.abspath, args)) application.open_main(paths, opts.encoding) page = application.get_current_page() if page is None: return if opts.translation_file is not None: path = os.path.abspath(opts.translation_file) method = opts.align_method.upper() method = getattr(aeidon.align_methods, method) application.open_translation(path, opts.encoding, method) if opts.video_file is not None: path = os.path.abspath(opts.video_file) page.project.video_path = path application.update_gui() application.load_video(path) if opts.jump is not None: page.view.set_focus(opts.jump) page.view.scroll_to_row(opts.jump) def _init_configuration(self): """Read configuration values from file.""" gaupol.conf.path = os.path.join( aeidon.CONFIG_HOME_DIR, "gaupol.conf") gaupol.conf.read_from_file() if (gaupol.conf.general.dark_theme or os.getenv("GTK_THEME", "").endswith(":dark")): Gtk.Settings.get_default().set_property( "gtk-application-prefer-dark_theme", True) def _init_menubar(self): """Initialize the window menubar.""" path = os.path.join(aeidon.DATA_DIR, "ui", "menubar.ui") self.menubar_builder = Gtk.Builder.new_from_file(path) self.set_menubar(self.menubar_builder.get_object("menubar")) def _on_activate(self, manager, args): """Initialize application and open files from `args`.""" opts, args = self._parse_args(args) sys.excepthook = gaupol.util.show_exception self._init_configuration() self._init_menubar() self._init_application(opts, args) def _on_shutdown(self, manager): """Terminate application.""" gaupol.conf.write_to_file() def _parse_args(self, args): """Parse and return options and arguments from `args`.""" parser = argparse.ArgumentParser( usage=_("gaupol [OPTION...] [FILE...] [+[NUM]]")) parser.add_argument( "files", metavar=_("FILE..."), nargs="*", default=[], help=_("subtitle files to open")) parser.add_argument( "--version", action="version", version="gaupol {}".format(gaupol.__version__)) parser.add_argument( "-e", "--encoding", action="store", metavar=_("ENCODING"), dest="encoding", default=None, help=_("set the character encoding used to open files")) parser.add_argument( "--list-encodings", action="store_true", dest="list_encodings", default=False, help=_("list all available character encodings")) parser.add_argument( "-t", "--translation-file", action="store", metavar=_("FILE"), dest="translation_file", default=None, help=_("open translation file")) parser.add_argument( "-a", "--align-method", action="store", metavar=_("METHOD"), dest="align_method", default="position", choices=["number", "position"], help=_("method used to align translation subtitles: 'number' or 'position'")) parser.add_argument( "-v", "--video-file", action="store", metavar=_("FILE"), dest="video_file", default=None, help=_("select video file")) args = parser.parse_args() args.jump = None if args.list_encodings: return self._print_encodings() if not args.encoding in (None, "auto"): args.encoding = aeidon.encodings.translate_code(args.encoding) # Parse row to jump to. If found, remove from args.files. for arg in filter(re.compile(r"\+\d*").match, args.files): args.jump = max(0, int(arg[1:]) - 1) if arg[1:] else -1 args.files.remove(arg) return args, args.files def _print_encodings(self): """Print available character encodings and exit.""" encodings = [x[0] for x in aeidon.encodings.get_valid()] if aeidon.util.chardet_available(): encodings.insert(0, "auto") print(", ".join(encodings)) raise SystemExit(0) gaupol-1.11/gaupol/assistants.py000066400000000000000000001347321422217132500167710ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 . """Assistant to guide through multiple text correction tasks.""" import aeidon import gaupol import os from aeidon.i18n import _, n_ from gi.repository import Gdk from gi.repository import GLib from gi.repository import GObject from gi.repository import Gtk from gi.repository import Pango __all__ = ("TextAssistant", "TextAssistantPage") class TextAssistantPage(Gtk.Box): """ Baseclass for pages of :class:`TextAssistant`. :ivar description: One-line description used in the introduction page :ivar handle: Unique unlocalized name for internal references :ivar page_title: Short string used as configuration page title :ivar page_type: A :class:`Gtk.AssistantPageType` constant :ivar title: Short title used in the introduction page Of these attributes, :attr:`description`, :attr:`handle` and :attr:`title` are only required for pages of type :attr:`Gtk.AssistantPageType.CONTENT`. """ def __init__(self, assistant): """Initialize a :class:`TextAssistantPage` instance.""" GObject.GObject.__init__(self, orientation=Gtk.Orientation.VERTICAL) self.assistant = assistant self.description = None self.handle = None self.page_title = None self.page_type = None self.title = None class BuilderPage(TextAssistantPage): """Baseclass for pages of :class:`TextAssistant` built with GtkBuilder.""" _widgets = [] def __init__(self, assistant, basename): """Initialize a :class:`BuilderPage` instance.""" TextAssistantPage.__init__(self, assistant) self._builder = Gtk.Builder() self._builder.set_translation_domain("gaupol") self._builder.add_from_file(os.path.join( aeidon.DATA_DIR, "ui", "text-assistant", basename)) self._builder.connect_signals(self) self._set_attributes(self._widgets) container = self._builder.get_object("main_container") window = container.get_parent() window.remove(container) self.add(container) gaupol.util.idle_add(window.destroy) def _set_attributes(self, widgets): """Assign all names in `widgets` as attributes of `self`.""" for name in widgets: widget = self._builder.get_object(name) setattr(self, "_{}".format(name), widget) class IntroductionPage(BuilderPage): """Page for listing all text correction tasks.""" _widgets = ["columns_combo", "subtitles_combo", "tree_view"] def __init__(self, assistant): """Initialize a :class:`IntroductionPage` instance.""" BuilderPage.__init__(self, assistant, "introduction-page.ui") # TRANSLATORS: Keep these page titles short, since they # affect the width of the text correction assistant sidebar. self.page_title = _("Tasks and Target") self.page_type = Gtk.AssistantPageType.INTRO self._init_columns_combo() self._init_subtitles_combo() self._init_tree_view() self._init_values() def get_field(self): """Return the selected field.""" index = self._columns_combo.get_active() return [gaupol.fields.MAIN_TEXT, gaupol.fields.TRAN_TEXT][index] def get_selected_pages(self): """Return selected content pages.""" store = self._tree_view.get_model() return [x[0] for x in store if x[1]] def get_target(self): """Return the selected target.""" index = self._subtitles_combo.get_active() return [gaupol.targets.SELECTED, gaupol.targets.CURRENT, gaupol.targets.ALL][index] def _init_columns_combo(self): """Initalize the columns target combo box.""" store = Gtk.ListStore(str) self._columns_combo.set_model(store) store.append((_("Correct texts in the text column"),)) store.append((_("Correct texts in the translation column"),)) renderer = Gtk.CellRendererText() self._columns_combo.pack_start(renderer, expand=True) self._columns_combo.add_attribute(renderer, "text", 0) def _init_subtitles_combo(self): """Initalize the subtitles target combo box.""" store = Gtk.ListStore(str) self._subtitles_combo.set_model(store) store.append((_("Correct texts in selected subtitles"),)) store.append((_("Correct texts in current project"),)) store.append((_("Correct texts in all open projects"),)) renderer = Gtk.CellRendererText() self._subtitles_combo.pack_start(renderer, expand=True) self._subtitles_combo.add_attribute(renderer, "text", 0) def _init_tree_view(self): """Initialize the tree view of tasks.""" store = Gtk.ListStore(object, bool, str) self._tree_view.set_model(store) selection = self._tree_view.get_selection() selection.set_mode(Gtk.SelectionMode.SINGLE) renderer = Gtk.CellRendererToggle() renderer.props.activatable = True renderer.props.xpad = 6 renderer.connect("toggled", self._on_tree_view_cell_toggled) column = Gtk.TreeViewColumn("", renderer, active=1) self._tree_view.append_column(column) renderer = Gtk.CellRendererText() renderer.props.ellipsize = Pango.EllipsizeMode.END column = Gtk.TreeViewColumn("", renderer, markup=2) self._tree_view.append_column(column) def _init_values(self): """Initialize default values for widgets.""" self._columns_combo.set_active({ gaupol.fields.MAIN_TEXT: 0, gaupol.fields.TRAN_TEXT: 1, }[gaupol.conf.text_assistant.field]) self._subtitles_combo.set_active({ gaupol.targets.SELECTED: 0, gaupol.targets.CURRENT: 1, gaupol.targets.ALL: 2, }[gaupol.conf.text_assistant.target]) def _on_columns_combo_changed(self, *args): """Save the selected field.""" gaupol.conf.text_assistant.field = self.get_field() def _on_subtitles_combo_changed(self, *args): """Save the selected target.""" gaupol.conf.text_assistant.target = self.get_target() def _on_tree_view_cell_toggled(self, renderer, path): """Toggle and save task check button value.""" store = self._tree_view.get_model() store[path][1] = not store[path][1] store[path][0].set_visible(store[path][1]) pages = [x.handle for x in self.get_selected_pages()] gaupol.conf.text_assistant.pages = pages def populate_tree_view(self, content_pages): """Populate the tree view with tasks from `content_pages`.""" self._tree_view.get_model().clear() store = self._tree_view.get_model() pages = gaupol.conf.text_assistant.pages for page in content_pages: title = GLib.markup_escape_text(page.title) description = GLib.markup_escape_text(page.description) markup = "{}\n{}".format(title, description) page.set_visible(page.handle in pages) store.append((page, page.handle in pages, markup)) self._tree_view.get_selection().unselect_all() class LocalePage(BuilderPage): """Page with script, language and coutry based pattern selection.""" _ui_file_basename = NotImplementedError _widgets = [ "country_combo", "country_label", "language_combo", "language_label", "script_combo", "script_label", "tree_view", ] def __init__(self, assistant): """Initialize a :class:`LocalePage` instance.""" BuilderPage.__init__(self, assistant, self._ui_file_basename) self.conf = None self._init_attributes() self._init_tree_view() self._init_combo_boxes() self._init_values() def correct_texts(self, project, indices, doc): """Correct texts in `project`.""" raise NotImplementedError def _filter_patterns(self, patterns): """Return a subset of `patterns` to show.""" return patterns def _get_country(self): """Return the selected country or ``None``.""" if not self._country_combo.get_sensitive(): return None index = self._country_combo.get_active() if index < 0: return None store = self._country_combo.get_model() value = store[index][0] return None if value == "other" else value def _get_language(self): """Return the selected language or ``None``.""" if not self._language_combo.get_sensitive(): return None index = self._language_combo.get_active() if index < 0: return None store = self._language_combo.get_model() value = store[index][0] return None if value == "other" else value def _get_script(self): """Return the selected script or ``None``.""" if not self._script_combo.get_sensitive(): return None index = self._script_combo.get_active() if index < 0: return None store = self._script_combo.get_model() value = store[index][0] return None if value == "other" else value def _init_attributes(self): """Initialize values of page attributes.""" raise NotImplementedError def _init_combo(self, combo_box): """Initialize `combo_box` and populate with `items`.""" store = Gtk.ListStore(str, str) combo_box.set_model(store) renderer = Gtk.CellRendererText() combo_box.pack_start(renderer, expand=True) combo_box.add_attribute(renderer, "text", 1) func = gaupol.util.separate_combo combo_box.set_row_separator_func(func, None) def _init_combo_boxes(self): """Initialize and populate combo boxes.""" self._init_combo(self._script_combo) self._init_combo(self._language_combo) self._init_combo(self._country_combo) self._populate_script_combo() self._populate_language_combo() self._populate_country_combo() def _init_tree_view(self): """Initialize the tree view of individual corrections.""" store = Gtk.ListStore(object, bool, bool, str) store_filter = store.filter_new() store_filter.set_visible_column(1) self._tree_view.set_model(store_filter) selection = self._tree_view.get_selection() selection.set_mode(Gtk.SelectionMode.SINGLE) renderer = Gtk.CellRendererToggle() renderer.props.activatable = True renderer.props.xpad = 6 renderer.connect("toggled", self._on_tree_view_cell_toggled) column = Gtk.TreeViewColumn("", renderer, active=2) self._tree_view.append_column(column) renderer = Gtk.CellRendererText() renderer.props.ellipsize = Pango.EllipsizeMode.END column = Gtk.TreeViewColumn("", renderer, markup=3) self._tree_view.append_column(column) def _init_values(self): """Initialize default values for widgets.""" pass def _on_country_combo_changed(self, combo_box): """Populate the tree view with a subset patterns.""" self.conf.country = self._get_country() or "" self._populate_tree_view() def _on_language_combo_changed(self, combo_box): """Populate the tree view with a subset patterns.""" language = self._get_language() sensitive = language is not None self._populate_country_combo() self._country_combo.set_sensitive(sensitive) self._country_label.set_sensitive(sensitive) self.conf.language = language or "" self._populate_tree_view() def _on_script_combo_changed(self, combo_box): """Populate the tree view with a subset patterns.""" script = self._get_script() sensitive = script is not None self._populate_language_combo() self._language_combo.set_sensitive(sensitive) self._language_label.set_sensitive(sensitive) language = self._get_language() sensitive = sensitive and language is not None self._populate_country_combo() self._country_combo.set_sensitive(sensitive) self._country_label.set_sensitive(sensitive) self.conf.script = script or "" self._populate_tree_view() def _on_tree_view_cell_toggled(self, renderer, path): """Toggle the check button value.""" store_filter = self._tree_view.get_model() store = store_filter.get_model() path = Gtk.TreePath.new_from_string(path) path = store_filter.convert_path_to_child_path(path) name = store[path][0].get_name(False) enabled = not store[path][2] for i in range(len(store)): # Toggle all patterns with the same name. if store[i][0].get_name(False) == name: store[i][0].enabled = enabled store[i][2] = enabled def _populate_combo(self, combo_box, items, active): """Populate `combo_box` with `items`.""" store = combo_box.get_model() combo_box.set_model(None) store.clear() for code, name in items: store.append((code, name)) if len(store) > 0: store.append((gaupol.COMBO_SEPARATOR, "")) store.append(("other", _("Other"))) combo_box.set_active(len(store) - 1) for i in range(len(store)): if store[i][0] == active and active: combo_box.set_active(i) combo_box.set_model(store) def _populate_country_combo(self): """Populate the country combo box.""" script = self._get_script() language = self._get_language() codes = self._manager.get_countries(script, language) names = list(map(aeidon.countries.code_to_name, codes)) items = [(codes[i], names[i]) for i in range(len(codes))] items.sort(key=lambda x: x[1]) self._populate_combo(self._country_combo, items, self.conf.country) def _populate_language_combo(self): """Populate the language combo box.""" script = self._get_script() codes = self._manager.get_languages(script) names = list(map(aeidon.languages.code_to_name, codes)) items = [(codes[i], names[i]) for i in range(len(codes))] items.sort(key=lambda x: x[1]) self._populate_combo(self._language_combo, items, self.conf.language) def _populate_script_combo(self): """Populate the script combo box.""" codes = self._manager.get_scripts() names = list(map(aeidon.scripts.code_to_name, codes)) items = [(codes[i], names[i]) for i in range(len(codes))] items.sort(key=lambda x: x[1]) self._populate_combo(self._script_combo, items, self.conf.script) def _populate_tree_view(self): """Populate the tree view with a subset patterns.""" store_filter = self._tree_view.get_model() store = store_filter.get_model() store.clear() script = self._get_script() language = self._get_language() country = self._get_country() patterns = self._manager.get_patterns(script, language, country) patterns = self._filter_patterns(patterns) names_entered = set(()) for pattern in patterns: name = pattern.get_name() visible = not name in names_entered names_entered.add(name) name = GLib.markup_escape_text(name) description = pattern.get_description() description = GLib.markup_escape_text(description) markup = "{}\n{}".format(name, description) store.append((pattern, visible, pattern.enabled, markup)) self._tree_view.get_selection().unselect_all() class CapitalizationPage(LocalePage): """Page for capitalizing texts in subtitles.""" _ui_file_basename = "capitalization-page.ui" def correct_texts(self, project, indices, doc): """Correct texts in `project`.""" script = self._get_script() language = self._get_language() country = self._get_country() self._manager.save_config(script, language, country) patterns = self._manager.get_patterns(script, language, country) project.capitalize(indices, doc, patterns) def _init_attributes(self): """Initialize values of page attributes.""" self._manager = aeidon.PatternManager("capitalization") self.conf = gaupol.conf.capitalization self.description = _("Capitalize texts written in lower case") self.handle = "capitalization" # TRANSLATORS: Keep these page titles short, since they # affect the width of the text correction assistant sidebar. self.page_title = _("Capitalization Patterns") self.page_type = Gtk.AssistantPageType.CONTENT self.title = _("Capitalize texts") class CommonErrorPage(LocalePage): """Page for correcting common human and OCR errors.""" _ui_file_basename = "common-error-page.ui" _widgets = ["human_check", "ocr_check"] + LocalePage._widgets def correct_texts(self, project, indices, doc): """Correct texts in `project`.""" script = self._get_script() language = self._get_language() country = self._get_country() self._manager.save_config(script, language, country) patterns = self._manager.get_patterns(script, language, country) project.correct_common_errors(indices, doc, patterns) def _init_attributes(self): """Initialize values of page attributes.""" self._manager = aeidon.PatternManager("common-error") self.conf = gaupol.conf.common_error self.description = _("Correct common errors made by humans or image recognition software") self.handle = "common-error" # TRANSLATORS: Keep these page titles short, since they # affect the width of the text correction assistant sidebar. self.page_title = _("Common Error Patterns") self.page_type = Gtk.AssistantPageType.CONTENT self.title = _("Correct common errors") def _filter_patterns(self, patterns): """Return a subset of `patterns` to show.""" def use_pattern(pattern): classes = set(pattern.get_field_list("Classes")) return(bool(classes & set(self.conf.classes))) return list(filter(use_pattern, patterns)) def _init_values(self): """Initialize default values for widgets.""" self._human_check.set_active("Human" in self.conf.classes) self._ocr_check.set_active("OCR" in self.conf.classes) def _on_human_check_toggled(self, check_button): """Populate the tree view with a subset patterns.""" if check_button.get_active(): self.conf.classes.append("Human") self.conf.classes = sorted(set(self.conf.classes)) elif "Human" in self.conf.classes: self.conf.classes.remove("Human") self._populate_tree_view() def _on_ocr_check_toggled(self, check_button): """Populate the tree view with a subset patterns.""" if check_button.get_active(): self.conf.classes.append("OCR") self.conf.classes = sorted(set(self.conf.classes)) elif "OCR" in self.conf.classes: self.conf.classes.remove("OCR") self._populate_tree_view() class HearingImpairedPage(LocalePage): """Page for removing hearing impaired parts from subtitles.""" _ui_file_basename = "hearing-impaired-page.ui" def correct_texts(self, project, indices, doc): """Correct texts in `project`.""" script = self._get_script() language = self._get_language() country = self._get_country() self._manager.save_config(script, language, country) patterns = self._manager.get_patterns(script, language, country) project.remove_hearing_impaired(indices, doc, patterns) def _init_attributes(self): """Initialize values of page attributes.""" self._manager = aeidon.PatternManager("hearing-impaired") self.conf = gaupol.conf.hearing_impaired self.description = _("Remove explanatory texts meant for the hearing impaired") self.handle = "hearing-impaired" # TRANSLATORS: Keep these page titles short, since they # affect the width of the text correction assistant sidebar. self.page_title = _("Hearing Impaired Patterns") self.page_type = Gtk.AssistantPageType.CONTENT self.title = _("Remove hearing impaired texts") class JoinSplitWordsPage(BuilderPage): """Page for joining or splitting words based on spell-check suggestions.""" _widgets = ["language_button", "join_check", "split_check"] def __init__(self, assistant): """Initialize a :class:`JoinSplitWordsPage` instance.""" BuilderPage.__init__(self, assistant, "join-split-page.ui") self.description = _("Use spell-check suggestions to fix whitespace detection errors of image recognition software") self.handle = "join-split-words" # TRANSLATORS: Keep these page titles short, since they # affect the width of the text correction assistant sidebar. self.page_title = _("Joining and Splitting Words") self.page_type = Gtk.AssistantPageType.CONTENT self.title = _("Join or Split Words") self._init_values() def correct_texts(self, project, indices, doc): """Correct texts in `project`.""" language = gaupol.conf.spell_check.language if gaupol.conf.join_split_words.join: try: # Can fail if the spell-check backend or dictionary is missing. project.spell_check_join_words(indices, doc, language) except Exception as error: return self._show_error_dialog(str(error)) if gaupol.conf.join_split_words.split: try: # Can fail if the spell-check backend or dictionary is missing. project.spell_check_split_words(indices, doc, language) except Exception as error: return self._show_error_dialog(str(error)) def _init_values(self): """Initialize default values for widgets.""" language = gaupol.conf.spell_check.language language = aeidon.locales.code_to_name(language) self._language_button.set_label(language) self._join_check.set_active(gaupol.conf.join_split_words.join) self._split_check.set_active(gaupol.conf.join_split_words.split) def _on_join_check_toggled(self, check_button, *args): """Save value of join option.""" gaupol.conf.join_split_words.join = check_button.get_active() def _on_language_button_clicked(self, button, *args): """Show a language dialog and update `button` label.""" gaupol.util.set_cursor_busy(self.assistant) dialog = gaupol.LanguageDialog(self.assistant, False) gaupol.util.set_cursor_normal(self.assistant) gaupol.util.flash_dialog(dialog) language = gaupol.conf.spell_check.language language = aeidon.locales.code_to_name(language) self._language_button.set_label(language) def _on_split_check_toggled(self, check_button, *args): """Save value of split option.""" gaupol.conf.join_split_words.split = check_button.get_active() def _show_error_dialog(self, message): """Show an error dialog after failing to load dictionary.""" name = gaupol.conf.spell_check.language name = aeidon.locales.code_to_name(name) title = _('Failed to load dictionary for language "{}"').format(name) dialog = gaupol.ErrorDialog(self.get_ancestor(Gtk.Window), title, message) dialog.add_button(_("_OK"), Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK) gaupol.util.flash_dialog(dialog) class LineBreakPage(LocalePage): """Page for breaking text into lines.""" _ui_file_basename = "line-break-page.ui" def correct_texts(self, project, indices, doc): """Correct texts in `project`.""" script = self._get_script() language = self._get_language() country = self._get_country() self._manager.save_config(script, language, country) patterns = self._manager.get_patterns(script, language, country) length_func = gaupol.ruler.get_length_function(self.conf.length_unit) skip = self.conf.use_skip_max_length or self.conf.use_skip_max_lines project.break_lines(indices=indices, doc=doc, patterns=patterns, length_func=length_func, max_length=self.conf.max_length, max_lines=self.conf.max_lines, skip=skip, max_skip_length=self._max_skip_length, max_skip_lines=self._max_skip_lines) def _init_attributes(self): """Initialize values of page attributes.""" self._manager = aeidon.PatternManager("line-break") self.conf = gaupol.conf.line_break self.description = _("Break text into lines of defined length") self.handle = "line-break" # TRANSLATORS: Keep these page titles short, since they # affect the width of the text correction assistant sidebar. self.page_title = _("Line-Break Patterns") self.page_type = Gtk.AssistantPageType.CONTENT self.title = _("Break lines") @property def _max_skip_length(self): """Return the maximum line length to skip.""" if self.conf.use_skip_max_length: return self.conf.skip_max_length return 32768 @property def _max_skip_lines(self): """Return the maximum amount of lines to skip.""" if self.conf.use_skip_max_lines: return self.conf.skip_max_lines return 32768 class LineBreakOptionsPage(BuilderPage): """Page for editing line-break options.""" _widgets = [ "max_length_spin", "max_lines_spin", "max_skip_length_spin", "max_skip_lines_spin", "skip_length_check", "skip_lines_check", "skip_unit_combo", "unit_combo", ] def __init__(self, assistant): """Initialize a :class:`LineBreakOptionsPage` instance.""" BuilderPage.__init__(self, assistant, "line-break-options-page.ui") self.conf = gaupol.conf.line_break # TRANSLATORS: Keep these page titles short, since they # affect the width of the text correction assistant sidebar. self.page_title = _("Line-Break Options") self.page_type = Gtk.AssistantPageType.CONTENT self._init_unit_combo(self._unit_combo) self._init_unit_combo(self._skip_unit_combo) self._init_values() def _init_unit_combo(self, combo_box): """Initialize line length unit `combo_box`.""" store = Gtk.ListStore(str) combo_box.set_model(store) for label in (x.label for x in gaupol.length_units): store.append((label,)) renderer = Gtk.CellRendererText() combo_box.pack_start(renderer, expand=True) combo_box.add_attribute(renderer, "text", 0) def _init_values(self): """Initialize default values for widgets.""" self._max_length_spin.set_value(self.conf.max_length) self._max_lines_spin.set_value(self.conf.max_lines) self._max_skip_length_spin.set_value(self.conf.skip_max_length) self._max_skip_lines_spin.set_value(self.conf.skip_max_lines) self._skip_length_check.set_active(self.conf.use_skip_max_length) self._skip_lines_check.set_active(self.conf.use_skip_max_lines) self._skip_unit_combo.set_active(self.conf.length_unit) self._unit_combo.set_active(self.conf.length_unit) def _on_max_length_spin_value_changed(self, spin_button): """Save maximum line length value.""" self.conf.max_length = spin_button.get_value_as_int() def _on_max_lines_spin_value_changed(self, spin_button): """Save maximum line amount value.""" self.conf.max_lines = spin_button.get_value_as_int() def _on_max_skip_length_spin_value_changed(self, spin_button): """Save maximum line length to skip value.""" self.conf.skip_max_length = spin_button.get_value_as_int() def _on_max_skip_lines_spin_value_changed(self, spin_button): """Save maximum line amount to skip value.""" self.conf.skip_max_lines = spin_button.get_value_as_int() def _on_skip_length_check_toggled(self, check_button): """Save skip by line length value.""" use_skip = check_button.get_active() self.conf.use_skip_max_length = use_skip self._max_skip_length_spin.set_sensitive(use_skip) self._skip_unit_combo.set_sensitive(use_skip) def _on_skip_lines_check_toggled(self, check_button): """Save skip by line amount value.""" use_skip = check_button.get_active() self.conf.use_skip_max_lines = use_skip self._max_skip_lines_spin.set_sensitive(use_skip) def _on_skip_unit_combo_changed(self, combo_box): """Save and sync length unit value of `combo_box.""" index = combo_box.get_active() length_unit = gaupol.length_units[index] self.conf.length_unit = length_unit self._unit_combo.set_active(index) def _on_unit_combo_changed(self, combo_box): """Save and sync length unit value of `combo_box.""" index = combo_box.get_active() length_unit = gaupol.length_units[index] self.conf.length_unit = length_unit self._skip_unit_combo.set_active(index) class ProgressPage(BuilderPage): """Page for showing progress of text corrections.""" _widgets = ["message_label", "progress_bar", "status_label", "task_label"] def __init__(self, assistant): """Initialize a :class:`ProgressPage` instance.""" BuilderPage.__init__(self, assistant, "progress-page.ui") self._current_task = None self._total_tasks = None # TRANSLATORS: Keep these page titles short, since they # affect the width of the text correction assistant sidebar. self.page_title = _("Correcting Texts") self.page_type = Gtk.AssistantPageType.PROGRESS self._init_values() def _init_values(self): """Initalize default values for widgets.""" message = _("Each task is now being run on each project.") self._message_label.set_text(message) self.reset(100) def bump_progress(self, n=1): """Bump the current progress by `n`.""" self.set_progress(self._current_task + n) def reset(self, total, clear_text=False): """Set `total` as the amount of tasks to be run.""" self._current_task = 0 self._total_tasks = total self.set_progress(0, total) self.set_project_name("") self.set_task_name("") if clear_text: self._progress_bar.set_text("") gaupol.util.iterate_main() def set_progress(self, current, total=None): """Set current as the task progress status.""" total = total or self._total_tasks fraction = current / total if total > 0 else 0 self._progress_bar.set_fraction(fraction) text = _("{current:d} of {total:d} tasks complete") self._progress_bar.set_text(text.format(**locals())) self._current_task = current self._total_tasks = total gaupol.util.iterate_main() def set_project_name(self, name): """Set `name` as the currently checked project.""" text = _("Project: {}").format(name) self._status_label.set_text(text) gaupol.util.iterate_main() def set_task_name(self, name): """Set `name` as the currently performed task.""" text = _("Task: {}").format(name) self._task_label.set_text(text) gaupol.util.iterate_main() class ConfirmationPage(BuilderPage): """Page to confirm changes made after performing all tasks.""" _widgets = [ "mark_all_button", "preview_button", "remove_check", "tree_view", "unmark_all_button", ] def __init__(self, assistant): """Initialize a :class:`ConfirmationPage` instance.""" BuilderPage.__init__(self, assistant, "confirmation-page.ui") self.application = None self.conf = gaupol.conf.text_assistant self.doc = None # TRANSLATORS: Keep these page titles short, since they # affect the width of the text correction assistant sidebar. self.page_title = _("Confirm Changes") self.page_type = Gtk.AssistantPageType.CONFIRM self._init_tree_view() self._init_values() def _add_text_column(self, index, ref_index, title): """Add a multiline text column to the tree view.""" renderer = gaupol.MultilineDiffCellRenderer() renderer.set_show_lengths(True) renderer.props.editable = (index == 4) renderer.props.ellipsize = Pango.EllipsizeMode.END renderer.props.font = gaupol.util.get_font() renderer.props.ref_type = ref_index - index renderer.props.yalign = 0 renderer.props.xpad = 4 renderer.props.ypad = 4 column = Gtk.TreeViewColumn( title, renderer, text=index, ref_text=ref_index) column.set_resizable(True) column.set_expand(True) self._tree_view.append_column(column) def _can_preview(self): """Return ``True`` if preview is possible.""" row = self._get_selected_row() if row is None: return False store = self._tree_view.get_model() page = store[row][0] if page is None: return False return bool(page.project.video_path and page.project.main_file) def get_confirmed_changes(self): """Return a sequence of changes marked as accepted.""" changes = [] store = self._tree_view.get_model() for row in (x for x in store if x[2]): page, index, accept, orig, new = row changes.append((page, index, orig, new)) return tuple(changes) def _get_selected_row(self): """Return the selected row in the tree view or ``None``.""" selection = self._tree_view.get_selection() store, itr = selection.get_selected() if itr is None: return None path = store.get_path(itr) return gaupol.util.tree_path_to_row(path) def _init_tree_view(self): """Initialize the tree view of corrections.""" # page, index, accept, original text, new text store = Gtk.ListStore(object, int, bool, str, str) self._tree_view.set_model(store) selection = self._tree_view.get_selection() selection.set_mode(Gtk.SelectionMode.SINGLE) selection.connect("changed", self._on_tree_view_selection_changed) renderer = Gtk.CellRendererToggle() renderer.props.activatable = True renderer.props.xpad = 6 renderer.connect("toggled", self._on_tree_view_cell_toggled) column = Gtk.TreeViewColumn(_("Accept"), renderer, active=2) column.set_resizable(True) self._tree_view.append_column(column) if gaupol.conf.editor.use_zebra_stripes: callback = self._on_renderer_set_background column.set_cell_data_func(renderer, callback, None) self._add_text_column(3, 4, _("Original Text")) self._add_text_column(4, 3, _("Corrected Text")) column = self._tree_view.get_column(2) renderer = column.get_cells()[0] renderer.connect("edited", self._on_tree_view_cell_edited) def _init_values(self): """Initialize default values for widgets.""" self._remove_check.set_active(self.conf.remove_blank) self._preview_button.set_sensitive(False) def _on_mark_all_button_clicked(self, *args): """Set all accept column values to ``True``.""" store = self._tree_view.get_model() for i in range(len(store)): store[i][2] = True def _on_preview_button_clicked(self, *args): """Preview original text in a video player.""" row = self._get_selected_row() store = self._tree_view.get_model() page = store[row][0] index = store[row][1] position = page.project.subtitles[index].start self.application.preview(page, position, self.doc) def _on_remove_check_toggled(self, check_button): """Save remove blank subtitles value.""" self.conf.remove_blank = check_button.get_active() def _on_renderer_set_background(self, column, renderer, store, itr, data): """Set zerba-striped backgrounds for all columns.""" path = self._tree_view.get_model().get_path(itr) row = gaupol.util.tree_path_to_row(path) color = (gaupol.util.get_zebra_color(self._tree_view) if row % 2 == 0 else None) for column in self._tree_view.get_columns(): for renderer in column.get_cells(): renderer.props.cell_background_rgba = color def _on_tree_view_cell_edited(self, renderer, path, text): """Edit text in the corrected text column.""" store = self._tree_view.get_model() store[path][4] = text def _on_tree_view_cell_toggled(self, renderer, path): """Toggle accept column value.""" store = self._tree_view.get_model() store[path][2] = not store[path][2] def _on_tree_view_selection_changed(self, *args): """Update preview button sensitivity.""" self._preview_button.set_sensitive(self._can_preview()) def _on_unmark_all_button_clicked(self, *args): """Set all accept column values to ``False``.""" store = self._tree_view.get_model() for i in range(len(store)): store[i][2] = False def populate_tree_view(self, changes): """Populate the tree view of changes to texts.""" self._tree_view.get_model().clear() store = self._tree_view.get_model() for page, index, orig, new in changes: store.append((page, index, True, orig, new)) self._tree_view.get_selection().unselect_all() class TextAssistant(Gtk.Assistant): """Assistant to guide through multiple text correction tasks.""" def __init__(self, parent, application): """Initialize a :class:`TextAssistant` instance.""" GObject.GObject.__init__(self) self._confirmation_page = ConfirmationPage(self) self._introduction_page = IntroductionPage(self) self._previous_page = None self._progress_page = ProgressPage(self) self.application = application self._init_properties() self._init_signal_handlers() self.resize(*gaupol.conf.text_assistant.size) if gaupol.conf.text_assistant.maximized: self.maximize() self.set_modal(True) self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) self.set_transient_for(parent) def add_page(self, page): """Add `page` and configure its properties.""" page.show_all() self.append_page(page) self.set_page_type(page, page.page_type) self.set_page_title(page, page.page_title) if page.page_type != Gtk.AssistantPageType.PROGRESS: self.set_page_complete(page, True) def add_pages(self, pages): """Add associated `pages` and configure their properties.""" for page in pages: self.add_page(page) def on_notify_visible(page, prop, pages): for page in pages[1:]: page.set_visible(pages[0].get_visible()) pages[0].connect("notify::visible", on_notify_visible, pages) def _copy_project(self, project): """Return a copy of `project` with some same properties.""" copy = aeidon.Project(project.framerate) copy.main_file = project.main_file copy.tran_file = project.tran_file copy.subtitles = [x.copy() for x in project.subtitles] return copy def _correct_texts(self, assistant_pages): """Correct texts by all pages and present changes.""" changes = [] target = self._introduction_page.get_target() field = self._introduction_page.get_field() doc = gaupol.util.text_field_to_document(field) rows = self.application.get_target_rows(target) application_pages = self.application.get_target_pages(target) total = len(application_pages) * len(assistant_pages) self._progress_page.reset(total) for application_page in application_pages: name = application_page.get_main_basename() self._progress_page.set_project_name(name) project = application_page.project # Initialize a dummy project to apply corrections in # to be able to present those corrections for approval and # to finally be able to apply only approved corrections. dummy = self._copy_project(project) static_subtitles = dummy.subtitles[:] for page in assistant_pages: self._progress_page.set_task_name(page.title) page.correct_texts(dummy, rows, doc) self._progress_page.bump_progress() for i in range(len(static_subtitles)): orig = project.subtitles[i].get_text(doc) new = static_subtitles[i].get_text(doc) if orig == new: continue changes.append((application_page, i, orig, new)) self._prepare_confirmation_page(doc, changes) self.set_current_page(self.get_current_page() + 1) def _init_properties(self): """Initialize assistant properties.""" self.set_title(_("Correct Texts")) self.add_page(self._introduction_page) self.add_page(HearingImpairedPage(self)) if (aeidon.SpellChecker.available() and aeidon.SpellChecker.list_languages()): self.add_page(JoinSplitWordsPage(self)) self.add_page(CommonErrorPage(self)) self.add_page(CapitalizationPage(self)) self.add_pages((LineBreakPage(self), LineBreakOptionsPage(self))) self.add_page(self._progress_page) self.add_page(self._confirmation_page) def _init_signal_handlers(self): """Initialize signal handlers.""" aeidon.util.connect(self, self, "apply") aeidon.util.connect(self, self, "cancel") aeidon.util.connect(self, self, "close") aeidon.util.connect(self, self, "prepare") aeidon.util.connect(self, self, "window-state-event") def _on_apply(self, *args): """Apply accepted changes to projects.""" gaupol.util.set_cursor_busy(self) edits = removals = 0 changes = self._confirmation_page.get_confirmed_changes() changed_pages = aeidon.util.get_unique([x[0] for x in changes]) field = self._introduction_page.get_field() doc = gaupol.util.text_field_to_document(field) description = _("Correcting texts") register = aeidon.registers.DO for page in changed_pages: indices = [x[1] for x in changes if x[0] is page] texts = [x[3] for x in changes if x[0] is page] if indices and texts: page.project.replace_texts(indices, doc, texts) page.project.set_action_description(register, description) edits += len(indices) indices = [x for i, x in enumerate(indices) if not texts[i]] if indices and gaupol.conf.text_assistant.remove_blank: page.project.remove_subtitles(indices) page.project.group_actions(register, 2, description) removals += len(indices) page.view.columns_autosize() edits = edits - removals message = _("Edited {edits:d} and removed {removals:d} subtitles") self.application.flash_message(message.format(**locals())) gaupol.util.set_cursor_normal(self) def _on_cancel(self, *args): """Destroy assistant.""" self._save_window_geometry() self.destroy() def _on_close(self, *args): """Destroy assistant.""" self._save_window_geometry() self.destroy() def _on_prepare(self, assistant, page): """Prepare `page` to be shown next.""" previous_page = self._previous_page self._previous_page = page if page is self._introduction_page: return self._prepare_introduction_page() pages = self._introduction_page.get_selected_pages() if page is self._progress_page: if previous_page is not self._confirmation_page: return self._prepare_progress_page(pages) def _on_window_state_event(self, window, event): """Save window maximization.""" state = event.new_window_state maximized = bool(state & Gdk.WindowState.MAXIMIZED) gaupol.conf.text_assistant.maximized = maximized def _prepare_confirmation_page(self, doc, changes): """Present `changes` and activate confirmation page.""" count = len(changes) title = n_("Confirm {:d} Change", "Confirm {:d} Changes", count).format(count) self.set_page_title(self._confirmation_page, title) self._confirmation_page.application = self.application self._confirmation_page.doc = doc self._confirmation_page.populate_tree_view(changes) self.set_page_complete(self._progress_page, True) def _prepare_introduction_page(self): """Prepare introduction page content.""" n = self.get_n_pages() pages = list(map(self.get_nth_page, range(n))) pages.remove(self._introduction_page) pages.remove(self._progress_page) pages.remove(self._confirmation_page) pages = [x for x in pages if hasattr(x, "correct_texts")] self._introduction_page.populate_tree_view(pages) def _prepare_progress_page(self, pages): """Prepare progress page for `pages`.""" self._progress_page.reset(0, True) self.set_page_complete(self._progress_page, False) gaupol.util.delay_add(10, self._correct_texts, pages) def _save_window_geometry(self): """Save the geometry of the assistant window.""" if not gaupol.conf.text_assistant.maximized: gaupol.conf.text_assistant.size = list(self.get_size()) gaupol-1.11/gaupol/attrdict.py000066400000000000000000000053361422217132500164100ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2006 Osmo Salomaa # # 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 . """Observable dictionary with attribute access to keys.""" import aeidon __all__ = ("AttributeDictionary",) class AttributeDictionary(aeidon.Observable): """ Observable dictionary with attribute access to keys. :class:`AttributeDictionary` is initialized from a root dictionary, which is kept in sync with attribute values. This allows convenient attribute access to dictionary keys and notifications of changes via the :class:`aeidon.Observable` interface. """ def __init__(self, root): """Initialize an :class:`AttributeDictionary` instance.""" aeidon.Observable.__init__(self) self._root = root self.update(root) def add_attribute(self, name, value): """Add instance attribute and corresponding root dictionary key.""" self._root[name] = value # In the case of dictionaries, set the original dictionary # to the root dictionary, but instantiate an AttributeDictionary # for use as the corresponding attribute. if isinstance(value, dict): value = AttributeDictionary(value) setattr(self, name, value) self.connect("notify::{}".format(name), self._on_notify, name) def extend(self, root): """Add new values from another root dictionary.""" for name, value in root.items(): if not hasattr(self, name): self.add_attribute(name, value) for name, value in root.items(): if isinstance(value, dict): getattr(self, name).extend(value) def _on_notify(self, obj, value, name): """Synchronize changed attribute value with root dictionary.""" self._root[name] = value def update(self, root): """Update values from another root dictionary.""" self.extend(root) for name, value in root.items(): if not isinstance(value, dict): setattr(self, name, value) for name, value in root.items(): if isinstance(value, dict): getattr(self, name).update(value) gaupol-1.11/gaupol/config.py000066400000000000000000000427321422217132500160400ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2010 Osmo Salomaa # # 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 . """Reading, writing and storing configurations.""" import aeidon import copy import gaupol import json import os import sys __all__ = ("ConfigurationStore",) CONFIG_DEFAULTS = { "application_window": { "layout": gaupol.orientation.VERTICAL, "maximized": False, "position": [0, 0], "show_main_toolbar": True, "size": [700, 433], "toolbar_style": gaupol.toolbar_styles.ICONS, }, "capitalization": { "country": "", "language": "", "script": "Latn", }, "common_error": { "classes": ["Human", "OCR"], "country": "", "language": "", "script": "Latn", }, "duration_adjust": { "gap": 0.0, "lengthen": True, "maximum": 6.0, "minimum": 1.5, "speed": 15.0, "shorten": False, "target": gaupol.targets.CURRENT, "use_minimum": True, "use_gap": True, "use_maximum": False, }, "general": { "dark_theme": False, "diff_color_change": "#ffff0033", "diff_color_delete": "#ff555533", "diff_color_insert": "#00ff0033", "version": None, }, "editor": { "custom_font": ("Consolas 9" if sys.platform == "win32" else "monospace"), "field_order": [ gaupol.fields.NUMBER, gaupol.fields.START, gaupol.fields.END, gaupol.fields.DURATION, gaupol.fields.MAIN_TEXT, gaupol.fields.TRAN_TEXT, ], "framerate": aeidon.framerates.FPS_23_976, "length_unit": gaupol.length_units.EM, "mode": aeidon.modes.TIME, "show_lengths_cell": True, "show_lengths_edit": True, "stretch_length": 0.05, "use_custom_font": True, "use_zebra_stripes": True, "visible_fields": [ gaupol.fields.NUMBER, gaupol.fields.START, gaupol.fields.END, gaupol.fields.DURATION, gaupol.fields.MAIN_TEXT, ], }, "encoding": { "fallback": ["utf_8", "cp1252"], "try_auto": True, "try_locale": True, "visible": ["utf_8", "cp1252"], }, "extensions": { "active": [], }, "file": { "align_method": aeidon.align_methods.POSITION, "directory": "", "encoding": "utf_8", "format": aeidon.formats.SUBRIP, "newline": aeidon.util.get_default_newline(), }, "framerate_convert": { "target": gaupol.targets.CURRENT, }, "hearing_impaired": { "country": "", "language": "", "script": "Latn", }, "join_split_words": { "join": True, "split": False, }, "line_break": { "country": "", "language": "", "length_unit": gaupol.length_units.EM, "max_length": 24, "max_lines": 3, "script": "Latn", "skip_max_length": 24, "skip_max_lines": 3, "use_skip_max_length": True, "use_skip_max_lines": True, }, "position_shift": { "target": gaupol.targets.CURRENT, }, "position_transform": { "target": gaupol.targets.CURRENT, }, "preview": { "custom_command": "", "force_utf_8": True, # mpv is the only player that supports precise seek, others need a longer offset. "offset": 1.0 if gaupol.util.get_default_player() == aeidon.players.MPV else 5.0, "player": gaupol.util.get_default_player(), "use_custom_command": False, }, "recent": { "show_not_found": False, }, "search": { "fields": [gaupol.fields.MAIN_TEXT], "ignore_case": True, "regex": False, "target": gaupol.targets.CURRENT, }, "spell_check": { "field": gaupol.fields.MAIN_TEXT, "inline": False, "language": "en", "size": [500, 309], "target": gaupol.targets.CURRENT, }, "subtitle_insert": { "above": False, }, "text_assistant": { "field": gaupol.fields.MAIN_TEXT, "maximized": False, "pages": [], "remove_blank": True, "size": [700, 433], "target": gaupol.targets.CURRENT, }, "video_player": { "autoplay": True, "context_length": 1.0, "line_alignment": "center", "seek_length": 30.0, "subtitle_alpha": 1.0, "subtitle_background": True, "subtitle_color": "#ffffff", "subtitle_font": "Sans 18", "subtitle_position_horizontal": "center", "subtitle_position_vertical": "bottom", "time_alpha": 1.0, "time_background": True, "time_color": "#ffffff", "time_font": "Monospace 14", "time_position_horizontal": "right", "time_position_vertical": "top", "volume": None, }, } CONFIG_ENUMS = { "application_window": { "layout": gaupol.orientation, "toolbar_style": gaupol.toolbar_styles, }, "duration_adjust": { "target": gaupol.targets, }, "editor": { "field_order": gaupol.fields, "framerate": aeidon.framerates, "length_unit": gaupol.length_units, "mode": aeidon.modes, "visible_fields": gaupol.fields, }, "extensions": { }, "file": { "align_method": aeidon.align_methods, "format": aeidon.formats, "newline": aeidon.newlines, }, "framerate_convert": { "target": gaupol.targets, }, "line_break": { "length_unit": gaupol.length_units, }, "position_shift": { "target": gaupol.targets, }, "position_transform": { "target": gaupol.targets, }, "preview": { "player": aeidon.players, }, "search": { "fields": gaupol.fields, "target": gaupol.targets, }, "spell_check": { "field": gaupol.fields, "target": gaupol.targets, }, "text_assistant": { "field": gaupol.fields, "target": gaupol.targets, }, } class EnumDecoder(json.JSONDecoder): """JSON decoder for enumerations of :mod:`aeidon` and :mod:`gaupol`.""" def __init__(self, *args, **kwargs): """ Initialize an :class:`EnumDecoder` instance. `kwargs` should contain an "enum" key with a value of ``None`` if not decoding an enumeration or the corresponding :class:`aeidon.Enumeration` instance if decoding an enumeration. """ self.enum = kwargs["enum"] del kwargs["enum"] json.JSONDecoder.__init__(self, *args, **kwargs) def decode(self, string): """Return Python object matching JSON `string`.""" if self.enum is None: return json.JSONDecoder.decode(self, string) if string.startswith("[") and string.endswith("]"): return [getattr(self.enum, x.strip()) for x in string[1:-1].split(",")] return getattr(self.enum, string) class EnumEncoder(json.JSONEncoder): """JSON encoder for enumerations of :mod:`aeidon` and :mod:`gaupol`.""" def encode(self, obj): """Return JSON string matching `obj`.""" if isinstance(obj, aeidon.EnumerationItem): return str(obj) if isinstance(obj, (list, tuple)) and obj: if isinstance(obj[0], aeidon.EnumerationItem): return "[{}]".format(", ".join(map(str, obj))) return json.JSONEncoder.encode(self, obj) class ConfigurationStore(gaupol.AttributeDictionary): """ Reading, writing and storing configurations. :cvar _defaults: Dictionary of default values of options :cvar _enums: Dictionary of :class:`aeidon.Enumeration` instances :ivar path: Path to user's local configuration file """ _defaults = copy.deepcopy(CONFIG_DEFAULTS) _enums = copy.deepcopy(CONFIG_ENUMS) def __init__(self): """Initialize a :class:`ConfigurationStore` instance.""" root = copy.deepcopy(self._defaults) gaupol.AttributeDictionary.__init__(self, root) self.path = None def __setattr__(self, name, value): """Avoid accidentally setting a tuple.""" if isinstance(value, tuple): value = list(value) return gaupol.AttributeDictionary.__setattr__(self, name, value) def connect_notify(self, sections, option, obj, *args): """Connect `option`'s notify signal to `obj`'s callback method.""" if isinstance(sections, str): sections = (sections,) container = self for section in sections: container = getattr(container, section) signal = "notify::{}".format(option) method_name = "_on_conf_{}_{}".format( "_".join(sections), signal.replace("::", "_")) if not hasattr(obj, method_name): method_name = method_name[1:] method = getattr(obj, method_name) container.connect(signal, method, *args) def disconnect_notify(self, sections, option, obj): """Disconnect `option`'s notify signal from `obj`'s callback method.""" if isinstance(sections, str): sections = (sections,) container = self for section in sections: container = getattr(container, section) signal = "notify::{}".format(option) method_name = "_on_conf_{}_{}".format( "_".join(sections), signal.replace("::", "_")) if not hasattr(obj, method_name): method_name = method_name[1:] method = getattr(obj, method_name) container.disconnect(signal, method) def _flatten(self, values): """Return a flattened version of `values` dictionary.""" def flatten(deep, parent): flat_dict = {parent: {}} deep = copy.deepcopy(deep) for key, value in deep.items(): if isinstance(value, dict): key = "::".join((parent, key)) value = flatten(value, key) flat_dict.update(value) else: # Non-dictionary key. flat_dict[parent][key] = value if not flat_dict[parent]: del flat_dict[parent] return flat_dict final_dict = {} values = copy.deepcopy(values) for key, value in values.items(): if isinstance(value, dict): final_dict.update(flatten(value, key)) else: # Non-dictionary key. final_dict[key] = value return final_dict def query_default(self, sections, option): """Return default value of configuration option.""" if isinstance(sections, str): sections = (sections,) container = self._defaults for section in sections: container = container[section] return container[option] def _read_from_file(self): """Read values of configuration options from file.""" if self.path is None: return if not os.path.isfile(self.path): return encoding = aeidon.util.get_default_encoding() # Ignore possible encoding errors, which are only related to # saved file and directory names and not in any way critical. with open(self.path, "r", encoding=encoding, errors="replace") as f: lines = f.readlines() lines = [x.strip() for x in lines] lines = [x for x in lines if x and not x.startswith("#")] sections, container, enums = None, None, None for line in lines: if line.startswith("[") and line.endswith("]"): sections, container, enums = self._read_section_line(line) else: # OPTION = VALUE if sections is None or container is None or enums is None: raise ValueError("Missing section header?") self._read_option_line(line, sections, container, enums) def read_from_file(self): """Read values of configuration options from file.""" try: self._read_from_file() except Exception as error: print("Failed to read configuration file {}: {!s}" .format(self.path, error), file=sys.stderr) def _read_option_line(self, line, sections, container, enums): """Read option-value line from configuration file.""" option, value = [x.strip() for x in line.split("=", 1)] enum = enums.get(option, None) try: value = json.loads(value, cls=EnumDecoder, enum=enum) except (AttributeError, ValueError): return print("Failed to parse value '{}' of option '{}.{}' from configuration file '{}'." .format(value, "::".join(sections), option, self.path), file=sys.stderr) if hasattr(container, option) and value is None: # Discard a None-value for all non-extension options. # None-values are not used for any options, but might # accidentally bet set in some corner or error cases. # By discarding them here, we ensure a clean start. return print("Discarding value '{}' of option '{}.{}' from configuration file '{}'." .format(value, "::".join(sections), option, self.path), file=sys.stderr) if not hasattr(container, option): # Add attribute if it does not exist in container, which # has been initialized from config_defaults. This is needed # for extensions, defaults of options of which are not # known until later. Any possible obsolete non-extension # options created here will be removed before writing in # write_to_file. container.add_attribute(option, value) setattr(container, option, value) def _read_section_line(self, line): """Read section header line from configuration file.""" sections = line[1:-1].strip().split("::") container = self enums = self._enums for section in sections: if not hasattr(container, section): container.add_attribute(section, {}) container = getattr(container, section) enums = enums.get(section, {}) return sections, container, enums def register_extension(self, name, defaults, enums=None): """ Add section and options for extension. `name` should be preferrably the module name of the extension and it will appear in the section name as ``extensions::name``. `defaults` should be a dictionary of default values for options. `enums` should be a dictionary of :class:`aeidon.Enumeration` instances corresponding to enumeration items that appear in options. """ self._defaults["extensions"].update({name: defaults}) self.extensions.extend({name: copy.deepcopy(defaults)}) self._enums["extensions"].update({name: enums or {}}) def restore_defaults(self): """Set all configuration options to their default values.""" self.update(self._defaults) def _write_to_file(self): """Write values of configuration options to file.""" if self.path is None: return self.general.version = gaupol.__version__ aeidon.util.makedirs(os.path.dirname(self.path)) encoding = aeidon.util.get_default_encoding() # Ignore possible encoding errors, which are only related to # saved file and directory names and not in any way critical. f = open(self.path, "w", encoding=encoding, errors="replace") root = self._flatten(self._root) defaults = self._flatten(self._defaults) for section in sorted(root): f.write("\n[{}]\n".format(section)) for option in sorted(root[section]): value = root[section][option] json_value = json.dumps( value, cls=EnumEncoder, ensure_ascii=False) # Discard removed options, but always keep # all options of all extensions. if (not section.startswith("extensions::") and (not section in defaults or not option in defaults[section])): continue # Write options that remain at their default value # (perhaps, but not necessarily unset) as commented out. if (section in defaults and option in defaults[section] and value == defaults[section][option]): f.write("# ") f.write("{} = {}\n".format(option, json_value)) f.close() def write_to_file(self): """Write values of configuration options to file.""" try: self._write_to_file() except Exception as error: print("Failed to write configuration file {}: {!s}" .format(self.path, error), file=sys.stderr) gaupol-1.11/gaupol/dialogs/000077500000000000000000000000001422217132500156335ustar00rootroot00000000000000gaupol-1.11/gaupol/dialogs/__init__.py000066400000000000000000000014111422217132500177410ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2010 Osmo Salomaa # # 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 . """Dialogs.""" import gaupol gaupol.util.install_module("dialogs", lambda: None) gaupol-1.11/gaupol/dialogs/about.py000066400000000000000000000043031422217132500173170ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Dialog for displaying credits and information.""" import gaupol from aeidon.i18n import _ from gi.repository import GObject from gi.repository import Gtk __all__ = ("AboutDialog",) class AboutDialog(Gtk.AboutDialog): """Dialog for displaying credits and information.""" def __init__(self, parent): """Initialize an :class:`AboutDialog` instance.""" GObject.GObject.__init__(self) self.set_title(_("About Gaupol")) self.set_transient_for(parent) self.set_artists(("Osmo Salomaa ",)) self.set_authors(("Osmo Salomaa ",)) self.set_comments(_("Subtitle editor")) self.set_copyright("Copyright © 2005–2022 Osmo Salomaa") self.set_license_type(Gtk.License.GPL_3_0) self.set_logo_icon_name("io.otsaloma.gaupol") self.set_program_name("Gaupol") # TRANSLATORS: This is a special message that shouldn't be translated # literally. It is used in the about dialog to give credits to the # translators. Thus, you should translate it to your name and email # address. You can also include other translators who have contributed # to this translation; in that case, please write them on separate # lines seperated by newlines (\n). self.set_translator_credits(_("translator-credits")) self.set_version(gaupol.__version__) self.set_website(gaupol.HOMEPAGE_URL) self.set_website_label(_("Gaupol Website")) self.set_wrap_license(True) gaupol-1.11/gaupol/dialogs/append.py000066400000000000000000000022541422217132500174570ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Dialog for selecting a subtitle file to append to project.""" import aeidon import gaupol from aeidon.i18n import _ __all__ = ("AppendDialog",) class AppendDialog(gaupol.OpenDialog): """Dialog for selecting a subtitle file to append to project.""" def __init__(self, parent): """Initialize an :class:`AppendDialog` instance.""" doc = aeidon.documents.MAIN gaupol.OpenDialog.__init__(self, parent, _("Append File"), doc) self.set_select_multiple(False) gaupol-1.11/gaupol/dialogs/builder.py000066400000000000000000000051101422217132500176300ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2006 Osmo Salomaa # # 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 . """Baseclass and wrapper for :class:`Gtk.Builder` constructed dialogs.""" import aeidon import os from gi.repository import Gtk __all__ = ("BuilderDialog",) class BuilderDialog: """ Baseclass and wrapper for :class:`Gtk.Builder` constructed dialogs. :cvar _widgets: List of names of widgets to be assigned as attributes All widgets defined in :attr:`_widgets` are assigned as instance variables with names preceded by a single underscore. All signals defined in the UI definition file are connected to ``self``. All :func:`getattr` calls not found in ``self`` are delegated to :attr:`self._dialog` allowing ``self`` to look and act like a :class:`Gtk.Dialog`. """ _widgets = [] def __init__(self, ui_file_path, connect_signals=True): """Initialize a :class:`BuilderDialog` instance from `ui_file_path`.""" if not os.path.isabs(ui_file_path): ui_file_path = os.path.join(aeidon.DATA_DIR, "ui", ui_file_path) self._builder = Gtk.Builder() self._builder.set_translation_domain("gaupol") self._builder.add_from_file(ui_file_path) self._dialog = self._builder.get_object("dialog") if connect_signals: self._builder.connect_signals(self) self._set_attributes(self._widgets) def __getattr__(self, name): """Return attribute from :attr:`_dialog`.""" return getattr(self._dialog, name) def run(self): """Show the dialog, run it and return response.""" self._dialog.show() return self._dialog.run() def _set_attributes(self, widgets, prefix=None): """Assign all names in `widgets` as attributes of `self`.""" for name in widgets: widget = self._builder.get_object(name) if prefix and name.startswith(prefix): name = name.replace(prefix, "") setattr(self, "_{}".format(name), widget) gaupol-1.11/gaupol/dialogs/debug.py000066400000000000000000000156361422217132500173060ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Dialog for displaying a traceback in case of an unhandled exception.""" import aeidon import gaupol import linecache import platform import sys import traceback from aeidon.i18n import _ from gi.repository import GObject from gi.repository import Gtk from gi.repository import Pango __all__ = ("DebugDialog",) class DebugDialog(Gtk.MessageDialog): """Dialog for displaying a traceback in case of an unhandled exception.""" def __init__(self): """Initialize a :class:`DebugDialog` instance.""" GObject.GObject.__init__(self, message_type=Gtk.MessageType.ERROR, text=_("Something went wrong"), secondary_text=_("You have probably discovered a bug. Please report it by providing the below information and a description of what you were doing.")) self._text_view = Gtk.TextView() self._init_dialog() self._init_text_view() def _init_dialog(self): """Initialize the dialog.""" self.add_button(_("_Report Bug"), Gtk.ResponseType.HELP) self.add_button(_("_Quit"), Gtk.ResponseType.NO) self.add_button(_("_Close"), Gtk.ResponseType.CLOSE) self.set_default_response(Gtk.ResponseType.CLOSE) self.set_modal(True) aeidon.util.connect(self, self, "response") def _init_text_view(self): """Initialize the text view.""" self._text_view.set_wrap_mode(Gtk.WrapMode.WORD) self._text_view.set_editable(False) self._text_view.set_cursor_visible(False) self._text_view.set_accepts_tab(False) self._text_view.set_left_margin(6) self._text_view.set_right_margin(6) with aeidon.util.silent(AttributeError): # Top and bottom margins available since GTK 3.18. self._text_view.set_top_margin(6) self._text_view.set_bottom_margin(6) text_buffer = self._text_view.get_buffer() text_buffer.create_tag("monospace", family="monospace") text_buffer.create_tag("bold", weight=Pango.Weight.BOLD) text_buffer.create_tag("large", scale=1.1) scroller = Gtk.ScrolledWindow() scroller.set_policy(*((Gtk.PolicyType.AUTOMATIC,)*2)) scroller.set_shadow_type(Gtk.ShadowType.ETCHED_IN) scroller.add(self._text_view) box = self.get_message_area() gaupol.util.pack_start_expand(box, scroller) box.show_all() def _insert_environment(self): """Insert information about user's platform and environment.""" locale = aeidon.locales.get_system_code() encoding = aeidon.encodings.get_locale_code() self._insert_text("Platform: {}\n".format(platform.platform(True))) self._insert_text("Locale: {}.{}\n\n".format(locale, encoding)) def _insert_dependencies(self): """Insert version numbers of selected dependencies.""" dotjoin = lambda x: ".".join(map(str, x)) chardet_version = aeidon.util.get_chardet_version() gspell_version = gaupol.util.get_gspell_version() gst_version = gaupol.util.get_gst_version() gtk_version = dotjoin(( Gtk.get_major_version(), Gtk.get_minor_version(), Gtk.get_micro_version(), )) pygobject_version = dotjoin(GObject.pygobject_version) python_version = dotjoin(sys.version_info[:3]) self._insert_text("aeidon: {}\n".format(aeidon.__version__)) self._insert_text("chardet: {}\n".format(chardet_version)) self._insert_text("gaupol: {}\n".format(gaupol.__version__)) self._insert_text("gspell: {}\n".format(gspell_version)) self._insert_text("gstreamer: {}\n".format(gst_version)) self._insert_text("gtk+: {}\n".format(gtk_version)) self._insert_text("pygobject: {}\n".format(pygobject_version)) self._insert_text("python: {}\n".format(python_version)) def _insert_text(self, text, *tags): """Insert `text` with `tags` to the text view.""" text_buffer = self._text_view.get_buffer() itr = text_buffer.get_end_iter() tags = tags + ("monospace",) text_buffer.insert_with_tags_by_name(itr, text, *tags) def _insert_title(self, text): """Insert `text` as a title to the text view.""" self._insert_text(text, "large", "bold") self._insert_text("\n\n") def _insert_traceback(self, exctype, value, tb, limit=100): """Insert up to `limit` stack trace entries from `tb`.""" # This function has been originally adapted from Gazpacho # Copyright (C) 2005 by Async Open Source and Sicem S.L., # available under the GNU LGPL version 2 or later. for i in range(limit): if tb is None: break path = tb.tb_frame.f_code.co_filename name = tb.tb_frame.f_code.co_name line = linecache.getline(path, tb.tb_lineno).strip() self._insert_text("File: {}\n".format(path)) self._insert_text("Line: {}\n".format(tb.tb_lineno)) self._insert_text("In: {}\n\n".format(name)) self._insert_text("    {}\n\n".format(line)) tb = tb.tb_next exception = traceback.format_exception_only(exctype, value)[0] exception, space, message = exception.partition(" ") self._insert_text(exception, "bold") self._insert_text("{}{}\n".format(space, message)) def _on_response(self, dialog, response): """Do not send response if reporting bug.""" if response != Gtk.ResponseType.HELP: return gaupol.util.show_uri(gaupol.BUG_REPORT_URL) self.stop_emission("response") def set_text(self, exctype, value, tb): """Set text from `tb` to the text view.""" self._insert_title("Traceback") self._insert_traceback(exctype, value, tb) self._insert_title("Environment") self._insert_environment() self._insert_title("Versions") self._insert_dependencies() gaupol.util.scale_to_content(self._text_view, min_nchar=60, max_nchar=100, min_nlines=10, max_nlines=25, font="monospace") gaupol-1.11/gaupol/dialogs/duration_adjust.py000066400000000000000000000147721422217132500214170ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Dialog for lengthening or shortening durations.""" import gaupol from aeidon.i18n import _, n_ from gi.repository import Gtk __all__ = ("DurationAdjustDialog",) class DurationAdjustDialog(gaupol.BuilderDialog): """Dialog for lengthening or shortening durations.""" _widgets = [ "all_radio", "current_radio", "gap_check", "gap_spin", "lengthen_check", "max_check", "max_spin", "min_check", "min_spin", "selected_radio", "shorten_check", "speed_spin", ] def __init__(self, parent, application): """Initialize a :class:`DurationAdjustDialog` instance.""" gaupol.BuilderDialog.__init__(self, "duration-adjust-dialog.ui") self.application = application self._init_dialog(parent) self._init_values() self._init_sensitivities() def _adjust_durations(self): """Adjust durations of subtitles.""" conf = gaupol.conf.duration_adjust target = self._get_target() for page in self.application.get_target_pages(target): self.application.set_current_page(page) rows = page.project.adjust_durations( indices=self.application.get_target_rows(target), speed=conf.speed, lengthen=conf.lengthen, shorten=conf.shorten, maximum=(conf.maximum if conf.use_maximum else None), minimum=(conf.minimum if conf.use_minimum else None), gap=conf.gap if conf.use_gap else None) self.application.flash_message(n_( "Adjusted duration of {:d} subtitle", "Adjusted durations of {:d} subtitles", len(rows)).format(len(rows))) def _get_target(self): """Return the selected target.""" if self._selected_radio.get_active(): return gaupol.targets.SELECTED if self._current_radio.get_active(): return gaupol.targets.CURRENT if self._all_radio.get_active(): return gaupol.targets.ALL raise ValueError("Invalid target radio state") def _init_dialog(self, parent): """Initialize the dialog.""" self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_Adjust"), Gtk.ResponseType.OK) self.set_default_response(Gtk.ResponseType.OK) self.set_transient_for(parent) self.set_modal(True) def _init_sensitivities(self): """Initialize sensitivities of widgets.""" self._all_radio.emit("toggled") self._current_radio.emit("toggled") self._gap_check.emit("toggled") self._gap_spin.emit("value-changed") self._lengthen_check.emit("toggled") self._max_check.emit("toggled") self._max_spin.emit("value-changed") self._min_check.emit("toggled") self._min_spin.emit("value-changed") self._selected_radio.emit("toggled") self._shorten_check.emit("toggled") self._speed_spin.emit("value-changed") def _init_values(self): """Intialize default values for widgets.""" conf = gaupol.conf.duration_adjust self._gap_check.set_active(conf.use_gap) self._gap_spin.set_value(conf.gap) self._lengthen_check.set_active(conf.lengthen) self._max_check.set_active(conf.use_maximum) self._max_spin.set_value(conf.maximum) self._min_check.set_active(conf.use_minimum) self._min_spin.set_value(conf.minimum) self._shorten_check.set_active(conf.shorten) self._speed_spin.set_value(conf.speed) self._selected_radio.set_active(conf.target == gaupol.targets.SELECTED) self._current_radio.set_active(conf.target == gaupol.targets.CURRENT) self._all_radio.set_active(conf.target == gaupol.targets.ALL) page = self.application.get_current_page() rows = page.view.get_selected_rows() if not rows and conf.target == gaupol.targets.SELECTED: self._current_radio.set_active(True) self._selected_radio.set_sensitive(bool(rows)) def _on_gap_check_toggled(self, check_button): """Set sensitivity of the gap spin button.""" self._gap_spin.set_sensitive(check_button.get_active()) def _on_lengthen_check_toggled(self, *args): """Set sensitivity of the speed spin button.""" lengthen = self._lengthen_check.get_active() shorten = self._shorten_check.get_active() self._speed_spin.set_sensitive(lengthen or shorten) def _on_max_check_toggled(self, check_button): """Set sensitivity of the maximum spin button.""" self._max_spin.set_sensitive(check_button.get_active()) def _on_min_check_toggled(self, check_button): """Set sensitivity of the minimum spin button.""" self._min_spin.set_sensitive(check_button.get_active()) def _on_response(self, dialog, response): """Save settings and adjust durations.""" conf = gaupol.conf.duration_adjust conf.gap = self._gap_spin.get_value() conf.lengthen = self._lengthen_check.get_active() conf.maximum = self._max_spin.get_value() conf.minimum = self._min_spin.get_value() conf.speed = self._speed_spin.get_value() conf.shorten = self._shorten_check.get_active() conf.target = self._get_target() conf.use_gap = self._gap_check.get_active() conf.use_maximum = self._max_check.get_active() conf.use_minimum = self._min_check.get_active() if response == Gtk.ResponseType.OK: self._adjust_durations() def _on_shorten_check_toggled(self, *args): """Set sensitivity of the speed spin button.""" lengthen = self._lengthen_check.get_active() shorten = self._shorten_check.get_active() self._speed_spin.set_sensitive(lengthen or shorten) gaupol-1.11/gaupol/dialogs/encoding.py000066400000000000000000000135301422217132500177750ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Dialogs for selecting character encodings.""" import aeidon import gaupol from aeidon.i18n import _ from gi.repository import GObject from gi.repository import Gtk __all__ = ("EncodingDialog", "MenuEncodingDialog") class EncodingDialog(Gtk.Dialog): """Dialog for selecting a character encoding.""" def __init__(self, parent): """Initialize an :class:`EncodingDialog` instance.""" GObject.GObject.__init__(self, use_header_bar=True) self._tree_view = Gtk.TreeView() self._init_dialog(parent) self._init_tree_view() gaupol.util.scale_to_content(self._tree_view, min_nchar=50, max_nchar=100, min_nlines=10, max_nlines=18) def get_encoding(self): """Return the selected encoding or ``None``.""" selection = self._tree_view.get_selection() store, itr = selection.get_selected() if itr is None: return return store.get_value(itr, 0) def _init_dialog(self, parent): """Initialize the dialog.""" self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_OK"), Gtk.ResponseType.OK) self.set_default_response(Gtk.ResponseType.OK) self.set_transient_for(parent) self.set_modal(True) self.set_title(_("Character Encodings")) def _init_tree_view(self): """Initialize the character encoding tree view.""" scroller = Gtk.ScrolledWindow() scroller.set_policy(*((Gtk.PolicyType.AUTOMATIC,)*2)) scroller.set_shadow_type(Gtk.ShadowType.NONE) scroller.add(self._tree_view) box = self.get_content_area() gaupol.util.pack_start_expand(box, scroller) box.show_all() selection = self._tree_view.get_selection() selection.set_mode(Gtk.SelectionMode.SINGLE) store = Gtk.ListStore(str, str, str) for item in aeidon.encodings.get_valid(): store.append((item[0], item[2], item[1])) store.set_sort_column_id(1, Gtk.SortType.ASCENDING) self._tree_view.set_model(store) column = Gtk.TreeViewColumn(_("Description"), Gtk.CellRendererText(), text=1) column.set_clickable(True) column.set_sort_column_id(1) self._tree_view.append_column(column) column = Gtk.TreeViewColumn(_("Encoding"), Gtk.CellRendererText(), text=2) column.set_clickable(True) column.set_sort_column_id(2) self._tree_view.append_column(column) aeidon.util.connect(self, "_tree_view", "row-activated") def _on_tree_view_row_activated(self, *args): """Send response to select activated character encoding.""" self.response(Gtk.ResponseType.OK) class MenuEncodingDialog(EncodingDialog): """Dialog for selecting character encodings.""" def get_visible_encodings(self): """Return encodings chosen to be visible.""" store = self._tree_view.get_model() return [store[i][0] for i in range(len(store)) if store[i][3]] def _init_tree_view(self): """Initialize the character encoding tree view.""" scroller = Gtk.ScrolledWindow() scroller.set_policy(*((Gtk.PolicyType.AUTOMATIC,)*2)) scroller.set_shadow_type(Gtk.ShadowType.NONE) scroller.add(self._tree_view) box = self.get_content_area() gaupol.util.pack_start_expand(box, scroller) box.show_all() selection = self._tree_view.get_selection() selection.set_mode(Gtk.SelectionMode.SINGLE) store = Gtk.ListStore(str, str, str, bool) visible = gaupol.conf.encoding.visible for item in aeidon.encodings.get_valid(): store.append((item[0], item[2], item[1], item[0] in visible)) store.set_sort_column_id(1, Gtk.SortType.ASCENDING) self._tree_view.set_model(store) column = Gtk.TreeViewColumn(_("Description"), Gtk.CellRendererText(), text=1) column.set_clickable(True) column.set_sort_column_id(1) self._tree_view.append_column(column) column = Gtk.TreeViewColumn(_("Encoding"), Gtk.CellRendererText(), text=2) column.set_clickable(True) column.set_sort_column_id(2) self._tree_view.append_column(column) renderer = Gtk.CellRendererToggle() renderer.connect("toggled", self._on_tree_view_cell_toggled) column = Gtk.TreeViewColumn(_("Show in Menu"), renderer, active=3) column.set_sort_column_id(3) self._tree_view.append_column(column) aeidon.util.connect(self, "_tree_view", "row-activated") def _on_tree_view_cell_toggled(self, renderer, path): """Toggle the value of the "Show in Menu" column.""" store = self._tree_view.get_model() store[path][3] = not store[path][3] gaupol-1.11/gaupol/dialogs/file.py000066400000000000000000000125451422217132500171330ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Base class for dialogs for selecting subtitle files.""" import aeidon import gaupol from aeidon.i18n import _ from gi.repository import Gtk __all__ = ("FileDialog",) class FileDialog: """Base class for dialogs for selecting subtitle files.""" _use_autodetection = False def get_encoding(self): """Return the selected encoding or ``None``.""" index = self._encoding_combo.get_active() if index < 0: return None store = self._encoding_combo.get_model() return store[index][0] def _init_encoding_combo(self): """Initialize the character encoding combo box.""" store = Gtk.ListStore(str, str) self._encoding_combo.set_model(store) self._populate_encoding_combo() view = self._encoding_combo.get_child() path = gaupol.util.tree_row_to_path(0) view.set_displayed_row(path) renderer = Gtk.CellRendererText() self._encoding_combo.pack_start(renderer, expand=True) self._encoding_combo.add_attribute(renderer, "text", 1) func = gaupol.util.separate_combo self._encoding_combo.set_row_separator_func(func, None) def _init_filters(self): """Initialize file filters.""" file_filter = Gtk.FileFilter() file_filter.set_name(_("All files")) file_filter.add_pattern("*") self.add_filter(file_filter) file_filter = Gtk.FileFilter() file_filter.set_name(_("All supported files")) for format in aeidon.formats: pattern = "*." for x in format.extension[1:]: pattern += "[{}{}]".format(x.upper(), x.lower()) file_filter.add_pattern(pattern) self.add_filter(file_filter) self.set_filter(file_filter) for format in aeidon.formats: extension = format.extension pattern = "*." for x in extension[1:]: pattern += "[{}{}]".format(x.upper(), x.lower()) format = format.label name = _("{format} (*{extension})").format(**locals()) file_filter = Gtk.FileFilter() file_filter.set_name(name) file_filter.add_pattern(pattern) self.add_filter(file_filter) def _on_encoding_combo_changed(self, *args): """Show the encoding selection dialog.""" encoding = self.get_encoding() if encoding != "other": return dialog = gaupol.MenuEncodingDialog(self) response = gaupol.util.run_dialog(dialog) encoding = dialog.get_encoding() visible = dialog.get_visible_encodings() dialog.destroy() self._encoding_combo.set_active(0) if response != Gtk.ResponseType.OK: return gaupol.conf.encoding.visible = visible if encoding is None: return self._populate_encoding_combo(encoding) self.set_encoding(encoding) def _populate_encoding_combo(self, custom=None): """Populate the encoding combo box, including custom encoding.""" encodings = list(gaupol.conf.encoding.visible) locale = aeidon.encodings.get_locale_code() encodings.insert(0, locale) encodings.append(custom) while None in encodings: encodings.remove(None) encodings = aeidon.util.get_unique(encodings) encodings = encodings or ["utf_8"] for i, encoding in enumerate(encodings): name = aeidon.encodings.code_to_long_name(encoding) encodings[i] = (encoding, name) if locale is not None: name = aeidon.encodings.get_locale_long_name() encodings[0] = (locale, name) a = 0 if locale is None else 1 encodings[a:] = sorted(encodings[a:], key=lambda x: x[1]) separator = gaupol.COMBO_SEPARATOR if self._use_autodetection: encodings.append((separator, separator)) encodings.append(("auto", _("Auto-detected"))) encodings.append((separator, separator)) encodings.append(("other", _("Other…"))) self._encoding_combo.get_model().clear() store = self._encoding_combo.get_model() for encoding in encodings: store.append(tuple(encoding)) def set_encoding(self, encoding): """Set the selected encoding.""" if encoding is None: return store = self._encoding_combo.get_model() for i in range(len(store)): if store[i][0] == encoding: return self._encoding_combo.set_active(i) if aeidon.encodings.is_valid_code(encoding): # Add encoding if not found in store. self._populate_encoding_combo(encoding) return self.set_encoding(encoding) self._encoding_combo.set_active(0) gaupol-1.11/gaupol/dialogs/framerate_convert.py000066400000000000000000000110261422217132500217130ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Dialog for converting framerates.""" import aeidon import gaupol from aeidon.i18n import _ from gi.repository import Gtk __all__ = ("FramerateConvertDialog",) class FramerateConvertDialog(gaupol.BuilderDialog): """Dialog for converting framerates.""" _widgets = ["all_radio", "current_radio", "input_combo", "output_combo"] def __init__(self, parent, application): """Initialize a :class:`FramerateConvertDialog` instance.""" gaupol.BuilderDialog.__init__(self, "framerate-convert-dialog.ui") self.application = application self._init_dialog(parent) self._init_input_combo() self._init_output_combo() self._init_values() def _convert_framerates(self): """Convert framerates in target projects.""" target = self._get_target() ifps = aeidon.framerates[self._input_combo.get_active()] ofps = aeidon.framerates[self._output_combo.get_active()] for page in self.application.get_target_pages(target): self.application.set_current_page(page) page.project.convert_framerate(None, ifps, ofps) def _get_target(self): """Return the selected target.""" if self._current_radio.get_active(): return gaupol.targets.CURRENT if self._all_radio.get_active(): return gaupol.targets.ALL raise ValueError("Invalid target radio state") def _init_dialog(self, parent): """Initialize the dialog.""" self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("Co_nvert"), Gtk.ResponseType.OK) self.set_default_response(Gtk.ResponseType.OK) self.set_transient_for(parent) self.set_modal(True) def _init_input_combo(self): """Initialize the input framerate combo box.""" store = Gtk.ListStore(str) self._input_combo.set_model(store) for label in (x.label for x in aeidon.framerates): store.append((label,)) renderer = Gtk.CellRendererText() self._input_combo.pack_start(renderer, expand=True) self._input_combo.add_attribute(renderer, "text", 0) def _init_output_combo(self): """Initialize the output framerate combo box.""" store = Gtk.ListStore(str) self._output_combo.set_model(store) for label in (x.label for x in aeidon.framerates): store.append((label,)) renderer = Gtk.CellRendererText() self._output_combo.pack_start(renderer, expand=True) self._output_combo.add_attribute(renderer, "text", 0) def _init_values(self): """Intialize default values for widgets.""" page = self.application.get_current_page() target = gaupol.conf.framerate_convert.target self._input_combo.set_active(page.project.framerate) self._output_combo.set_active(page.project.framerate) self._all_radio.set_active(target == gaupol.targets.ALL) self._current_radio.set_active(target == gaupol.targets.CURRENT) def _on_input_combo_changed(self, *args): """Set response sensitivity.""" index_in = self._input_combo.get_active() index_out = self._output_combo.get_active() self._dialog.set_response_sensitive(Gtk.ResponseType.OK, index_in != index_out) def _on_output_combo_changed(self, *args): """Set response sensitivity.""" index_in = self._input_combo.get_active() index_out = self._output_combo.get_active() self._dialog.set_response_sensitive(Gtk.ResponseType.OK, index_in != index_out) def _on_response(self, dialog, response): """Save target and convert framerates.""" gaupol.conf.framerate_convert.target = self._get_target() if response == Gtk.ResponseType.OK: self._convert_framerates() gaupol-1.11/gaupol/dialogs/insert.py000066400000000000000000000063341422217132500175170ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Dialog for inserting new subtitles.""" import gaupol from aeidon.i18n import _ from gi.repository import Gtk __all__ = ("InsertDialog",) class InsertDialog(gaupol.BuilderDialog): """Dialog for inserting new subtitles.""" _widgets = ["amount_spin", "position_combo", "position_label"] def __init__(self, parent, application): """Initialize an :class:`InsertDialog` instance.""" gaupol.BuilderDialog.__init__(self, "insert-dialog.ui") self.application = application self._init_dialog(parent) self._init_position_combo() self._init_values() def _init_dialog(self, parent): """Initialize the dialog.""" self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_Insert"), Gtk.ResponseType.OK) self.set_default_response(Gtk.ResponseType.OK) self.set_transient_for(parent) self.set_modal(True) def _init_position_combo(self): """Initialize the position combo box.""" store = Gtk.ListStore(str) self._position_combo.set_model(store) store.append((_("Above selection"),)) store.append((_("Below selection"),)) renderer = Gtk.CellRendererText() self._position_combo.pack_start(renderer, expand=True) self._position_combo.add_attribute(renderer, "text", 0) def _init_values(self): """Initialize default values for widgets.""" self._amount_spin.set_value(1) index = 0 if gaupol.conf.subtitle_insert.above else 1 self._position_combo.set_active(index) page = self.application.get_current_page() sensitive = bool(page.project.subtitles) self._position_combo.set_sensitive(sensitive) self._position_label.set_sensitive(sensitive) def _insert_subtitles(self, amount, above): """Insert `amount` of subtitles to project.""" page = self.application.get_current_page() if page.project.subtitles: index = page.view.get_selected_rows()[-1] if not above: index += 1 else: # No subtitles in project. index = 0 indices = list(range(index, index + amount)) page.project.insert_subtitles(indices) def _on_response(self, dialog, response): """Save default values and insert subtitles.""" amount = self._amount_spin.get_value_as_int() above = (self._position_combo.get_active() == 0) gaupol.conf.subtitle_insert.above = above if response == Gtk.ResponseType.OK: self._insert_subtitles(amount, above) gaupol-1.11/gaupol/dialogs/language.py000066400000000000000000000111531422217132500177710ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Dialog for configuring spell-check.""" import aeidon import gaupol from aeidon.i18n import _ from gi.repository import Gtk __all__ = ("LanguageDialog",) class LanguageDialog(gaupol.BuilderDialog): """Dialog for configuring spell-check.""" _widgets = [ "all_radio", "current_radio", "language_scroller", "language_title_label", "main_radio", "target_vbox", "tran_radio", "tree_view", ] def __init__(self, parent, show_target=True): """Initialize a :class:`LanguageDialog` instance.""" gaupol.BuilderDialog.__init__(self, "language-dialog.ui") self._init_dialog(parent) self._init_visibilities(show_target) self._init_tree_view() self._init_values() gaupol.util.scale_to_content(self._tree_view, min_nchar=30, max_nchar=60, min_nlines=8, max_nlines=20) def _init_dialog(self, parent): """Initialize the dialog.""" self.set_default_response(Gtk.ResponseType.CLOSE) self.set_transient_for(parent) self.set_modal(True) def _init_tree_view(self): """Initialize the tree view.""" selection = self._tree_view.get_selection() selection.set_mode(Gtk.SelectionMode.SINGLE) selection.connect("changed", self._on_tree_view_selection_changed) store = Gtk.ListStore(str, str) self._populate_store(store) store.set_sort_column_id(1, Gtk.SortType.ASCENDING) self._tree_view.set_model(store) renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn("", renderer, text=1) column.set_sort_column_id(1) self._tree_view.append_column(column) def _init_values(self): """Initialize default values for widgets.""" language = gaupol.conf.spell_check.language field = gaupol.conf.spell_check.field target = gaupol.conf.spell_check.target store = self._tree_view.get_model() selection = self._tree_view.get_selection() for i in range(len(store)): if store[i][0] == language: selection.select_path(i) self._main_radio.set_active(field == gaupol.fields.MAIN_TEXT) self._tran_radio.set_active(field == gaupol.fields.TRAN_TEXT) self._all_radio.set_active(target == gaupol.targets.ALL) self._current_radio.set_active(target == gaupol.targets.CURRENT) def _init_visibilities(self, show_target): """Initialize visibilities of target widgets.""" if not show_target: self._language_title_label.hide() self._target_vbox.hide() self._dialog.set_title(_("Set Language")) def _on_current_radio_toggled(self, radio_button): """Save the selected target.""" gaupol.conf.spell_check.target = ( gaupol.targets.CURRENT if radio_button.get_active() else gaupol.targets.ALL) def _on_main_radio_toggled(self, radio_button): """Save the selected field.""" gaupol.conf.spell_check.field = ( gaupol.fields.MAIN_TEXT if radio_button.get_active() else gaupol.fields.TRAN_TEXT) def _on_tree_view_selection_changed(self, selection): """Save the selected language.""" store, itr = selection.get_selected() if itr is None: return value = store.get_value(itr, 0) gaupol.conf.spell_check.language = value def _populate_store(self, store): """Add all available languages to `store`.""" locales = [] with aeidon.util.silent(Exception): locales = aeidon.SpellChecker.list_languages() for locale in locales: with aeidon.util.silent(Exception): name = aeidon.locales.code_to_name(locale) store.append((locale, name)) gaupol-1.11/gaupol/dialogs/message.py000066400000000000000000000066551422217132500176450ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Message dialog classes.""" from gi.repository import Gtk __all__ = ("ErrorDialog", "InfoDialog", "QuestionDialog", "WarningDialog") class ErrorDialog(Gtk.MessageDialog): """Base class for error dialogs.""" def __init__(self, parent, title, message=None): """Initialize an :class:`ErrorDialog` instance.""" Gtk.MessageDialog.__init__(self, transient_for=parent, modal=True, destroy_with_parent=True, message_type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.NONE, text=title) if message is not None: self.format_secondary_text(message) class InfoDialog(Gtk.MessageDialog): """Base class for info dialogs.""" def __init__(self, parent, title, message=None): """Initialize an :class:`InfoDialog` instance.""" Gtk.MessageDialog.__init__(self, transient_for=parent, modal=True, destroy_with_parent=True, message_type=Gtk.MessageType.INFO, buttons=Gtk.ButtonsType.NONE, text=title) if message is not None: self.format_secondary_text(message) class QuestionDialog(Gtk.MessageDialog): """Base class for question dialogs.""" def __init__(self, parent, title, message=None): """Initialize a :class:`QuestionDialog` instance.""" Gtk.MessageDialog.__init__(self, transient_for=parent, modal=True, destroy_with_parent=True, message_type=Gtk.MessageType.QUESTION, buttons=Gtk.ButtonsType.NONE, text=title) if message is not None: self.format_secondary_text(message) class WarningDialog(Gtk.MessageDialog): """Base class for warning dialogs.""" def __init__(self, parent, title, message=None): """Initialize a :class:`WarningDialog` instance.""" Gtk.MessageDialog.__init__(self, transient_for=parent, modal=True, destroy_with_parent=True, message_type=Gtk.MessageType.WARNING, buttons=Gtk.ButtonsType.NONE, text=title) if message is not None: self.format_secondary_text(message) gaupol-1.11/gaupol/dialogs/multi_close.py000066400000000000000000000155771422217132500205430ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Dialog for warning when closing multiple documents.""" import aeidon import gaupol from aeidon.i18n import _ from gi.repository import GObject from gi.repository import Gtk __all__ = ("MultiCloseDialog",) class MultiCloseDialog(Gtk.MessageDialog): """Dialog for warning when closing multiple documents.""" def __init__(self, parent, application, pages): """Initialize a :class:`MultiCloseDialog` instance.""" GObject.GObject.__init__(self, message_type=Gtk.MessageType.ERROR, text=_("Save changes to documents before closing?"), secondary_text=_("If you don't save, changes will be permanently lost.")) self.application = application self._main_tree_view = Gtk.TreeView() self._main_vbox = gaupol.util.new_vbox(6) self.pages = tuple(pages) self._tran_tree_view = Gtk.TreeView() self._tran_vbox = gaupol.util.new_vbox(6) self._init_dialog(parent) self._init_main_tree_view() self._init_tran_tree_view() def _init_dialog(self, parent): """Initialize the dialog.""" self.add_button(_("Close _Without Saving"), Gtk.ResponseType.NO) self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_Save"), Gtk.ResponseType.YES) self.set_default_response(Gtk.ResponseType.YES) self.set_transient_for(parent) self.set_modal(True) aeidon.util.connect(self, self, "response") def _init_main_tree_view(self): """Initialize the main tree view.""" store = self._init_tree_view(self._main_tree_view) for page in (x for x in self.pages if x.project.main_changed): store.append((page, True, page.get_main_basename())) scroller = Gtk.ScrolledWindow() scroller.set_policy(*((Gtk.PolicyType.AUTOMATIC,)*2)) scroller.set_shadow_type(Gtk.ShadowType.ETCHED_IN) scroller.add(self._main_tree_view) label = Gtk.Label(label=_("Select the _main documents you want to save:")) label.props.xalign = 0 label.set_use_underline(True) label.set_mnemonic_widget(self._main_tree_view) gaupol.util.pack_start(self._main_vbox, label) gaupol.util.pack_start_expand(self._main_vbox, scroller) gaupol.util.pack_start_expand(self.get_message_area(), self._main_vbox) self._main_vbox.set_visible(len(store) > 0) if len(store) > 0: self._main_vbox.show_all() gaupol.util.scale_to_content(self._main_tree_view, min_nchar=30, max_nchar=60, min_nlines=2, max_nlines=6) def _init_tran_tree_view(self): """Initialize the translation tree view.""" store = self._init_tree_view(self._tran_tree_view) for page in (x for x in self.pages if x.project.tran_changed): store.append((page, True, page.get_translation_basename())) scroller = Gtk.ScrolledWindow() scroller.set_policy(*((Gtk.PolicyType.AUTOMATIC,)*2)) scroller.set_shadow_type(Gtk.ShadowType.ETCHED_IN) scroller.add(self._tran_tree_view) label = Gtk.Label(label=_("Select the _translation documents you want to save:")) label.props.xalign = 0 label.set_use_underline(True) label.set_mnemonic_widget(self._tran_tree_view) gaupol.util.pack_start(self._tran_vbox, label) gaupol.util.pack_start_expand(self._tran_vbox, scroller) gaupol.util.pack_start_expand(self.get_message_area(), self._tran_vbox) self._tran_vbox.set_visible(len(store) > 0) if len(store) > 0: self._tran_vbox.show_all() gaupol.util.scale_to_content(self._tran_tree_view, min_nchar=30, max_nchar=60, min_nlines=2, max_nlines=6) def _init_tree_view(self, tree_view): """Initialize `tree_view` and return its model.""" tree_view.set_headers_visible(False) tree_view.set_enable_search(False) store = Gtk.ListStore(object, bool, str) tree_view.set_model(store) selection = tree_view.get_selection() selection.set_mode(Gtk.SelectionMode.SINGLE) renderer = Gtk.CellRendererToggle() renderer.props.activatable = True renderer.connect("toggled", self._on_tree_view_cell_toggled, store) column = Gtk.TreeViewColumn("", renderer, active=1) tree_view.append_column(column) renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn("", renderer, text=2) tree_view.append_column(column) return store def _on_response(self, dialog, response): """Save the selected documents and close pages.""" if response == Gtk.ResponseType.YES: for page in self.pages: self._save_and_close_page(page) if response == Gtk.ResponseType.NO: for page in self.pages: self.application.close(page, confirm=False) def _on_tree_view_cell_toggled(self, renderer, path, store): """Toggle save document check button value.""" store[path][1] = not store[path][1] store = self._main_tree_view.get_model() mains = [x for x in store if x[1]] store = self._tran_tree_view.get_model() trans = [x for x in store if x[1]] sensitive = bool(mains or trans) self.set_response_sensitive(Gtk.ResponseType.YES, sensitive) @aeidon.deco.silent(gaupol.Default) def _save_and_close_page(self, page): """Save the selected documents and close `page`.""" store = self._main_tree_view.get_model() pages = [x for x in store if x[0] is page] if pages and pages[0][1]: self.application.save_main(page) store = self._tran_tree_view.get_model() pages = [x for x in store if x[0] is page] if pages and pages[0][1]: self.application.save_translation(page) self.application.close(page, confirm=False) gaupol-1.11/gaupol/dialogs/multi_save.py000066400000000000000000000212561422217132500203630ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Dialog for selecting properties to save multiple files with.""" import aeidon import gaupol import os from aeidon.i18n import _ from gi.repository import Gtk __all__ = ("MultiSaveDialog",) class MultiSaveDialog(gaupol.BuilderDialog, gaupol.FileDialog): """Dialog for selecting properties to save multiple files with.""" _widgets = [ "encoding_combo", "filechooser_button", "format_combo", "framerate_combo", "framerate_label", "newline_combo", ] def __init__(self, parent, application, modes): """Initialize a :class:`MultiSaveDialog` instance.""" gaupol.BuilderDialog.__init__(self, "multi-save-dialog.ui") self.application = application self._modes = modes self._init_dialog(parent) self._init_format_combo() self._init_encoding_combo() self._init_newline_combo() self._init_framerate_combo() width = gaupol.util.char_to_px(60) self._filechooser_button.set_size_request(width, -1) self._init_values() def get_directory(self): """Return the selected directory.""" return self._filechooser_button.get_filename() def get_format(self): """Return the selected format.""" index = self._format_combo.get_active() return aeidon.formats[index] def get_framerate(self): """Return the selected framerate.""" index = self._framerate_combo.get_active() return aeidon.framerates[index] def get_newline(self): """Return the selected newline.""" index = self._newline_combo.get_active() return aeidon.newlines[index] def _get_pages(self): """Return a list of pages to consider.""" return [x for x in self.application.pages if x.project.main_file is not None] def _init_dialog(self, parent): """Initialize the dialog.""" self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_Save"), Gtk.ResponseType.OK) self.set_default_response(Gtk.ResponseType.OK) self.set_transient_for(parent) self.set_modal(True) def _init_format_combo(self): """Initialize the format combo box.""" store = Gtk.ListStore(str) self._format_combo.set_model(store) for name in (x.label for x in aeidon.formats): if name == "SubRip": # Mark the SubRip format as recommended, since # it's the most common one and best supported, # both in Gaupol and elsewhere. name = _("{} (recommended)").format(name) store.append((name,)) view = self._format_combo.get_child() view.set_displayed_row(gaupol.util.tree_row_to_path(0)) renderer = Gtk.CellRendererText() self._format_combo.pack_start(renderer, expand=True) self._format_combo.add_attribute(renderer, "text", 0) def _init_framerate_combo(self): """Initialize the framerate combo box.""" store = Gtk.ListStore(str) self._framerate_combo.set_model(store) for name in (x.label for x in aeidon.framerates): store.append((name,)) view = self._framerate_combo.get_child() path = gaupol.util.tree_row_to_path(0) view.set_displayed_row(path) renderer = Gtk.CellRendererText() self._framerate_combo.pack_start(renderer, expand=True) self._framerate_combo.add_attribute(renderer, "text", 0) def _init_newline_combo(self): """Initialize the newline combo box.""" store = Gtk.ListStore(str) self._newline_combo.set_model(store) for name in (x.label for x in aeidon.newlines): store.append((name,)) view = self._newline_combo.get_child() view.set_displayed_row(gaupol.util.tree_row_to_path(0)) renderer = Gtk.CellRendererText() self._newline_combo.pack_start(renderer, expand=True) self._newline_combo.add_attribute(renderer, "text", 0) def _init_values(self): """Initialize default values for widgets.""" # Suggest format, encoding and newlines to match # those from the first page to consider. pages = self._get_pages() file = pages[0].project.main_file self.set_directory(os.path.dirname(file.path)) self.set_format(file.format) self.set_encoding(file.encoding) self.set_newline(file.newline) self.set_framerate(gaupol.conf.editor.framerate) visible = len(set(self._modes)) > 1 self._framerate_combo.set_visible(visible) self._framerate_label.set_visible(visible) def _on_format_combo_changed(self, *args): """Change the extension of the current filename.""" format = self.get_format() modes = list(self._modes) + [format.mode] visible = len(set(modes)) > 1 self._framerate_combo.set_visible(visible) self._framerate_label.set_visible(visible) def _on_response(self, dialog, response): """Save default values for widgets.""" gaupol.conf.file.encoding = self.get_encoding() gaupol.conf.file.format = self.get_format() gaupol.conf.file.newline = self.get_newline() gaupol.conf.editor.framerate = self.get_framerate() if response != Gtk.ResponseType.OK: return gaupol.util.set_cursor_busy(self._dialog) self._save_all_documents_as() gaupol.util.set_cursor_normal(self._dialog) @aeidon.deco.silent(gaupol.Default) def _save_all_documents_as(self): """Save all documents with selected properties.""" pages = self._get_pages() files = [None for x in pages] for i, page in enumerate(pages): if self._framerate_combo.get_visible(): # Set framerate to the selected one. framerate = self.get_framerate() self.application.set_current_page(page) action = self.application.get_action("set-framerate") action.activate(str(framerate)) path = os.path.basename(page.project.main_file.path) path = aeidon.util.replace_extension(path, self.get_format()) path = os.path.join(self.get_directory(), path) files[i] = aeidon.files.new(self.get_format(), path, self.get_encoding(), self.get_newline()) if sum(os.path.isfile(x.path) for x in files) > 0: self._show_overwrite_question_dialog(files, self.get_directory()) for i, page in enumerate(pages): self.application.save_main_as(page, files[i]) def set_directory(self, path): """Set the selected directory.""" return self._filechooser_button.set_filename(path) def set_format(self, format): """Set the selected format.""" if format is None: return self._format_combo.set_active(format) def set_framerate(self, framerate): """Set the selected framerate.""" if framerate is None: return self._framerate_combo.set_active(framerate) def set_newline(self, newline): """Set the selected newline.""" if newline is None: return self._newline_combo.set_active(newline) def _show_overwrite_question_dialog(self, files, path): """Show a question dialog if about to overwrite files.""" n = sum(os.path.isfile(x.path) for x in files) title = _("{:d} of the files to be saved already exist. Do you want to replace them?").format(n) message = _('The files already exist in "{}". Replacing them will overwrite their contents.').format(path) dialog = gaupol.QuestionDialog(self._dialog, title, message) dialog.add_button(_("_Cancel"), Gtk.ResponseType.NO) dialog.add_button(_("_Replace"), Gtk.ResponseType.YES) dialog.set_default_response(Gtk.ResponseType.YES) response = gaupol.util.flash_dialog(dialog) gaupol.util.raise_default(response != Gtk.ResponseType.YES) gaupol-1.11/gaupol/dialogs/open.py000066400000000000000000000100251422217132500171440ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Dialog for selecting subtitle files to open.""" import aeidon import gaupol import os from aeidon.i18n import _ from gi.repository import GObject from gi.repository import Gtk __all__ = ("OpenDialog",) class OpenDialog(Gtk.FileChooserDialog, gaupol.FileDialog): """Dialog for selecting subtitle files to open.""" _widgets = ["align_combo", "align_label", "encoding_combo"] def __init__(self, parent, title, doc): """Initialize an :class:`OpenDialog` instance.""" GObject.GObject.__init__(self) self._use_autodetection = aeidon.util.chardet_available() self._init_dialog(parent, title) self._init_extra_widget() self._init_filters() self._init_encoding_combo() self._init_align_combo() self._init_values(doc) def _init_align_combo(self): """Initialize the align method combo box.""" store = Gtk.ListStore(str) self._align_combo.set_model(store) for align_method in aeidon.align_methods: store.append((align_method.label,)) view = self._align_combo.get_child() path = gaupol.util.tree_row_to_path(0) view.set_displayed_row(path) renderer = Gtk.CellRendererText() self._align_combo.pack_start(renderer, expand=True) self._align_combo.add_attribute(renderer, "text", 0) def _init_dialog(self, parent, title): """Initialize the dialog.""" self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_Open"), Gtk.ResponseType.OK) self.set_default_response(Gtk.ResponseType.OK) self.set_transient_for(parent) self.set_title(title) self.connect("response", self._on_response) self.set_action(Gtk.FileChooserAction.OPEN) def _init_extra_widget(self): """Initialize the extra widget from UI definition file.""" ui_file_path = os.path.join(aeidon.DATA_DIR, "ui", "open-dialog.ui") builder = Gtk.Builder() builder.set_translation_domain("gaupol") builder.add_from_file(ui_file_path) builder.connect_signals(self) for name in self._widgets: widget = builder.get_object(name) setattr(self, "_{}".format(name), widget) vbox = gaupol.util.new_vbox(spacing=0) main_vbox = builder.get_object("main_vbox") main_vbox.get_parent().remove(main_vbox) vbox.add(main_vbox) vbox.show_all() self.set_extra_widget(vbox) def _init_values(self, doc): """Initialize default values for widgets.""" self.set_select_multiple(doc == aeidon.documents.MAIN) if os.path.isdir(gaupol.conf.file.directory): self.set_current_folder(gaupol.conf.file.directory) self.set_encoding(gaupol.conf.file.encoding) self._align_combo.set_active(gaupol.conf.file.align_method) self._align_combo.set_visible(doc == aeidon.documents.TRAN) self._align_label.set_visible(doc == aeidon.documents.TRAN) def _on_response(self, dialog, response): """Save default values for widgets.""" gaupol.conf.file.encoding = self.get_encoding() directory = self.get_current_folder() if directory is not None: gaupol.conf.file.directory = directory index = self._align_combo.get_active() gaupol.conf.file.align_method = aeidon.align_methods[index] gaupol-1.11/gaupol/dialogs/position_shift.py000066400000000000000000000141111422217132500212440ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Dialogs for shifting positions.""" import aeidon import gaupol from aeidon.i18n import _ from gi.repository import Gtk __all__ = ("FrameShiftDialog", "TimeShiftDialog") class PositionShiftDialog(gaupol.BuilderDialog): """Base class for dialogs for shifting positions.""" _widgets = [ "all_radio", "amount_spin", "current_radio", "preview_button", "selected_radio", "to_end_radio", "unit_label", ] def __init__(self, parent, application): """Initialize a :class:`PositionShiftDialog` instance.""" gaupol.BuilderDialog.__init__(self, "position-shift-dialog.ui") self.application = application self._init_dialog(parent) self._init_widgets() self._init_values() def _get_preview_row(self): """Return row to start preview from.""" page = self.application.get_current_page() rows = page.view.get_selected_rows() return rows[0] if rows else 0 def _get_target(self): """Return the selected target.""" if self._selected_radio.get_active(): return gaupol.targets.SELECTED if self._to_end_radio.get_active(): return gaupol.targets.SELECTED_TO_END if self._current_radio.get_active(): return gaupol.targets.CURRENT if self._all_radio.get_active(): return gaupol.targets.ALL raise ValueError("Invalid target radio state") def _init_dialog(self, parent): """Initialize the dialog.""" self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_Shift"), Gtk.ResponseType.OK) self.set_default_response(Gtk.ResponseType.OK) self.set_transient_for(parent) self.set_modal(True) def _init_values(self): """Intialize default values for widgets.""" target = gaupol.conf.position_shift.target self._selected_radio.set_active(target == gaupol.targets.SELECTED) self._to_end_radio.set_active(target == gaupol.targets.SELECTED_TO_END) self._current_radio.set_active(target == gaupol.targets.CURRENT) self._all_radio.set_active(target == gaupol.targets.ALL) page = self.application.get_current_page() rows = page.view.get_selected_rows() if not rows and target in ( gaupol.targets.SELECTED, gaupol.targets.SELECTED_TO_END): self._current_radio.set_active(True) self._selected_radio.set_sensitive(bool(rows)) self._to_end_radio.set_sensitive(bool(rows)) if (page.project.video_path is None or page.project.main_file is None): self._preview_button.set_sensitive(False) self._amount_spin.emit("value-changed") def _init_widgets(self): """Initialize widgets.""" raise NotImplementedError def _on_amount_spin_value_changed(self, spin_button): """Set response sensitivity.""" has_value = (spin_button.get_value() != 0.0) self.set_response_sensitive(Gtk.ResponseType.OK, has_value) def _on_preview_button_clicked(self, *args): """Preview shift changes with a video player.""" page = self.application.get_current_page() target = self._get_target() rows = self.application.get_target_rows(target) self.application.preview_changes(page, self._get_preview_row(), aeidon.documents.MAIN, page.project.shift_positions, (rows, self._get_amount())) def _on_response(self, dialog, response): """Save target and shift positions.""" gaupol.conf.position_shift.target = self._get_target() if response == Gtk.ResponseType.OK: self._shift_positions() def _shift_positions(self): """Shift positions in subtitles.""" gaupol.util.set_cursor_busy(self) target = self._get_target() amount = self._get_amount() for page in self.application.get_target_pages(target): self.application.set_current_page(page) rows = self.application.get_target_rows(target) page.project.shift_positions(rows, amount) gaupol.util.set_cursor_normal(self) class FrameShiftDialog(PositionShiftDialog): """Dialog for shifting frames.""" def _get_amount(self): """Return the amount of frames to shift.""" return aeidon.as_frame(self._amount_spin.get_value_as_int()) def _init_widgets(self): """Initialize widgets.""" self._amount_spin.set_numeric(True) self._amount_spin.set_digits(0) self._amount_spin.set_increments(1, 10) self._amount_spin.set_range(-9999999, 9999999) self._amount_spin.set_value(0) self._unit_label.set_text(_("frames")) class TimeShiftDialog(PositionShiftDialog): """Dialog for shifting times.""" def _get_amount(self): """Return the amount of seconds to shift.""" return aeidon.as_seconds(self._amount_spin.get_value()) def _init_widgets(self): """Initialize widgets.""" self._amount_spin.set_numeric(True) self._amount_spin.set_digits(3) self._amount_spin.set_increments(0.1, 1) self._amount_spin.set_range(-99999, 99999) self._amount_spin.set_value(0.000) self._unit_label.set_text(_("seconds")) gaupol-1.11/gaupol/dialogs/position_transform.py000066400000000000000000000331511422217132500221470ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Dialogs for applying linear transformations to positions.""" import aeidon import gaupol from aeidon.i18n import _ from gi.repository import Gtk from gi.repository import Pango __all__ = ("FrameTransformDialog", "TimeTransformDialog") class PositionTransformDialog(gaupol.BuilderDialog): """Base class for dialogs for transforming positions.""" _widgets = [ "correction_hbox_1", "correction_hbox_2", "correction_label_1", "correction_label_2", "current_radio", "input_entry_1", "input_entry_2", "preview_button_1", "preview_button_2", "selected_radio", "subtitle_spin_1", "subtitle_spin_2", "text_label_1", "text_label_2", ] def __init__(self, parent, application): """Initialize a :class:`PositionTransformDialog` instance.""" gaupol.BuilderDialog.__init__(self, "position-transform-dialog.ui") self.application = application self._init_dialog(parent) self._init_sensitivities() self._init_sizes() def _get_target(self): """Return the selected target.""" if self._selected_radio.get_active(): return gaupol.targets.SELECTED if self._current_radio.get_active(): return gaupol.targets.CURRENT raise ValueError("Invalid target radio state") def _init_dialog(self, parent): """Initialize the dialog.""" self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_Transform"), Gtk.ResponseType.OK) self.set_default_response(Gtk.ResponseType.OK) self.set_transient_for(parent) self.set_modal(True) def _init_sensitivities(self): """Initialize sensitivities of widgets.""" page = self.application.get_current_page() if page.project.video_path is None: self._preview_button_1.set_sensitive(False) self._preview_button_2.set_sensitive(False) if page.project.main_file is None: self._preview_button_1.set_sensitive(False) self._preview_button_2.set_sensitive(False) def _init_sizes(self): """Initialize widget sizes.""" self._text_label_1.set_ellipsize(Pango.EllipsizeMode.END) self._text_label_2.set_ellipsize(Pango.EllipsizeMode.END) width = gaupol.util.char_to_px(50) self._text_label_1.set_size_request(width, -1) self._text_label_2.set_size_request(width, -1) def _init_values(self): """Intialize default values for widgets.""" page = self.application.get_current_page() self._subtitle_spin_1.set_value(1) self._subtitle_spin_2.set_value(len(page.project.subtitles)) self._subtitle_spin_1.emit("value-changed") self._subtitle_spin_2.emit("value-changed") target = gaupol.conf.position_transform.target self._selected_radio.set_active(target == gaupol.targets.SELECTED) self._current_radio.set_active(target == gaupol.targets.CURRENT) rows = page.view.get_selected_rows() if not rows and target == gaupol.targets.SELECTED: self._current_radio.set_active(True) self._selected_radio.set_sensitive(bool(rows)) self._selected_radio.emit("toggled") def _init_widgets(self): """Initialize properties of widgets.""" page = self.application.get_current_page() last_subtitle = len(page.project.subtitles) self._subtitle_spin_1.set_range(1, last_subtitle) self._subtitle_spin_2.set_range(1, last_subtitle) with aeidon.util.silent(AttributeError): self._text_label_1.props.xalign = 0 self._text_label_2.props.xalign = 0 def _on_preview_button_1_clicked(self, *args): """Preview changes from the first point.""" page = self.application.get_current_page() row = self._subtitle_spin_1.get_value_as_int() - 1 doc = aeidon.documents.MAIN method = page.project.transform_positions target = self._get_target() rows = self.application.get_target_rows(target) point_1 = self._get_first_point() point_2 = self._get_second_point() args = (rows, point_1, point_2) self.application.preview_changes(page, row, doc, method, args) def _on_preview_button_2_clicked(self, *args): """Preview changes from the second point.""" page = self.application.get_current_page() row = self._subtitle_spin_2.get_value_as_int() - 1 doc = aeidon.documents.MAIN method = page.project.transform_positions target = self._get_target() rows = self.application.get_target_rows(target) point_1 = self._get_first_point() point_2 = self._get_second_point() args = (rows, point_1, point_2) self.application.preview_changes(page, row, doc, method, args) def _on_response(self, dialog, response): """Save target and transform positions.""" gaupol.conf.position_transform.target = self._get_target() if response == Gtk.ResponseType.OK: self._transform_positions() def _on_selected_radio_toggled(self, *args): """Set subtitle values from selection.""" page = self.application.get_current_page() rows = page.view.get_selected_rows() ranges = aeidon.util.get_ranges(rows) if (self._selected_radio.get_active() and len(rows) > 1 and len(ranges) == 1 and not self._output_edited()): self._subtitle_spin_1.set_value(rows[0] + 1) self._subtitle_spin_2.set_value(rows[-1] + 1) elif not self._output_edited(): self._subtitle_spin_1.set_value(1) self._subtitle_spin_2.set_value(len(page.project.subtitles)) def _transform_positions(self): """Transform positions in subtitles.""" page = self.application.get_current_page() target = self._get_target() rows = self.application.get_target_rows(target) point_1 = self._get_first_point() point_2 = self._get_second_point() page.project.transform_positions(rows, point_1, point_2) class FrameTransformDialog(PositionTransformDialog): """Dialog for applying a linear tranfromation to frames.""" def __init__(self, parent, application): """Initialize a :class:`FrameTransformDialog` instance.""" PositionTransformDialog.__init__(self, parent, application) self._output_spin_1 = Gtk.SpinButton() self._output_spin_2 = Gtk.SpinButton() self._init_widgets() self._init_values() def _get_first_point(self): """Return row, output frame of the first sync point.""" return (self._subtitle_spin_1.get_value_as_int() - 1, aeidon.as_frame(self._output_spin_1.get_value_as_int())) def _get_second_point(self): """Return row, output frame of the second sync point.""" return (self._subtitle_spin_2.get_value_as_int() - 1, aeidon.as_frame(self._output_spin_2.get_value_as_int())) def _init_widgets(self): """Initialize properties of widgets.""" PositionTransformDialog._init_widgets(self) self._input_entry_1.set_width_chars(6) self._input_entry_2.set_width_chars(6) self._output_spin_1.set_digits(0) self._output_spin_2.set_digits(0) self._output_spin_1.set_increments(1, 10) self._output_spin_2.set_increments(1, 10) self._output_spin_1.set_range(0, 999999) self._output_spin_2.set_range(0, 999999) gaupol.util.pack_start_expand(self._correction_hbox_1, self._output_spin_1) gaupol.util.pack_start_expand(self._correction_hbox_2, self._output_spin_2) self._correction_hbox_1.show_all() self._correction_hbox_2.show_all() self._correction_label_1.set_mnemonic_widget(self._output_spin_1) self._correction_label_2.set_mnemonic_widget(self._output_spin_2) def _on_subtitle_spin_1_value_changed(self, spin_button): """Update subtitle data in widgets.""" page = self.application.get_current_page() row = spin_button.get_value_as_int() - 1 subtitle = page.project.subtitles[row] self._input_entry_1.set_text(str(subtitle.start_frame)) self._output_spin_1.set_value(int(subtitle.start_frame)) text = subtitle.main_text.replace("\n", " ") text = aeidon.RE_ANY_TAG.sub("", text) self._text_label_1.set_text(text) self._text_label_1.set_tooltip_text(subtitle.main_text) self._subtitle_spin_2.get_adjustment().set_lower(row + 2) def _on_subtitle_spin_2_value_changed(self, spin_button): """Update subtitle data in widgets.""" page = self.application.get_current_page() row = spin_button.get_value_as_int() - 1 subtitle = page.project.subtitles[row] self._input_entry_2.set_text(str(subtitle.start_frame)) self._output_spin_2.set_value(int(subtitle.start_frame)) text = subtitle.main_text.replace("\n", " ") text = aeidon.RE_ANY_TAG.sub("", text) self._text_label_2.set_text(text) self._text_label_2.set_tooltip_text(subtitle.main_text) self._subtitle_spin_1.get_adjustment().set_upper(row) def _output_edited(self): """Return ``True`` if output of either point has been edited.""" in_1 = aeidon.as_frame(self._input_entry_1.get_text()) in_2 = aeidon.as_frame(self._input_entry_2.get_text()) out_1 = aeidon.as_frame(self._output_spin_1.get_value_as_int()) out_2 = aeidon.as_frame(self._output_spin_2.get_value_as_int()) return (out_1 != in_1 or out_2 != in_2) class TimeTransformDialog(PositionTransformDialog): """Dialog for applying a linear tranfromation to times.""" def __init__(self, parent, application): """Initialize a :class:`TimeTransformDialog` instance.""" PositionTransformDialog.__init__(self, parent, application) self._output_entry_1 = gaupol.TimeEntry() self._output_entry_2 = gaupol.TimeEntry() self._init_widgets() self._init_values() def _get_first_point(self): """Return row, output time of the first sync point.""" return (self._subtitle_spin_1.get_value_as_int() - 1, aeidon.as_time(self._output_entry_1.get_text())) def _get_second_point(self): """Return row, output time of the second sync point.""" return (self._subtitle_spin_2.get_value_as_int() - 1, aeidon.as_time(self._output_entry_2.get_text())) def _init_widgets(self): """Initialize properties of widgets.""" PositionTransformDialog._init_widgets(self) self._input_entry_1.set_width_chars(13) self._input_entry_2.set_width_chars(13) gaupol.util.pack_start_expand(self._correction_hbox_1, self._output_entry_1) gaupol.util.pack_start_expand(self._correction_hbox_2, self._output_entry_2) self._correction_hbox_1.show_all() self._correction_hbox_2.show_all() self._correction_label_1.set_mnemonic_widget(self._output_entry_1) self._correction_label_2.set_mnemonic_widget(self._output_entry_2) def _on_subtitle_spin_1_value_changed(self, spin_button): """Update subtitle data in widgets.""" page = self.application.get_current_page() row = spin_button.get_value_as_int() - 1 subtitle = page.project.subtitles[row] self._input_entry_1.set_text(str(subtitle.start_time)) self._output_entry_1.set_text(str(subtitle.start_time)) text = subtitle.main_text.replace("\n", " ") text = aeidon.RE_ANY_TAG.sub("", text) self._text_label_1.set_text(text) self._text_label_1.set_tooltip_text(subtitle.main_text) self._subtitle_spin_2.get_adjustment().set_lower(row + 2) # Allow the GLib.idle_add-using TimeEntry to update. gaupol.util.iterate_main() def _on_subtitle_spin_2_value_changed(self, spin_button): """Update subtitle data in widgets.""" page = self.application.get_current_page() row = spin_button.get_value_as_int() - 1 subtitle = page.project.subtitles[row] self._input_entry_2.set_text(str(subtitle.start_time)) self._output_entry_2.set_text(str(subtitle.start_time)) text = subtitle.main_text.replace("\n", " ") text = aeidon.RE_ANY_TAG.sub("", text) self._text_label_2.set_text(text) self._text_label_2.set_tooltip_text(subtitle.main_text) self._subtitle_spin_1.get_adjustment().set_upper(row) # Allow the GLib.idle_add-using TimeEntry to update. gaupol.util.iterate_main() def _output_edited(self): """Return ``True`` if output of either point has been edited.""" in_1 = aeidon.as_time(self._input_entry_1.get_text()) in_2 = aeidon.as_time(self._input_entry_2.get_text()) out_1 = aeidon.as_time(self._output_entry_1.get_text()) out_2 = aeidon.as_time(self._output_entry_2.get_text()) return (out_1 != in_1 or out_2 != in_2) gaupol-1.11/gaupol/dialogs/preferences.py000066400000000000000000000564601422217132500205210ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Dialog for editing preferences.""" import aeidon import gaupol from aeidon.i18n import _ from gi.repository import Gtk from gi.repository import Pango __all__ = ("PreferencesDialog",) class EditorPage(aeidon.Delegate, gaupol.BuilderDialog): """Editor preferences page.""" _widgets = [ "editor_default_font_check", "editor_font_button", "editor_font_hbox", "editor_length_cell_check", "editor_length_combo", "editor_length_edit_check", "editor_length_hbox", "editor_spell_check_check", ] def __init__(self, master, application): """Initialize an :class:`EditorPage` instance.""" aeidon.Delegate.__init__(self, master) self._set_attributes(self._widgets, "editor_") self.application = application self._init_length_combo() self._init_values() def _get_custom_font(self): """Return custom font as string.""" context = Gtk.Label().get_pango_context() font_desc = context.get_font_description() font = gaupol.conf.editor.custom_font custom_font_desc = Pango.FontDescription(font) font_desc.merge(custom_font_desc, True) return font_desc.to_string() def _init_length_combo(self): """Initialize the line length combo box.""" store = Gtk.ListStore(str) for label in (x.label for x in gaupol.length_units): store.append((label,)) self._length_combo.set_model(store) renderer = Gtk.CellRendererText() self._length_combo.pack_start(renderer, expand=True) self._length_combo.add_attribute(renderer, "text", 0) def _init_values(self): """Initialize default values for widgets.""" use_custom = gaupol.conf.editor.use_custom_font self._default_font_check.set_active(not use_custom) self._font_hbox.set_sensitive(use_custom) self._font_button.set_font(self._get_custom_font()) show_cell = gaupol.conf.editor.show_lengths_cell show_edit = gaupol.conf.editor.show_lengths_edit self._length_hbox.set_sensitive(show_cell or show_edit) self._length_cell_check.set_active(show_cell) self._length_edit_check.set_active(show_edit) self._length_combo.set_active(gaupol.conf.editor.length_unit) if gaupol.SpellChecker.available(): inline = gaupol.conf.spell_check.inline self._spell_check_check.set_active(inline) self._spell_check_check.set_sensitive(True) else: # not available self._spell_check_check.set_active(False) self._spell_check_check.set_sensitive(False) def _on_default_font_check_toggled(self, check_button): """Save default font usage.""" use_custom = not check_button.get_active() gaupol.conf.editor.use_custom_font = use_custom self._font_hbox.set_sensitive(use_custom) def _on_font_button_font_set(self, font_button): """Save custom font.""" gaupol.conf.editor.custom_font = font_button.get_font_name() def _on_length_cell_check_toggled(self, check_button): """Save line length display on cells.""" gaupol.conf.editor.show_lengths_cell = check_button.get_active() show_cell = gaupol.conf.editor.show_lengths_cell show_edit = gaupol.conf.editor.show_lengths_edit self._length_hbox.set_sensitive(show_cell or show_edit) def _on_length_combo_changed(self, combo_box): """Save line length unit.""" index = combo_box.get_active() gaupol.conf.editor.length_unit = gaupol.length_units[index] def _on_length_edit_check_toggled(self, check_button): """Save line length display on text views.""" gaupol.conf.editor.show_lengths_edit = check_button.get_active() show_cell = gaupol.conf.editor.show_lengths_cell show_edit = gaupol.conf.editor.show_lengths_edit self._length_hbox.set_sensitive(show_cell or show_edit) def _on_spell_check_check_toggled(self, check_button): """Save inline spell-check use on text views.""" gaupol.conf.spell_check.inline = check_button.get_active() class ExtensionPage(aeidon.Delegate, gaupol.BuilderDialog): """Extension activation and preferences page.""" _widgets = [ "extensions_about_button", "extensions_help_button", "extensions_preferences_button", "extensions_toolbar", "extensions_tree_view", ] def __init__(self, master, application): """Initialize an :class:`ExtensionPage` instance.""" aeidon.Delegate.__init__(self, master) self._set_attributes(self._widgets, "extensions_") self.application = application self.manager = self.application.extension_manager self._init_tree_view() self._init_toolbar() self._init_values() self._init_sensitivities() def _get_selected_module(self): """Return the selected module in the tree view or ``None``.""" selection = self._tree_view.get_selection() store, itr = selection.get_selected() if itr is None: return None return store.get_value(itr, 0) def _init_sensitivities(self): """Initialize button sensitivities.""" self._about_button.set_sensitive(False) self._help_button.set_sensitive(False) self._preferences_button.set_sensitive(False) def _init_toolbar(self): """Initialize the tree view inline toolbar.""" self._toolbar.set_icon_size(Gtk.IconSize.MENU) style = self._toolbar.get_style_context() style.add_class(Gtk.STYLE_CLASS_INLINE_TOOLBAR) def _init_tree_view(self): """Initialize the tree view.""" store = Gtk.ListStore(str, bool, str) self._tree_view.set_model(store) selection = self._tree_view.get_selection() selection.set_mode(Gtk.SelectionMode.SINGLE) selection.connect("changed", self._on_tree_view_selection_changed) renderer = Gtk.CellRendererToggle() renderer.props.activatable = True renderer.props.xpad = 6 renderer.connect("toggled", self._on_tree_view_cell_toggled) column = Gtk.TreeViewColumn("", renderer, active=1) self._tree_view.append_column(column) renderer = Gtk.CellRendererText() renderer.props.ellipsize = Pango.EllipsizeMode.END column = Gtk.TreeViewColumn("", renderer, markup=2) self._tree_view.append_column(column) def _init_values(self): """Initialize default values for widgets.""" store = self._tree_view.get_model() extensions = [] for module in self.manager.get_modules(): metadata = self.manager.get_metadata(module) if metadata.get_field_boolean("Hidden", False): continue markup = "{}\n{}".format( metadata.get_name(), metadata.get_description()) extensions.append((module, markup)) extensions.sort(key=lambda x: x[1]) for module, markup in extensions: active = module in gaupol.conf.extensions.active store.append((module, active, markup)) def _on_about_button_clicked(self, *args): """Construct and show a :class:`Gtk.AboutDialog` for extension.""" module = self._get_selected_module() metadata = self.manager.get_metadata(module) dialog = Gtk.AboutDialog() dialog.set_transient_for(self._dialog) dialog.set_program_name(metadata.get_name()) dialog.set_comments(metadata.get_description()) dialog.set_logo_icon_name("io.otsaloma.gaupol") if metadata.has_field("Version"): dialog.set_version(metadata.get_field("Version")) if metadata.has_field("Copyright"): copyright = "\n".join(metadata.get_field_list("Copyright")) dialog.set_copyright(copyright) if metadata.has_field("Website"): dialog.set_website(metadata.get_field("Website")) label = _("{} Extension Website").format(metadata.get_name()) dialog.set_website_label(label) if metadata.has_field("Authors"): dialog.set_authors(metadata.get_field_list("Authors")) gaupol.util.flash_dialog(dialog) def _on_help_button_clicked(self, *args): """Show extension's own documentation.""" module = self._get_selected_module() self.manager.show_help(module) def _on_preferences_button_clicked(self, *args): """Show extension's preferences dialog.""" module = self._get_selected_module() self.manager.show_preferences_dialog(module, self._dialog) def _on_tree_view_cell_toggled(self, renderer, path): """Activate or deactivate toggled extension.""" store = self._tree_view.get_model() module = store[path][0] active = store[path][1] if active: self.manager.teardown_extension(module) gaupol.conf.extensions.active.remove(module) else: self.manager.setup_extension(module) gaupol.conf.extensions.active.append(module) for row in store: row[1] = self.manager.is_active(row[0]) selection = self._tree_view.get_selection() selection.emit("changed") def _on_tree_view_selection_changed(self, *args): """Set sensitivities of buttons.""" module = self._get_selected_module() have_selection = self._get_selected_module() is not None self._about_button.set_sensitive(have_selection) if module in gaupol.conf.extensions.active: has_help = self.manager.has_help(module) self._help_button.set_sensitive(has_help) has_preferences = self.manager.has_preferences_dialog(module) self._preferences_button.set_sensitive(has_preferences) else: # Cannot query unimported extensions. self._help_button.set_sensitive(False) self._preferences_button.set_sensitive(False) class FilePage(aeidon.Delegate, gaupol.BuilderDialog): """File preferences page.""" _widgets = [ "file_add_button", "file_auto_check", "file_down_button", "file_locale_check", "file_remove_button", "file_toolbar", "file_tree_view", "file_up_button", ] def __init__(self, master, application): """Initialize a :class:`FilePage` instance.""" aeidon.Delegate.__init__(self, master) self._set_attributes(self._widgets, "file_") self.application = application self._init_tree_view() self._init_toolbar() self._init_values() def _get_selected_row(self): """Return the selected row in the tree view or ``None``.""" selection = self._tree_view.get_selection() store, itr = selection.get_selected() if itr is None: return None path = store.get_path(itr) return gaupol.util.tree_path_to_row(path) def _init_toolbar(self): """Initialize the tree view inline toolbar.""" self._toolbar.set_icon_size(Gtk.IconSize.MENU) style = self._toolbar.get_style_context() style.add_class(Gtk.STYLE_CLASS_INLINE_TOOLBAR) theme = Gtk.IconTheme.get_default() # Tool buttons in the UI file are specified as symbolic icons # by name, found in adwaita-icon-theme. If missing in another # theme fall back to non-symbolic icons. if not all((theme.has_icon(self._add_button.get_icon_name()), theme.has_icon(self._remove_button.get_icon_name()), theme.has_icon(self._up_button.get_icon_name()), theme.has_icon(self._down_button.get_icon_name()))): self._add_button.set_icon_name("list-add") self._remove_button.set_icon_name("list-remove") self._up_button.set_icon_name("go-up") self._down_button.set_icon_name("go-down") def _init_tree_view(self): """Initialize the fallback encoding tree view.""" selection = self._tree_view.get_selection() selection.set_mode(Gtk.SelectionMode.SINGLE) update = lambda x, self: self._set_sensitivities() selection.connect("changed", update, self) store = Gtk.ListStore(str) self._tree_view.set_model(store) renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn("", renderer, text=0) self._tree_view.append_column(column) def _init_values(self): """Initialize default values for widgets.""" self._auto_check.set_active(gaupol.conf.encoding.try_auto) self._auto_check.set_sensitive(aeidon.util.chardet_available()) self._locale_check.set_active(gaupol.conf.encoding.try_locale) self._reload_tree_view() def _on_add_button_clicked(self, *args): """Add a new fallback encoding.""" dialog = gaupol.EncodingDialog(self._dialog) response = gaupol.util.run_dialog(dialog) encoding = dialog.get_encoding() dialog.destroy() if response != Gtk.ResponseType.OK: return if encoding is None: return if encoding in gaupol.conf.encoding.fallback: return gaupol.conf.encoding.fallback.append(encoding) self._reload_tree_view() self._tree_view.grab_focus() store = self._tree_view.get_model() self._tree_view.set_cursor(len(store) - 1) def _on_auto_check_toggled(self, check_button): """Save encoding auto-detection usage.""" gaupol.conf.encoding.try_auto = check_button.get_active() def _on_down_button_clicked(self, *args): """Move the selected fallback encoding down.""" row = self._get_selected_row() encodings = gaupol.conf.encoding.fallback encodings.insert(row + 1, encodings.pop(row)) self._reload_tree_view() self._tree_view.grab_focus() self._tree_view.set_cursor(row + 1) def _on_locale_check_toggled(self, check_button): """Save locale encoding usage.""" gaupol.conf.encoding.try_locale = check_button.get_active() def _on_remove_button_clicked(self, *args): """Remove the selected fallback encoding.""" row = self._get_selected_row() gaupol.conf.encoding.fallback.pop(row) self._reload_tree_view() self._tree_view.grab_focus() store = self._tree_view.get_model() if len(store) <= 0: return self._tree_view.set_cursor(max(row-1, 0)) def _on_up_button_clicked(self, *args): """Move the selected fallback encoding up.""" row = self._get_selected_row() encodings = gaupol.conf.encoding.fallback encodings.insert(row-1, encodings.pop(row)) self._reload_tree_view() self._tree_view.grab_focus() self._tree_view.set_cursor(row-1) def _reload_tree_view(self): """Reload the fallback encoding tree view.""" store = self._tree_view.get_model() store.clear() for encoding in gaupol.conf.encoding.fallback: store.append((aeidon.encodings.code_to_long_name(encoding),)) self._set_sensitivities() def _set_sensitivities(self): """Set the fallback tree view button sensitivities.""" store = self._tree_view.get_model() row = self._get_selected_row() row = -1 if row is None else row self._remove_button.set_sensitive(row >= 0) self._up_button.set_sensitive(row > 0) self._down_button.set_sensitive(0 <= row < len(store) - 1) class PreviewPage(aeidon.Delegate, gaupol.BuilderDialog): """Preview preferences page.""" _widgets = [ "preview_app_combo", "preview_command_entry", "preview_force_utf_8_check", "preview_offset_spin", ] def __init__(self, master, application): """Initialize a :class:`PreviewPage` instance.""" aeidon.Delegate.__init__(self, master) self._set_attributes(self._widgets, "preview_") self.application = application self._init_app_combo() self._init_values() def _init_app_combo(self): """Initialize the application combo box.""" store = Gtk.ListStore(str) self._app_combo.set_model(store) for label in (x.label for x in aeidon.players): store.append((label,)) store.append((gaupol.COMBO_SEPARATOR,)) store.append((_("Custom"),)) renderer = Gtk.CellRendererText() self._app_combo.pack_start(renderer, expand=True) self._app_combo.add_attribute(renderer, "text", 0) func = gaupol.util.separate_combo self._app_combo.set_row_separator_func(func, None) def _init_values(self): """Initialize default values for widgets.""" store = self._app_combo.get_model() self._app_combo.set_active((len(store) - 1 if gaupol.conf.preview.use_custom_command else gaupol.conf.preview.player)) self._command_entry.set_text(gaupol.util.get_preview_command()) editable = gaupol.conf.preview.use_custom_command self._command_entry.set_editable(editable) self._force_utf_8_check.set_active(gaupol.conf.preview.force_utf_8) self._offset_spin.set_value(gaupol.conf.preview.offset) def _on_app_combo_changed(self, combo_box): """Save video player and show it's command.""" index = combo_box.get_active() use_custom = not index in aeidon.players gaupol.conf.preview.use_custom_command = use_custom if not use_custom: gaupol.conf.preview.player = aeidon.players[index] self._command_entry.set_text(gaupol.util.get_preview_command()) editable = gaupol.conf.preview.use_custom_command self._command_entry.set_editable(editable) def _on_command_entry_changed(self, entry): """Save custom command.""" if not gaupol.conf.preview.use_custom_command: return gaupol.conf.preview.custom_command = entry.get_text() def _on_force_utf_8_check_toggled(self, check_button): """Save forced UTF-8 preview setting.""" gaupol.conf.preview.force_utf_8 = check_button.get_active() self._command_entry.set_text(gaupol.util.get_preview_command()) def _on_offset_spin_value_changed(self, spin_button): """Save start position offset.""" gaupol.conf.preview.offset = spin_button.get_value() class VideoPage(aeidon.Delegate, gaupol.BuilderDialog): """Video preferences page.""" _widgets = [ "video_seek_spin", "video_subtitle_bg_check", "video_subtitle_color_button", "video_subtitle_font_button", "video_time_bg_check", "video_time_color_button", "video_time_font_button", ] def __init__(self, master, application): """Initialize a :class:`PreviewPage` instance.""" aeidon.Delegate.__init__(self, master) self._set_attributes(self._widgets, "video_") self.application = application self.conf = gaupol.conf.video_player self._init_values() def _get_custom_font(self, font): """Return custom font as string.""" context = Gtk.Label().get_pango_context() font_desc = context.get_font_description() custom_font_desc = Pango.FontDescription(font) font_desc.merge(custom_font_desc, True) return font_desc.to_string() def _init_values(self): """Initialize default values for widgets.""" font = self._get_custom_font(self.conf.subtitle_font) self._subtitle_font_button.set_font(font) font = self._get_custom_font(self.conf.time_font) self._time_font_button.set_font(font) self._subtitle_bg_check.set_active(self.conf.subtitle_background) color = gaupol.util.hex_to_rgba(self.conf.subtitle_color) color.alpha = self.conf.subtitle_alpha self._subtitle_color_button.set_rgba(color) self._time_bg_check.set_active(self.conf.time_background) color = gaupol.util.hex_to_rgba(self.conf.time_color) color.alpha = self.conf.time_alpha self._time_color_button.set_rgba(color) self._seek_spin.set_value(self.conf.seek_length) def _on_seek_spin_value_changed(self, spin_button): """Save seek length.""" self.conf.seek_length = spin_button.get_value() def _on_subtitle_bg_check_toggled(self, check_button): """Save subtitle background use.""" self.conf.subtitle_background = check_button.get_active() def _on_subtitle_color_button_color_set(self, color_button): """Save subtitle color.""" color = color_button.get_rgba() self.conf.subtitle_color = gaupol.util.rgba_to_hex(color) self.conf.subtitle_alpha = color.alpha def _on_subtitle_font_button_font_set(self, font_button): """Save subtitle font.""" self.conf.subtitle_font = font_button.get_font_name() def _on_time_bg_check_toggled(self, check_button): """Save time background use.""" self.conf.time_background = check_button.get_active() def _on_time_color_button_color_set(self, color_button): """Save time color.""" color = color_button.get_rgba() self.conf.time_color = gaupol.util.rgba_to_hex(color) self.conf.time_alpha = color.alpha def _on_time_font_button_font_set(self, font_button): """Save time font.""" self.conf.time_font = font_button.get_font_name() class PreferencesDialog(gaupol.BuilderDialog): """Dialog for editing preferences.""" _widgets = ["notebook"] def __init__(self, parent, application): """Initialize a :class:`PreferencesDialog` instance.""" gaupol.BuilderDialog.__init__(self, "preferences-dialog.ui", connect_signals=False) self._editor_page = EditorPage(self, application) self._extension_page = ExtensionPage(self, application) self._file_page = FilePage(self, application) self._preview_page = PreviewPage(self, application) self._video_page = VideoPage(self, application) self._builder.connect_signals(self._get_callbacks()) self._init_dialog(parent) def _get_callbacks(self): """Return a dictionary mapping names to callback methods.""" callbacks = {} for page in (self._editor_page, self._extension_page, self._file_page, self._preview_page, self._video_page): for name in (x for x in dir(page) if x.startswith("_on_")): callbacks[name] = getattr(page, name) return callbacks def _init_dialog(self, parent): """Initialize the dialog.""" self.set_default_response(Gtk.ResponseType.CLOSE) self.set_transient_for(parent) self.set_modal(True) gaupol-1.11/gaupol/dialogs/preview_error.py000066400000000000000000000061371422217132500211060ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Dialog for informing that preview failed.""" import aeidon import gaupol from aeidon.i18n import _ from gi.repository import GObject from gi.repository import Gtk class PreviewErrorDialog(Gtk.MessageDialog): """Dialog for informing that preview failed.""" def __init__(self, parent, output): """Initialize a :class:`PreviewErrorDialog` instance.""" GObject.GObject.__init__(self, message_type=Gtk.MessageType.ERROR, text=_("Preview in video player failed"), secondary_text=_("There is probably a problem with either the video file or the video player. See the preferences dialog to choose the video player or to customize the command.")) self._text_view = Gtk.TextView() self._init_dialog(parent) self._init_text_view(output) def _init_dialog(self, parent): """Initialize the dialog.""" self.add_button(_("_Close"), Gtk.ResponseType.CLOSE) self.set_default_response(Gtk.ResponseType.CLOSE) self.set_transient_for(parent) self.set_modal(True) def _init_text_view(self, output): """Initialize the text view.""" self._text_view.set_wrap_mode(Gtk.WrapMode.WORD) self._text_view.set_editable(False) self._text_view.set_cursor_visible(False) self._text_view.set_accepts_tab(False) self._text_view.set_left_margin(6) self._text_view.set_right_margin(6) with aeidon.util.silent(AttributeError): # Available since GTK 3.18. self._text_view.set_top_margin(6) self._text_view.set_bottom_margin(6) text_buffer = self._text_view.get_buffer() text_buffer.set_text(output) gaupol.style.use_font(self._text_view, "monospace") scroller = Gtk.ScrolledWindow() scroller.set_policy(*((Gtk.PolicyType.AUTOMATIC,)*2)) scroller.set_shadow_type(Gtk.ShadowType.ETCHED_IN) scroller.add(self._text_view) box = self.get_message_area() gaupol.util.pack_start_expand(box, scroller) gaupol.util.scale_to_content(self._text_view, min_nchar=60, max_nchar=100, min_nlines=10, max_nlines=25, font="monospace") box.show_all() gaupol-1.11/gaupol/dialogs/save.py000066400000000000000000000207071422217132500171510ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Dialog for selecting a subtitle file to save.""" import aeidon import gaupol import os from aeidon.i18n import _ from gi.repository import GObject from gi.repository import Gtk __all__ = ("SaveDialog",) class SaveDialog(Gtk.FileChooserDialog, gaupol.FileDialog): """Dialog for selecting a subtitle file to save.""" _widgets = [ "encoding_combo", "format_combo", "framerate_combo", "framerate_label", "newline_combo", ] def __init__(self, parent, title, mode): """Initialize a :class:`SaveDialog` instance.""" GObject.GObject.__init__(self) self._mode = mode self._init_dialog(parent, title) self._init_extra_widget() self._init_filters() self._init_format_combo() self._init_encoding_combo() self._init_newline_combo() self._init_framerate_combo() self._init_values() def get_format(self): """Return the selected format.""" index = self._format_combo.get_active() return aeidon.formats[index] def get_framerate(self): """Return the selected framerate.""" index = self._framerate_combo.get_active() return aeidon.framerates[index] def get_newline(self): """Return the selected newline.""" index = self._newline_combo.get_active() return aeidon.newlines[index] def _init_dialog(self, parent, title): """Initialize the dialog.""" self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_Save"), Gtk.ResponseType.OK) self.set_default_response(Gtk.ResponseType.OK) self.set_transient_for(parent) self.set_title(title) self.connect("response", self._on_response) save_button = self.get_widget_for_response(Gtk.ResponseType.OK) save_button.connect("event", self._on_save_button_event) self.set_action(Gtk.FileChooserAction.SAVE) self.set_do_overwrite_confirmation(True) def _init_extra_widget(self): """Initialize the extra widget from UI definition file.""" ui_file_path = os.path.join(aeidon.DATA_DIR, "ui", "save-dialog.ui") builder = Gtk.Builder() builder.set_translation_domain("gaupol") builder.add_from_file(ui_file_path) builder.connect_signals(self) for name in self._widgets: widget = builder.get_object(name) setattr(self, "_{}".format(name), widget) vbox = gaupol.util.new_vbox(spacing=0) main_vbox = builder.get_object("main_vbox") main_vbox.get_parent().remove(main_vbox) vbox.add(main_vbox) vbox.show_all() self.set_extra_widget(vbox) def _init_format_combo(self): """Initialize the format combo box.""" store = Gtk.ListStore(str) self._format_combo.set_model(store) for name in (x.label for x in aeidon.formats): if name == "SubRip": # Mark the SubRip format as recommended, since # it's the most common one and best supported, # both in Gaupol and elsewhere. name = _("{} (recommended)").format(name) store.append((name,)) view = self._format_combo.get_child() path = gaupol.util.tree_row_to_path(0) view.set_displayed_row(path) renderer = Gtk.CellRendererText() self._format_combo.pack_start(renderer, expand=True) self._format_combo.add_attribute(renderer, "text", 0) def _init_framerate_combo(self): """Initialize the framerate combo box.""" store = Gtk.ListStore(str) self._framerate_combo.set_model(store) for name in (x.label for x in aeidon.framerates): store.append((name,)) view = self._framerate_combo.get_child() path = gaupol.util.tree_row_to_path(0) view.set_displayed_row(path) renderer = Gtk.CellRendererText() self._framerate_combo.pack_start(renderer, expand=True) self._framerate_combo.add_attribute(renderer, "text", 0) def _init_newline_combo(self): """Initialize the newline combo box.""" store = Gtk.ListStore(str) self._newline_combo.set_model(store) for name in (x.label for x in aeidon.newlines): store.append((name,)) view = self._newline_combo.get_child() path = gaupol.util.tree_row_to_path(0) view.set_displayed_row(path) renderer = Gtk.CellRendererText() self._newline_combo.pack_start(renderer, expand=True) self._newline_combo.add_attribute(renderer, "text", 0) def _init_values(self): """Initialize default values for widgets.""" if os.path.isdir(gaupol.conf.file.directory): self.set_current_folder(gaupol.conf.file.directory) self.set_encoding(gaupol.conf.file.encoding) self.set_format(gaupol.conf.file.format) self.set_newline(gaupol.conf.file.newline) self.set_framerate(gaupol.conf.editor.framerate) self._framerate_combo.hide() self._framerate_label.hide() def _on_format_combo_changed(self, *args): """Change the extension of the current filename.""" format = self.get_format() path = self.get_filename() if path is not None: dirname = os.path.dirname(path) basename = os.path.basename(path) if not path.endswith(format.extension): basename = aeidon.util.replace_extension(basename, format) path = os.path.join(dirname, basename) self.unselect_filename(path) self.set_current_name(basename) self.set_filename(path) visible = (format.mode != self._mode) self._framerate_combo.set_visible(visible) self._framerate_label.set_visible(visible) def _on_response(self, dialog, response): """Save default values for widgets.""" directory = self.get_current_folder() if directory is not None: gaupol.conf.file.directory = directory gaupol.conf.file.encoding = self.get_encoding() gaupol.conf.file.format = self.get_format() gaupol.conf.file.newline = self.get_newline() gaupol.conf.editor.framerate = self.get_framerate() if (response == Gtk.ResponseType.OK and not self.get_filename().endswith(self.get_format().extension)): # If the filename is lacking the extension, add it, stop this # response and emit a new one so that overwrite confirmation gets # called with the full filename. The filename extension might have # already been added in self._on_save_button_event, but not # necessarily if the user hit Enter on the keyboard. self._format_combo.emit("changed") gaupol.util.iterate_main() self.stop_emission("response") return self.response(Gtk.ResponseType.OK) def _on_save_button_event(self, button, event): """Ensure that the filename contains an extension.""" # Add possibly lacking extension to the filename. self._format_combo.emit("changed") gaupol.util.iterate_main() def set_format(self, format): """Set the selected format.""" if format is None: return self._format_combo.set_active(format) def set_framerate(self, framerate): """Set the selected framerate.""" if framerate is None: return self._framerate_combo.set_active(framerate) def set_name(self, path): """Set the selected filename.""" if os.path.isfile(path): return self.set_filename(path) return self.set_current_name(path) def set_newline(self, newline): """Set the selected newline.""" if newline is None: return self._newline_combo.set_active(newline) gaupol-1.11/gaupol/dialogs/search.py000066400000000000000000000564311422217132500174630ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2006 Osmo Salomaa # # 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 . """Dialog for searching for and replacing text.""" import aeidon import functools import gaupol import os import re from aeidon.i18n import _, n_ from gi.repository import Gdk from gi.repository import Gtk __all__ = ("SearchDialog",) def page_changing(function): """Decorator for :class:`SearchDialog` methods that edit data.""" @functools.wraps(function) def wrapper(*args, **kwargs): args[0]._handle_page_changes = False value = function(*args, **kwargs) args[0]._handle_page_changes = True return value return wrapper class SearchDialog(gaupol.BuilderDialog): """ Dialog for searching for and replacing text. :ivar _handle_page_changes: ``True`` to invalidate search on page changes :ivar _match_doc: :attr:`gaupol.documents` item of the last match :ivar _match_page: :class:`gaupol.Page` instance of the last match :ivar _match_row: Row in :attr:`_match_page` of the last match :ivar _match_span: Start, end position of the last match :ivar patterns: List of patterns previously searched for :ivar replacements: List of replacements previously used :ivar _statuslabel: Instance of :class:`gaupol.FloatingLabel` used :ivar _was_next: ``True`` if the last search was "next", else ``False`` """ _widgets = [ "all_radio", "current_radio", "ignore_case_check", "main_check", "next_button", "overlay", "pattern_combo", "previous_button", "regex_check", "replace_all_button", "replace_button", "replacement_combo", "search_vbox", "text_view", "tran_check", ] def __init__(self, parent, application): """Initialize a :class:`SearchDialog` instance.""" gaupol.BuilderDialog.__init__(self, "search-dialog.ui") self.application = application self._handle_page_changes = True self._match_doc = None self._match_page = None self._match_row = None self._match_span = None self.max_history = 10 self._pattern_entry = None self.patterns = [] self._replacement_entry = None self.replacements = [] self._statuslabel = gaupol.FloatingLabel() self._was_next = None self._read_history("patterns") self._read_history("replacements") self._init_dialog(parent) self._init_text_view() self._init_pattern_combo() self._init_replacement_combo() self._init_keys() self._init_values() self._init_signal_handlers() self._init_sensitivities() self._overlay.add_overlay(self._statuslabel) self._overlay.show_all() self._statuslabel.set_text(None) def _add_pattern_to_history(self): """Add current pattern to the pattern combo box.""" pattern = self._pattern_entry.get_text() store = self._pattern_combo.get_model() if pattern == self.application.pattern: return self.application.pattern = pattern self.patterns.insert(0, pattern) self.patterns = aeidon.util.get_unique(self.patterns) del self.patterns[self.max_history:] store.clear() for pattern in self.patterns: store.append((pattern,)) self._write_history("patterns") self.application.update_gui() def _add_replacement_to_history(self): """Add current replacement to the replacement combo box.""" replacement = self._replacement_entry.get_text() store = self._replacement_combo.get_model() if replacement == self.application.replacement: return self.application.replacement = replacement self.replacements.insert(0, replacement) self.replacements = aeidon.util.get_unique(self.replacements) del self.replacements[self.max_history:] store.clear() for replacement in self.replacements: store.append((replacement,)) self._write_history("replacements") self.application.update_gui() def _get_cursor_offset(self, page, row, doc, next): """Return current cursor offset of the search or ``None``.""" if page is not self._match_page: return None if row != self._match_row: return None if doc != self._match_doc: return None return self._match_span[next] def _get_fields(self): """Return a sequence of fields to search in.""" fields = [] if self._main_check.get_active(): fields.append(gaupol.fields.MAIN_TEXT) if self._tran_check.get_active(): fields.append(gaupol.fields.TRAN_TEXT) return tuple(fields) def _get_position(self, next): """ Return current position of the search. Raise :exc:`gaupol.Default` if no pages open. Return row, document, cursor offset. """ page = self.application.get_current_page() gaupol.util.raise_default(page is None) rows = page.view.get_selected_rows() row = rows[0] if rows else None if row is None: row = 0 if next else len(page.project.subtitles) - 1 col = page.view.get_focus()[1] doc = None if page.view.is_text_column(col): doc = page.text_column_to_document(col) docs = list(map(gaupol.util.text_field_to_document, gaupol.conf.search.fields)) if doc is None or not doc in docs: doc = docs[0] if next else docs[-1] pos = self._get_cursor_offset(page, row, doc, next) return row, doc, pos def _get_target(self): """Return :attr:`gaupol.targets` item to search in.""" if self._current_radio.get_active(): return gaupol.targets.CURRENT if self._all_radio.get_active(): return gaupol.targets.ALL raise ValueError("Invalid target radio state") def _init_dialog(self, parent): """Initialize the dialog.""" self.add_button(_("_Help"), Gtk.ResponseType.HELP) self._dialog.set_default_response(Gtk.ResponseType.CLOSE) self._dialog.set_transient_for(parent) self.set_modal(False) def _init_keys(self): """Initialize keyboard shortcuts.""" accel_group = Gtk.AccelGroup() accel_group.connect(Gdk.KEY_f, Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.MASK, self._on_find_key_pressed) self.add_accel_group(accel_group) def _init_pattern_combo(self): """Initialize the pattern combo box.""" store = Gtk.ListStore(str) self._pattern_combo.set_model(store) for pattern in self.patterns: store.append((pattern,)) self._pattern_combo.set_entry_text_column(0) self._pattern_entry = self._pattern_combo.get_child() def _init_replacement_combo(self): """Initialize the replacement combo box.""" store = Gtk.ListStore(str) self._replacement_combo.set_model(store) for replacement in self.replacements: store.append((replacement,)) self._replacement_combo.set_entry_text_column(0) self._replacement_entry = self._replacement_combo.get_child() def _init_sensitivities(self): """Initialize widget sensitivities.""" self._next_button.set_sensitive(False) self._pattern_entry.emit("changed") self._previous_button.set_sensitive(False) self._regex_check.emit("toggled") self._replace_all_button.set_sensitive(False) self._replace_button.set_sensitive(False) self._replacement_entry.emit("changed") self._text_view.set_sensitive(False) def _init_signal_handlers(self): """Initialize signal handlers.""" aeidon.util.connect(self, "_pattern_entry", "changed") aeidon.util.connect(self, "application", "page-changed") callback = lambda *args: args[-1]._update_search_targets() self.application.connect("page-added", callback, self) gaupol.conf.search.connect("notify::fields", callback, self) gaupol.conf.search.connect("notify::target", callback, self) def _init_text_view(self): """Initialize the text view.""" with aeidon.util.silent(AttributeError): # Top and bottom margins available since GTK 3.18. self._text_view.set_top_margin(6) self._text_view.set_bottom_margin(6) gaupol.util.prepare_text_view(self._text_view) gaupol.util.scale_to_size(self._text_view, nchar=55, nlines=6, font="custom") text_buffer = self._text_view.get_buffer() text_buffer.connect("changed", self._on_text_buffer_changed) def _init_values(self): """Initialize default values for widgets.""" self._pattern_entry.set_text(self.application.pattern) self._replacement_entry.set_text(self.application.replacement) self._regex_check.set_active(gaupol.conf.search.regex) self._ignore_case_check.set_active(gaupol.conf.search.ignore_case) fields = gaupol.conf.search.fields target = gaupol.conf.search.target self._main_check.set_active(gaupol.fields.MAIN_TEXT in fields) self._tran_check.set_active(gaupol.fields.TRAN_TEXT in fields) self._all_radio.set_active(target == gaupol.targets.ALL) self._current_radio.set_active(target == gaupol.targets.CURRENT) self._update_search_targets() @aeidon.deco.silent(gaupol.Default) def next(self): """Find the next match of pattern.""" page = self.application.get_current_page() row, doc, pos = self._get_position(next=True) pages = self.application.pages[:] i = pages.index(page) # Loop twice over the current page, # since starting in the middle. for page in (pages[i:] + pages[:i+1]): self._set_pattern(page) try: # Return match in page after position. row, doc, span = page.project.find_next(row, doc, pos) return self._set_success_state(page, row, doc, span, next=True) except StopIteration: target = gaupol.conf.search.target if target == gaupol.targets.CURRENT: # Fail wrapped single-page search. return self._set_failure_state() # Proceed to the next page. row = doc = pos = None # Fail wrapped search of all pages. self._set_failure_state() def _on_all_radio_toggled(self, radio_button): """Save search target.""" gaupol.conf.search.target = self._get_target() def _on_application_page_changed(self, application, page): """Invalidate the current search if underlying data has changed.""" # If data in page was changed from outside the search dialog, # the current search must be invalidated to avoid making edits # (especially via the text view's focus-out handler) based on data # that no longer exists. All search dialog's data changing methods # need to be wrapped to disable this handling of application's # page-changed signals. if self._handle_page_changes: if self._match_page is not None: self._reset_properties() def _on_current_radio_toggled(self, radio_button): """Save search target.""" gaupol.conf.search.target = self._get_target() def _on_find_key_pressed(self, *args): """Move focus to the pattern entry.""" self._pattern_entry.grab_focus() def _on_ignore_case_check_toggled(self, check_button): """Save ignore case setting.""" gaupol.conf.search.ignore_case = check_button.get_active() def _on_main_check_toggled(self, check_button): """Save search target.""" gaupol.conf.search.fields = list(self._get_fields()) self._search_vbox.set_sensitive(bool(self._get_fields())) def _on_next_button_clicked(self, *args): """Find the next match of pattern.""" # Make sure the text view experiences a focus-out-event. self._next_button.grab_focus() self.next() def _on_pattern_entry_changed(self, entry): """Update action sensitivities.""" have_pattern = bool(entry.get_text()) self._next_button.set_sensitive(have_pattern) self._previous_button.set_sensitive(have_pattern) self._replace_all_button.set_sensitive(have_pattern) def _on_previous_button_clicked(self, *args): """Find the previous match of pattern.""" # Make sure the text view experiences a focus-out-event. self._previous_button.grab_focus() self.previous() def _on_regex_check_toggled(self, check_button): """Save regular expression setting.""" use_regex = check_button.get_active() gaupol.conf.search.regex = use_regex self.set_response_sensitive(Gtk.ResponseType.HELP, use_regex) def _on_replace_all_button_clicked(self, *args): """Replace all matches of pattern.""" # Make sure the text view experiences a focus-out-event. self._replace_all_button.grab_focus() gaupol.util.set_cursor_busy(self._dialog) self.replace_all() gaupol.util.set_cursor_normal(self._dialog) def _on_replace_button_clicked(self, *args): """Replace the current match of pattern.""" # Make sure the text view experiences a focus-out-event. self._replace_button.grab_focus() self._replace_button.set_sensitive(False) self.replace() def _on_response(self, dialog, response): """Do not send response if browsing help.""" if response == Gtk.ResponseType.HELP: gaupol.util.show_uri(gaupol.REGEX_HELP_URL) self.stop_emission_by_name("response") def _on_show(self, *args): """Move focus to the pattern entry and select the pattern.""" self._pattern_entry.select_region(0, -1) self._pattern_entry.grab_focus() def _on_text_buffer_changed(self, *args): """Disable replace action.""" self._replace_button.set_sensitive(False) @page_changing def _on_text_view_focus_out_event(self, text_view, event): """Save changes made in `text_view`.""" if self._match_page is None: return if self._match_row is None: return if self._match_doc is None: return if not self._text_view.get_sensitive(): return page = self.application.get_current_page() if page is not self._match_page: return text_buffer = text_view.get_buffer() start, end = text_buffer.get_bounds() text = text_buffer.get_text(start, end, False) page.project.set_text(self._match_row, self._match_doc, text) def _on_tran_check_toggled(self, check_button): """Save search target.""" gaupol.conf.search.fields = list(self._get_fields()) self._search_vbox.set_sensitive(bool(self._get_fields())) @aeidon.deco.silent(gaupol.Default) def previous(self): """Find the previous match of pattern.""" page = self.application.get_current_page() row, doc, pos = self._get_position(next=False) pages = self.application.pages[::-1] i = pages.index(page) # Loop twice over the current page, # since starting in the middle. for page in (pages[i:] + pages[:i+1]): self._set_pattern(page) try: # Return match in page before position. row, doc, span = page.project.find_previous(row, doc, pos) return self._set_success_state(page, row, doc, span, next=False) except StopIteration: target = gaupol.conf.search.target if target == gaupol.targets.CURRENT: # Fail wrapped single-page search. return self._set_failure_state() # Proceed to the previous page. row = doc = pos = None # Fail wrapped search of all pages. self._set_failure_state() def _read_history(self, name): """Read history from file of type `name`.""" directory = os.path.join(aeidon.CONFIG_HOME_DIR, "search") path = os.path.join(directory, "{}.history".format(name)) if not os.path.isfile(path): return history = aeidon.util.readlines(path) setattr(self, name, history) @page_changing @aeidon.deco.silent(gaupol.Default) def replace(self): """Replace the current match of pattern.""" page = self.application.get_current_page() if page is not self._match_page: return self._set_replacement(page) subtitle = page.project.subtitles[self._match_row] length = len(subtitle.get_text(self._match_doc)) try: page.project.replace() except re.error as error: return self._show_regex_error_dialog_replacement(str(error)) shift = (len(subtitle.get_text(self._match_doc)) - length) self._match_span[1] += shift if self._was_next: return self.next() return self.previous() @page_changing @aeidon.deco.silent(gaupol.Default) def replace_all(self): """Replace all matches of pattern.""" count = 0 target = gaupol.conf.search.target for page in self.application.get_target_pages(target): self._set_pattern(page) self._set_replacement(page) try: count += page.project.replace_all() except re.error as error: self._show_regex_error_dialog_replacement(str(error)) break self._reset_properties() self._statuslabel.flash_text(n_( "Found and replaced {:d} occurence", "Found and replaced {:d} occurences", count).format(count)) def _reset_properties(self): """Reset search properties to defaults.""" self._match_page = None self._match_doc = None self._match_row = None self._match_span = None self._text_view.get_buffer().set_text("") self._text_view.set_sensitive(False) def _set_failure_state(self): """Set search properties for failure to find a match.""" self._reset_properties() pattern = self._pattern_entry.get_text() message = _('"{}" not found').format(pattern) self._statuslabel.flash_text(message) def _set_pattern(self, page): """ Set search pattern for `page`. Raise :exc:`gaupol.Default` if pattern empty or bad. """ pattern = self._pattern_entry.get_text() gaupol.util.raise_default(not pattern) ignore_case = gaupol.conf.search.ignore_case if not gaupol.conf.search.regex: self._add_pattern_to_history() return page.project.set_search_string(pattern, ignore_case) flags = re.DOTALL | re.MULTILINE if gaupol.conf.search.ignore_case: flags = flags | re.IGNORECASE try: page.project.set_search_regex(pattern, flags) except re.error as error: self._show_regex_error_dialog_pattern(str(error)) raise gaupol.Default self._add_pattern_to_history() def _set_replacement(self, page): """Set search replacement for `page`.""" replacement = self._replacement_entry.get_text() page.project.set_search_replacement(replacement) self._add_replacement_to_history() def _set_success_state(self, page, row, doc, match_span, next): """Set search properties for found match.""" self._match_page = page self._match_row = row self._match_doc = doc self._match_span = list(match_span) self._was_next = next self.application.set_current_page(page) self._set_text(page, row, doc, match_span) col = page.document_to_text_column(doc) page.view.set_focus(row, col) page.view.scroll_to_row(row) self._replace_button.set_sensitive(True) def _set_text(self, page, row, doc, match_span): """Set subtitle text to text view.""" text_buffer = self._text_view.get_buffer() subtitle = page.project.subtitles[row] text = subtitle.get_text(doc) text_buffer.set_text(text) bound = text_buffer.get_iter_at_offset(match_span[1]) mark = text_buffer.create_mark(None, bound, True) self._text_view.scroll_to_mark(mark=mark, within_margin=0, use_align=False, xalign=0.5, yalign=0.5) self._text_view.set_sensitive(True) self._text_view.grab_focus() def select_text(text_buffer, match_span): ins = text_buffer.get_iter_at_offset(match_span[0]) bound = text_buffer.get_iter_at_offset(match_span[1]) text_buffer.select_range(ins, bound) # Some calls fail to select unless idle_add used (GTK 3.24). gaupol.util.idle_add(select_text, text_buffer, match_span) def _show_regex_error_dialog_pattern(self, message): """Show an error dialog if regex pattern failed to compile.""" title = _("Error in regular expression pattern") dialog = gaupol.ErrorDialog(self._dialog, title, message) dialog.add_button(_("_OK"), Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK) gaupol.util.flash_dialog(dialog) def _show_regex_error_dialog_replacement(self, message): """Show an error dialog if regex replacement is invalid.""" title = _("Error in regular expression replacement") dialog = gaupol.ErrorDialog(self._dialog, title, message) dialog.add_button(_("_OK"), Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK) gaupol.util.flash_dialog(dialog) def _update_search_targets(self): """Update search targets in all pages.""" docs = list(map(gaupol.util.text_field_to_document, gaupol.conf.search.fields)) wrap = (gaupol.conf.search.target != gaupol.targets.ALL) for page in self.application.pages: page.project.set_search_target(None, docs, wrap) def _write_history(self, name): """Write history to file of type `name`.""" directory = os.path.join(aeidon.CONFIG_HOME_DIR, "search") with aeidon.util.silent(OSError, tb=True): path = os.path.join(directory, "{}.history".format(name)) history = getattr(self, name) text = "\n".join(history) + "\n" aeidon.util.write(path, text) gaupol-1.11/gaupol/dialogs/spell_check.py000066400000000000000000000277521422217132500204760ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Dialog for checking and correcting spelling.""" import aeidon import gaupol from aeidon.i18n import _ from gi.repository import Gtk from gi.repository import Pango __all__ = ("SpellCheckDialog",) class SpellCheckDialog(gaupol.BuilderDialog): """ Dialog for checking and correcting spelling. :ivar _doc: :attr:`aeidon.documents` item currectly being checked :ivar _entry_handler: Handler for replacement entry's "changed" signal :ivar _language: Language code for :attr:`_navigator` :ivar _navigator: :class:`aeidon.SpellCheckNavigator` instance used :ivar _new_rows: List of rows in the current page with changed texts :ivar _new_texts: List of changed texts in the current page :ivar _page: :class:`gaupol.Page` instance currectly being checked :ivar _pager: Iterator to iterate over all target pages :ivar _row: Row currently being checked :ivar _rower: Iterator to iterate over all rows """ _widgets = [ "add_button", "edit_button", "entry", "grid", "ignore_all_button", "ignore_button", "join_back_button", "join_forward_button", "replace_all_button", "replace_button", "text_view", "tree_view", ] def __init__(self, parent, application): """Initialize a :class:`SpellCheckDialog` instance.""" gaupol.BuilderDialog.__init__(self, "spell-check-dialog.ui") self.application = application self._doc = None self._entry_handler = None self._language = gaupol.conf.spell_check.language self._language_name = aeidon.locales.code_to_name(self._language) self._navigator = aeidon.SpellCheckNavigator(self._language) self._new_rows = [] self._new_texts = [] self._page = None self._pager = None self._row = None self._rower = None self._init_dialog(parent) self._init_widgets() self._init_sensitivities() self.resize(*gaupol.conf.spell_check.size) self._pager = self._yield_pages() next(self._pager) self._proceed() def _append_changes(self): """Append current changes to the list of changes.""" subtitle = self._page.project.subtitles[self._row] if self._navigator.text == subtitle.get_text(self._doc): return self._new_rows.append(self._row) self._new_texts.append(self._navigator.text) def _init_dialog(self, parent): """Initialize the dialog.""" self.set_default_response(Gtk.ResponseType.CLOSE) self.set_transient_for(parent) self.set_modal(True) def _init_sensitivities(self): """Initialize widget sensitivities.""" self._join_back_button.set_sensitive(False) self._join_forward_button.set_sensitive(False) self._replace_all_button.set_sensitive(False) self._replace_button.set_sensitive(False) def _init_tree_view(self): """Initialize the suggestion tree view.""" selection = self._tree_view.get_selection() selection.set_mode(Gtk.SelectionMode.SINGLE) selection.connect("changed", self._on_tree_view_selection_changed) store = Gtk.ListStore(str) self._tree_view.set_model(store) column = Gtk.TreeViewColumn("", Gtk.CellRendererText(), text=0) self._tree_view.append_column(column) def _init_widgets(self): """Initialize widget properties.""" self._init_tree_view() gaupol.style.use_font(self._entry, "custom") gaupol.style.use_font(self._text_view, "custom") gaupol.style.use_font(self._tree_view, "custom") with aeidon.util.silent(AttributeError): # Top and bottom margins available since GTK 3.18. self._text_view.set_top_margin(6) self._text_view.set_bottom_margin(6) text_buffer = self._text_view.get_buffer() text_buffer.create_tag("misspelled", weight=Pango.Weight.BOLD) scale = gaupol.util.scale_to_size scale(self._text_view, nchar=55, nlines=4, font="custom") scale(self._tree_view, nchar=20, nlines=6, font="custom") self._entry_handler = self._entry.connect("changed", self._on_entry_changed) def _on_add_button_clicked(self, *args): """Add the current word to personal word list.""" self._navigator.add() self._proceed() def _on_edit_button_clicked(self, *args): """Edit the current text in a separate dialog.""" text = self._navigator.text dialog = gaupol.TextEditDialog(self._dialog, text) response = gaupol.util.run_dialog(dialog) text = dialog.get_text() dialog.destroy() if response != Gtk.ResponseType.OK: return self._navigator.reset(text) self._proceed() def _on_entry_changed(self, entry): """Populate suggestions based on text in `entry`.""" word = entry.get_text() suggestions = self._navigator.checker.suggest(word) if word else [] self._populate_tree_view(suggestions, select=False) self._replace_button.set_sensitive(bool(word)) self._replace_all_button.set_sensitive(bool(word)) def _on_ignore_all_button_clicked(self, *args): """Ignore the current word and any subsequent instances.""" self._navigator.ignore_all() self._proceed() def _on_ignore_button_clicked(self, *args): """Ignore the current word.""" self._navigator.ignore() self._proceed() def _on_join_back_button_clicked(self, *args): """Join the current word with the previous.""" self._navigator.join_with_previous() self._proceed() def _on_join_forward_button_clicked(self, *args): """Join the current word with the next.""" self._navigator.join_with_next() self._proceed() def _on_replace_all_button_clicked(self, *args): """Replace the current word and subsequent instances with `replacement`.""" self._navigator.replace_all(self._entry.get_text()) self._proceed() def _on_replace_button_clicked(self, *args): """Replace the current word with `replacement`.""" self._navigator.replace(self._entry.get_text()) self._proceed() def _on_response(self, dialog, response): """Apply changes to the current page.""" self._register_changes() self._save_geometry() self._set_done() def _on_tree_view_selection_changed(self, *args): """Copy the selected suggestion into the entry.""" selection = self._tree_view.get_selection() store, itr = selection.get_selected() if itr is None: return path = store.get_path(itr) row = gaupol.util.tree_path_to_row(path) self._set_entry_text(store[row][0]) def _populate_tree_view(self, suggestions, select=True): """Populate the tree view with `suggestions`.""" store = self._tree_view.get_model() self._tree_view.set_model(None) store.clear() for suggestion in suggestions: store.append((suggestion,)) self._tree_view.set_model(store) if select and len(store) > 0: self._tree_view.set_cursor(0) self._tree_view.scroll_to_cell(0) def _proceed(self): """Move on to the next spelling error.""" try: # Move on to the next spelling error in the current text. return self._proceed_current() except StopIteration: # Commit changes to the current text. self._append_changes() try: # Move on to the next row. next(self._rower) return self._proceed() except StopIteration: # Commit changes to the current page. self._register_changes() try: # Move on to the next page. next(self._pager) # Use idle_add here to break out of recursion to # reduce the likelihood of hitting the recursion limit. return gaupol.util.idle_add(self._proceed) except StopIteration: self._set_done() def _proceed_current(self): """Move on to the next spelling error in the current text.""" next(self._navigator) col = self._page.document_to_text_column(self._doc) self._page.view.set_focus(self._row, col) self._page.view.scroll_to_row(self._row) text_buffer = self._text_view.get_buffer() text_buffer.set_text(self._navigator.text) start = text_buffer.get_iter_at_offset(self._navigator.pos) end = text_buffer.get_iter_at_offset(self._navigator.endpos) text_buffer.apply_tag_by_name("misspelled", start, end) mark = text_buffer.create_mark(None, end, True) self._text_view.scroll_to_mark(mark=mark, within_margin=0, use_align=False, xalign=0.5, yalign=0.5) leading = self._navigator.leading_context(1) trailing = self._navigator.trailing_context(1) self._join_back_button.set_sensitive(leading.isspace()) self._join_forward_button.set_sensitive(trailing.isspace()) self._set_entry_text("") self._populate_tree_view(self._navigator.suggest()) self._tree_view.grab_focus() def _register_changes(self): """Register changes to the current page.""" if not self._new_rows: return self._page.project.replace_texts( self._new_rows, self._doc, self._new_texts) self._page.project.set_action_description( aeidon.registers.DO, _("Spell-checking")) self._new_rows = [] self._new_texts = [] def _save_geometry(self): """Save dialog size.""" if self.is_maximized(): return gaupol.conf.spell_check.size = list(self.get_size()) def _set_done(self): """Set state of widgets for finished spell-check.""" self._text_view.get_buffer().set_text("") self._set_entry_text("") self._populate_tree_view([]) self._grid.set_sensitive(False) self._navigator.checker.write_replacements() def _set_entry_text(self, word): """Set `word` to the entry with its "changed" handler blocked.""" self._entry.handler_block(self._entry_handler) self._entry.set_text(word) self._entry.handler_unblock(self._entry_handler) self._replace_button.set_sensitive(bool(word)) self._replace_all_button.set_sensitive(bool(word)) def _yield_pages(self): """Yield pages to check spelling in.""" field = gaupol.conf.spell_check.field doc = gaupol.util.text_field_to_document(field) target = gaupol.conf.spell_check.target for page in self.application.get_target_pages(target): if not page.project.subtitles: continue self.application.set_current_page(page) self._page = page self._doc = doc self._rower = self._yield_rows(page) next(self._rower) yield page def _yield_rows(self, page): """Yield rows to check spelling in.""" for row, subtitle in enumerate(page.project.subtitles): self._row = row text = subtitle.get_text(self._doc) self._navigator.reset(text) yield row gaupol-1.11/gaupol/dialogs/split.py000066400000000000000000000075131422217132500173460ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2006 Osmo Salomaa # # 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 . """Dialog for splitting a project in two.""" import aeidon import gaupol from aeidon.i18n import _ from gi.repository import Gtk __all__ = ("SplitDialog",) class SplitDialog(gaupol.BuilderDialog): """Dialog for splitting a project in two.""" _widgets = ["subtitle_spin"] def __init__(self, parent, application): """Initialize a :class:`SplitDialog` instance.""" gaupol.BuilderDialog.__init__(self, "split-dialog.ui") self.application = application self._init_dialog(parent) self._init_subtitle_spin() def _init_dialog(self, parent): """Initialize the dialog.""" self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_Split"), Gtk.ResponseType.OK) self.set_default_response(Gtk.ResponseType.OK) self.set_transient_for(parent) self.set_modal(True) def _init_subtitle_spin(self): """Initialize the subtitle spin button.""" page = self.application.get_current_page() rows = page.view.get_selected_rows() subtitle = rows[0] + 1 if rows else 2 self._subtitle_spin.set_value(subtitle) self._subtitle_spin.set_range(2, len(page.project.subtitles)) self._subtitle_spin.emit("value-changed") def _on_subtitle_spin_value_changed(self, spin_button): """Select matching row in the view.""" page = self.application.get_current_page() row = self._subtitle_spin.get_value_as_int() - 1 page.view.set_focus(row, None) def _on_response(self, dialog, response): """Split the current project if OK'd.""" if response == Gtk.ResponseType.OK: self._split_project() def _remove_from_source(self, page, index): """Remove rows starting at `index` from `page`.""" indices = list(range(index, len(page.project.subtitles))) page.project.block("action-done") page.project.remove_subtitles(indices) page.project.set_action_description( aeidon.registers.DO, _("Splitting project")) page.project.unblock("action-done") def _shift_destination(self, src, dst): """Shift subtitles in `dst` page.""" amount = -1 * src.project.subtitles[-1].end_seconds dst.project.shift_positions(None, amount, register=None) def _split_project(self): """Split the current project in two.""" gaupol.util.set_cursor_busy(self.application.window) index = self._subtitle_spin.get_value_as_int() - 1 src = self.application.get_current_page() dst = gaupol.Page(next(self.application.counter)) subtitles = [x.copy() for x in src.project.subtitles[index:]] indices = list(range(len(subtitles))) dst.project.insert_subtitles(indices, subtitles) dst.reload_view_all() self._remove_from_source(src, index) self._shift_destination(src, dst) self.application.add_page(dst) message = _('Split {amount:d} subtitles to project "{name}"').format( amount=len(dst.project.subtitles), name=dst.untitle) self.application.flash_message(message) gaupol.util.set_cursor_normal(self.application.window) gaupol-1.11/gaupol/dialogs/test/000077500000000000000000000000001422217132500166125ustar00rootroot00000000000000gaupol-1.11/gaupol/dialogs/test/__init__.py000066400000000000000000000000001422217132500207110ustar00rootroot00000000000000gaupol-1.11/gaupol/dialogs/test/test_about.py000066400000000000000000000017271422217132500213440ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class TestAboutDialog(gaupol.TestCase): def run_dialog(self): self.dialog.run() self.dialog.destroy() def setup_method(self, method): self.dialog = gaupol.AboutDialog(Gtk.Window()) self.dialog.show() gaupol-1.11/gaupol/dialogs/test/test_append.py000066400000000000000000000020601422217132500214700ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol import os from gi.repository import Gtk from gaupol.dialogs.test.test_file import _TestFileDialog class TestAppendDialog(_TestFileDialog): def run_dialog(self): self.dialog.run() def setup_method(self, method): gaupol.conf.file.directory = os.getcwd() self.dialog = gaupol.AppendDialog(Gtk.Window()) self.dialog.show() gaupol-1.11/gaupol/dialogs/test/test_debug.py000066400000000000000000000020631422217132500213120ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol import sys class TestDebugDialog(gaupol.TestCase): def run_dialog(self): self.dialog.run() self.dialog.destroy() def setup_method(self, method): self.dialog = gaupol.DebugDialog() try: self.dialog.foo() except AttributeError: self.dialog.set_text(*sys.exc_info()) self.dialog.show() gaupol-1.11/gaupol/dialogs/test/test_duration_adjust.py000066400000000000000000000022311422217132500234200ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class TestDurationAdjustDialog(gaupol.TestCase): def run_dialog(self): self.dialog.run() self.dialog.destroy() def setup_method(self, method): self.application = self.new_application() self.dialog = gaupol.DurationAdjustDialog( self.application.window, self.application) self.dialog.show() def test__on_response(self): self.dialog.response(Gtk.ResponseType.OK) gaupol-1.11/gaupol/dialogs/test/test_encoding.py000066400000000000000000000022171422217132500220130ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class TestEncodingDialog(gaupol.TestCase): def run_dialog(self): self.dialog.run() self.dialog.destroy() def setup_method(self, method): self.dialog = gaupol.EncodingDialog(Gtk.Window()) self.dialog.show() class TestMenuEncodingDialog(TestEncodingDialog): def setup_method(self, method): self.dialog = gaupol.MenuEncodingDialog(Gtk.Window()) self.dialog.show() gaupol-1.11/gaupol/dialogs/test/test_file.py000066400000000000000000000024301422217132500211410ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol class _TestFileDialog(gaupol.TestCase): def test_get_encoding(self): encoding = gaupol.conf.encoding.visible[0] self.dialog.set_encoding(encoding) assert self.dialog.get_encoding() == encoding self.dialog.set_encoding("johab") assert self.dialog.get_encoding() == "johab" def test_set_encoding(self): encoding = gaupol.conf.encoding.visible[0] self.dialog.set_encoding(encoding) assert self.dialog.get_encoding() == encoding self.dialog.set_encoding("utf_8") assert self.dialog.get_encoding() == "utf_8" gaupol-1.11/gaupol/dialogs/test/test_framerate_convert.py000066400000000000000000000023771422217132500237420ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class TestFramerateConversionDialog(gaupol.TestCase): def run_dialog(self): self.dialog.run() self.dialog.destroy() def setup_method(self, method): self.application = self.new_application() self.dialog = gaupol.FramerateConvertDialog( self.application.window, self.application) self.dialog.show() def test__on_response(self): self.dialog._input_combo.set_active(0) self.dialog._output_combo.set_active(1) self.dialog.response(Gtk.ResponseType.OK) gaupol-1.11/gaupol/dialogs/test/test_insert.py000066400000000000000000000023401422217132500215260ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class TestInsertDialog(gaupol.TestCase): def run_dialog(self): self.dialog.run() self.dialog.destroy() def setup_method(self, method): self.application = self.new_application() page = self.application.get_current_page() page.view.select_rows((2,)) self.dialog = gaupol.InsertDialog( self.application.window, self.application) self.dialog.show() def test__on_response(self): self.dialog.response(Gtk.ResponseType.OK) gaupol-1.11/gaupol/dialogs/test/test_language.py000066400000000000000000000024711422217132500220120ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class TestLanguageDialog(gaupol.TestCase): def run_dialog__hide_target(self): self.dialog.destroy() self.dialog = gaupol.LanguageDialog( Gtk.Window(), show_target=False) self.dialog.run() self.dialog.destroy() def run_dialog__show_target(self): self.dialog.destroy() self.dialog = gaupol.LanguageDialog( Gtk.Window(), show_target=True) self.dialog.run() self.dialog.destroy() def setup_method(self, method): self.dialog = gaupol.LanguageDialog(Gtk.Window()) self.dialog.show() gaupol-1.11/gaupol/dialogs/test/test_message.py000066400000000000000000000041351422217132500216520ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class _TestMessageDialog(gaupol.TestCase): def run_dialog(self): self.dialog.run() self.dialog.destroy() class TestErrorDialog(_TestMessageDialog): def setup_method(self, method): self.dialog = gaupol.ErrorDialog(Gtk.Window(), "test", "test") self.dialog.add_button("_OK", Gtk.ResponseType.OK) self.dialog.set_default_response(Gtk.ResponseType.OK) self.dialog.show() class TestInfoDialog(_TestMessageDialog): def setup_method(self, method): self.dialog = gaupol.InfoDialog(Gtk.Window(), "test", "test") self.dialog.add_button("_OK", Gtk.ResponseType.OK) self.dialog.set_default_response(Gtk.ResponseType.OK) self.dialog.show() class TestQuestionDialog(_TestMessageDialog): def setup_method(self, method): self.dialog = gaupol.QuestionDialog(Gtk.Window(), "test", "test") self.dialog.add_button("_No", Gtk.ResponseType.NO) self.dialog.add_button("_Yes", Gtk.ResponseType.YES) self.dialog.set_default_response(Gtk.ResponseType.YES) self.dialog.show() class TestWarningDialog(_TestMessageDialog): def setup_method(self, method): self.dialog = gaupol.WarningDialog(Gtk.Window(), "test", "test") self.dialog.add_button("_OK", Gtk.ResponseType.OK) self.dialog.set_default_response(Gtk.ResponseType.OK) self.dialog.show() gaupol-1.11/gaupol/dialogs/test/test_multi_close.py000066400000000000000000000025261422217132500225470ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class TestMultiCloseDialog(gaupol.TestCase): def run_dialog(self): self.dialog.run() self.dialog.destroy() def setup_method(self, method): self.application = self.new_application() for page in self.application.pages: page.project.remove_subtitles((0,)) self.dialog = gaupol.MultiCloseDialog(self.application.window, self.application, self.application.pages) self.dialog.show() def test__on_response(self): self.dialog.response(Gtk.ResponseType.YES) gaupol-1.11/gaupol/dialogs/test/test_multi_save.py000066400000000000000000000033241422217132500223750ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon import gaupol from gi.repository import Gtk from gaupol.dialogs.test.test_file import _TestFileDialog class TestMultiSaveDialog(_TestFileDialog): def run_dialog(self): self.dialog.run() self.dialog.destroy() @aeidon.deco.silent(gaupol.Default) def run__show_overwrite_question_dialog(self): files = [x.project.main_file for x in self.application.pages] self.dialog._show_overwrite_question_dialog(files, "test") def setup_method(self, method): self.application = self.new_application() self.application.add_page(self.new_page()) self.application.add_page(self.new_page()) modes = [x.project.main_file.mode for x in self.application.pages] self.dialog = gaupol.MultiSaveDialog(parent=Gtk.Window(), application=self.application, modes=modes) self.dialog.show() def test__on_response(self): self.dialog.response(Gtk.ResponseType.CANCEL) gaupol-1.11/gaupol/dialogs/test/test_open.py000066400000000000000000000030731422217132500211670ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon import gaupol import os from gi.repository import Gtk from gaupol.dialogs.test.test_file import _TestFileDialog class TestOpenDialog(_TestFileDialog): def run_dialog__main(self): gaupol.conf.file.directory = os.getcwd() doc = aeidon.documents.MAIN self.dialog = gaupol.OpenDialog(Gtk.Window(), "test", doc) self.dialog.run() def run_dialog__translation(self): gaupol.conf.file.directory = os.getcwd() doc = aeidon.documents.TRAN self.dialog = gaupol.OpenDialog(Gtk.Window(), "test", doc) self.dialog.run() def setup_method(self, method): gaupol.conf.file.directory = os.getcwd() doc = aeidon.documents.MAIN self.dialog = gaupol.OpenDialog(Gtk.Window(), "test", doc) self.dialog.show() def test__on_response(self): self.dialog.response(Gtk.ResponseType.CANCEL) gaupol-1.11/gaupol/dialogs/test/test_position_shift.py000066400000000000000000000032321422217132500232640ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class _TestPositionShiftDialog(gaupol.TestCase): def run_dialog(self): self.dialog.run() self.dialog.destroy() def setup_method(self, method): raise NotImplementedError def test__on_response(self): self.dialog._current_radio.set_active(True) self.dialog._amount_spin.spin(Gtk.SpinType.STEP_FORWARD, 1) self.dialog.response(Gtk.ResponseType.OK) class TestFrameShiftDialog(_TestPositionShiftDialog): def setup_method(self, method): self.application = self.new_application() self.dialog = gaupol.FrameShiftDialog( self.application.window, self.application) self.dialog.show() class TestTimeShiftDialog(_TestPositionShiftDialog): def setup_method(self, method): self.application = self.new_application() self.dialog = gaupol.TimeShiftDialog( self.application.window, self.application) self.dialog.show() gaupol-1.11/gaupol/dialogs/test/test_position_transform.py000066400000000000000000000027671422217132500241760ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class _TestPositionTransformDialog(gaupol.TestCase): def run_dialog(self): self.dialog.run() self.dialog.destroy() def test__on_response(self): self.dialog.response(Gtk.ResponseType.OK) class TestFrameTransformDialog(_TestPositionTransformDialog): def setup_method(self, method): self.application = self.new_application() self.dialog = gaupol.FrameTransformDialog( self.application.window, self.application) self.dialog.show() class TestTimeTransformDialog(_TestPositionTransformDialog): def setup_method(self, method): self.application = self.new_application() self.dialog = gaupol.TimeTransformDialog( self.application.window, self.application) self.dialog.show() gaupol-1.11/gaupol/dialogs/test/test_preferences.py000066400000000000000000000020401422217132500225200ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol class TestPreferencesDialog(gaupol.TestCase): def run_dialog(self): self.dialog.run() self.dialog.destroy() def setup_method(self, method): self.application = self.new_application() self.dialog = gaupol.PreferencesDialog( self.application.window, self.application) self.dialog.show() gaupol-1.11/gaupol/dialogs/test/test_preview_error.py000066400000000000000000000020701422217132500231140ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon import gaupol from gi.repository import Gtk class TestPreviewErrorDialog(gaupol.TestCase): def run_dialog(self): self.dialog.run() self.dialog.destroy() def setup_method(self, method): output = self.get_sample_text(aeidon.formats.SUBRIP) self.dialog = gaupol.PreviewErrorDialog(Gtk.Window(), output) self.dialog.show() gaupol-1.11/gaupol/dialogs/test/test_save.py000066400000000000000000000050501422217132500211610ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon import gaupol import os from gi.repository import Gtk from gaupol.dialogs.test.test_file import _TestFileDialog class TestSaveDialog(_TestFileDialog): def run_dialog(self): self.dialog.run() self.dialog.destroy() def setup_method(self, method): gaupol.conf.file.directory = os.getcwd() self.dialog = gaupol.SaveDialog(parent=Gtk.Window(), title="test", mode=aeidon.modes.TIME) self.dialog.show() def test_get_format(self): self.dialog.set_format(aeidon.formats.SUBRIP) value = self.dialog.get_format() assert value == aeidon.formats.SUBRIP def test_get_framerate(self): self.dialog.set_framerate(aeidon.framerates.FPS_23_976) value = self.dialog.get_framerate() assert value == aeidon.framerates.FPS_23_976 def test_get_newline(self): self.dialog.set_newline(aeidon.newlines.UNIX) value = self.dialog.get_newline() assert value == aeidon.newlines.UNIX def test__on_response(self): self.dialog.response(Gtk.ResponseType.CANCEL) def test_set_format(self): self.dialog.set_format(aeidon.formats.MICRODVD) value = self.dialog.get_format() assert value == aeidon.formats.MICRODVD def test_set_framerate(self): self.dialog.set_framerate(aeidon.framerates.FPS_25_000) value = self.dialog.get_framerate() assert value == aeidon.framerates.FPS_25_000 def test_set_name__name__basename(self): self.dialog.set_name("test") def test_set_name__name__path(self): self.dialog.set_name(self.new_subrip_file()) def test_set_newline(self): self.dialog.set_newline(aeidon.newlines.WINDOWS) value = self.dialog.get_newline() assert value == aeidon.newlines.WINDOWS gaupol-1.11/gaupol/dialogs/test/test_search.py000066400000000000000000000054751422217132500215030ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2006 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class TestSearchDialog(gaupol.TestCase): def run_dialog(self): self.dialog.run() self.dialog.destroy() def run__show_regex_error_dialog_pattern(self): self.dialog._show_regex_error_dialog_pattern("test") def run__show_regex_error_dialog_replacement(self): self.dialog._show_regex_error_dialog_replacement("test") def setup_method(self, method): self.application = self.new_application() self.dialog = gaupol.SearchDialog( self.application.window, self.application) self.dialog.show() def test_next(self): self.dialog._regex_check.set_active(True) for char in "aeiouy": self.dialog._pattern_entry.set_text(char) self.dialog.next() self.dialog.next() def test__on_application_page_changed(self): # Ensure that editing obsolete data is not possible. # https://bugzilla.gnome.org/show_bug.cgi?id=572676 self.dialog._pattern_entry.set_text("a") self.dialog.next() page = self.application.get_current_page() page.project.remove_subtitles((self.dialog._match_row,)) assert not self.dialog._text_view.get_sensitive() assert not self.dialog._replace_button.get_sensitive() def test__on_response(self): self.dialog.response(Gtk.ResponseType.HELP) def test_previous(self): self.dialog._regex_check.set_active(True) for char in "aeiouy": self.dialog._pattern_entry.set_text(char) self.dialog.previous() self.dialog.previous() def test_replace(self): self.dialog._regex_check.set_active(True) for char in "aeiouy": self.dialog._pattern_entry.set_text(char) self.dialog._replacement_entry.set_text("x") self.dialog.next() self.dialog.replace() self.dialog.replace() def test_replace_all(self): self.dialog._regex_check.set_active(True) self.dialog._pattern_entry.set_text("^") self.dialog._replacement_entry.set_text("-") self.dialog.replace_all() gaupol-1.11/gaupol/dialogs/test/test_spell_check.py000066400000000000000000000045221422217132500225020ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon import gaupol from gi.repository import Gtk class TestSpellCheckDialog(gaupol.TestCase): def run_dialog(self): self.dialog.run() self.dialog.destroy() def setup_method(self, method): # Don't interact with the config files at all. aeidon.SpellChecker.add_to_personal = aeidon.SpellChecker.add_to_session aeidon.SpellChecker.read_replacements = lambda *args: None aeidon.SpellChecker.write_replacements = lambda *args: None language = self.get_spell_check_language("en") gaupol.conf.spell_check.language = language self.application = self.new_application() for page in self.application.pages: for subtitle in page.project.subtitles: subtitle.main_text = subtitle.main_text.replace("a", "x") subtitle.tran_text = subtitle.tran_text.replace("a", "x") page.reload_view_all() self.dialog = gaupol.SpellCheckDialog(self.application.window, self.application) self.dialog.show() def test__on_add_button_clicked(self): self.dialog._add_button.emit("clicked") def test__on_ignore_all_button_clicked(self): self.dialog._ignore_all_button.emit("clicked") def test__on_ignore_button_clicked(self): self.dialog._ignore_button.emit("clicked") def test__on_replace_all_button_clicked(self): self.dialog._replace_all_button.emit("clicked") def test__on_replace_button_clicked(self): self.dialog._replace_button.emit("clicked") def test__on_response(self): self.dialog._replace_button.emit("clicked") self.dialog.response(Gtk.ResponseType.CLOSE) gaupol-1.11/gaupol/dialogs/test/test_split.py000066400000000000000000000024701422217132500213610ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2006 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class TestSplitDialog(gaupol.TestCase): def run_dialog(self): self.dialog.run() self.dialog.destroy() def setup_method(self, method): self.application = self.new_application() self.dialog = gaupol.SplitDialog( self.application.window, self.application) self.dialog.show() def test__on_response(self): npages = len(self.application.pages) self.dialog.show() self.dialog._subtitle_spin.set_value(5) self.dialog.response(Gtk.ResponseType.OK) assert len(self.application.pages) == npages + 1 gaupol-1.11/gaupol/dialogs/test/test_text_edit.py000066400000000000000000000020361422217132500222150ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class TestTextEditDialog(gaupol.TestCase): def run_dialog(self): self.dialog.run() self.dialog.destroy() def setup_method(self, method): text = "etaoin shrdlu etaoin shrdlu etaoin shrdlu" self.dialog = gaupol.TextEditDialog(Gtk.Window(), text) self.dialog.show() gaupol-1.11/gaupol/dialogs/test/test_video.py000066400000000000000000000021361422217132500213330ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class TestVideoDialog(gaupol.TestCase): def run_dialog(self): self.dialog.run() self.dialog.destroy() def setup_method(self, method): self.dialog = gaupol.VideoDialog(parent=Gtk.Window(), title="Select Video", button_label="Select") self.dialog.show() gaupol-1.11/gaupol/dialogs/text_edit.py000066400000000000000000000057071422217132500202070ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Dialog for editing text of a single subtitle.""" import aeidon import gaupol from aeidon.i18n import _ from gi.repository import GObject from gi.repository import Gtk class TextEditDialog(Gtk.Dialog): """Dialog for editing text of a single subtitle.""" def __init__(self, parent, text=""): """Initialize a :class:`TextEditDialog` instance.""" GObject.GObject.__init__(self, use_header_bar=True) self._text_view = Gtk.TextView() self._init_dialog(parent) self._init_text_view() self.set_text(text) def get_text(self): """Return text in the text view.""" text_buffer = self._text_view.get_buffer() start, end = text_buffer.get_bounds() return text_buffer.get_text(start, end, False) def _init_dialog(self, parent): """Initialize the dialog.""" self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(_("_OK"), Gtk.ResponseType.OK) self.set_default_response(Gtk.ResponseType.OK) self.set_transient_for(parent) self.set_modal(True) self.set_title(_("Edit Text")) def _init_text_view(self): """Initialize the text view.""" gaupol.util.prepare_text_view(self._text_view) self._text_view.set_wrap_mode(Gtk.WrapMode.NONE) self._text_view.set_accepts_tab(False) self._text_view.set_left_margin(6) self._text_view.set_right_margin(6) with aeidon.util.silent(AttributeError): # Top and bottom margins available since GTK 3.18. self._text_view.set_top_margin(6) self._text_view.set_bottom_margin(6) scroller = Gtk.ScrolledWindow() scroller.set_policy(*((Gtk.PolicyType.AUTOMATIC,)*2)) scroller.set_shadow_type(Gtk.ShadowType.NONE) scroller.add(self._text_view) box = self.get_content_area() gaupol.util.pack_start_expand(box, scroller) gaupol.util.scale_to_size(self._text_view, nchar=55, nlines=7, font="custom") box.show_all() def set_text(self, text): """Set `text` to the text view.""" text_buffer = self._text_view.get_buffer() text_buffer.set_text(text) gaupol-1.11/gaupol/dialogs/video.py000066400000000000000000000041431422217132500173150ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Dialog for selecting a video file.""" import sys from aeidon.i18n import _ from gi.repository import GObject from gi.repository import Gtk __all__ = ("VideoDialog",) class VideoDialog(Gtk.FileChooserDialog): """Dialog for selecting a video file.""" def __init__(self, parent, title, button_label): """Initialize a :class:`VideoDialog` instance.""" GObject.GObject.__init__(self) self._init_dialog(parent, title, button_label) self._init_filters() def _init_dialog(self, parent, title, button_label): """Initialize the dialog.""" self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL) self.add_button(button_label, Gtk.ResponseType.OK) self.set_default_response(Gtk.ResponseType.OK) self.set_transient_for(parent) self.set_title(title) self.set_action(Gtk.FileChooserAction.OPEN) def _init_filters(self): """Intialize the file filters.""" all_filter = Gtk.FileFilter() all_filter.add_pattern("*") all_filter.set_name(_("All files")) self.add_filter(all_filter) video_filter = Gtk.FileFilter() video_filter.add_mime_type("video/*") video_filter.set_name(_("Video files")) self.add_filter(video_filter) # Mimetype detection seems unreliable on Windows. self.set_filter(all_filter if sys.platform == "win32" else video_filter) gaupol-1.11/gaupol/entries.py000066400000000000000000000132711422217132500162400ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Entry for time data in format ``[-]HH:MM:SS.SSS``.""" import aeidon import functools import gaupol import re from gi.repository import Gdk from gi.repository import GObject from gi.repository import Gtk __all__ = ("TimeEntry",) def _blocked(function): """Decorator for methods to be run blocked to avoid recursion.""" @functools.wraps(function) def wrapper(entry, *args, **kwargs): entry.handler_block(entry._delete_handler) entry.handler_block(entry._insert_handler) value = function(entry, *args, **kwargs) entry.handler_unblock(entry._insert_handler) entry.handler_unblock(entry._delete_handler) return value return wrapper class TimeEntry(Gtk.Entry): """ Entry for time data in format ``[-]HH:MM:SS.SSS``. :ivar _delete_handler: Handler for "delete-text" signal :ivar _insert_handler: Handler for "insert-text" signal This widget uses :func:`GLib.idle_add` a lot, which means that clients may need to call :func:`Gtk.main_iteration` to ensure proper updating. """ _re_digit = re.compile(r"\d") _re_time = re.compile(r"^-?\d\d:[0-5]\d:[0-5]\d\.\d\d\d$") def __init__(self): """Initialize a :class:`TimeEntry` instance.""" GObject.GObject.__init__(self) self._delete_handler = None self._insert_handler = None self.set_width_chars(13) self.set_max_length(13) self._init_signal_handlers() def _init_signal_handlers(self): """Initialize signal handlers.""" aeidon.util.connect(self, self, "cut-clipboard") aeidon.util.connect(self, self, "key-press-event") aeidon.util.connect(self, self, "toggle-overwrite") self._delete_handler = aeidon.util.connect(self, self, "delete-text") self._insert_handler = aeidon.util.connect(self, self, "insert-text") @_blocked def _insert_text(self, value): """Insert `value` as text after validation.""" pos = self.get_position() text = self.get_text() if pos == 0 and value.startswith("-"): text = text if text.startswith("-") else "-{}".format(text) length = len(value) text = text[:pos] + value + text[pos+length:] text = text.replace(",", ".") if not self._re_time.match(text): return self.set_text(text) self.set_position(pos) if length != 1: return self.set_position(pos + 1) if len(text) > pos + 1 and text[pos+1] in (":", "."): self.set_position(pos + 2) def _on_cut_clipboard(self, entry): """Change "cut-clipboard" signal to "copy-clipboard".""" self.stop_emission_by_name("cut-clipboard") self.emit("copy-clipboard") def _on_delete_text(self, entry, start_pos, end_pos): """Do not allow deleting text.""" self.stop_emission_by_name("delete-text") self.set_position(start_pos) def _on_key_press_event(self, entry, event): """Change numbers to zero if Backspace or Delete pressed.""" keys = (Gdk.KEY_BackSpace, Gdk.KEY_Delete) if not event.keyval in keys: return self.stop_emission_by_name("key-press-event") if self.get_selection_bounds(): gaupol.util.idle_add(self._zero_selection) elif event.keyval == Gdk.KEY_BackSpace: gaupol.util.idle_add(self._zero_previous) elif event.keyval == Gdk.KEY_Delete: gaupol.util.idle_add(self._zero_next) def _on_insert_text(self, entry, text, length, pos): """Insert `text` after validation.""" self.stop_emission_by_name("insert-text") gaupol.util.idle_add(self._insert_text, text) def _on_toggle_overwrite(self, entry): """Do not allow toggling overwrite.""" self.stop_emission_by_name("toggle-overwrite") @_blocked def _zero_next(self): """Change the next digit to zero.""" pos = self.get_position() text = self.get_text() if pos >= len(text): return if pos == 0 and text.startswith("-"): self.set_text(text[1:]) return self.set_position(0) if not text[pos].isdigit(): return self.set_text(text[:pos] + "0" + text[pos+1:]) self.set_position(pos) @_blocked def _zero_previous(self): """Change the previous digit to zero.""" pos = self.get_position() text = self.get_text() if pos <= 0: return if pos == 1 and text.startswith("-"): self.set_text(text[1:]) return self.set_position(0) if not text[pos-1].isdigit(): return self.set_position(pos-1) self.set_text(text[:pos-1] + "0" + text[pos:]) self.set_position(pos-1) @_blocked def _zero_selection(self): """Change digits in selection to zero.""" if not self.get_selection_bounds(): return a, z = self.get_selection_bounds() text = self.get_text() zero = self._re_digit.sub("0", text[a:z]) self.set_text(text[:a] + zero + text[z:]) self.set_position(a) gaupol-1.11/gaupol/enums.py000066400000000000000000000070441422217132500157170ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2016 Osmo Salomaa # # 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 . """Miscellanous enumerations.""" import aeidon from aeidon.i18n import _ from gi.repository import Gtk __all__ = [ "fields", "length_units", "orientation", "targets", "toolbar_styles", ] class FieldNumber(aeidon.EnumerationItem): is_position = False is_text = False label = _("No.") tooltip = _("Subtitle number") class FieldStart(aeidon.EnumerationItem): is_position = True is_text = False label = _("Start") tooltip = _("Start position") class FieldEnd(aeidon.EnumerationItem): is_position = True is_text = False label = _("End") tooltip = _("End position") class FieldDuration(aeidon.EnumerationItem): is_position = True is_text = False # TRANSLATORS: 'Dur.' is short for duration. It is used in the header # of a column that contains numbers five digits wide. label = _("Dur.") tooltip = _("Duration") class FieldMainText(aeidon.EnumerationItem): is_position = False is_text = True label = _("Text") tooltip = _("Text") class FieldTranslationText(aeidon.EnumerationItem): is_position = False is_text = True label = _("Translation") tooltip = _("Translation") fields = aeidon.Enumeration() fields.NUMBER = FieldNumber() fields.START = FieldStart() fields.END = FieldEnd() fields.DURATION = FieldDuration() fields.MAIN_TEXT = FieldMainText() fields.TRAN_TEXT = FieldTranslationText() class LengthUnitChar(aeidon.EnumerationItem): label = _("characters") class LengthUnitEm(aeidon.EnumerationItem): label = _("ems") length_units = aeidon.Enumeration() length_units.CHAR = LengthUnitChar() length_units.EM = LengthUnitEm() class OrientationHorizontal(aeidon.EnumerationItem): value = Gtk.Orientation.HORIZONTAL class OrientationVertical(aeidon.EnumerationItem): value = Gtk.Orientation.VERTICAL orientation = aeidon.Enumeration() orientation.HORIZONTAL = OrientationHorizontal() orientation.VERTICAL = OrientationVertical() class TargetSelected(aeidon.EnumerationItem): pass class TargetSelectedToEnd(aeidon.EnumerationItem): pass class TargetCurrent(aeidon.EnumerationItem): pass class TargetAll(aeidon.EnumerationItem): pass targets = aeidon.Enumeration() targets.SELECTED = TargetSelected() targets.SELECTED_TO_END = TargetSelectedToEnd() targets.CURRENT = TargetCurrent() targets.ALL = TargetAll() class ToolbarStyleBoth(aeidon.EnumerationItem): value = Gtk.ToolbarStyle.BOTH class ToolbarStyleBothHoriz(aeidon.EnumerationItem): value = Gtk.ToolbarStyle.BOTH_HORIZ class ToolbarStyleIcons(aeidon.EnumerationItem): value = Gtk.ToolbarStyle.ICONS class ToolbarStyleText(aeidon.EnumerationItem): value = Gtk.ToolbarStyle.TEXT toolbar_styles = aeidon.Enumeration() toolbar_styles.ICONS = ToolbarStyleIcons() toolbar_styles.TEXT = ToolbarStyleText() toolbar_styles.BOTH = ToolbarStyleBoth() toolbar_styles.BOTH_HORIZ = ToolbarStyleBothHoriz() gaupol-1.11/gaupol/errors.py000066400000000000000000000015341422217132500161020ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 . """All :mod:`gaupol` error classes.""" import aeidon __all__ = ("Default",) class Default(aeidon.Error): """Cancelled or something of the sort.""" pass gaupol-1.11/gaupol/extension.py000066400000000000000000000044511422217132500166030ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2008 Osmo Salomaa # # 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 . """Separate object that can be activated and deactivated during runtime.""" __all__ = ("Extension",) class Extension: """Separate object that can be activated and deactivated during runtime.""" def setup(self, application): """ Setup extension for use with `application`. This method is called every time the extension is associated with `application`, i.e. both when it is manually activated and also every time right after `application` start. """ pass def show_help(self): """ Show documentation on using extension. Subclasses can override this to, for example, launch a web browser with :func:`gaupol.util.show_uri` to view HTML documentation. """ raise NotImplementedError def show_preferences_dialog(self, parent): """ Show a preferences dialog for configuring extension. `parent` is the parent window that the dialog can be centered on. """ raise NotImplementedError def teardown(self, application): """ End use of extension with `application`. This method is called every time the extension is unassociated with `application`, i.e. both when it is manually deactivated and also every time right before `application` exit. """ pass def update(self, application, page): """ Update state of extension for `application` and active `page`. The main purpose of this method is to update sensitivities of UI manager actions associated with this extension. """ pass gaupol-1.11/gaupol/extensionman.py000066400000000000000000000175171422217132500173060ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2008 Osmo Salomaa # # 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 . """Finding activating, storing and deactivating extensions.""" import aeidon import gaupol import importlib.machinery import inspect import os import re __all__ = ("ExtensionManager", "ExtensionMetadata",) class ExtensionManager: """ Finding activating, storing and deactivating extensions. :ivar _active: Dictionary mapping module names to extensions :ivar _dependants: Dictionary mapping module names to a list of others :ivar _metadata: Dictionary mapping module names to metadata items :ivar _slaves: List of modules activated to satisfy a dependency """ _global_dir = os.path.join(aeidon.DATA_DIR, "extensions") _local_dir = os.path.join(aeidon.DATA_HOME_DIR, "extensions") _re_comment = re.compile(r"#.*$") def __init__(self, application): """Initialize an :class:`ExtensionManager` instance.""" self._active = {} self.application = application self._dependants = {} self._metadata = {} self._slaves = [] def find_extensions(self): """Find all extensions and parse their metadata files.""" self._find_extensions_in_directory(self._global_dir) self._find_extensions_in_directory(self._local_dir) def _find_extensions_in_directory(self, directory): """Find all extensions in `directory` and parse their metadata.""" def is_metadata_file(path): return (path.endswith(".extension") or path.endswith(".extension.in")) for root, dirs, files in os.walk(directory): files = list(filter(is_metadata_file, files)) for name in [x for x in files if x.endswith(".in")]: # If both untranslated and translated metadata files are found, # load extension only from the translated one. if name[:-3] in files: files.remove(name) for name in files: path = os.path.abspath(os.path.join(root, name)) self._parse_metadata(path) def get_metadata(self, module): """Return an :class:`ExtensionMetadata` instance for `module`.""" return self._metadata[module] def get_modules(self): """Return a list of all extension module names.""" return list(self._metadata.keys()) def has_help(self, module): """Return ``True`` if extension can display documentation.""" extension = self._active[module] return (extension.__class__.show_help is not gaupol.Extension.show_help) def has_preferences_dialog(self, module): """Return True if extension can display a preferences dialog.""" extension = self._active[module] return (extension.__class__.show_preferences_dialog is not gaupol.Extension.show_preferences_dialog) def is_active(self, module): """Return ``True`` if extension is active, ``False`` if not.""" return (module in self._active) def _parse_metadata(self, path): """Parse extension metadata file at `path`.""" lines = aeidon.util.readlines(path, "utf_8", fallback=None) lines = [self._re_comment.sub("", x) for x in lines] lines = [x.strip() for x in lines] metadata = ExtensionMetadata() metadata.path = path for line in (x for x in lines if x): if line.startswith("["): continue name, value = line.split("=", 1) name = name[1:] if name.startswith("_") else name metadata.set_field(name, value) module = metadata.get_field("Module") self._metadata[module] = metadata @aeidon.deco.silent(ImportError, tb=True) def setup_extension(self, module, slave=False): """Import and setup extension by module name.""" if module in self._active: return metadata = self._metadata[module] for dependency in metadata.get_field_list("Requires", ()): if not dependency in self._active: self.setup_extension(dependency, slave=True) self._slaves.append(dependency) self._dependants[dependency].append(module) directory = os.path.dirname(metadata.path) name = "gaupol.extension.{:s}".format(module) path = os.path.join(directory, "{}.py".format(module)) loader = importlib.machinery.SourceFileLoader(name, path) module_object = loader.load_module(name) for attribute in dir(module_object): if attribute.startswith("_"): continue value = getattr(module_object, attribute) if not inspect.isclass(value): continue if issubclass(value, gaupol.Extension): extension = value() extension.setup(self.application) self._active[module] = extension self._dependants[module] = [] self.application.update_gui() def setup_extensions(self): """Import and setup all extensions configured as active.""" active = gaupol.conf.extensions.active[:] gaupol.conf.extensions.active.clear() for module in sorted(set(active) & self._metadata.keys()): self.setup_extension(module) gaupol.conf.extensions.active.append(module) def show_help(self, module): """Show documentation on using extension.""" extension = self._active[module] extension.show_help() def show_preferences_dialog(self, module, parent): """Show a preferences dialog for configuring extension.""" extension = self._active[module] extension.show_preferences_dialog(parent) def teardown_extension(self, module): """Teardown extension by module name.""" if not module in self._active: return for user in self._dependants[module]: # Teardown all extensions depending on this one. self.teardown_extension(user) if not module in self._active: return extension = self._active[module] extension.teardown(self.application) del self._active[module] del self._dependants[module] for dependency in list(self._dependants.keys()): # Teardown no longer used dependencies. if module in self._dependants[dependency]: self._dependants[dependency].remove(module) if self._dependants[dependency]: continue if not dependency in self._slaves: continue self.teardown_extension(dependency) if module in self._slaves: self._slaves.remove(module) gaupol.conf.write_to_file() def teardown_extensions(self): """Teardown all active extensions.""" for module in list(self._active.keys()): self.teardown_extension(module) def update_extensions(self, page): """Call ``update`` on all active extensions.""" for name, extension in self._active.items(): extension.update(self.application, page) class ExtensionMetadata(aeidon.MetadataItem): """Extension metadata specified in a separate desktop-style file.""" def __init__(self, fields=None): """Initialize an :class:`ExtensionMetadata` instance.""" aeidon.MetadataItem.__init__(self, fields) self.path = None gaupol-1.11/gaupol/floatlabel.py000066400000000000000000000062161422217132500166750ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2013 Osmo Salomaa # # 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 . """Floating label that can be overlaid on another widget.""" import gaupol from gi.repository import GObject from gi.repository import Gtk __all__ = ("FloatingLabel",) class FloatingLabel(Gtk.Box): """Floating label that can be overlaid on another widget.""" # FloatingLabel is inspired by, but not an implementation of, # the floating statusbar found in nautilus. # https://gitlab.gnome.org/GNOME/nautilus/blob/master/src/nautilus-floating-bar.c def __init__(self): """Initialize a :class:`FloatingLabel` instance.""" GObject.GObject.__init__(self, orientation=Gtk.Orientation.HORIZONTAL) self._event_box = Gtk.EventBox() self._handlers = [] self._hide_id = None self._label = Gtk.Label() self.set_halign(Gtk.Align.START) self.set_valign(Gtk.Align.END) self._init_widgets() def _clear_hide_events(self): """Disconnect registered hide events.""" while self._handlers: widget, handler_id = self._handlers.pop() if widget.handler_is_connected(handler_id): widget.handler_disconnect(handler_id) def flash_text(self, text, duration=6): """Show label with `text` for `duration` seconds.""" if not text: return self._hide() self.set_text(text) self._hide_id = gaupol.util.delay_add(duration * 1000, self._hide) def get_text(self): """Return text shown in the label.""" return self._label.get_text() def _hide(self, *args): """Hide and disconnect handlers.""" self.hide() self._hide_id = None self._clear_hide_events() def _init_widgets(self): """Initialize widgets contained in the box.""" style = self._label.get_style_context() style.add_class("gaupol-floating-label") self._event_box.add(self._label) gaupol.util.pack_start(self, self._event_box) self._event_box.connect("enter-notify-event", self._hide) def register_hide_event(self, widget, signal): """Register `widget`'s `signal` as cause to hide the label.""" handler_id = widget.connect(signal, self._hide) self._handlers.append((widget, handler_id)) def set_text(self, text): """Show `text` in the label.""" if not text: return self._hide() if self._hide_id is not None: GObject.source_remove(self._hide_id) self._label.set_text(text) self.show() gaupol-1.11/gaupol/page.py000066400000000000000000000343401422217132500155030ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """User interface container and controller for :class:`aeidon.Project`.""" import aeidon import gaupol import os import sys from aeidon.i18n import _ from gi.repository import Gtk from gi.repository import Pango __all__ = ("Page",) class Page(aeidon.Observable): """ User interface container and controller for :class:`aeidon.Project`. :ivar edit_mode: :attr:`aeidon.modes` item corresponding to editing mode :ivar project: The associated :class:`aeidon.Project` instance :ivar tab_label: :class:`Gtk.Label` contained in :attr:`tab_widget` :ivar tab_widget: Widget that can be placed in a notebook tab :ivar untitle: Title used if :attr:`project.main_file` is unsaved :ivar view: The associated :class:`gaupol.View` instance Signals and their arguments for callback functions: * ``close-request``: page * ``view-created``: page, view This class represents one page in a notebook of user interfaces for projects. The view is updated automatically when project data changes. """ signals = ("close-request", "view-created") def __init__(self, count=0): """Initialize a :class:`Page` instance.""" aeidon.Observable.__init__(self) self.edit_mode = gaupol.conf.editor.mode self.project = None self.tab_label = None self.tab_widget = None self.untitle = _("Untitled {:d}").format(count) self.view = gaupol.View(self.edit_mode) self._init_project() self._init_widgets() self._init_signal_handlers() self.update_tab_label() self.emit("view-created", self.view) def document_to_text_column(self, doc): """Translate document enumeration to view's column enumeration.""" if doc == aeidon.documents.MAIN: return self.view.columns.MAIN_TEXT if doc == aeidon.documents.TRAN: return self.view.columns.TRAN_TEXT raise ValueError("Invalid document: {!r}" .format(doc)) def get_basename(self, doc): """Return basename of `doc`.""" if doc == aeidon.documents.MAIN: return self.get_main_basename() if doc == aeidon.documents.TRAN: return self.get_translation_basename() raise ValueError("Invalid document: {!r}" .format(doc)) def get_main_basename(self): """Return basename of the main document.""" if self.project.main_file is not None: return os.path.basename(self.project.main_file.path) return self.untitle def _get_subtitle_value(self, row, field): """Return value of subtitle data for `row` and `field`.""" mode = self.edit_mode subtitle = self.project.subtitles[row] if field == gaupol.fields.START: return subtitle.get_start(mode) if field == gaupol.fields.END: return subtitle.get_end(mode) if field == gaupol.fields.DURATION: if mode == aeidon.modes.TIME: return subtitle.duration_seconds if mode == aeidon.modes.FRAME: return subtitle.duration_frame raise ValueError("Invalid mode: {!r}" .format(mode)) if field == gaupol.fields.MAIN_TEXT: return subtitle.main_text if field == gaupol.fields.TRAN_TEXT: return subtitle.tran_text raise ValueError("Invalid field: {!r}" .format(field)) def _get_tab_close_button(self): """Initialize and return a tab close button.""" button = Gtk.Button() style = button.get_style_context() style.add_class("gaupol-tab-close-button") image = gaupol.util.get_icon_image("window-close-symbolic", "window-close", Gtk.IconSize.MENU) button.add(image) button.set_relief(Gtk.ReliefStyle.NONE) button.set_focus_on_click(False) width = image.get_preferred_width()[1] height = image.get_preferred_height()[1] padding = 6 if sys.platform == "win32" else 2 button.set_size_request(width + padding, height + padding) request_close = lambda x, self: self.emit("close-request") button.connect("clicked", request_close, self) button.set_tooltip_text(_("Close project")) return button def get_translation_basename(self): """Return basename of the translation document.""" if self.project.tran_file is not None: return os.path.basename(self.project.tran_file.path) basename = self.get_main_basename() if self.project.main_file is not None: extension = self.project.main_file.format.extension if basename.endswith(extension): basename = basename[:-len(extension)] return _("{} translation").format(basename) def _init_project(self): """Initialize :class:`aeidon.Project` with proper properties.""" framerate = gaupol.conf.editor.framerate self.project = aeidon.Project(framerate) def _init_signal_handlers(self): """Initialize signal handlers.""" self._init_signal_handlers_for_data() self._init_signal_handlers_for_tab_label() def _init_signal_handlers_for_data(self): """Initialize signal handlers for project data updates.""" aeidon.util.connect(self, "project", "main-file-opened") aeidon.util.connect(self, "project", "main-texts-changed") aeidon.util.connect(self, "project", "positions-changed") aeidon.util.connect(self, "project", "subtitles-changed") aeidon.util.connect(self, "project", "subtitles-inserted") aeidon.util.connect(self, "project", "subtitles-removed") aeidon.util.connect(self, "project", "translation-file-opened") aeidon.util.connect(self, "project", "translation-texts-changed") def _init_signal_handlers_for_tab_label(self): """Initialize signal handlers for tab label updates.""" aeidon.util.connect(self, "tab_label", "query-tooltip") update_label = lambda *args: args[-1].update_tab_label() self.project.connect("main-file-opened", update_label, self) self.project.connect("main-file-saved", update_label, self) self.project.connect("notify::main_changed", update_label, self) self.project.connect("notify::tran_changed", update_label, self) def _init_widgets(self): """Initialize widgets to use in a notebook tab.""" self.tab_label = Gtk.Label() self.tab_label.set_halign(Gtk.Align.CENTER) self.tab_label.set_ellipsize(Pango.EllipsizeMode.MIDDLE) # Set minimum width for tab label. The actual width taken # depends on window size, amount of tabs and notebook # child properties 'tab-expand' and 'tab-fill'. width = gaupol.util.char_to_px(24) self.tab_label.set_size_request(width, -1) self.tab_label.set_tooltip_text(self.untitle) button = self._get_tab_close_button() box = gaupol.util.new_hbox(spacing=4) gaupol.util.pack_start_expand(box, self.tab_label) gaupol.util.pack_start(box, button) box.gaupol_button = button self.tab_widget = Gtk.EventBox() self.tab_widget.add(box) self.tab_widget.set_visible_window(False) self.tab_widget.show_all() def _on_project_main_file_opened(self, *args): """Reload the entire view.""" self.reload_view_all() gaupol.util.iterate_main() def _on_project_main_texts_changed(self, project, rows): """Reload and select main texts in rows.""" if not rows: return fields = (gaupol.fields.MAIN_TEXT,) self.reload_view(rows, fields) if not self.view.get_focus()[0] in rows: col = self.view.columns.MAIN_TEXT self.view.set_focus(rows[0], col) self.view.select_rows(rows) gaupol.util.iterate_main() def _on_project_positions_changed(self, project, rows): """Reload and select positions in rows.""" if not rows: return enum = gaupol.fields fields = (enum.START, enum.END, enum.DURATION) self.reload_view(rows, fields) if not self.view.get_focus()[0] in rows: self.view.set_focus(rows[0]) self.view.select_rows(rows) gaupol.util.iterate_main() def _on_project_subtitles_changed(self, project, rows): """Reload and select subtitles in rows.""" if not rows: return fields = [x for x in gaupol.fields] fields.remove(gaupol.fields.NUMBER) self.reload_view(rows, fields) if not self.view.get_focus()[0] in rows: self.view.set_focus(rows[0]) self.view.select_rows(rows) gaupol.util.iterate_main() def _on_project_subtitles_inserted(self, project, rows): """Insert rows to the view and select them.""" if not rows: return mode = self.edit_mode store = self.view.get_model() for row in sorted(rows): subtitle = self.project.subtitles[row] store.insert(row) store[row][0] = row + 1 store[row][1] = subtitle.get_start(mode) store[row][2] = subtitle.get_end(mode) if mode == aeidon.modes.TIME: store[row][3] = subtitle.duration_seconds if mode == aeidon.modes.FRAME: store[row][3] = subtitle.duration_frame store[row][4] = subtitle.main_text store[row][5] = subtitle.tran_text self.view.set_focus(rows[0]) self.view.select_rows(rows) gaupol.util.iterate_main() def _on_project_subtitles_removed(self, project, rows): """Remove rows from the view.""" if not rows: return store = self.view.get_model() if len(rows) > 50: # Unset and later reset the model if removing a large amount # of rows, because a large batch of separate live updates # directly made to the view are slow. self.view.set_model(None) for row in reversed(sorted(rows)): path = gaupol.util.tree_row_to_path(row) store.remove(store.get_iter(path)) if len(rows) > 50: self.view.set_model(store) if self.project.subtitles: row = min(rows[0], len(self.project.subtitles)-1) col = self.view.get_focus()[1] self.view.set_focus(row, col) gaupol.util.iterate_main() def _on_project_translation_file_opened(self, *args): """Reload the entire view.""" self.reload_view_all() gaupol.util.iterate_main() def _on_project_translation_texts_changed(self, project, rows): """Reload and select translation texts in rows.""" if not rows: return fields = (gaupol.fields.TRAN_TEXT,) self.reload_view(rows, fields) if not self.view.get_focus()[0] in rows: col = self.view.columns.TRAN_TEXT self.view.set_focus(rows[0], col) self.view.select_rows(rows) gaupol.util.iterate_main() def _on_tab_label_query_tooltip(self, label, x, y, keyboard, tooltip): """Update the text in the tab tooltip.""" if self.project.main_file is None: return path = self.project.main_file.path format = self.project.main_file.format encoding = self.project.main_file.encoding encoding = aeidon.encodings.code_to_long_name(encoding) newline = self.project.main_file.newline tooltip.set_markup("{}\n{}\n{}\n{}".format( "{} {}".format(_("Path:"), path), "{} {}".format(_("Format:"), format.label), "{} {}".format(_("Encoding:"), encoding), "{} {}".format(_("Newlines:"), newline.label))) return True # to show the tooltip. def reload_view(self, rows, fields): """Reload the view in `rows` and `fields`.""" store = self.view.get_model() for row, field in ((x, y) for x in rows for y in fields): value = self._get_subtitle_value(row, field) store[row][field] = value def reload_view_all(self): """Clear and repopulate the entire view.""" store = self.view.get_model() self.view.set_model(None) store.clear() mode = self.edit_mode for i, subtitle in enumerate(self.project.subtitles): store.insert(i) store[i][0] = i + 1 store[i][1] = subtitle.get_start(mode) store[i][2] = subtitle.get_end(mode) if mode == aeidon.modes.TIME: store[i][3] = subtitle.duration_seconds if mode == aeidon.modes.FRAME: store[i][3] = subtitle.duration_frame store[i][4] = subtitle.main_text store[i][5] = subtitle.tran_text self.view.set_model(store) def text_column_to_document(self, col): """Translate view's column enumeration to document enumeration.""" if col == self.view.columns.MAIN_TEXT: return aeidon.documents.MAIN if col == self.view.columns.TRAN_TEXT: return aeidon.documents.TRAN raise ValueError("Invalid column: {!r}" .format(col)) def update_tab_label(self): """Update the notebook tab label and return title.""" title = self.get_main_basename() if self.project.main_changed or self.project.tran_changed: title = "*{}".format(title) # Adwaita theme uses bold notebook tab labels since 3.12. self.tab_label.set_markup("{}".format(title)) return title gaupol-1.11/gaupol/player.py000066400000000000000000000421041422217132500160600ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2012 Osmo Salomaa # # 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 . """GStreamer video player.""" import aeidon import gaupol import time from collections import namedtuple from aeidon.i18n import _ from gi.repository import GLib from gi.repository import Gtk with aeidon.util.silent(Exception): from gi.repository import Gst __all__ = ("VideoPlayer",) class VideoPlayer(aeidon.Observable): """ GStreamer video player. :ivar audio_track: Current audio track as integer :ivar calc: The instance of :class:`aeidon.Calculator` used :ivar _in_default_segment: ``True`` if in the default playback segment :ivar _info: :class:`Gst.DiscovererInfo` from current URI :ivar _playbin: GStreamer "playbin" element :ivar _prev_state: Previous state of `_playbin` :ivar ready: ``True`` if a file is loaded and ready to play :ivar subtitle_text: Current text shown in the subtitle overlay :ivar subtitle_text_raw: `subtitle_text` before removal of tags :ivar _text_overlay: GStreamer "textoverlay" element :ivar _time_overlay: GStreamer "timeoverlay" element :ivar volume: Current audio stream volume :ivar widget: :class:`Gtk.DrawingArea` used to render video Signals and their arguments for callback functions: * ``state-changed``: player new state """ signals = ("state-changed",) TrackInfo = namedtuple("TrackInfo", ["title", "language_code", "language_name"]) def __init__(self): """Initialize a :class:`VideoPlayer` instance.""" aeidon.Observable.__init__(self) self.calc = aeidon.Calculator() self._in_default_segment = True self._info = None self._playbin = None self._prev_state = None self.ready = False self.subtitle_text_raw = "" self._text_overlay = None self._time_overlay = None self.widget = None self._init_widget() self._init_text_overlay() self._init_time_overlay() self._init_pipeline() self._init_bus() @property def audio_track(self): """Return number of the current audio track.""" track = self._playbin.props.current_audio # If at the default value, the first track is used, # which is (probably?) zero. return 0 if track == -1 else track @audio_track.setter def audio_track(self, track): """Set the current audio track.""" self._playbin.props.current_audio = track def _ensure_default_segment(self): """ Reset playback start and stop positions. When using `play_segment`, the playback limits are set to those (instead of the default 0 and -1). To be able to do useful things, we often need to reset those segment limits to their defaults. Any methods that need to rely on the whole duration being accessible, should as first thing call this method. """ if self._in_default_segment: return # XXX: There's got to be a simpler way to do this. seek_flags = Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE pos = self.get_position(aeidon.modes.SECONDS) * Gst.SECOND end = self.get_duration(aeidon.modes.SECONDS) * Gst.SECOND if pos is None: return if end is None: return self._playbin.seek(rate=1.0, format=Gst.Format.TIME, flags=seek_flags, start_type=Gst.SeekType.SET, start=0, stop_type=Gst.SeekType.SET, stop=end) self._playbin.seek_simple(Gst.Format.TIME, seek_flags, pos) self._in_default_segment = True def get_audio_infos(self): """Return a sequence of audio track infos.""" return tuple( self._make_track_infos(self._playbin.emit("get-audio-tags", i)) for i in range(self._playbin.props.n_audio) ) def _make_track_infos(self, tags): return self.TrackInfo( tags.get_string("title")[1], tags.get_string("language-code")[1], tags.get_string("language-name")[1] ) def get_duration(self, mode=None): """Return duration of video stream or ``None``.""" q = self._playbin.query_duration for i in range(100): # Querying duration sometimes fails very unreproducibly, # likely due to a particular pipeline state or state change. # Try repeated times, hoping to pass the bad state. success, duration = q(Gst.Format.TIME) if success: break time.sleep(1/100) if not success: return None if mode is None: return duration duration = duration / Gst.SECOND if mode == aeidon.modes.SECONDS: return duration if mode == aeidon.modes.TIME: return self.calc.to_time(duration) if mode == aeidon.modes.FRAME: return self.calc.to_frame(duration) raise ValueError("Invalid mode: {!r}".format(mode)) def get_position(self, mode=None): """Return current position in video stream or ``None``.""" q = self._playbin.query_position for i in range(100): # Querying position sometimes fails very unreproducibly, # likely due to a particular pipeline state or state change. # Try repeated times, hoping to pass the bad state. success, pos = q(Gst.Format.TIME) if success: break time.sleep(1/100) if not success: return None if mode is None: return pos pos = pos / Gst.SECOND if mode == aeidon.modes.SECONDS: return pos if mode == aeidon.modes.TIME: return self.calc.to_time(pos) if mode == aeidon.modes.FRAME: return self.calc.to_frame(pos) raise ValueError("Invalid mode: {!r}".format(mode)) def _init_bus(self): """Initialize the GStreamer message bus.""" bus = self._playbin.get_bus() bus.add_signal_watch() bus.connect("message::eos", self._on_bus_message_eos) bus.connect("message::error", self._on_bus_message_error) bus.connect("message::state-changed", self._on_bus_message_state_changed) def _init_pipeline(self): """Initialize the GStreamer playback pipeline.""" self._playbin = Gst.ElementFactory.make("playbin", None) if gaupol.conf.video_player.volume is not None: self.volume = gaupol.conf.video_player.volume sink = Gst.ElementFactory.make("gtksink", None) self.widget.pack_start(sink.props.widget, True, True, 0) bin = Gst.Bin() bin.add(self._time_overlay) bin.add(self._text_overlay) pad = self._time_overlay.get_static_pad("video_sink") bin.add_pad(Gst.GhostPad.new("sink", pad)) bin.add(sink) self._time_overlay.link(self._text_overlay) self._text_overlay.link(sink) self._playbin.props.video_sink = bin # We need to disable playbin's own subtitle rendering, since we don't # want embedded subtitles to be displayed, but rather what we # explicitly set to our own overlays. Since Gst.PlayFlags is not # available via introspection, we need to use Gst.util_set_object_arg. # Playbin's default values can be found via 'gst-inspect-1.0 playbin'. Gst.util_set_object_arg(self._playbin, "flags", "+".join(("soft-colorbalance", "deinterlace", "soft-volume", "audio", "video"))) def _init_text_overlay(self): """Initialize the text overlay element.""" self._text_overlay = Gst.ElementFactory.make("textoverlay", None) conf = gaupol.conf.video_player callback = self._on_conf_notify_subtitle_property conf.connect("notify::subtitle_font", callback) conf.connect("notify::subtitle_color", callback) conf.connect("notify::subtitle_alpha", callback) conf.connect("notify::subtitle_background", callback) self._on_conf_notify_subtitle_property() def _init_time_overlay(self): """Initialize the time overlay element.""" self._time_overlay = Gst.ElementFactory.make("timeoverlay", None) conf = gaupol.conf.video_player callback = self._on_conf_notify_time_property conf.connect("notify::time_font", callback) conf.connect("notify::time_color", callback) conf.connect("notify::time_alpha", callback) conf.connect("notify::time_background", callback) self._on_conf_notify_time_property() def _init_widget(self): """Initialize the rendering widget.""" self.widget = Gtk.Box() style = self.widget.get_style_context() style.add_class("gaupol-video-background") gaupol.style.load_css(self.widget) def is_playing(self): """Return ``True`` if playing video.""" # GStreamer's state information is far too detailed for our purposes. # Let's consider the state to be playing also if undergoing a state # change and/or having a pending playing state. success, current, pending = self._playbin.get_state(timeout=1) return (success == Gst.StateChangeReturn.ASYNC or current == Gst.State.PLAYING or pending == Gst.State.PLAYING) def _on_bus_message_eos(self, bus, message): """Handle EOS message from the bus.""" self._ensure_default_segment() self.pause() def _on_bus_message_error(self, bus, message): """Handle error message from the bus.""" title, message = message.parse_error() dialog = gaupol.ErrorDialog(None, title, message) dialog.add_button(_("_OK"), Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK) gaupol.util.flash_dialog(dialog) def _on_bus_message_state_changed(self, bus, message): """Emit signal if state changed in a relevant manner.""" old, new, pending = message.parse_state_changed() states = (Gst.State.NULL, Gst.State.PAUSED, Gst.State.PLAYING) if not new in states: return if new == self._prev_state: return self.emit("state-changed", new) self._prev_state = new def _on_conf_notify_subtitle_property(self, *args): """Update subtitle text overlay properties.""" conf = gaupol.conf.video_player self._text_overlay.props.font_desc = conf.subtitle_font self._text_overlay.props.halignment = conf.subtitle_position_horizontal self._text_overlay.props.valignment = conf.subtitle_position_vertical self._text_overlay.props.line_alignment = conf.line_alignment self._text_overlay.props.shaded_background = conf.subtitle_background alpha = "{:02x}".format(int(conf.subtitle_alpha * 255)) color = conf.subtitle_color.replace("#", "") color = int(float.fromhex("".join((alpha, color)))) self._text_overlay.props.color = color def _on_conf_notify_time_property(self, *args): """Update time overlay properties.""" conf = gaupol.conf.video_player self._time_overlay.props.font_desc = conf.time_font self._time_overlay.props.halignment = conf.time_position_horizontal self._time_overlay.props.valignment = conf.time_position_vertical self._time_overlay.props.shaded_background = conf.time_background alpha = "{:02x}".format(int(conf.time_alpha * 255)) color = conf.time_color.replace("#", "") color = int(float.fromhex("".join((alpha, color)))) self._time_overlay.props.color = color def pause(self): """Pause.""" self._playbin.set_state(Gst.State.PAUSED) def play(self): """Play.""" self._playbin.set_state(Gst.State.PLAYING) def play_segment(self, start, end): """Play from `start` to `end`.""" self._in_default_segment = False seek_flags = Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE start = max(0, self.calc.to_seconds(start)) * Gst.SECOND duration = self.get_duration(aeidon.modes.SECONDS) if duration is None: return end = min(duration, self.calc.to_seconds(end)) * Gst.SECOND self._playbin.seek(rate=1.0, format=Gst.Format.TIME, flags=seek_flags, start_type=Gst.SeekType.SET, start=start, stop_type=Gst.SeekType.SET, stop=end) self.play() def seek(self, pos): """Seek to `pos`.""" self._ensure_default_segment() seek_flags = Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE pos = self.calc.to_seconds(pos) * Gst.SECOND self._playbin.seek_simple(Gst.Format.TIME, seek_flags, pos) def _seek_null(self): """Seek to the current position.""" self._ensure_default_segment() pos = self.get_position(mode=None) if pos is None: return seek_flags = Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE self._playbin.seek_simple(Gst.Format.TIME, seek_flags, pos) def seek_relative(self, offset): """Seek to `offset` relative to current position.""" self._ensure_default_segment() pos = self.get_position(aeidon.modes.SECONDS) duration = self.get_duration(aeidon.modes.SECONDS) if pos is None or duration is None: return pos = pos + self.calc.to_seconds(offset) pos = max(0, min(pos, duration)) pos = pos * Gst.SECOND seek_flags = Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE self._playbin.seek_simple(Gst.Format.TIME, seek_flags, pos) def set_path(self, path): """Set the path of the file to play.""" self.set_uri(aeidon.util.path_to_uri(path)) def set_uri(self, uri): """Set the URI of the file to play.""" self.ready = False self._playbin.props.uri = uri self.subtitle_text = "" try: # Find out the exact framerate to be able # to convert between position types. from gi.repository import GstPbutils discoverer = GstPbutils.Discoverer() self._info = discoverer.discover_uri(uri) streams = self._info.get_stream_list() stream_types = [x.get_stream_type_nick() for x in streams] if "video" not in stream_types: raise Exception(_("No video streams found")) stream = self._info.get_video_streams()[0] num = float(stream.get_framerate_num()) denom = float(stream.get_framerate_denom()) self.calc = aeidon.Calculator(num/denom) self.ready = True except Exception as error: title = _("Failed to initialize playback") dialog = gaupol.ErrorDialog(None, title, str(error)) dialog.add_button(_("_OK"), Gtk.ResponseType.OK) dialog.set_default_response(Gtk.ResponseType.OK) gaupol.util.flash_dialog(dialog) else: # Make stream tags available from _playbin self._playbin.set_state(Gst.State.PAUSED) self._playbin.get_state(Gst.CLOCK_TIME_NONE) def stop(self): """Stop.""" self._playbin.set_state(Gst.State.NULL) self.subtitle_text = "" @property def subtitle_text(self): """Return text shown in the subtitle overlay.""" return self._text_overlay.props.text @subtitle_text.setter def subtitle_text(self, text): """Set `text` to the subtitle overlay.""" self.subtitle_text_raw = text text = aeidon.RE_ANY_TAG.sub("", text) text = GLib.markup_escape_text(text) self._text_overlay.props.text = text # Do a zero seek to force an update of the overlay. # https://github.com/otsaloma/gaupol/issues/181 if self._in_default_segment: with aeidon.util.silent(Exception, tb=True): self._seek_null() @property def volume(self): """Return the current volume, in range [0,1].""" return self._playbin.props.volume @volume.setter def volume(self, volume): """Set the volume to use, in range [0,1].""" volume = round(max(0, min(1, volume)), 2) if abs(volume - self.volume) < 0.001: return self._playbin.props.volume = volume gaupol.conf.video_player.volume = volume gaupol-1.11/gaupol/renderers/000077500000000000000000000000001422217132500162025ustar00rootroot00000000000000gaupol-1.11/gaupol/renderers/__init__.py000066400000000000000000000021311422217132500203100ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Cell renderer widgets for subtitle data.""" from .float import FloatCellRenderer from .integer import IntegerCellRenderer from .multiline import MultilineCellRenderer from .multiline import MultilineDiffCellRenderer from .time import TimeCellRenderer __all__ = ( "FloatCellRenderer", "IntegerCellRenderer", "MultilineCellRenderer", "MultilineDiffCellRenderer", "TimeCellRenderer", ) gaupol-1.11/gaupol/renderers/float.py000066400000000000000000000050641422217132500176660ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2009 Osmo Salomaa # # 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 . """Cell renderer for float data with fixed precision.""" import aeidon import gaupol import re from gi.repository import GLib from gi.repository import GObject from gi.repository import Gtk __all__ = ("FloatCellRenderer",) class FloatCellRenderer(Gtk.CellRendererText): """Cell renderer for float data with fixed precision.""" __gtype_name__ = "FloatCellRenderer" def __init__(self, format="{:.3f}"): """Initialize a :class:`FloatCellRenderer` instance.""" GObject.GObject.__init__(self) self._format = format aeidon.util.connect(self, self, "notify::text") aeidon.util.connect(self, self, "edited") aeidon.util.connect(self, self, "editing-started") def _on_edited(self, renderer, path, text): """Check `text` for validity before sending onwards.""" if re.match(r"^[+-]?(\d+[,.]?\d*|\d*[,.]?\d+)$", text) is None: renderer.stop_emission("edited") renderer.stop_editing(True) def _on_editing_started(self, renderer, editor, path): """Set `editor` to use same font as `self`.""" gaupol.style.use_font(editor, "custom") def _on_notify_text(self, *args): """Cut decimals to fixed precision.""" # Since GTK 3.6, the notify::text signal seems to get # emitted insanely often even if text hasn't changed at # all. Let's try to keep this callback as fast as possible. self.props.markup = self._text_to_markup(self.props.text) @aeidon.deco.memoize(1000) def _text_to_markup(self, text): """Return `text` renderer as markup for display.""" if not text: return "" has_comma = text.find(",") > 0 if has_comma: text = text.replace(",", ".") text = self._format.format(float(text)) if has_comma: text = text.replace(".", ",") return GLib.markup_escape_text(text) gaupol-1.11/gaupol/renderers/integer.py000066400000000000000000000031721422217132500202140ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2009 Osmo Salomaa # # 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 . """Cell renderer for integer data.""" import aeidon import gaupol import re from gi.repository import GObject from gi.repository import Gtk __all__ = ("IntegerCellRenderer",) class IntegerCellRenderer(Gtk.CellRendererText): """Cell renderer for integer data.""" __gtype_name__ = "IntegerCellRenderer" def __init__(self): """Initialize a :class:`IntegerCellRenderer` instance.""" GObject.GObject.__init__(self) aeidon.util.connect(self, self, "edited") aeidon.util.connect(self, self, "editing-started") def _on_edited(self, renderer, path, text): """Check `text` for validity before sending onwards.""" if re.match(r"[+-]?\d+", text) is None: renderer.stop_emission("edited") renderer.stop_editing(True) def _on_editing_started(self, renderer, editor, path): """Set `editor` to use same font as `self`.""" gaupol.style.use_font(editor, "custom") gaupol-1.11/gaupol/renderers/multiline.py000066400000000000000000000277671422217132500206010ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Cell renderer for multiline text data.""" import aeidon import difflib import gaupol import re from aeidon.i18n import _ from gi.repository import Gdk from gi.repository import GLib from gi.repository import GObject from gi.repository import Gtk __all__ = ("MultilineCellRenderer", "MultilineDiffCellRenderer") class CellTextView(Gtk.TextView, Gtk.CellEditable): """A :class:`Gtk.TextView` suitable for cell renderer use.""" __gproperties__ = { "editing-canceled": (bool, "Editing canceled", "Editing canceled", False, GObject.ParamFlags.READWRITE), } __gtype_name__ = "CellTextView" def __init__(self, text_buffer=None): """Initialize a :class:`CellTextView` instance.""" GObject.GObject.__init__(self) gaupol.util.prepare_text_view(self) aeidon.util.connect(self, self, "key-press-event") aeidon.util.connect(self, self, "populate-popup") def do_editing_done(self, *args): """End editing.""" pass def do_remove_widget(self, *args): """Remove widget.""" pass def do_start_editing(self, *args): """Start editing.""" # Don't let anyone else handle button-press-events # that happen within the text view. self.connect_after("button-press-event", lambda *args: True) def get_text(self): """Return text.""" text_buffer = self.get_buffer() start, end = text_buffer.get_bounds() return text_buffer.get_text(start, end, False) def _on_key_press_event(self, text_view, event): """Toggle italicization if Control+I pressed.""" if (event.get_state() & Gdk.ModifierType.CONTROL_MASK and event.keyval in (Gdk.KEY_i, Gdk.KEY_I)): self._on_toggle_italic() return True return False def _on_populate_popup(self, text_view, popup): """Add a context menu item to toggle italicization.""" if not isinstance(popup, Gtk.Menu): return item = Gtk.MenuItem(label=_("Italic")) item.connect("activate", self._on_toggle_italic) child = item.get_child() if isinstance(child, Gtk.AccelLabel): child.set_accel(Gdk.KEY_i, Gdk.ModifierType.CONTROL_MASK) item.show_all() popup.append(item) def _on_toggle_italic(self, *args): """Add or remove italic tags around selection.""" if not getattr(gaupol, "italic_tag", None): return if not getattr(gaupol, "italicize", None): return text_buffer = self.get_buffer() start, end = text_buffer.get_bounds() text = text_buffer.get_text(start, end, False) bounds = text_buffer.get_selection_bounds() if not bounds: # If no selection, replicate cursor position. cursor = text_buffer.get_insert() cursor = text_buffer.get_iter_at_mark(cursor) bounds = (cursor, cursor) a, b = [x.get_offset() for x in bounds] # Strip possible existing italic tags around selection. # If none found, then selection should be italicized. text1 = re.sub(gaupol.italic_tag.pattern + r"\Z", "", text[:a]) text2 = re.sub(gaupol.italic_tag.pattern, "", text[a:b]) text3 = re.sub(r"\A" + gaupol.italic_tag.pattern, "", text[b:]) if text1 + text2 + text3 == text: text2 = gaupol.italicize(text2) match = gaupol.italic_tag.match(text2) a += match.end() - match.start() b += match.end() - match.start() else: a = len(text1) b = len(text1) + len(text2) text_buffer.set_text(text1 + text2 + text3) ins = text_buffer.get_iter_at_offset(a) bound = text_buffer.get_iter_at_offset(b) text_buffer.select_range(ins, bound) def set_text(self, text): """Set text.""" self.get_buffer().set_text(text) class MultilineCellRenderer(Gtk.CellRendererText): """ Cell renderer for multiline text data. If :attr:`gaupol.conf.editor.show_lengths_cell` is ``True``, line lengths are shown at the end of each line. """ __gtype_name__ = "MultilineCellRenderer" def __init__(self): """Initialize a :class:`MultilineCellRenderer` instance.""" GObject.GObject.__init__(self) self._in_editor_menu = False self._show_lengths = gaupol.conf.editor.show_lengths_cell self._text = "" gaupol.conf.connect_notify("editor", "show_lengths_cell", self) aeidon.util.connect(self, self, "notify::text") def do_start_editing(self, event, widget, path, bg_area, cell_area, flags): """Initialize and return a :class:`CellTextView` widget.""" editor = CellTextView() gaupol.style.use_font(editor, "custom") editor.set_text(self._text) editor.set_size_request(cell_area.width, cell_area.height) editor.set_left_margin(self.props.xpad) editor.set_right_margin(self.props.xpad) with aeidon.util.silent(AttributeError): # Top and bottom margins available since GTK 3.18. editor.set_top_margin(self.props.ypad) editor.set_bottom_margin(self.props.ypad) editor.gaupol_path = path editor.connect("focus-out-event", self._on_editor_focus_out_event) editor.connect("key-press-event", self._on_editor_key_press_event) editor.connect("populate-popup", self._on_editor_populate_popup) editor.show() return editor def _on_conf_editor_notify_show_lengths_cell(self, *args): """Hide or show line lengths if ``conf`` changed.""" self._show_lengths = gaupol.conf.editor.show_lengths_cell def _on_editor_focus_out_event(self, editor, *args): """End editing.""" if self._in_editor_menu: return editor.remove_widget() self.emit("editing-canceled") def _on_editor_key_press_event(self, editor, event): """End editing if ``Enter`` or ``Escape`` pressed.""" if (event.get_state() & (Gdk.ModifierType.SHIFT_MASK | Gdk.ModifierType.CONTROL_MASK)): return if event.keyval in (Gdk.KEY_Return, Gdk.KEY_KP_Enter): editor.editing_done() editor.remove_widget() self.emit("edited", editor.gaupol_path, editor.get_text()) return True if event.keyval == Gdk.KEY_Escape: editor.editing_done() editor.remove_widget() self.emit("editing-canceled") return True def _on_editor_populate_popup(self, editor, menu): """Disable "focus-out-event" ending editing.""" self._in_editor_menu = True def on_menu_unmap(menu, self): self._in_editor_menu = False menu.connect("unmap", on_menu_unmap, self) def _on_notify_text(self, *args): """Set markup by adding line lengths to text.""" # Since GTK 3.6, the notify::text signal seems to get # emitted insanely often even if text hasn't changed at # all. Let's try to keep this callback as fast as possible. self._text = self.props.text self.props.markup = self._text_to_markup(self.props.text, self._show_lengths, gaupol.conf.editor.length_unit) def set_show_lengths(self, show_lengths): """Show or hide line lengths, overriding ``conf``.""" self._show_lengths = show_lengths gaupol.conf.disconnect_notify("editor", "show_lengths_cell", self) @aeidon.deco.memoize(1000) def _text_to_markup(self, text, show_lengths, length_unit): """Return `text` rendered as markup for display.""" # We don't actually use the length_unit argument, # but do need it accounted for in memoized values. if not text: return "" markup = GLib.markup_escape_text(text) if not show_lengths: return markup lines = markup.split("\n") lengths = gaupol.ruler.get_lengths(text) return "\n".join(("{} [{:d}]" .format(lines[i], lengths[i]) if lines[i] else lines[i] for i in range(len(lines)))) class MultilineDiffCellRenderer(MultilineCellRenderer): """Cell renderer for multiline diffed text data.""" __gtype_name__ = "MultilineDiffCellRenderer" ref_text = GObject.Property(type=str, default="") ref_type = GObject.Property(type=int, default=-1) COLOR_CHANGE = gaupol.conf.general.diff_color_change COLOR_DELETE = gaupol.conf.general.diff_color_delete COLOR_INSERT = gaupol.conf.general.diff_color_insert def __init__(self): """Initialize a :class:`MultilineDiffCellRenderer` instance.""" MultilineCellRenderer.__init__(self) self._ref_text = "" def _add_diff_markup(self, a, b): """Return `a` with markup for parts different from `b`.""" matcher = difflib.SequenceMatcher(a=a, b=b) ops = matcher.get_opcodes() return "".join(self._highlight(a[i1:i2], tag) for tag, i1, i2, j1, j2 in ops) def _get_diff_color(self, tag): """Return color to use to highlight changes of type `tag`.""" if tag == "insert" and self.props.ref_type > 0: return self.COLOR_INSERT if tag == "insert" and self.props.ref_type < 0: return self.COLOR_DELETE if tag == "delete" and self.props.ref_type > 0: return self.COLOR_DELETE if tag == "delete" and self.props.ref_type < 0: return self.COLOR_INSERT return self.COLOR_CHANGE def _highlight(self, text, tag): """Return `text` as markup highlighting changes of type `tag`.""" if tag == "equal": return text color = self._get_diff_color(tag) return '{}'.format(color, text) def _on_notify_text(self, *args): """Set markup by adding line lengths to text.""" # Since GTK 3.6, the notify::text signal seems to get # emitted insanely often even if text hasn't changed at # all. Let's try to keep this callback as fast as possible. self._text = self.props.text self._ref_text = self.props.ref_text self.props.markup = self._text_to_markup(self.props.text, self.props.ref_text, self._show_lengths, gaupol.conf.editor.length_unit) @aeidon.deco.memoize(1000) def _text_to_markup(self, text, ref_text, show_lengths, length_unit): """Return `text` rendered as markup for display.""" # We don't actually use the length_unit argument, # but do need it accounted for in memoized values. if not text: return "" text = GLib.markup_escape_text(text) ref_text = GLib.markup_escape_text(ref_text) with aeidon.util.silent(Exception, tb=True): text = self._add_diff_markup(text, ref_text) if not show_lengths: return text lines = text.split("\n") lengths = gaupol.ruler.get_lengths(text) return "\n".join(("{} [{:d}]" .format(lines[i], lengths[i]) if lines[i] else lines[i] for i in range(len(lines)))) gaupol-1.11/gaupol/renderers/test/000077500000000000000000000000001422217132500171615ustar00rootroot00000000000000gaupol-1.11/gaupol/renderers/test/__init__.py000066400000000000000000000000001422217132500212600ustar00rootroot00000000000000gaupol-1.11/gaupol/renderers/test/test_float.py000066400000000000000000000027221422217132500217020ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2009 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class TestFloatCellRenderer(gaupol.TestCase): def run_renderer(self): tree_view = Gtk.TreeView() tree_view.set_headers_visible(False) store = Gtk.ListStore(float) store.append((12.345,)) tree_view.set_model(store) self.renderer.props.editable = True column = Gtk.TreeViewColumn("", self.renderer, text=0) tree_view.append_column(column) window = Gtk.Window() window.connect("delete-event", Gtk.main_quit) window.set_position(Gtk.WindowPosition.CENTER) window.set_default_size(200, 50) window.add(tree_view) window.show_all() Gtk.main() def setup_method(self, method): self.renderer = gaupol.FloatCellRenderer() gaupol-1.11/gaupol/renderers/test/test_integer.py000066400000000000000000000027201422217132500222300ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2009 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class TestIntegerCellRenderer(gaupol.TestCase): def run_renderer(self): tree_view = Gtk.TreeView() tree_view.set_headers_visible(False) store = Gtk.ListStore(int) store.append((12,)) tree_view.set_model(store) self.renderer.props.editable = True column = Gtk.TreeViewColumn("", self.renderer, text=0) tree_view.append_column(column) window = Gtk.Window() window.connect("delete-event", Gtk.main_quit) window.set_position(Gtk.WindowPosition.CENTER) window.set_default_size(200, 50) window.add(tree_view) window.show_all() Gtk.main() def setup_method(self, method): self.renderer = gaupol.IntegerCellRenderer() gaupol-1.11/gaupol/renderers/test/test_multiline.py000066400000000000000000000043761422217132500226060ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class TestMultilineCellRenderer(gaupol.TestCase): def run_renderer(self): tree_view = Gtk.TreeView() tree_view.set_headers_visible(False) store = Gtk.ListStore(str) store.append(("test\ntest test",)) tree_view.set_model(store) self.renderer.props.editable = True column = Gtk.TreeViewColumn("", self.renderer, text=0) tree_view.append_column(column) window = Gtk.Window() window.connect("delete-event", Gtk.main_quit) window.set_position(Gtk.WindowPosition.CENTER) window.set_default_size(240, 70) window.add(tree_view) window.show_all() Gtk.main() def setup_method(self, method): self.renderer = gaupol.MultilineCellRenderer() class TestMultilineDiffCellRenderer(gaupol.TestCase): def run_renderer(self): tree_view = Gtk.TreeView() tree_view.set_headers_visible(False) store = Gtk.ListStore(str, str) store.append(("test", "test\ntest")) tree_view.set_model(store) self.renderer.props.editable = True column = Gtk.TreeViewColumn("", self.renderer, text=1, ref_text=0) tree_view.append_column(column) window = Gtk.Window() window.connect("delete-event", Gtk.main_quit) window.set_position(Gtk.WindowPosition.CENTER) window.set_default_size(240, 70) window.add(tree_view) window.show_all() Gtk.main() def setup_method(self, method): self.renderer = gaupol.MultilineDiffCellRenderer() gaupol-1.11/gaupol/renderers/test/test_time.py000066400000000000000000000027261422217132500215370ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class TestTimeCellRenderer(gaupol.TestCase): def run_renderer(self): tree_view = Gtk.TreeView() tree_view.set_headers_visible(False) store = Gtk.ListStore(str) store.append(("12:34:56.789",)) tree_view.set_model(store) self.renderer.props.editable = True column = Gtk.TreeViewColumn("", self.renderer, text=0) tree_view.append_column(column) window = Gtk.Window() window.connect("delete-event", Gtk.main_quit) window.set_position(Gtk.WindowPosition.CENTER) window.set_default_size(200, 50) window.add(tree_view) window.show_all() Gtk.main() def setup_method(self, method): self.renderer = gaupol.TimeCellRenderer() gaupol-1.11/gaupol/renderers/time.py000066400000000000000000000056171422217132500175230ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Cell renderer for time data in format ``[-]HH:MM:SS.SSS``.""" import gaupol from gi.repository import Gdk from gi.repository import GObject from gi.repository import Gtk __all__ = ("TimeCellRenderer",) class TimeCellRenderer(Gtk.CellRendererText): """Cell renderer for time data in format ``[-]HH:MM:SS.SSS``.""" __gtype_name__ = "TimeCellRenderer" def __init__(self): """Initialize a :class:`TimeCellRenderer` instance.""" GObject.GObject.__init__(self) self._in_editor_menu = False def do_start_editing(self, event, widget, path, bg_area, cell_area, flags): """Initialize and return a :class:`gaupol.TimeEntry` widget.""" editor = gaupol.TimeEntry() gaupol.style.use_font(editor, "custom") editor.set_has_frame(False) editor.set_alignment(self.props.xalign) editor.set_text(self.props.text) editor.select_region(0, -1) editor.gaupol_path = path editor.connect("focus-out-event", self._on_editor_focus_out_event) editor.connect("key-press-event", self._on_editor_key_press_event) editor.connect("populate-popup", self._on_editor_populate_popup) editor.show() return editor def _on_editor_focus_out_event(self, editor, *args): """End editing.""" if self._in_editor_menu: return editor.remove_widget() self.emit("editing-canceled") def _on_editor_key_press_event(self, editor, event): """End editing if ``Enter`` or ``Escape`` pressed.""" if (event.get_state() & (Gdk.ModifierType.SHIFT_MASK | Gdk.ModifierType.CONTROL_MASK)): return if event.keyval in (Gdk.KEY_Return, Gdk.KEY_KP_Enter): editor.remove_widget() self.emit("edited", editor.gaupol_path, editor.get_text()) return True if event.keyval == Gdk.KEY_Escape: editor.remove_widget() self.emit("editing-canceled") def _on_editor_populate_popup(self, editor, menu): """Disable "focus-out-event" ending editing.""" self._in_editor_menu = True def on_menu_unmap(menu, self): self._in_editor_menu = False menu.connect("unmap", on_menu_unmap, self) gaupol-1.11/gaupol/ruler.py000066400000000000000000000107371422217132500157240ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2006 Osmo Salomaa # # 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 . """Functions to calculate line lengths and to show them in widgets.""" import aeidon import gaupol from gi.repository import Gtk from gi.repository import Pango class _Ruler: """Measurer of line lengths in various units.""" def __init__(self): """Initialize a :class:`_Ruler` instance.""" self._em_length = None self._label = Gtk.Label() self._update_em_length() def get_char_length(self, text, strip=False, floor=False): """Return length of `text` measured in characters.""" text = aeidon.RE_ANY_TAG.sub("", text) if strip else text return len(text.replace("\n", " ")) def get_em_length(self, text, strip=False, floor=False): """Return length of `text` measured in ems.""" text = aeidon.RE_ANY_TAG.sub("", text) if strip else text self._label.set_text(text.replace("\n", " ")) width = self._label.get_preferred_width()[1] length = width / self._em_length return int(length) if floor else length def _update_em_length(self): """Update the length of em based on font rendering.""" text = "abcdefghijklmnopqrstuvwxyz" self._label.set_text(text) self._label.show() width = self._label.get_preferred_width()[1] # About 0.55 em per a-z average character. # https://bugzilla.gnome.org/show_bug.cgi?id=763589 self._em_length = width / (0.55 * len(text)) _ruler = _Ruler() def _on_text_view_draw(text_view, cairoc): """Calculate and show line lengths in text view margin.""" text_buffer = text_view.get_buffer() start, end = text_buffer.get_bounds() text = text_buffer.get_text(start, end, False) if not text: return lengths = get_lengths(text) layout = Pango.Layout(text_view.get_pango_context()) # XXX: Lines overlap if we don't set a spacing!? layout.set_spacing(2 * Pango.SCALE) layout.set_markup("\n".join(str(x) for x in lengths), -1) layout.set_alignment(Pango.Alignment.RIGHT) width = layout.get_pixel_size()[0] text_view.set_border_window_size(Gtk.TextWindowType.RIGHT, width + 6) x, y = text_view.window_to_buffer_coords(Gtk.TextWindowType.RIGHT, 2, 4) x += text_view.get_border_width() with aeidon.util.silent(AttributeError): # Top margin available since GTK 3.18. y += text_view.props.top_margin style = text_view.get_style_context() Gtk.render_layout(style, cairoc, x, y, layout) def connect_text_view(text_view): """Connect `text_view` to show line lengths in its margin.""" context = text_view.get_pango_context() layout = Pango.Layout(context) layout.set_text("8", -1) width = layout.get_pixel_size()[0] text_view.set_border_window_size(Gtk.TextWindowType.RIGHT, width + 6) handler_id = text_view.connect_after("draw", _on_text_view_draw) text_view.gaupol_ruler_handler_id = handler_id return handler_id def disconnect_text_view(text_view): """Disconnect `text_view` from showing line lengths in its margin.""" text_view.set_border_window_size(Gtk.TextWindowType.RIGHT, 0) if not hasattr(text_view, "gaupol_ruler_handler_id"): return handler_id = text_view.gaupol_ruler_handler_id del text_view.gaupol_ruler_handler_id return text_view.disconnect(handler_id) def get_length_function(unit): """Return a function that returns text length in `unit`.""" if unit == gaupol.length_units.CHAR: return _ruler.get_char_length if unit == gaupol.length_units.EM: return _ruler.get_em_length raise ValueError("Invalid length unit: {!r}" .format(unit)) def get_lengths(text): """Return a sequence of floored line lengths without tags.""" fun = get_length_function(gaupol.conf.editor.length_unit) return [fun(line, strip=True, floor=True) for line in text.split("\n")] gaupol-1.11/gaupol/spell.py000066400000000000000000000025331422217132500157050ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2019 Osmo Salomaa # # 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 . """Checking and correcting spelling.""" import aeidon with aeidon.util.silent(Exception): from gi.repository import Gspell __all__ = ("SpellChecker",) class SpellChecker(aeidon.SpellChecker): """Checking the spelling of an individual word.""" def attach(self, text_view): """Attach inline spell-check to `text_view`.""" text_buffer = text_view.get_buffer() gspell_buffer = Gspell.TextBuffer.get_from_gtk_text_buffer(text_buffer) gspell_buffer.set_spell_checker(self.checker) gspell_view = Gspell.TextView.get_from_gtk_text_view(text_view) gspell_view.set_inline_spell_checking(True) return gspell_view gaupol-1.11/gaupol/style.py000066400000000000000000000056141422217132500157310ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2016 Osmo Salomaa # # 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 . """CSS styles and helper functions for styling.""" import aeidon import gaupol import os from gi.repository import Gtk from gi.repository import Pango CSS_FILE = os.path.join(aeidon.DATA_DIR, "ui", "gaupol.css") with open(CSS_FILE, "r") as f: CSS = f.read() def _get_editor_font_css(): """Return CSS for custom editor font.""" font_desc = Pango.FontDescription("monospace") if (gaupol.conf.editor.custom_font and gaupol.conf.editor.use_custom_font): font_desc = Pango.FontDescription(gaupol.conf.editor.custom_font) # They fucking broke theming again with GTK 3.22. unit = "pt" if Gtk.check_version(3, 22, 0) is None else "px" css = """ .gaupol-custom-font {{ font-family: {family},monospace; font-size: {size}{unit}; font-weight: {weight}; }}""".format( family=font_desc.get_family().split(",")[0], size=int(round(font_desc.get_size() / Pango.SCALE)), unit=unit, weight=int(font_desc.get_weight())) css = css.replace("font-size: 0{unit};".format(unit=unit), "") css = css.replace("font-weight: 0;", "") css = "\n".join(filter(lambda x: x.strip(), css.splitlines())) return css def load_css(widget): """Load CSS rules from file and conf for `widget`.""" provider = Gtk.CssProvider() css = "\n".join((CSS, _get_editor_font_css())) provider.load_from_data(bytes(css.encode())) style = widget.get_style_context() priority = Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION style.add_provider_for_screen(widget.get_screen(), provider, priority) def _update_css(*args, **kwargs): """Update CSS rules for the default provider.""" provider = Gtk.CssProvider() provider.load_from_data(bytes(_get_editor_font_css().encode())) def use_font(widget, font): """Use `font` ("custom" or "monospace") for `widget`.""" if not font: return load_css(widget) style = widget.get_style_context() style.add_class({ "custom": "gaupol-custom-font", "monospace": "monospace", }[font]) gaupol.conf.editor.connect("notify::custom_font", _update_css) gaupol.conf.editor.connect("notify::use_custom_font", _update_css) gaupol-1.11/gaupol/test/000077500000000000000000000000001422217132500151705ustar00rootroot00000000000000gaupol-1.11/gaupol/test/__init__.py000066400000000000000000000000001422217132500172670ustar00rootroot00000000000000gaupol-1.11/gaupol/test/test_assistants.py000066400000000000000000000127311422217132500210010ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 aeidon import gaupol from gi.repository import Gtk from unittest.mock import patch from gaupol.assistants import CapitalizationPage from gaupol.assistants import CommonErrorPage from gaupol.assistants import ConfirmationPage from gaupol.assistants import HearingImpairedPage from gaupol.assistants import IntroductionPage from gaupol.assistants import JoinSplitWordsPage from gaupol.assistants import LineBreakOptionsPage from gaupol.assistants import LineBreakPage from gaupol.assistants import ProgressPage OK = lambda *args: Gtk.ResponseType.OK class _TestBuilderPage(gaupol.TestCase): def run_page(self): self.window.connect("delete-event", Gtk.main_quit) Gtk.main() class TestIntroductionPage(_TestBuilderPage): def setup_method(self, method): self.window = Gtk.Window() self.window.set_border_width(12) self.window.set_default_size(800, 500) self.page = IntroductionPage(self.window) self.window.add(self.page) self.window.show_all() class _TestLocalePage(_TestBuilderPage): def test_correct_texts(self): self.page.correct_texts(self.new_project(), None, aeidon.documents.MAIN) class TestCapitalizationPage(_TestLocalePage): def setup_method(self, method): self.window = Gtk.Window() self.window.set_border_width(12) self.window.set_default_size(800, 500) self.page = CapitalizationPage(self.window) self.window.add(self.page) self.window.show_all() class TestCommonErrorPage(_TestLocalePage): def setup_method(self, method): self.window = Gtk.Window() self.window.set_border_width(12) self.window.set_default_size(800, 500) self.page = CommonErrorPage(self.window) self.window.add(self.page) self.window.show_all() class TestHearingImpairedPage(_TestLocalePage): def setup_method(self, method): self.window = Gtk.Window() self.window.set_border_width(12) self.window.set_default_size(800, 500) self.page = HearingImpairedPage(self.window) self.window.add(self.page) self.window.show_all() class TestJoinSplitWordsPage(_TestBuilderPage): def run__show_error_dialog(self): self.page._show_error_dialog("test") def setup_method(self, method): self.window = Gtk.Window() self.window.set_border_width(12) self.window.set_default_size(800, 500) self.project = self.new_project() self.page = JoinSplitWordsPage(self.window) self.window.add(self.page) self.window.show_all() @patch("gaupol.util.flash_dialog", OK) def test_correct_texts(self): language = self.get_spell_check_language("en") gaupol.conf.spell_check.language = language self.page.correct_texts(self.project, None, aeidon.documents.MAIN) class TestLineBreakPage(_TestLocalePage): def setup_method(self, method): self.window = Gtk.Window() self.window.set_border_width(12) self.window.set_default_size(800, 500) self.page = LineBreakPage(self.window) self.window.add(self.page) self.window.show_all() class TestLineBreakOptionsPage(_TestBuilderPage): def setup_method(self, method): self.window = Gtk.Window() self.window.set_border_width(12) self.window.set_default_size(800, 500) self.page = LineBreakOptionsPage(self.window) self.window.add(self.page) self.window.show_all() class TestProgressPage(_TestBuilderPage): def setup_method(self, method): self.window = Gtk.Window() self.window.set_border_width(12) self.window.set_default_size(800, 500) self.page = ProgressPage(self.window) self.page.reset(100) self.window.add(self.page) self.window.show_all() class TestConfirmationPage(_TestBuilderPage): def setup_method(self, method): self.window = Gtk.Window() self.window.set_border_width(12) self.window.set_default_size(800, 500) self.page = ConfirmationPage(self.window) self.window.add(self.page) self.window.show_all() class TestTextAssistant(gaupol.TestCase): def run_assistant(self): self.assistant.show() self.assistant.connect("apply", Gtk.main_quit) self.assistant.connect("cancel", Gtk.main_quit) self.assistant.connect("delete-event", Gtk.main_quit) Gtk.main() def setup_method(self, method): gaupol.conf.text_assistant.pages = ["common-error"] self.application = self.new_application() self.assistant = gaupol.TextAssistant( self.application.window, self.application) self.assistant.show() gaupol-1.11/gaupol/test/test_attrdict.py000066400000000000000000000062531422217132500204250ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2006 Osmo Salomaa # # 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 gaupol class TestAttrDict(gaupol.TestCase): def setup_method(self, method): self.root = dict(test=1, rest=0) self.attr_dict = gaupol.AttributeDictionary(self.root) def test___getattr__(self): assert self.attr_dict.test == 1 assert self.attr_dict.rest == 0 def test___setattr__(self): self.attr_dict.test = 5 assert self.attr_dict.test == 5 assert self.root["test"] == 5 def test_add_attribute(self): self.attr_dict.add_attribute("best", 2) assert self.attr_dict.best == 2 assert self.root["best"] == 2 def test_add_attribute__nested(self): root = dict(test=1, rest=0) self.attr_dict.add_attribute("nest", root) assert self.attr_dict.nest.test == 1 assert self.attr_dict.nest.rest == 0 assert self.root["nest"]["test"] == 1 assert self.root["nest"]["rest"] == 0 def test_extend(self): root = dict(test=3, pest=4) self.attr_dict.extend(root) assert self.attr_dict.test == 1 assert self.attr_dict.rest == 0 assert self.attr_dict.pest == 4 assert self.root["test"] == 1 assert self.root["rest"] == 0 assert self.root["pest"] == 4 def test_extend__nested(self): root = dict(test=1, rest=0) self.attr_dict.add_attribute("nest", root) root = dict(nest=dict(test=3, pest=4)) self.attr_dict.extend(root) assert self.attr_dict.nest.test == 1 assert self.attr_dict.nest.rest == 0 assert self.attr_dict.nest.pest == 4 assert self.root["nest"]["test"] == 1 assert self.root["nest"]["rest"] == 0 assert self.root["nest"]["pest"] == 4 def test_update(self): root = dict(test=3, pest=4) self.attr_dict.update(root) assert self.attr_dict.test == 3 assert self.attr_dict.rest == 0 assert self.attr_dict.pest == 4 assert self.root["test"] == 3 assert self.root["rest"] == 0 assert self.root["pest"] == 4 def test_update__nested(self): root = dict(test=1, rest=0) self.attr_dict.add_attribute("nest", root) root = dict(nest=dict(test=3, pest=4)) self.attr_dict.update(root) assert self.attr_dict.nest.test == 3 assert self.attr_dict.nest.rest == 0 assert self.attr_dict.nest.pest == 4 assert self.root["nest"]["test"] == 3 assert self.root["nest"]["rest"] == 0 assert self.root["nest"]["pest"] == 4 gaupol-1.11/gaupol/test/test_config.py000066400000000000000000000036531422217132500200550ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2010 Osmo Salomaa # # 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 aeidon import gaupol import os import shutil class TestConfigurationStore(gaupol.TestCase): def setup_method(self, method): self.conf = gaupol.ConfigurationStore() self.directory = aeidon.temp.create_directory() self.conf.path = os.path.join(self.directory, "test") def teardown_method(self, method): shutil.rmtree(self.directory) gaupol.TestCase.teardown_method(self, method) def test_read_from_file(self): self.conf.write_to_file() self.conf.restore_defaults() self.conf.read_from_file() def test_register_extension(self): defaults = dict(x=1, mode=aeidon.modes.TIME) enums = dict(mode=aeidon.modes) self.conf.register_extension("test", defaults, enums) assert self.conf.extensions.test.x == 1 assert self.conf.extensions.test.mode == aeidon.modes.TIME def test_restore_defaults(self): size = list(self.conf.application_window.size) self.conf.application_window.size = [99, 99] self.conf.restore_defaults() assert self.conf.application_window.size == size def test_write_to_file(self): self.conf.write_to_file() self.conf.restore_defaults() self.conf.read_from_file() gaupol-1.11/gaupol/test/test_entries.py000066400000000000000000000022361422217132500202550ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class TestTimeEntry(gaupol.TestCase): def run_entry(self): self.entry.set_text("12:34:56.789") window = Gtk.Window() window.connect("delete-event", Gtk.main_quit) window.set_position(Gtk.WindowPosition.CENTER) window.set_default_size(200, 50) window.add(self.entry) window.show_all() Gtk.main() def setup_method(self, method): self.entry = gaupol.TimeEntry() gaupol-1.11/gaupol/test/test_extensionman.py000066400000000000000000000030721422217132500213130ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2008 Osmo Salomaa # # 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 aeidon import gaupol class TestExtensionManager(gaupol.TestCase): def setup_method(self, method): gaupol.conf.path = aeidon.temp.create(".conf") self.manager = gaupol.ExtensionManager(self.new_application()) gaupol.conf.extensions.active = ["custom-framerates", "none"] self.manager.find_extensions() self.manager.setup_extensions() def teardown_method(self, method): self.manager.teardown_extensions() gaupol.TestCase.teardown_method(self, method) def test_setup_extension(self): self.manager.setup_extension("custom-framerates") assert self.manager.is_active("custom-framerates") def test_teardown_extension(self): self.manager.setup_extension("custom-framerates") self.manager.teardown_extension("custom-framerates") assert not self.manager.is_active("custom-framerates") gaupol-1.11/gaupol/test/test_floatlabel.py000066400000000000000000000025621422217132500207130ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2013 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class TestFloatingLabel(gaupol.TestCase): def run(self): self.label.flash_text("Testing floating label") self.window.connect("notify::visible", Gtk.main_quit) Gtk.main() def setup_method(self, method): self.window = Gtk.Window() gaupol.style.load_css(self.window) self.window.set_default_size(800, 480) self.window.connect("delete-event", Gtk.main_quit) self.overlay = Gtk.Overlay() self.overlay.add(Gtk.Label()) self.window.add(self.overlay) self.label = gaupol.FloatingLabel() self.overlay.add_overlay(self.label) self.window.show_all() gaupol-1.11/gaupol/test/test_ruler.py000066400000000000000000000040551422217132500177360ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2006 Osmo Salomaa # # 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 gaupol from gi.repository import Gtk class TestModule(gaupol.TestCase): def test_connect_text_view(self): text_view = Gtk.TextView() gaupol.ruler.connect_text_view(text_view) text_buffer = text_view.get_buffer() text_buffer.insert_at_cursor("test\ntest") def test_disconnect_text_view(self): text_view = Gtk.TextView() gaupol.ruler.connect_text_view(text_view) gaupol.ruler.disconnect_text_view(text_view) text_buffer = text_view.get_buffer() text_buffer.insert_at_cursor("test\ntest") def test_get_length_function__char(self): unit = gaupol.length_units.CHAR function = gaupol.ruler.get_length_function(unit) assert function("iii") == 3 def test_get_length_function__em(self): unit = gaupol.length_units.EM function = gaupol.ruler.get_length_function(unit) assert 0.5 < function("M") < 1.5 def test_get_lengths__char(self): unit = gaupol.length_units.CHAR gaupol.conf.editor.length_unit = unit lengths = gaupol.ruler.get_lengths("MMM\niii") assert tuple(lengths) == (3, 3) def test_get_lengths__em(self): unit = gaupol.length_units.EM gaupol.conf.editor.length_unit = unit lengths = gaupol.ruler.get_lengths("MMM\niii") assert -1 < lengths[1] < 1 < lengths[0] gaupol-1.11/gaupol/test/test_spell.py000066400000000000000000000026361422217132500177270ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2019 Osmo Salomaa # # 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 aeidon import gaupol from gi.repository import Gtk class TestSpellChecker(aeidon.TestCase): def run_checker(self): text_view = Gtk.TextView() text_buffer = text_view.get_buffer() text_buffer.set_text("It's a humanoid weapon-system\ncreated by the URM Technarchy.") self.checker.attach(text_view) window = Gtk.Window() window.connect("delete-event", Gtk.main_quit) window.set_position(Gtk.WindowPosition.CENTER) window.set_default_size(400, 200) window.add(text_view) window.show_all() Gtk.main() def setup_method(self, method): language = self.get_spell_check_language("en") self.checker = gaupol.SpellChecker(language) gaupol-1.11/gaupol/test/test_util.py000066400000000000000000000045441422217132500175650ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 gaupol from gi.repository import Gdk class TestModule(gaupol.TestCase): def test_char_to_px(self): px1 = gaupol.util.char_to_px(1) px2 = gaupol.util.char_to_px(2) assert 2 < px1 < 10 assert 4 < px2 < 20 assert abs(2 * px1 - px2) <= 1 def test_char_to_px__font(self): deft = gaupol.util.char_to_px(100) cust = gaupol.util.char_to_px(100, font="custom") mono = gaupol.util.char_to_px(100, font="monospace") assert 200 < deft < cust assert 200 < deft < mono def test_hex_to_rgba(self): color = gaupol.util.hex_to_rgba("#ff0000") assert color.equal(Gdk.RGBA(red=1, green=0, blue=0, alpha=1)) def test_lines_to_px(self): px1 = gaupol.util.lines_to_px(1) px2 = gaupol.util.lines_to_px(2) assert 10 < px1 < 30 assert 20 < px2 < 60 assert abs(2 * px1 - px2) <= 1 def test_lines_to_px__font(self): deft = gaupol.util.lines_to_px(10) cust = gaupol.util.lines_to_px(10, font="custom") mono = gaupol.util.lines_to_px(10, font="monospace") assert 50 < deft < 200 assert 50 < cust < 200 assert 50 < mono < 200 def test_rgba_to_hex(self): rgba = Gdk.RGBA(red=1, green=0, blue=1) color = gaupol.util.rgba_to_hex(rgba) assert color == "#ff00ff" def test_tree_path_to_row(self): path = gaupol.util.tree_row_to_path(1) assert gaupol.util.tree_path_to_row(path) == 1 assert gaupol.util.tree_path_to_row("1") == 1 def test_tree_row_to_path(self): path = gaupol.util.tree_row_to_path(1) assert gaupol.util.tree_path_to_row(path) == 1 gaupol-1.11/gaupol/test/test_view.py000066400000000000000000000060131422217132500175530ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 aeidon import gaupol import random from gi.repository import Gtk class TestView(gaupol.TestCase): def run_view_frame(self): self.setup_frame() window = Gtk.Window() window.connect("delete-event", Gtk.main_quit) window.set_position(Gtk.WindowPosition.CENTER) window.set_default_size(200, 200) window.add(self.view) window.show_all() Gtk.main() def run_view_time(self): self.setup_time() window = Gtk.Window() window.connect("delete-event", Gtk.main_quit) window.set_position(Gtk.WindowPosition.CENTER) window.set_default_size(200, 200) window.add(self.view) window.show_all() Gtk.main() def setup_frame(self): self.view = gaupol.View(aeidon.modes.FRAME) store = self.view.get_model() self.project = self.new_project() for i, subtitle in enumerate(self.project.subtitles): store.append((i + 1, subtitle.start_frame, subtitle.end_frame, subtitle.duration_frame, subtitle.main_text, subtitle.tran_text)) def setup_method(self, method): random.choice((self.setup_frame, self.setup_time))() self.conf = gaupol.conf.editor def setup_time(self): self.view = gaupol.View(aeidon.modes.TIME) store = self.view.get_model() self.project = self.new_project() for i, subtitle in enumerate(self.project.subtitles): store.append((i + 1, subtitle.start_time, subtitle.end_time, subtitle.duration_seconds, subtitle.main_text, subtitle.tran_text)) def test_select_rows(self): self.view.select_rows(()) assert self.view.get_selected_rows() == () self.view.select_rows((1, 2)) assert self.view.get_selected_rows() == (1, 2) def test_set_focus(self): self.view.set_focus(2, None) assert self.view.get_focus() == (2, None) self.view.set_focus(1, 3) assert self.view.get_focus() == (1, 3) self.view.set_focus(-1, 4) n = len(self.project.subtitles) assert self.view.get_focus() == (n-1, 4) gaupol-1.11/gaupol/unittest.py000066400000000000000000000040361422217132500164450ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Base class for GTK unit test cases.""" import aeidon import gaupol __all__ = ("TestCase",) class TestCase(aeidon.TestCase): """ Base class for GTK unit test cases. Unit tests are designed to be run with ``py.test``, ``nose`` or something compatible. Tests should use plain ``assert`` statements to allow multiple different tools to be used to run the tests. """ def new_application(self): """Return a new application with one open page.""" application = gaupol.Application() application.add_page(self.new_page()) application.window.show() return application def new_page(self): """Return a new page with two open documents.""" page = gaupol.Page() page.project.open_main(self.new_subrip_file(), "ascii") page.project.open_translation(self.new_microdvd_file(), "ascii") return page def teardown_method(self, method): """Remove state set for executing tests in `method`.""" gaupol.util.iterate_main() for name in ("assistant", "dialog", "window"): if hasattr(self, name): getattr(self, name).destroy() if hasattr(self, "application"): self.application.window.hide() self.application.window.destroy() gaupol.util.iterate_main() gaupol.conf.restore_defaults() gaupol-1.11/gaupol/urls.py000066400000000000000000000024101422217132500155450ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2007 Osmo Salomaa # # 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 . """ Website URLs. :var BUG_REPORT_URL: Web page where to submit bug reports :var DOCUMENTATION_URL: Documentation for users :var HOMEPAGE_URL: Gaupol web pages :var REGEX_HELP_URL: Documentation on regular expressions """ __all__ = ( "BUG_REPORT_URL", "DOCUMENTATION_URL", "HOMEPAGE_URL", "REGEX_HELP_URL", ) BUG_REPORT_URL = "https://github.com/otsaloma/gaupol/issues" DOCUMENTATION_URL = "https://github.com/otsaloma/gaupol/tree/master/doc" HOMEPAGE_URL = "https://otsaloma.io/gaupol/" REGEX_HELP_URL = "https://docs.python.org/3/library/re.html#regular-expression-syntax" gaupol-1.11/gaupol/util.py000066400000000000000000000355161422217132500155520ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Miscellaneous functions and decorators.""" import aeidon import gaupol import inspect import sys import traceback import webbrowser from gi.repository import Gdk from gi.repository import GLib from gi.repository import Gtk def char_to_px(nchar, font=None): """Convert characters to pixels.""" if nchar < 0: return nchar label = Gtk.Label(label="etaoin shrdlu") gaupol.style.use_font(label, font) label.show() width = label.get_preferred_width()[1] return int(round(nchar * width/len(label.props.label))) def delay_add(delay, function, *args, **kwargs): """Call `function` with `args` and `kwargs` once after `delay` (ms).""" def call_function(*args, **kwargs): function(*args, **kwargs) return False # to not be called again. return GLib.timeout_add(delay, call_function, *args, **kwargs) def document_to_text_field(doc): """Return :attr:`gaupol.fields` item corresponding to `doc`.""" if doc == aeidon.documents.MAIN: return gaupol.fields.MAIN_TEXT if doc == aeidon.documents.TRAN: return gaupol.fields.TRAN_TEXT raise ValueError("Invalid document: {!r}" .format(doc)) def flash_dialog(dialog): """Run `dialog`, destroy it and return response.""" response = dialog.run() dialog.destroy() return response def get_content_size(widget, font=None): """Return the width and height desired by `widget`.""" if isinstance(widget, Gtk.TextView): return get_text_view_size(widget, font) if isinstance(widget, Gtk.TreeView): return get_tree_view_size(widget, font) raise ValueError("Unsupported container type: {!r}" .format(type(widget))) def get_default_player(): """Return the default video player to use for preview.""" players = [aeidon.players.MPV, aeidon.players.MPLAYER, aeidon.players.VLC] players = [x for x in players if x.found] return players[0] if players else aeidon.players.MPV def get_font(): """Return custom font or blank string.""" return (gaupol.conf.editor.custom_font if gaupol.conf.editor.use_custom_font and gaupol.conf.editor.custom_font else "") def get_gspell_version(): """Return :mod:`Gspell` version number as string or ``None``.""" try: # XXX: The full version number is not available. # https://gitlab.gnome.org/GNOME/gspell/issues/8 from gi.repository import Gspell return str(Gspell._version) except Exception: return None def get_gst_version(): """Return :mod:`Gst` version number as string or ``None``.""" try: from gi.repository import Gst return ".".join(map(str, Gst.version())) except Exception: return None def get_icon_image(name, fallback, size): """Return icon image from `name` or `fallback` in theme.""" theme = Gtk.IconTheme.get_default() if theme.has_icon(name): return Gtk.Image(icon_name=name, icon_size=size) return Gtk.Image(icon_name=fallback, icon_size=size) def get_preview_command(): """Return command to use for lauching video player.""" if gaupol.conf.preview.use_custom_command: return gaupol.conf.preview.custom_command if gaupol.conf.preview.force_utf_8: return gaupol.conf.preview.player.command_utf_8 return gaupol.conf.preview.player.command def get_text_view_size(text_view, font=None): """Return the width and height desired by `text_view`.""" text_buffer = text_view.get_buffer() start, end = text_buffer.get_bounds() text = text_buffer.get_text(start, end, False) label = Gtk.Label(label=text) gaupol.style.use_font(label, font) label.show() return (label.get_preferred_width()[1] + text_view.get_left_margin() + text_view.get_right_margin(), label.get_preferred_height()[1]) def get_tree_view_size(tree_view, font=None): """Return the width and height desired by `tree_view`.""" scroller = tree_view.get_parent() policy = scroller.get_policy() scroller.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER) width = scroller.get_preferred_width()[1] height = scroller.get_preferred_height()[1] scroller.set_policy(*policy) return width, height @aeidon.deco.once def get_zebra_color(tree_view): """Return background color to use for tree view zebra-stripes.""" # XXX: Zebra stripes would be faster and cleaner done with CSS # selectors :nth-child(odd) and :nth-child(even), but they don't # seem to work, might even be deliberately broken. # https://bugzilla.gnome.org/show_bug.cgi?id=709617#c1 style = tree_view.get_style_context() fg = style.get_color(Gtk.StateFlags.NORMAL) bg = style.get_background_color(Gtk.StateFlags.NORMAL) color = Gdk.RGBA() color.red = 0.92 * bg.red + 0.08 * fg.red color.green = 0.92 * bg.green + 0.08 * fg.green color.blue = 0.92 * bg.blue + 0.08 * fg.blue return(color) @aeidon.deco.once def gst_available(): """Return ``True`` if :mod:`Gst` and needed plugins are available.""" try: from gi.repository import Gst except Exception: return False if not Gst.ElementFactory.find("playbin"): print("GStreamer found, but playbin missing.", "Try installing gst-plugins-base.", file=sys.stderr) return False if not Gst.ElementFactory.find("textoverlay"): print("GStreamer found, but textoverlay missing.", "Try installing gst-plugins-base.", file=sys.stderr) return False if not Gst.ElementFactory.find("timeoverlay"): print("GStreamer found, but timeoverlay missing.", "Try installing gst-plugins-base.", file=sys.stderr) return False if not Gst.ElementFactory.find("gtksink"): print("GStreamer found, but gtksink missing.", "Try installing gst-plugins-good.", file=sys.stderr) return False if Gst.ElementFactory.find("vaapisink"): print("GStreamer-vaapi found, known to sometimes cause trouble.", "If video doesn't play, please try uninstalling it.", "See https://github.com/otsaloma/gaupol/issues/79", file=sys.stderr) return True def hex_to_rgba(string): """Return a :class:`Gdk.RGBA` for hexadecimal `string`.""" rgba = Gdk.RGBA() success = rgba.parse(string) if not success: raise ValueError("Parsing string {!r} failed".format(string)) return rgba def idle_add(function, *args, **kwargs): """Call `function` with `args` and `kwargs` when idle.""" def call_function(*args, **kwargs): function(*args, **kwargs) return False # to not be called again. return GLib.idle_add(call_function, *args, **kwargs) def install_module(name, obj): """ Install `obj`'s module into the :mod:`gaupol` namespace. Typical call is of form:: gaupol.util.install_module("foo", lambda: None) """ gaupol.__dict__[name] = inspect.getmodule(obj) def iterate_main(): """Iterate the GTK main loop while events are pending.""" while Gtk.events_pending(): Gtk.main_iteration() def lines_to_px(nlines, font=None): """Convert lines to pixels.""" if nlines < 0: return nlines text = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" label = Gtk.Label(label=text) gaupol.style.use_font(label, font) label.show() height = label.get_preferred_height()[1] return int(round(nlines * height)) def new_hbox(spacing): """Return a new horizontal :class:`Gtk.Box`.""" return Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=spacing) def new_vbox(spacing): """Return a new vertical :class:`Gtk.Box`.""" return Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=spacing) def pack_start(box, widget, padding=0): """Pack widget to box without fill or expand.""" box.pack_start(widget, expand=False, fill=False, padding=padding) def pack_start_expand(box, widget, padding=0): """Pack widget to box with fill and expand.""" box.pack_start(widget, expand=True, fill=True, padding=padding) def pack_start_fill(box, widget, padding=0): """Pack widget to box with fill, but no expand.""" box.pack_start(widget, expand=False, fill=True, padding=padding) def prepare_text_view(text_view): """Set spell-check, line-length margin and font properties.""" if (gaupol.SpellChecker.available() and gaupol.conf.spell_check.inline): language = gaupol.conf.spell_check.language with aeidon.util.silent(Exception): checker = gaupol.SpellChecker(language) checker.attach(text_view) connect = gaupol.conf.editor.connect def update_margin(section, value, text_view): if gaupol.conf.editor.show_lengths_edit: return gaupol.ruler.connect_text_view(text_view) return gaupol.ruler.disconnect_text_view(text_view) connect("notify::show_lengths_edit", update_margin, text_view) update_margin(None, None, text_view) def update_font(section, value, text_view): text_view.reset_style() gaupol.style.use_font(text_view, "custom") connect("notify::use_custom_font", update_font, text_view) connect("notify::custom_font", update_font, text_view) update_font(None, None, text_view) def update_spacing(section, value, text_view): if gaupol.conf.editor.show_lengths_cell: return text_view.set_pixels_above_lines(2) return text_view.set_pixels_above_lines(0) connect("notify::show_lengths_cell", update_spacing, text_view) update_spacing(None, None, text_view) def raise_default(expression): """Raise :exc:`gaupol.Default` if `expression` evaluates to ``True``.""" if expression: raise gaupol.Default def rgba_to_hex(color): """Return hexadecimal string for :class:`Gdk.RGBA` `color`.""" return "#{:02x}{:02x}{:02x}".format( int(color.red * 255), int(color.green * 255), int(color.blue * 255), ) def run_dialog(dialog): """Run `dialog` and return response.""" return dialog.run() def scale_to_content(widget, min_nchar=0, max_nchar=32768, min_nlines=0, max_nlines=32768, font=None): """Set `widget's` size by content, but limited by `min` and `max`.""" width, height = get_content_size(widget, font) width = max(width, char_to_px(min_nchar, font)) width = min(width, char_to_px(max_nchar, font)) height = max(height, lines_to_px(min_nlines, font)) height = min(height, lines_to_px(max_nlines, font)) parent = widget.get_parent() if isinstance(parent, Gtk.ScrolledWindow): # Vaguely account for possible scrollbars. return parent.set_size_request(width + 24, height + 24) widget.set_size_request(width, height) def scale_to_size(widget, nchar, nlines, font=None): """Set `widget`'s size to `nchar` and `nlines`.""" width = char_to_px(nchar, font) height = lines_to_px(nlines, font) parent = widget.get_parent() if isinstance(parent, Gtk.ScrolledWindow): # Vaguely account for possible scrollbars. return parent.set_size_request(width + 24, height + 24) widget.set_size_request(width, height) def separate_combo(store, itr, data=None): """Separator function for combo box models.""" return store.get_value(itr, 0) == gaupol.COMBO_SEPARATOR def set_cursor_busy(window): """Set mouse pointer busy when above window.""" cursor = window.get_window().get_cursor() if (cursor is not None and cursor.get_cursor_type() == Gdk.CursorType.WATCH): return cursor = Gdk.Cursor.new_for_display( Gdk.Display.get_default(), Gdk.CursorType.WATCH) window.get_window().set_cursor(cursor) iterate_main() def set_cursor_normal(window): """Set mouse pointer normal when above window.""" cursor = window.get_window().get_cursor() if (cursor is not None and cursor.get_cursor_type() == Gdk.CursorType.LEFT_PTR): return cursor = Gdk.Cursor.new_for_display( Gdk.Display.get_default(), Gdk.CursorType.LEFT_PTR) window.get_window().set_cursor(cursor) iterate_main() def show_exception(exctype, value, tb): """A :class:`gaupol.DebugDialog` :attr`sys.excepthook`.""" traceback.print_exception(exctype, value, tb) if not isinstance(value, Exception): return try: # to avoid recursion. dialog = gaupol.DebugDialog() dialog.set_text(exctype, value, tb) response = dialog.run() dialog.destroy() if response == Gtk.ResponseType.NO: raise SystemExit(1) except Exception: traceback.print_exc() def show_uri(uri): """Open `uri` in default application.""" try: return Gtk.show_uri(None, uri, Gdk.CURRENT_TIME) except Exception: # Gtk.show_uri fails on Windows and some misconfigured installations. # GError: No application is registered as handling this file # Gtk.show_uri: Operation not supported if uri.startswith(("http://", "https://")): return webbrowser.open(uri) raise # Exception def text_field_to_document(field): """Return :attr:`aeidon.documents` item corresponding to `field`.""" if field == gaupol.fields.MAIN_TEXT: return aeidon.documents.MAIN if field == gaupol.fields.TRAN_TEXT: return aeidon.documents.TRAN raise ValueError("Invalid field: {!r}" .format(field)) def tree_path_to_row(path): """ Convert `path` to a list row integer. `path` can be either a :class:`Gtk.Treepath` instance or a string representation of it (as commonly used by various callbacks). """ if path is None: return None if isinstance(path, Gtk.TreePath): return path.get_indices()[0] if isinstance(path, str): return int(path) raise TypeError("Bad type {!r} for path {!r}" .format(type(path), path)) def tree_row_to_path(row): """Convert list row integer to a :class:`Gtk.TreePath`.""" if row is None: return None return Gtk.TreePath.new_from_string(str(row)) gaupol-1.11/gaupol/view.py000066400000000000000000000376331422217132500155510ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2005 Osmo Salomaa # # 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 . """Widget to display subtitle data in the form of a list.""" import aeidon import gaupol import re from gi.repository import Gdk from gi.repository import GLib from gi.repository import GObject from gi.repository import Gtk __all__ = ("View",) class View(Gtk.TreeView): """ Widget to display subtitle data in the form of a list. :ivar columns: Enumeration for columns currently shown The values of the enumeration items correspond to the column indices and are updated when columns are added, removed or reordered. Note that these indices are not necessarily the same as the column indices in the underlying :class:`Gtk.ListStore` data model. """ def __init__(self, edit_mode): """Initialize a :class:`View` instance.""" GObject.GObject.__init__(self) self._active_col_name = "" self._calc = aeidon.Calculator() self.columns = aeidon.Enumeration() self._selection_changed_handlers = {} self._init_signal_handlers() self._init_props(edit_mode) def connect_selection_changed(self, callback): """ Connect to the "changed" signal of selection. Using this instead of the tree selection's own ``connect`` method allows signal handlers to be blocked while in the process of selecting multiple rows, which should be significantly faster if actually doing something in the signal handler. Return signal handler ID. """ selection = self.get_selection() handler_id = selection.connect("changed", callback) self._selection_changed_handlers[handler_id] = callback return handler_id def disconnect_selection_changed(self, callback): """Disconnect from the "changed" signal of selection.""" selection = self.get_selection() for handler_id in list(self._selection_changed_handlers): if self._selection_changed_handlers[handler_id] is callback: selection.handler_disconnect(handler_id) self._selection_changed_handlers.pop(handler_id) def get_focus(self): """Return the row and column of the current focus.""" path, col = self.get_cursor() row = gaupol.util.tree_path_to_row(path) if col is not None: col = self.get_columns().index(col) return row, col def get_header_label(self, field=None, title=None): """Return a column header label from `text`.""" title = title or field.label label = Gtk.Label(label=title) # Avoid column resizing by "preallocating" # sufficient width for usual expected data. if field == gaupol.fields.NUMBER: size_label = Gtk.Label(label="8888") size_label.show() width = size_label.get_preferred_width()[1] label.set_size_request(width, -1) if field == gaupol.fields.DURATION: size_label = Gtk.Label(label="88.888") size_label.show() width = size_label.get_preferred_width()[1] label.set_size_request(width, -1) label.set_halign(Gtk.Align.START) label.show() return label def _get_renderer(self, field, edit_mode): """Initialize and return a new cell renderer for `field`.""" font = gaupol.util.get_font() if field == gaupol.fields.NUMBER: renderer = gaupol.IntegerCellRenderer() renderer.props.editable = False renderer.props.xalign = 1 elif field.is_position: if edit_mode == aeidon.modes.TIME: if field == gaupol.fields.DURATION: renderer = gaupol.FloatCellRenderer() else: renderer = gaupol.TimeCellRenderer() elif edit_mode == aeidon.modes.FRAME: renderer = gaupol.IntegerCellRenderer() renderer.props.editable = True renderer.props.xalign = 1 elif field.is_text: renderer = gaupol.MultilineCellRenderer() renderer.props.editable = True renderer.props.xalign = 0 renderer.props.font = font renderer.props.yalign = 0 renderer.props.xpad = 4 renderer.props.ypad = 4 return renderer def get_selected_rows(self): """Return a sequence of selected rows.""" paths = self.get_selection().get_selected_rows()[1] return tuple(gaupol.util.tree_path_to_row(x) for x in paths) def _init_cell_data_functions(self): """Initialize functions to automatically update cell data.""" # Set the data in the number column automatically. def set_number(column, renderer, store, itr, data): path = store.get_path(itr) row = gaupol.util.tree_path_to_row(path) renderer.props.text = str(row + 1) column = self.get_column(self.columns.NUMBER) renderer = column.get_cells()[0] column.set_cell_data_func(renderer, set_number, None) if gaupol.conf.editor.use_zebra_stripes: column = self.get_column(self.columns.MAIN_TEXT) renderer = column.get_cells()[0] callback = self._on_renderer_set_background column.set_cell_data_func(renderer, callback, None) def _init_columns(self, edit_mode): """Initialize the tree view columns.""" visible_fields = gaupol.conf.editor.visible_fields for field in gaupol.conf.editor.field_order: renderer = self._get_renderer(field, edit_mode) column = Gtk.TreeViewColumn(field.label, renderer, text=field) column.gaupol_id = field.name.lower() self.append_column(column) column.set_clickable(True) column.set_resizable(True) column.set_reorderable(True) column.set_expand(field.is_text) column.set_visible(field in visible_fields) label = self.get_header_label(field) label.set_tooltip_text(field.tooltip) column.set_widget(label) def _init_props(self, edit_mode): """Initialize properties.""" if edit_mode == aeidon.modes.TIME: columns = (int, str, str, float, str, str) if edit_mode == aeidon.modes.FRAME: columns = (int, int, int, int, str, str) store = Gtk.ListStore(*columns) self.set_model(store) self._init_columns(edit_mode) self._init_cell_data_functions() self.set_name("gaupol-view") self.set_headers_visible(True) self.set_rubber_banding(True) selection = self.get_selection() selection.set_mode(Gtk.SelectionMode.MULTIPLE) self._init_search() def _init_search(self): """Initialize the interactive search properties.""" self.set_enable_search(True) self.set_search_column(self.columns.NUMBER) self.set_search_equal_func(self._search_equals, None) def _init_signal_handlers(self): """Initialize signal handlers.""" aeidon.util.connect(self, self, "columns-changed") aeidon.util.connect(self, self, "cursor-changed") aeidon.util.connect(self, self, "key-press-event") gaupol.conf.connect_notify("editor", "custom_font", self) gaupol.conf.connect_notify("editor", "length_unit", self) gaupol.conf.connect_notify("editor", "show_lengths_cell", self) gaupol.conf.connect_notify("editor", "use_custom_font", self) def is_position_column(self, col): """Return ``True`` if `col` is a position column.""" return col in (self.columns.START, self.columns.END, self.columns.DURATION) def is_text_column(self, col): """Return True if `col` is a text column.""" return col in (self.columns.MAIN_TEXT, self.columns.TRAN_TEXT) def _on_conf_editor_notify_custom_font(self, *args): """Apply the new font to all columns.""" font = gaupol.util.get_font() for column in self.get_columns(): renderer = column.get_cells()[0] if hasattr(renderer.props, "font"): renderer.props.font = font self.columns_autosize() def _on_conf_editor_notify_length_unit(self, *args): """Repaint the cells to update line length display.""" if gaupol.conf.editor.show_lengths_cell: self.columns_autosize() def _on_conf_editor_notify_show_lengths_cell(self, *args): """Repaint the cells to update line length display.""" self.columns_autosize() def _on_conf_editor_notify_use_custom_font(self, *args): """Apply the new font to all columns.""" font = gaupol.util.get_font() for column in self.get_columns(): renderer = column.get_cells()[0] if hasattr(renderer.props, "font"): renderer.props.font = font self.columns_autosize() def _on_columns_changed(self, *args): """Reset the columns enumeration to match new column layout.""" count_changed = (len(self.columns) != len(self.get_columns())) self._reset_columns() field_order = [] for column in self.get_columns(): attribute = column.gaupol_id.upper() item = aeidon.EnumerationItem() setattr(self.columns, attribute, item) if hasattr(gaupol.fields, attribute): field = getattr(gaupol.fields, attribute) field_order.append(field) if not count_changed: gaupol.conf.editor.field_order = field_order def _on_cursor_changed(self, *args): """Update the column header labels to reflect changed focus.""" self.update_headers() def _on_key_press_event(self, widget, event): """Handle various special-case key combinations.""" # Disable Ctrl+PageUp/PageDown to allow them to be # used solely for navigation between notebook tabs. if event.get_state() & Gdk.ModifierType.CONTROL_MASK: if event.keyval in (Gdk.KEY_Page_Up, Gdk.KEY_Page_Down): return widget.stop_emission("key-press-event") # Use interactive search for a subtitle number or time # only if valid string keys have been pressed. self.set_enable_search(event.string.isdigit() or event.string == ":" or event.string == ".") def _on_renderer_set_background(self, column, renderer, store, itr, data): """Set zerba-striped backgrounds for all columns.""" path = self.get_model().get_path(itr) row = gaupol.util.tree_path_to_row(path) color = (gaupol.util.get_zebra_color(self) if row % 2 == 0 else None) for column in self.get_columns(): for renderer in column.get_cells(): renderer.props.cell_background_rgba = color def _reset_columns(self): """Recreate the columns enumeration and set all items to ``None``.""" self.columns = aeidon.Enumeration() self.columns.NUMBER = None self.columns.START = None self.columns.END = None self.columns.DURATION = None self.columns.MAIN_TEXT = None self.columns.TRAN_TEXT = None def scroll_to_row(self, row): """Scroll view until `row` is visible.""" self.scroll_to_cell(path=row, column=None, use_align=False, row_align=0.5, col_align=0) def _search_equals(self, store, column, key, itr, data): """Return ``False`` if `key` matches either subtitle number or time.""" path = store.get_path(itr) row = gaupol.util.tree_path_to_row(path) if key.count(":") == 0: # Search for subtitle number. try: return row != (int(key) - 1) except ValueError: return False col = gaupol.conf.editor.field_order.index(gaupol.fields.START) hours = minutes = seconds = 0 if key.count(":") == 1 and key.startswith(":"): # Search for time of form ':MM' match = re.search(r"^:(\d{1,2})$", key) if match is None: return False minutes = int(match.group(1)) if key.count(":") == 1 and not key.startswith(":"): # Search for time of form 'MM:[SS.SSS]' match = re.search(r"^(\d{1,2}):([\d.]+)?$", key) if match is None: return False minutes = int(match.group(1)) try: seconds = float(match.group(2) or "00.000") except ValueError: return False if key.count(":") == 2: # Search for time of form '[HH]:MM:[SS.SSS]' match = re.search(r"^(\d{,2}):(\d{1,2}):([\d.]+)?$", key) if match is None: return False hours = int(match.group(1) or "00") minutes = int(match.group(2)) try: seconds = float(match.group(3) or "00.000") except ValueError: return False time_key = "{:02d}:{:02d}:{:06.3f}".format(hours, minutes, seconds) if not self._calc.is_valid_time(time_key): return False time_iter = store[row][col] if not ":" in time_iter: return False try: time_next = store[row+1][col] except IndexError: time_next = "99:59:59.999" return not (self._calc.time_to_seconds(time_iter) <= self._calc.time_to_seconds(time_key) < self._calc.time_to_seconds(time_next)) def select_rows(self, rows): """Select `rows`, clearing previous selection.""" # Avoid sending more than one 'changed' signal. selection = self.get_selection() for handler_id in self._selection_changed_handlers: selection.handler_block(handler_id) selection.unselect_all() for lst in aeidon.util.get_ranges(rows): start = gaupol.util.tree_row_to_path(lst[0]) end = gaupol.util.tree_row_to_path(lst[-1]) selection.select_range(start, end) for handler_id in self._selection_changed_handlers: selection.handler_unblock(handler_id) selection.emit("changed") def set_focus(self, row, col=None): """Set the focus to `row` (-1 for last), `col`.""" if row == -1: row = len(self.get_model()) - 1 if col is not None: col = self.get_column(col) path = gaupol.util.tree_row_to_path(row) self.set_cursor(path, col, start_editing=False) if col is not None: self.update_headers() def update_headers(self): """Update the attributes of all column header labels.""" fcol = self.get_focus()[1] acol = getattr(self.columns, self._active_col_name, None) if fcol == acol: return self._active_col_name = "" if acol is not None: label = self.get_column(acol).get_widget() text = GLib.markup_escape_text(label.get_text()) label.set_markup("{}".format(text)) if fcol is not None: label = self.get_column(fcol).get_widget() text = GLib.markup_escape_text(label.get_text()) label.set_markup("{}".format(text)) self._active_col_name = self.columns[fcol].name gaupol-1.11/manifests/000077500000000000000000000000001422217132500147135ustar00rootroot00000000000000gaupol-1.11/manifests/aeidon.manifest000066400000000000000000000001171422217132500177010ustar00rootroot00000000000000[share/gaupol/headers] data/headers/* [share/gaupol/patterns] data/patterns/* gaupol-1.11/manifests/clean.manifest000066400000000000000000000007571422217132500175360ustar00rootroot00000000000000__pycache__ */__pycache__ */*/__pycache__ */*/*/__pycache__ */*/*/*/__pycache__ .pytest_cache */.pytest_cache */*/.pytest_cache */*/*/.pytest_cache */*/*/*/.pytest_cache *.egg-info build data/extensions/*/*.extension data/io.otsaloma.gaupol.appdata.xml data/io.otsaloma.gaupol.desktop data/patterns/*.capitalization data/patterns/*.common-error data/patterns/*.hearing-impaired data/patterns/*.line-break dist flatpak/.flatpak-builder flatpak/build locale po/*~ po/LINGUAS MANIFEST winsetup.log gaupol-1.11/manifests/gaupol.manifest000066400000000000000000000005051422217132500177320ustar00rootroot00000000000000[share/gaupol/extensions/custom-framerates] data/extensions/custom-framerates/*.* [share/icons/hicolor/scalable/apps] data/icons/io.otsaloma.gaupol.svg [share/icons/hicolor/symbolic/apps] data/icons/io.otsaloma.gaupol-symbolic.svg [share/gaupol/ui] data/ui/*.* [share/gaupol/ui/text-assistant] data/ui/text-assistant/*.* gaupol-1.11/manifests/iso-codes.manifest000066400000000000000000000000571422217132500203320ustar00rootroot00000000000000[share/gaupol/iso-codes] data/iso-codes/*.json gaupol-1.11/po/000077500000000000000000000000001422217132500133405ustar00rootroot00000000000000gaupol-1.11/po/README.md000066400000000000000000000011271422217132500146200ustar00rootroot00000000000000Translating Gaupol ================== Translations are available at [Transifex][]. Please use that to add and update translations. To try your translation, get the source code from GitHub, add your translation file from Transifex, compile your translation and run. ```bash git clone https://github.com/otsaloma/gaupol.git cd gaupol # Download your translation as po/xx.po. # https://www.transifex.com/otsaloma/gaupol/language/xx/ mkdir -p locale/xx/LC_MESSAGES msgfmt -cv po/xx.po -o locale/xx/LC_MESSAGES/gaupol.mo LANG=xx bin/gaupol ``` [Transifex]: https://www.transifex.com/otsaloma/gaupol/ gaupol-1.11/po/cs.po000066400000000000000000002243461422217132500143200ustar00rootroot00000000000000# 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. # # Translators: # Osmo Salomaa , 2016 # fri, 2020 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-04-03 04:00+0300\n" "PO-Revision-Date: 2016-07-07 00:55+0000\n" "Last-Translator: fri, 2020\n" "Language-Team: Czech (https://www.transifex.com/otsaloma/teams/64879/cs/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: cs\n" "Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n" #: aeidon/enums.py:40 gaupol/enums.py:38 msgid "Subtitle number" msgstr "Číslo titulku" #: aeidon/enums.py:43 msgid "Subtitle position" msgstr "Poloha titulku" #: aeidon/enums.py:59 msgid "23.976 fps" msgstr "23.976 fps" #: aeidon/enums.py:63 msgid "24.000 fps" msgstr "24.000 fps" #: aeidon/enums.py:67 msgid "25.000 fps" msgstr "25.000 fps" #: aeidon/enums.py:71 msgid "29.970 fps" msgstr "29.970 fps" #: aeidon/enums.py:75 data/ui/menubar.ui:248 msgid "30.000 fps" msgstr "" #: aeidon/enums.py:79 data/ui/menubar.ui:253 msgid "50.000 fps" msgstr "" #: aeidon/enums.py:83 data/ui/menubar.ui:258 msgid "59.940 fps" msgstr "" #: aeidon/enums.py:87 data/ui/menubar.ui:263 msgid "60.000 fps" msgstr "" #: aeidon/enums.py:112 msgid "Mac (classic)" msgstr "Mac (klasický)" #. TRANSLATORS: Most of the character encoding descriptions are copied from #. gedit, which is translated to very many languages. Check the gedit .po #. files for a reference: #. . #: aeidon/encodings.py:40 aeidon/encodings.py:43 aeidon/encodings.py:46 msgid "English" msgstr "Angličtina" #: aeidon/encodings.py:41 aeidon/encodings.py:42 aeidon/encodings.py:69 msgid "Chinese traditional" msgstr "Tradiční čínština" #: aeidon/encodings.py:44 msgid "German" msgstr "Němčina" #: aeidon/encodings.py:45 aeidon/encodings.py:54 aeidon/encodings.py:59 #: aeidon/encodings.py:79 aeidon/encodings.py:105 msgid "Hebrew" msgstr "Hebrejština" #: aeidon/encodings.py:47 aeidon/encodings.py:51 aeidon/encodings.py:56 #: aeidon/encodings.py:73 aeidon/encodings.py:76 aeidon/encodings.py:98 #: aeidon/encodings.py:111 aeidon/encodings.py:122 msgid "Western" msgstr "Západní" #: aeidon/encodings.py:48 aeidon/encodings.py:61 aeidon/encodings.py:80 #: aeidon/encodings.py:103 msgid "Arabic" msgstr "Arabština" #: aeidon/encodings.py:49 aeidon/encodings.py:64 aeidon/encodings.py:66 #: aeidon/encodings.py:77 aeidon/encodings.py:104 aeidon/encodings.py:119 msgid "Greek" msgstr "Řečtina" #: aeidon/encodings.py:50 aeidon/encodings.py:81 aeidon/encodings.py:101 #: aeidon/encodings.py:109 msgid "Baltic" msgstr "Baltské jazyky" #: aeidon/encodings.py:52 aeidon/encodings.py:74 aeidon/encodings.py:99 #: aeidon/encodings.py:121 msgid "Central European" msgstr "Středoevropské jazyky" #: aeidon/encodings.py:53 aeidon/encodings.py:75 aeidon/encodings.py:102 #: aeidon/encodings.py:118 msgid "Cyrillic" msgstr "Cyrilika" #: aeidon/encodings.py:55 aeidon/encodings.py:71 aeidon/encodings.py:78 #: aeidon/encodings.py:106 aeidon/encodings.py:123 msgid "Turkish" msgstr "Turečtina" #: aeidon/encodings.py:57 msgid "Portuguese" msgstr "Portugalština" #: aeidon/encodings.py:58 aeidon/encodings.py:120 msgid "Icelandic" msgstr "Islandština" #: aeidon/encodings.py:60 msgid "Canadian" msgstr "Kanadské" #: aeidon/encodings.py:62 aeidon/encodings.py:107 msgid "Nordic" msgstr "Skandinávské jazyky" #: aeidon/encodings.py:63 aeidon/encodings.py:114 msgid "Russian" msgstr "Ruština" #: aeidon/encodings.py:65 aeidon/encodings.py:108 msgid "Thai" msgstr "Thajština" #: aeidon/encodings.py:67 aeidon/encodings.py:83 aeidon/encodings.py:84 #: aeidon/encodings.py:85 aeidon/encodings.py:91 aeidon/encodings.py:92 #: aeidon/encodings.py:93 aeidon/encodings.py:94 aeidon/encodings.py:95 #: aeidon/encodings.py:96 aeidon/encodings.py:125 aeidon/encodings.py:126 #: aeidon/encodings.py:127 msgid "Japanese" msgstr "Japonština" #: aeidon/encodings.py:68 aeidon/encodings.py:86 aeidon/encodings.py:97 #: aeidon/encodings.py:113 msgid "Korean" msgstr "Korejština" #: aeidon/encodings.py:70 msgid "Urdu" msgstr "Urdština" #: aeidon/encodings.py:72 aeidon/encodings.py:116 msgid "Ukrainian" msgstr "Ukrajinština" #: aeidon/encodings.py:82 msgid "Vietnamese" msgstr "Vietnamština" #: aeidon/encodings.py:87 aeidon/encodings.py:90 msgid "Chinese simplified" msgstr "Zjednodušená čínština" #: aeidon/encodings.py:88 aeidon/encodings.py:89 msgid "Chinese unified" msgstr "Sjednocená čínština" #: aeidon/encodings.py:100 aeidon/encodings.py:112 msgid "South European" msgstr "Jihoevropské jazyky" #: aeidon/encodings.py:110 msgid "Celtic" msgstr "Keltština" #: aeidon/encodings.py:115 msgid "Tajik" msgstr "Tádžičtina" #: aeidon/encodings.py:117 msgid "Kazakh" msgstr "Kazaština" #: aeidon/encodings.py:124 msgid "Cyrillic Asian" msgstr "Asijská cyrilice" #: aeidon/encodings.py:128 aeidon/encodings.py:129 aeidon/encodings.py:130 #: aeidon/encodings.py:131 aeidon/encodings.py:132 aeidon/encodings.py:133 #: aeidon/encodings.py:134 aeidon/encodings.py:135 aeidon/encodings.py:136 msgid "Unicode" msgstr "Unicode" #: aeidon/encodings.py:156 #, python-brace-format msgid "{description} ({name})" msgstr "{description} ({name})" #: aeidon/encodings.py:232 msgid "Current locale ({})" msgstr "Nynější kódování ({})" #: aeidon/locales.py:46 #, python-brace-format msgid "{language} ({country})" msgstr "{language} ({country})" #: aeidon/agents/search.py:227 msgid "Replacing" msgstr "Nahradit" #: aeidon/agents/search.py:256 aeidon/agents/search.py:258 msgid "Replacing all" msgstr "Nahradit vše" #: aeidon/agents/position.py:74 msgid "Adjusting durations" msgstr "Upravit doby trvání" #: aeidon/agents/position.py:96 msgid "Converting framerate" msgstr "Převést rychlost opakování obrázků" #: aeidon/agents/position.py:146 msgid "Setting framerate" msgstr "Nastavení rychlosti opakování obrázků" #: aeidon/agents/position.py:168 msgid "Shifting positions" msgstr "Posunout polohy" #: aeidon/agents/position.py:188 msgid "Transforming positions" msgstr "Předělat polohy" #: aeidon/agents/clipboard.py:44 msgid "Cutting texts" msgstr "Vyjmout texty" #: aeidon/agents/clipboard.py:61 msgid "Pasting texts" msgstr "Vložit texty" #: aeidon/agents/text.py:91 msgid "Breaking lines" msgstr "Zalomit řádky" #: aeidon/agents/text.py:128 msgid "Capitalizing texts" msgstr "Psát texty velkým písmem" #: aeidon/agents/text.py:185 msgid "Correcting common errors" msgstr "Opravit běžné chyby" #: aeidon/agents/text.py:234 msgid "Removing hearing impaired texts" msgstr "Odstranit texty pro sluchově postižené" #: aeidon/agents/text.py:315 msgid "Joining words by spell-check suggestions" msgstr "Spojit slova podle návrhů správného psaní" #: aeidon/agents/text.py:354 msgid "Splitting words by spell-check suggestions" msgstr "Rozdělit slova podle návrhů správného psaní" #: aeidon/agents/set.py:58 aeidon/agents/set.py:80 aeidon/agents/set.py:113 msgid "Editing position" msgstr "Upravit polohu" #: aeidon/agents/set.py:129 msgid "Editing text" msgstr "Upravit text" #: aeidon/agents/edit.py:35 msgid "Clearing texts" msgstr "Uklidit texty" #: aeidon/agents/edit.py:61 aeidon/agents/edit.py:83 msgid "Inserting subtitles" msgstr "Vložit titulky" #: aeidon/agents/edit.py:103 msgid "Merging subtitles" msgstr "Sloučit titulky" #: aeidon/agents/edit.py:114 msgid "Removing subtitles" msgstr "Odstranit titulky" #: aeidon/agents/edit.py:131 msgid "Replacing positions" msgstr "Nahradit polohy" #: aeidon/agents/edit.py:147 msgid "Replacing texts" msgstr "Nahradit texty" #: aeidon/agents/edit.py:171 msgid "Splitting subtitle" msgstr "Rozdělit titulky" #: aeidon/agents/format.py:49 msgid "Adding dialogue dashes" msgstr "Přidat pomlčky" #: aeidon/agents/format.py:68 msgid "Changing case" msgstr "Psát velká/malá písmena" #: aeidon/agents/format.py:92 msgid "Italicizing" msgstr "Sázet kurzívou" #: aeidon/agents/format.py:108 msgid "Removing dialogue dashes" msgstr "Odstranit pomlčky" #: aeidon/agents/format.py:174 msgid "Unitalicizing" msgstr "Napřímit písmo" #: gaupol/application.py:219 gaupol/agents/open.py:203 msgid "Open" msgstr "Otevřít" #: gaupol/application.py:223 msgid "Open main files" msgstr "Otevřít hlavní soubory" #: gaupol/application.py:230 msgid "Save" msgstr "Uložit" #: gaupol/application.py:233 msgid "Save the current main document" msgstr "Uložit nynější hlavní dokument" #: gaupol/application.py:238 msgid "Undo" msgstr "Zpět" #: gaupol/application.py:242 msgid "Undo the last action" msgstr "Vrátit předchozí krok" #: gaupol/application.py:249 msgid "Redo" msgstr "Znovu" #: gaupol/application.py:252 msgid "Redo the last undone action" msgstr "Znovu provést poslední krok vrácený zpět" #: gaupol/application.py:260 msgid "Insert" msgstr "Vložit" #: gaupol/application.py:262 msgid "Insert new subtitles" msgstr "Vložit nové titulky" #: gaupol/application.py:266 #: data/extensions/custom-framerates/preferences-dialog.ui:78 msgid "Remove" msgstr "Odstranit" #: gaupol/application.py:268 msgid "Remove the selected subtitles" msgstr "Odstranit vybrané titulky" #: gaupol/application.py:273 data/ui/search-dialog.ui:283 msgid "Find" msgstr "Najít" #: gaupol/application.py:275 msgid "Search for and replace text" msgstr "Hledat a nahradit text" #: gaupol/application.py:279 data/ui/preferences-dialog.ui:942 msgid "Video" msgstr "Obraz" #: gaupol/application.py:281 msgid "Show or hide the video player" msgstr "Ukázat nebo skrýt přehrávač obrazového záznamu" #: gaupol/application.py:285 data/ui/preferences-dialog.ui:1173 msgid "Preview" msgstr "Náhled" #: gaupol/application.py:287 msgid "Preview from selected position with a video player" msgstr "Náhled od vybrané polohy v přehrávači obrazového záznamu" #: gaupol/enums.py:37 msgid "No." msgstr "Číslo" #: gaupol/enums.py:43 msgid "Start" msgstr "Začátek" #: gaupol/enums.py:44 msgid "Start position" msgstr "Začáteční poloha" #: gaupol/enums.py:49 msgid "End" msgstr "Konec" #: gaupol/enums.py:50 msgid "End position" msgstr "Koncová poloha" #. TRANSLATORS: 'Dur.' is short for duration. It is used in the header #. of a column that contains numbers five digits wide. #: gaupol/enums.py:57 msgid "Dur." msgstr "Doba" #: gaupol/enums.py:58 msgid "Duration" msgstr "Doba trvání" #: gaupol/enums.py:63 gaupol/enums.py:64 msgid "Text" msgstr "Text" #: gaupol/enums.py:69 gaupol/enums.py:70 msgid "Translation" msgstr "Překlad" #: gaupol/enums.py:82 msgid "characters" msgstr "znaky" #: gaupol/enums.py:85 msgid "ems" msgstr "ems" #: gaupol/page.py:60 msgid "Untitled {:d}" msgstr "Bez názvu {:d}" #: gaupol/page.py:133 msgid "Close project" msgstr "Zavřít projekt" #: gaupol/page.py:145 msgid "{} translation" msgstr "{} překlad" #: gaupol/page.py:302 msgid "Path:" msgstr "Cesta:" #: gaupol/page.py:303 msgid "Format:" msgstr "Formát:" #: gaupol/page.py:304 msgid "Encoding:" msgstr "Kódování:" #: gaupol/page.py:305 msgid "Newlines:" msgstr "Zalomení řádků:" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:99 msgid "Tasks and Target" msgstr "Úkoly a cíl" #: gaupol/assistants.py:128 msgid "Correct texts in the text column" msgstr "Opravit texty v textovém sloupci" #: gaupol/assistants.py:129 msgid "Correct texts in the translation column" msgstr "Opravit texty v překladovém sloupci" #: gaupol/assistants.py:138 msgid "Correct texts in selected subtitles" msgstr "Opravit texty ve vybraných titulcích" #: gaupol/assistants.py:139 msgid "Correct texts in current project" msgstr "Opravit texty v nynějším projektu" #: gaupol/assistants.py:140 msgid "Correct texts in all open projects" msgstr "Opravit texty ve všech otevřených projektech" #: gaupol/assistants.py:363 msgid "Other" msgstr "Jiné" #: gaupol/assistants.py:439 msgid "Capitalize texts written in lower case" msgstr "Psát texty psané malými písmeny velkými písmeny" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:443 msgid "Capitalization Patterns" msgstr "Vzory pro psaní velkých písmen" #: gaupol/assistants.py:445 msgid "Capitalize texts" msgstr "Psát texty velkými písmeny" #: gaupol/assistants.py:468 msgid "Correct common errors made by humans or image recognition software" msgstr "" "Opravit běžné chyby způsobené lidmi nebo programem na rozpoznávání textu" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:472 msgid "Common Error Patterns" msgstr "Vzory běžných chyb" #: gaupol/assistants.py:474 msgid "Correct common errors" msgstr "Opravit běžné chyby" #: gaupol/assistants.py:526 msgid "Remove explanatory texts meant for the hearing impaired" msgstr "Odstranit vysvětlivky pro sluchově postižené" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:530 msgid "Hearing Impaired Patterns" msgstr "Vzory pro sluchově postižené" #: gaupol/assistants.py:532 msgid "Remove hearing impaired texts" msgstr "Odstranit texty pro sluchově postižené" #: gaupol/assistants.py:544 msgid "" "Use spell-check suggestions to fix whitespace detection errors of image " "recognition software" msgstr "" "Použít návrhy na správné psaní pro opravení chyb zjištěných prázdných míst " "programu na rozpoznávání obrázků" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:548 msgid "Joining and Splitting Words" msgstr "Spojit nebo rozdělit slova" #: gaupol/assistants.py:550 msgid "Join or Split Words" msgstr "Spojit nebo rozdělit slova" #: gaupol/assistants.py:599 gaupol/agents/tools.py:45 msgid "Failed to load dictionary for language \"{}\"" msgstr "Nepodařilo se nahrát slovník pro jazyk \"{}\"" #: gaupol/assistants.py:601 gaupol/player.py:263 gaupol/player.py:381 #: gaupol/dialogs/search.py:560 gaupol/dialogs/search.py:568 #: gaupol/dialogs/text_edit.py:49 gaupol/dialogs/encoding.py:56 #: gaupol/agents/open.py:328 gaupol/agents/open.py:337 #: gaupol/agents/open.py:345 gaupol/agents/open.py:354 #: gaupol/agents/tools.py:48 gaupol/agents/save.py:197 #: gaupol/agents/save.py:205 gaupol/agents/preview.py:108 #: gaupol/agents/preview.py:116 gaupol/agents/preview.py:125 #: gaupol/agents/preview.py:133 msgid "_OK" msgstr "_OK" #: gaupol/assistants.py:635 msgid "Break text into lines of defined length" msgstr "Zalomit text do řádků s předem danou délkou" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:639 msgid "Line-Break Patterns" msgstr "Vzory pro zalomení řádku" #: gaupol/assistants.py:641 msgid "Break lines" msgstr "Zalomit řádky" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:679 msgid "Line-Break Options" msgstr "Volby pro zalomení řádku" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:763 msgid "Correcting Texts" msgstr "Opravit texty" #: gaupol/assistants.py:769 msgid "Each task is now being run on each project." msgstr "Každý úkol je nyní proveden pro každý projekt." #: gaupol/assistants.py:793 #, python-brace-format msgid "{current:d} of {total:d} tasks complete" msgstr "{current:d} z {total:d} úkolů hotovo" #: gaupol/assistants.py:801 msgid "Project: {}" msgstr "Projekt: {}" #: gaupol/assistants.py:807 msgid "Task: {}" msgstr "Úkol: {}" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:832 msgid "Confirm Changes" msgstr "Potvrdit změny" #: gaupol/assistants.py:892 msgid "Accept" msgstr "Přijmout" #: gaupol/assistants.py:898 msgid "Original Text" msgstr "Původní text:" #: gaupol/assistants.py:899 msgid "Corrected Text" msgstr "Opravený text" #: gaupol/assistants.py:1048 msgid "Correct Texts" msgstr "Opravit texty" #: gaupol/assistants.py:1076 msgid "Correcting texts" msgstr "Opravují se texty" #: gaupol/assistants.py:1092 #, python-brace-format msgid "Edited {edits:d} and removed {removals:d} subtitles" msgstr "Upraveno {edits:d} a odstraněno {removals:d} titulků" #: gaupol/assistants.py:1126 msgid "Confirm {:d} Change" msgid_plural "Confirm {:d} Changes" msgstr[0] "Potvrdit {:d} změnu" msgstr[1] "Potvrdit {:d} změny" msgstr[2] "Potvrdit {:d} změn" msgstr[3] "Potvrdit {:d} změn" #: gaupol/renderers/multiline.py:86 msgid "Italic" msgstr "Kurzíva" #: gaupol/player.py:372 msgid "No video streams found" msgstr "" #: gaupol/player.py:379 msgid "Failed to initialize playback" msgstr "Spuštění přehrávání se nezdařilo" #: gaupol/dialogs/search.py:189 data/ui/menubar.ui:524 msgid "_Help" msgstr "_Nápověda" #: gaupol/dialogs/search.py:471 msgid "Found and replaced {:d} occurence" msgid_plural "Found and replaced {:d} occurences" msgstr[0] "Nalezen a nahrazen {:d} výskyt" msgstr[1] "Nalezeny a nahrazeny {:d} výskyty" msgstr[2] "Nalezeno a nahrazeno {:d} výskytů" msgstr[3] "Nalezeno a nahrazeno {:d} výskytů" #: gaupol/dialogs/search.py:488 msgid "\"{}\" not found" msgstr "\"{}\" nenalezeno" #: gaupol/dialogs/search.py:558 msgid "Error in regular expression pattern" msgstr "Chyba ve vzoru regulárního výrazu" #: gaupol/dialogs/search.py:566 msgid "Error in regular expression replacement" msgstr "Chyba v nahrazení od regulárního výrazu" #: gaupol/dialogs/text_edit.py:48 gaupol/dialogs/framerate_convert.py:63 #: gaupol/dialogs/insert.py:44 gaupol/dialogs/encoding.py:55 #: gaupol/dialogs/split.py:44 gaupol/dialogs/multi_close.py:54 #: gaupol/dialogs/open.py:63 gaupol/dialogs/position_transform.py:69 #: gaupol/dialogs/position_shift.py:71 gaupol/dialogs/multi_save.py:83 #: gaupol/dialogs/multi_save.py:215 gaupol/dialogs/duration_adjust.py:86 #: gaupol/dialogs/save.py:73 gaupol/dialogs/video.py:41 #: gaupol/agents/open.py:363 gaupol/agents/open.py:375 #: gaupol/agents/open.py:387 gaupol/agents/close.py:71 #: data/extensions/custom-framerates/custom-framerates.py:39 msgid "_Cancel" msgstr "_Zrušit" #: gaupol/dialogs/text_edit.py:53 msgid "Edit Text" msgstr "Upravit text" #: gaupol/dialogs/framerate_convert.py:64 msgid "Co_nvert" msgstr "Převést" #: gaupol/dialogs/insert.py:45 msgid "_Insert" msgstr "_Vložit" #: gaupol/dialogs/insert.py:54 msgid "Above selection" msgstr "Výběr nahoře" #: gaupol/dialogs/insert.py:55 msgid "Below selection" msgstr "Výběr dole" #: gaupol/dialogs/encoding.py:60 data/ui/preferences-dialog.ui:70 msgid "Character Encodings" msgstr "Kódování znaků" #: gaupol/dialogs/encoding.py:78 gaupol/dialogs/encoding.py:125 msgid "Description" msgstr "Popis" #: gaupol/dialogs/encoding.py:85 gaupol/dialogs/encoding.py:132 msgid "Encoding" msgstr "Kódování" #: gaupol/dialogs/encoding.py:141 msgid "Show in Menu" msgstr "Ukázat v nabídce" #: gaupol/dialogs/split.py:45 msgid "_Split" msgstr "_Rozdělit" #: gaupol/dialogs/split.py:76 msgid "Splitting project" msgstr "Rozdělit projekt" #: gaupol/dialogs/split.py:97 #, python-brace-format msgid "Split {amount:d} subtitles to project \"{name}\"" msgstr "Rozdělit {amount:d} titulků k projektu \"{name}\"" #: gaupol/dialogs/spell_check.py:269 msgid "Spell-checking" msgstr "Ověření pravopisu" #: gaupol/dialogs/preferences.py:217 msgid "{} Extension Website" msgstr "Stránky rozšíření {}" #: gaupol/dialogs/preferences.py:429 msgid "Custom" msgstr "Vlastní" #: gaupol/dialogs/multi_close.py:38 msgid "Save changes to documents before closing?" msgstr "Uložit před zavřením změny v dokumentech?" #: gaupol/dialogs/multi_close.py:39 gaupol/agents/open.py:384 #: gaupol/agents/close.py:68 msgid "If you don't save, changes will be permanently lost." msgstr "Pokud je neuložíte, budou změny navždy ztraceny." #: gaupol/dialogs/multi_close.py:53 gaupol/agents/close.py:70 msgid "Close _Without Saving" msgstr "Zavřít _bez uložení" #: gaupol/dialogs/multi_close.py:55 gaupol/dialogs/multi_save.py:84 #: gaupol/dialogs/save.py:74 gaupol/agents/open.py:388 #: gaupol/agents/close.py:72 data/ui/menubar.ui:34 msgid "_Save" msgstr "_Uložit" #: gaupol/dialogs/multi_close.py:70 msgid "Select the _main documents you want to save:" msgstr "Vyberte _hlavní dokument, který chcete uložit:" #: gaupol/dialogs/multi_close.py:95 msgid "Select the _translation documents you want to save:" msgstr "Vyberte _překladový dokument, který chcete uložit:" #: gaupol/dialogs/open.py:64 gaupol/agents/open.py:364 #: gaupol/agents/open.py:376 msgid "_Open" msgstr "_Otevřít" #: gaupol/dialogs/position_transform.py:70 msgid "_Transform" msgstr "_Předělat" #: gaupol/dialogs/position_shift.py:72 msgid "_Shift" msgstr "_Posunout" #: gaupol/dialogs/position_shift.py:150 msgid "frames" msgstr "Obrázky" #: gaupol/dialogs/position_shift.py:168 data/ui/preferences-dialog.ui:911 msgid "seconds" msgstr "sekund" #: gaupol/dialogs/about.py:36 msgid "About Gaupol" msgstr "O programu Gaupol" #: gaupol/dialogs/about.py:40 msgid "Subtitle editor" msgstr "Editor titulků" #. TRANSLATORS: This is a special message that shouldn't be translated #. literally. It is used in the about dialog to give credits to the #. translators. Thus, you should translate it to your name and email #. address. You can also include other translators who have contributed #. to this translation; in that case, please write them on separate #. lines seperated by newlines (\n). #: gaupol/dialogs/about.py:51 msgid "translator-credits" msgstr "Pavel Fric " #: gaupol/dialogs/about.py:54 msgid "Gaupol Website" msgstr "Stránky Gaupolu" #: gaupol/dialogs/append.py:35 msgid "Append File" msgstr "Připojit soubor" #: gaupol/dialogs/debug.py:43 msgid "Something went wrong" msgstr "Něco se nepovedlo" #: gaupol/dialogs/debug.py:44 msgid "" "You have probably discovered a bug. Please report it by providing the below " "information and a description of what you were doing." msgstr "" "Pravděpodobně jste objevil chybu. Nahlašte ji, prosím. Poskytněte informace " "níže a popište, co jste dělal." #: gaupol/dialogs/debug.py:52 msgid "_Report Bug" msgstr "_Nahlásit chybu" #: gaupol/dialogs/debug.py:53 data/ui/menubar.ui:56 msgid "_Quit" msgstr "_Ukončit" #: gaupol/dialogs/debug.py:54 gaupol/dialogs/preview_error.py:45 #: data/ui/menubar.ui:52 data/ui/tab-popup.ui:16 msgid "_Close" msgstr "_Zavřít" #: gaupol/dialogs/multi_save.py:98 gaupol/dialogs/save.py:110 msgid "{} (recommended)" msgstr "{} (doporučeno)" #: gaupol/dialogs/multi_save.py:212 msgid "" "{:d} of the files to be saved already exist. Do you want to replace them?" msgstr "{:d} ze souborů k uložení již existuje. Chcete je nahradit?" #: gaupol/dialogs/multi_save.py:213 msgid "" "The files already exist in \"{}\". Replacing them will overwrite their " "contents." msgstr "" "Soubory již existují v \"{}\". Jejich nahrazením dojde k přepsání jejich " "obsahu." #: gaupol/dialogs/multi_save.py:216 data/ui/search-dialog.ui:192 #: data/ui/spell-check-dialog.ui:122 msgid "_Replace" msgstr "_Nahradit" #: gaupol/dialogs/duration_adjust.py:70 msgid "Adjusted duration of {:d} subtitle" msgid_plural "Adjusted durations of {:d} subtitles" msgstr[0] "Upravená délka trvání {:d} titulku" msgstr[1] "Upravená délka trvání {:d} titulků" msgstr[2] "Upravená délka trvání {:d} titulků" msgstr[3] "Upravená délka trvání {:d} titulků" #: gaupol/dialogs/duration_adjust.py:87 msgid "_Adjust" msgstr "_Upravit" #: gaupol/dialogs/preview_error.py:36 msgid "Preview in video player failed" msgstr "Náhled v přehrávači obrazového záznamu se nezdařil" #: gaupol/dialogs/preview_error.py:37 msgid "" "There is probably a problem with either the video file or the video player. " "See the preferences dialog to choose the video player or to customize the " "command." msgstr "" "Je tu problém buď se souborem s obrazovým záznamem nebo s přehrávačem " "obrazového záznamu. Podívejte se na dialog s nastavením a vyberte přehrávač " "obrazového záznamu nebo přizpůsobte příkaz." #: gaupol/dialogs/language.py:97 msgid "Set Language" msgstr "Nastavit jazyk" #: gaupol/dialogs/video.py:52 gaupol/dialogs/file.py:59 msgid "All files" msgstr "Všechny soubory" #: gaupol/dialogs/video.py:56 msgid "Video files" msgstr "Soubory s obrazovým záznamem" #: gaupol/dialogs/file.py:63 msgid "All supported files" msgstr "Všechny podporované soubory" #: gaupol/dialogs/file.py:77 #, python-brace-format msgid "{format} (*{extension})" msgstr "{format} (*{extension})" #: gaupol/dialogs/file.py:120 msgid "Auto-detected" msgstr "Zjištěno automaticky" #: gaupol/dialogs/file.py:122 msgid "Other…" msgstr "Další…" #: gaupol/agents/menu.py:94 gaupol/agents/menu.py:103 #: gaupol/agents/menu.py:110 msgid "File not found" msgstr "" #: gaupol/agents/open.py:85 #, python-brace-format msgid "Appended {amount:d} subtitles from \"{basename}\"" msgstr "Připojeno {amount:d} titulků z \"{basename}\"" #: gaupol/agents/open.py:96 msgid "Appending file" msgstr "Připojit soubor" #: gaupol/agents/open.py:111 msgid "File \"{}\" is already open" msgstr "Soubor \"{}\" je již otevřen" #: gaupol/agents/open.py:214 msgid "Open Translation" msgstr "Otevřít překlad" #: gaupol/agents/open.py:223 msgid "Select Video" msgstr "Vybrat obrazový záznam" #: gaupol/agents/open.py:224 msgid "_Select" msgstr "_Vybrat" #: gaupol/agents/open.py:325 msgid "Failed to decode file \"{}\" with all attempted codecs" msgstr "Dekódování souboru \"{}\" se nezdařilo ani se všemi vyzkoušenými kodeky" #: gaupol/agents/open.py:326 msgid "Please try to open the file with a different character encoding." msgstr "Zkuste, prosím, soubor otevřít s jiným kódováním znaků." #: gaupol/agents/open.py:334 msgid "Failed to recognize format of file \"{}\"" msgstr "Formát souboru \"{}\" se nepodařilo rozpoznat" #: gaupol/agents/open.py:335 msgid "" "Please check that the file you are trying to open is a subtitle file of a " "format supported by Gaupol." msgstr "" "Ověřte, prosím, že soubor, který se pokoušíte otevřít, je soubor s titulky, " "jehož formát Gaupol podporuje." #: gaupol/agents/open.py:343 msgid "Failed to open file \"{}\"" msgstr "Nepodařilo se otevřít soubor \"{}\"" #: gaupol/agents/open.py:351 msgid "Failed to parse file \"{}\"" msgstr "Zpracování souboru \"{}\" se nezdařilo" #: gaupol/agents/open.py:352 msgid "Please check that the file you are trying to open is a valid {} file." msgstr "" "Ověřte, prosím, že soubor, který se pokoušíte otevřít, je platný soubor {}." #: gaupol/agents/open.py:360 msgid "Open abnormally large file \"{}\"?" msgstr "Otevřít mimořádně velký soubor\"{}\"?" #: gaupol/agents/open.py:361 msgid "" "Size of the file is {:.1f} MB, which is abnormally large for a text-based " "subtitle file. Please, check that you are not trying to open a binary file." msgstr "" "Soubor je {:.1f} MB velký, což je pro textově založený soubor s " "titulkymimořádně hodně. Ověřte, prosím, že se nepokoušíte otevřít binární " "soubor." #: gaupol/agents/open.py:371 msgid "Open unsorted file \"{}\"?" msgstr "Otevřít nezařazený soubor \"{}\"?" #: gaupol/agents/open.py:372 msgid "" "The order of {:d} subtitles needs to be changed. If {:d} sounds like a lot, " "the file may be erroneously composed." msgstr "" "Pořadí {:d} titulků se musí změnit. Když {:d} zní, jako by to bylo mnoho, " "soubor by mohl být složen chybně." #: gaupol/agents/open.py:383 msgid "Save changes to translation document \"{}\" before opening a new one?" msgstr "Uložit změny do překladového dokumentu »{}« před otevřením nového?" #: gaupol/agents/open.py:386 msgid "Open _Without Saving" msgstr "Otevřít _bez uložení" #: gaupol/agents/close.py:66 msgid "Save changes to document \"{}\" before closing?" msgstr "Uložit před zavřením změny do dokumentu \"{}\"?" #: gaupol/agents/edit.py:101 gaupol/agents/edit.py:119 msgid "Stretching end position" msgstr "Natažení polohy konce" #: gaupol/agents/edit.py:208 msgid "Inserted {:d} subtitle to fit clipboard contents" msgid_plural "Inserted {:d} subtitles to fit clipboard contents" msgstr[0] "Vložen {:d} titulek, aby se shodoval s obsahem schránky" msgstr[1] "Vloženy {:d} nové titulky, aby se shodoval s obsahem schránky" msgstr[2] "Vloženo {:d} nových titulků, aby se shodoval s obsahem schránky" msgstr[3] "Vloženo {:d} nových titulků, aby se shodoval s obsahem schránky" #: gaupol/agents/edit.py:334 gaupol/agents/edit.py:352 msgid "Stretching start position" msgstr "Natažení polohy začátku" #: gaupol/agents/edit.py:411 msgid "Use Shift+Return for line-break" msgstr "Pro zalomení řádku použít Shift+Enter" #: gaupol/agents/save.py:129 msgid "Save As" msgstr "Uložit jako" #: gaupol/agents/save.py:135 msgid "Saved main document as \"{}\"" msgstr "Hlavní dokument uložen jako \"{}\"" #: gaupol/agents/save.py:153 msgid "Save Translation As" msgstr "Uložit překlad jako" #: gaupol/agents/save.py:159 msgid "Saved translation document as \"{}\"" msgstr "Uložit překladový dokument jako \"{}\"" #: gaupol/agents/save.py:194 #, python-brace-format msgid "Failed to encode file \"{basename}\" with codec \"{codec}\"" msgstr "Zakódování souboru \"{basename}\" kodekem \"{codec}\" se nezdařilo" #: gaupol/agents/save.py:195 msgid "Please try to save the file with a different character encoding." msgstr "Zkuste, prosím, soubor uložit s jiným kódováním znaků." #: gaupol/agents/save.py:203 msgid "Failed to save file \"{}\"" msgstr "Nepodařilo se uložit soubor \"{}\"" #: gaupol/agents/video.py:67 data/ui/menubar.ui:380 msgid "_Play/Pause" msgstr "_Přehrát/Pozastavit" #: gaupol/agents/video.py:69 msgid "Play or pause video" msgstr "Přehrát nebo pozastavit obrazový záznam" #: gaupol/agents/video.py:75 data/ui/menubar.ui:390 msgid "Seek _Previous" msgstr "Přetočit na _předchozí" #: gaupol/agents/video.py:77 msgid "Seek to the start of the previous subtitle" msgstr "Vyhledat začátek předchozího titulku" #: gaupol/agents/video.py:81 data/ui/menubar.ui:394 msgid "Seek _Next" msgstr "Přetočit na _další" #: gaupol/agents/video.py:83 msgid "Seek to the start of the next subtitle" msgstr "Vyhledat začátek dalšího titulku" #: gaupol/agents/video.py:88 data/ui/menubar.ui:400 msgid "Seek _Backward" msgstr "Přetočit _zpět" #: gaupol/agents/video.py:90 msgid "Seek backward" msgstr "Přetočit zpět" #: gaupol/agents/video.py:94 data/ui/menubar.ui:404 msgid "Seek _Forward" msgstr "Přetočit _vpřed" #: gaupol/agents/video.py:96 msgid "Seek forward" msgstr "Přetočit vpřed" #: gaupol/agents/video.py:109 msgid "Volume" msgstr "Hlasitost" #: gaupol/agents/video.py:189 msgid "Load Video" msgstr "Nahrát obrazový záznam" #: gaupol/agents/video.py:189 msgid "_Load" msgstr "_Nahrát" #: gaupol/agents/video.py:361 msgid "Track {:d}" msgstr "" #: gaupol/agents/preview.py:105 msgid "Failed to encode subtitle file to temporary directory \"{}\"" msgstr "Soubor titulků se nepodařilo zakódovat do dočasného adresáře \"{}\"" #: gaupol/agents/preview.py:106 msgid "" "Subtitle data could not be encoded to a temporary file for preview with the " "current character encoding. Please first save the subtitle file with a " "different character encoding." msgstr "" "Data titulků se nepodařilo zakódovat do dočasného adresáře pro náhled s " "nynějším kódováním znaků. Nejprve, prosím, titulky uložte s jiným kódováním " "znaků." #: gaupol/agents/preview.py:114 msgid "Failed to save subtitle file to temporary directory \"{}\"" msgstr "Uložení souboru s titulky do dočasného adresáře \"{}\" se nezdařilo" #: gaupol/agents/preview.py:122 msgid "Video player not found" msgstr "Přehrávač obrazového záznamu nenalezen" #: gaupol/agents/preview.py:123 msgid "" "Please install one of the supported video players: mpv (recommended), " "MPlayer or VLC. See the preferences dialog to choose the video player or to " "customize the command." msgstr "" "Nainstalujte, prosím, jeden z podporovaných přehrávačů obrazového záznamu: " "mpv (doporučeno), MPlayer nebo VLC. Podívejte se na dialog s nastavením a " "vyberte přehrávač obrazového záznamu nebo přizpůsobte příkaz." #: gaupol/agents/preview.py:131 msgid "Failed to launch video player" msgstr "Spuštění přehrávače obrazového záznamu se nezdařilo" #: gaupol/applicationman.py:105 msgid "gaupol [OPTION...] [FILE...] [+[NUM]]" msgstr "gaupol [VOLBA...] [SOUBOR...] [+[ČÍSLO]]" #: gaupol/applicationman.py:109 msgid "FILE..." msgstr "SOUBOR..." #: gaupol/applicationman.py:112 msgid "subtitle files to open" msgstr "Soubory s titulky k otevření" #: gaupol/applicationman.py:122 msgid "ENCODING" msgstr "KÓDOVÁNÍ" #: gaupol/applicationman.py:125 msgid "set the character encoding used to open files" msgstr "Nastavit kódování znaků, které se používá při otevírání souborů" #: gaupol/applicationman.py:132 msgid "list all available character encodings" msgstr "Vypsat všechna dostupná kódování znaků" #: gaupol/applicationman.py:137 gaupol/applicationman.py:154 msgid "FILE" msgstr "SOUBOR" #: gaupol/applicationman.py:140 msgid "open translation file" msgstr "Otevřít překladový soubor" #: gaupol/applicationman.py:145 msgid "METHOD" msgstr "METODA" #: gaupol/applicationman.py:149 msgid "method used to align translation subtitles: 'number' or 'position'" msgstr "" "Metoda, která se používá k zarovnání překladových titulků: \"Číslo\" nebo " "\"Poloha\"" #: gaupol/applicationman.py:157 msgid "select video file" msgstr "Vybrat soubor s obrazovým záznamem" #: data/extensions/custom-framerates/custom-framerates.py:40 #: data/ui/spell-check-dialog.ui:152 msgid "_Add" msgstr "_Přidat" #: data/extensions/custom-framerates/custom-framerates.py:171 msgid "{:.3f} fps" msgstr "{:.3f} fps" #: data/extensions/custom-framerates/add-framerate-dialog.ui:13 msgid "Add Framerate" msgstr "Přidat rychlost opakování obrázků" #: data/extensions/custom-framerates/add-framerate-dialog.ui:44 msgid "_Framerate:" msgstr "_Rychlost opakování obrázků:" #: data/extensions/custom-framerates/add-framerate-dialog.ui:73 msgid "fps" msgstr "fps" #: data/extensions/custom-framerates/preferences-dialog.ui:8 msgid "Framerates" msgstr "Rychlosti opakování obrázků" #: data/extensions/custom-framerates/preferences-dialog.ui:64 msgid "Add" msgstr "Přidat" #: data/ui/columns-popup.ui:6 data/ui/menubar.ui:275 msgid "_No." msgstr "Čís_lo" #: data/ui/columns-popup.ui:10 data/ui/menubar.ui:279 msgid "_Start" msgstr "_Začátek" #: data/ui/columns-popup.ui:14 data/ui/menubar.ui:283 msgid "_End" msgstr "Kon_ec" #: data/ui/columns-popup.ui:18 data/ui/menubar.ui:287 msgid "_Duration" msgstr "_Doba trvání" #: data/ui/columns-popup.ui:22 data/ui/menubar.ui:291 data/ui/menubar.ui:303 msgid "_Text" msgstr "_Text" #: data/ui/columns-popup.ui:26 data/ui/menubar.ui:295 msgid "T_ranslation" msgstr "_Překlad" #: data/ui/split-dialog.ui:15 msgid "Split Project" msgstr "Rozdělit projekt" #: data/ui/split-dialog.ui:48 msgid "_First subtitle of new project:" msgstr "_První titulek nového projektu:" #: data/ui/search-dialog.ui:89 msgid "_Search for:" msgstr "_Hledat:" #: data/ui/search-dialog.ui:103 data/ui/spell-check-dialog.ui:193 msgid "Replace _with:" msgstr "_Nahradit:" #: data/ui/search-dialog.ui:162 data/ui/menubar.ui:328 msgid "Find _Next" msgstr "Najít _další" #: data/ui/search-dialog.ui:177 msgid "Find _Previous" msgstr "Najít _předchozí" #: data/ui/search-dialog.ui:207 msgid "Replace _All" msgstr "Nahradit _vše" #: data/ui/search-dialog.ui:241 msgid "R_egular expression" msgstr "_Regulární výraz" #: data/ui/search-dialog.ui:258 msgid "_Ignore case" msgstr "_Přehlížet psaní velkých/malých písmen" #: data/ui/search-dialog.ui:304 data/ui/language-dialog.ui:108 msgid "Columns" msgstr "Sloupce" #: data/ui/search-dialog.ui:324 msgid "Find in _text column" msgstr "Najít v _textovém sloupci" #: data/ui/search-dialog.ui:341 msgid "Find in t_ranslation column" msgstr "Najít v _překladovém sloupci" #: data/ui/search-dialog.ui:381 data/ui/framerate-convert-dialog.ui:144 #: data/ui/language-dialog.ui:186 #: data/ui/text-assistant/line-break-options-page.ui:178 #: data/ui/duration-adjust-dialog.ui:388 data/ui/position-shift-dialog.ui:180 #: data/ui/position-transform-dialog.ui:444 msgid "Subtitles" msgstr "Titulky" #: data/ui/search-dialog.ui:401 msgid "Find in c_urrent project" msgstr "Najít v _nynějším projektu" #: data/ui/search-dialog.ui:419 msgid "Find in _all open projects" msgstr "Najít ve _všech otevřených projektech" #: data/ui/search-dialog.ui:452 msgid "Target" msgstr "Cíl" #: data/ui/framerate-convert-dialog.ui:8 msgid "Convert Framerate" msgstr "Převést rychlost opakování obrázků" #: data/ui/framerate-convert-dialog.ui:48 msgid "Framerate" msgstr "Rychlost opakování obrázků" #: data/ui/framerate-convert-dialog.ui:71 msgid "_Input:" msgstr "_Vstup" #: data/ui/framerate-convert-dialog.ui:86 msgid "_Output:" msgstr "Vý_stup" #: data/ui/framerate-convert-dialog.ui:164 msgid "Convert c_urrent project" msgstr "Převést n_ynější projekt" #: data/ui/framerate-convert-dialog.ui:181 msgid "Convert _all open projects" msgstr "Převést vše_chny otevřené projekty" #: data/ui/spell-check-dialog.ui:8 msgid "Check Spelling" msgstr "Ověřit pravopis" #: data/ui/spell-check-dialog.ui:47 msgid "Join _Back" msgstr "Spojit _zpět" #: data/ui/spell-check-dialog.ui:62 msgid "Join _Forward" msgstr "Spojit _vpřed" #: data/ui/spell-check-dialog.ui:77 data/ui/menubar.ui:62 msgid "_Edit" msgstr "Úp_ravy" #: data/ui/spell-check-dialog.ui:92 msgid "_Ignore" msgstr "_Přehlížet" #: data/ui/spell-check-dialog.ui:107 msgid "Ig_nore All" msgstr "Přehlížet _vše" #: data/ui/spell-check-dialog.ui:137 msgid "Rep_lace All" msgstr "_Nahradit vše" #: data/ui/spell-check-dialog.ui:179 msgid "_Suggestions:" msgstr "Náv_rhy:" #: data/ui/multi-save-dialog.ui:8 msgid "Save All As" msgstr "Uložit vše jako" #: data/ui/multi-save-dialog.ui:46 msgid "Save in _folder:" msgstr "Uložit ve _složce:" #: data/ui/multi-save-dialog.ui:60 data/ui/save-dialog.ui:25 msgid "For_mat:" msgstr "_Formát:" #: data/ui/multi-save-dialog.ui:74 data/ui/open-dialog.ui:25 #: data/ui/save-dialog.ui:39 msgid "_Encoding:" msgstr "_Kódování:" #: data/ui/multi-save-dialog.ui:88 data/ui/save-dialog.ui:53 msgid "Ne_wlines:" msgstr "Za_lomení řádků:" #: data/ui/multi-save-dialog.ui:103 msgid "Select A Folder" msgstr "Vybrat složku" #: data/ui/multi-save-dialog.ui:150 data/ui/save-dialog.ui:102 msgid "F_ramerate:" msgstr "Rychlost snímkování:" #: data/ui/menubar.ui:5 msgid "_File" msgstr "_Soubor" #: data/ui/menubar.ui:8 msgid "_New" msgstr "_Nový" #: data/ui/menubar.ui:12 msgid "_Open…" msgstr "_Otevřít…" #: data/ui/menubar.ui:16 msgid "Open _Translation…" msgstr "Otevřít _překlad…" #: data/ui/menubar.ui:22 msgid "Open _Recent" msgstr "Otevřít ne_dávný" #: data/ui/menubar.ui:27 msgid "Open R_ecent Translation" msgstr "Otevřít _nynější překlad" #: data/ui/menubar.ui:38 msgid "Save _As…" msgstr "Uložit _jako..." #: data/ui/menubar.ui:42 msgid "Save Trans_lation" msgstr "Uložit přek_lad" #: data/ui/menubar.ui:46 msgid "Save Translat_ion As…" msgstr "Uložit pře_klad jako…" #: data/ui/menubar.ui:65 msgid "_Undo" msgstr "_Zpět" #: data/ui/menubar.ui:69 msgid "_Redo" msgstr "Z_novu" #: data/ui/menubar.ui:75 msgid "_Edit Cell" msgstr "_Upravit buňku" #: data/ui/menubar.ui:79 msgid "Edit _Next Cell" msgstr "Upravit _další buňku" #: data/ui/menubar.ui:85 msgid "Stretc_h" msgstr "&Natáhnout" #: data/ui/menubar.ui:88 msgid "_Start Earlier" msgstr "_Začít dříve" #: data/ui/menubar.ui:92 msgid "S_tart Later" msgstr "Z_ačít později" #: data/ui/menubar.ui:98 msgid "E_nd Earlier" msgstr "U_končit dříve" #: data/ui/menubar.ui:102 msgid "En_d Later" msgstr "_Ukončit později" #: data/ui/menubar.ui:108 msgid "Set St_art From Video Position" msgstr "Nastavit _začátek z polohy obrazového záznamu" #: data/ui/menubar.ui:112 msgid "Set En_d From Video Position" msgstr "Nastavit kon_ec z polohy obrazového záznamu" #: data/ui/menubar.ui:118 data/ui/view-popup.ui:6 msgid "_Split Subtitle" msgstr "_Rozdělit titulek" #: data/ui/menubar.ui:122 data/ui/view-popup.ui:10 msgid "_Merge Subtitles" msgstr "_Sloučit titulky" #: data/ui/menubar.ui:128 data/ui/view-popup.ui:16 msgid "_Insert Subtitles…" msgstr "_Vložit titulky..." #: data/ui/menubar.ui:132 msgid "Inser_t Subtitle At Video Position" msgstr "_Vložit titulek v poloze obrazového záznamu" #: data/ui/menubar.ui:136 data/ui/view-popup.ui:20 msgid "Rem_ove Subtitles" msgstr "O_dstranit titulky" #: data/ui/menubar.ui:142 msgid "Sele_ction" msgstr "Vý_běr" #: data/ui/menubar.ui:145 msgid "Select _All" msgstr "_Vybrat vše" #: data/ui/menubar.ui:149 msgid "_Invert Selection" msgstr "_Obrátit výběr" #: data/ui/menubar.ui:155 msgid "Extend To _Beginning" msgstr "Rozšířit po _začátek" #: data/ui/menubar.ui:159 msgid "Extend To _End" msgstr "Rozšířit po _konec" #: data/ui/menubar.ui:165 msgid "_Previous From Video Position" msgstr "" #: data/ui/menubar.ui:169 msgid "_Next From Video Position" msgstr "" #: data/ui/menubar.ui:177 msgid "_Preferences" msgstr "_Nastavení" #: data/ui/menubar.ui:183 msgid "_View" msgstr "_Pohled" #: data/ui/menubar.ui:186 msgid "Tool_bar" msgstr "Nástrojový _pruh" #: data/ui/menubar.ui:190 msgid "_Video Player" msgstr "Přehrávač _obrazového záznamu" #: data/ui/menubar.ui:196 msgid "_Layout" msgstr "_Rozvržení" #: data/ui/menubar.ui:199 msgid "_Horizontal" msgstr "_Vodorovně" #: data/ui/menubar.ui:204 msgid "_Vertical" msgstr "_Svisle" #: data/ui/menubar.ui:213 msgid "_Times" msgstr "Č_asy" #: data/ui/menubar.ui:218 msgid "_Frames" msgstr "_Obrázky" #: data/ui/menubar.ui:225 msgid "F_ramerate" msgstr "Rychlost opakování _obrázků" #: data/ui/menubar.ui:228 msgid "2_3.976 fps" msgstr "2_3,976 fps" #: data/ui/menubar.ui:233 msgid "2_4.000 fps" msgstr "2_4,000 fps" #: data/ui/menubar.ui:238 msgid "2_5.000 fps" msgstr "2_5,000 fps" #: data/ui/menubar.ui:243 msgid "2_9.970 fps" msgstr "2_9,970 fps" #: data/ui/menubar.ui:272 msgid "_Columns" msgstr "_Sloupce" #: data/ui/menubar.ui:306 msgid "Cu_t" msgstr "_Vyjmout" #: data/ui/menubar.ui:310 msgid "_Copy" msgstr "_Kopírovat" #: data/ui/menubar.ui:314 msgid "_Paste" msgstr "V_ložit" #: data/ui/menubar.ui:318 msgid "Cl_ear" msgstr "_Uklidit" #: data/ui/menubar.ui:324 msgid "_Find And Replace…" msgstr "_Najít a nahradit" #: data/ui/menubar.ui:332 msgid "Find Pre_vious" msgstr "Najít _předchozí" #: data/ui/menubar.ui:338 msgid "_Italic" msgstr "_Kurzíva" #: data/ui/menubar.ui:342 msgid "_Dialogue" msgstr "_Dialog" #: data/ui/menubar.ui:348 msgid "Ca_se" msgstr "Velikost _písmen" #: data/ui/menubar.ui:351 msgid "_Title" msgstr "_Název" #: data/ui/menubar.ui:355 msgid "_Sentence" msgstr "_Věta" #: data/ui/menubar.ui:359 msgid "_Upper" msgstr "_Velká písmena" #: data/ui/menubar.ui:363 msgid "_Lower" msgstr "_Malá písmena" #: data/ui/menubar.ui:371 msgid "Vi_deo" msgstr "_Obraz" #: data/ui/menubar.ui:374 msgid "_Load Video…" msgstr "Nahrát obrazový záznam…" #: data/ui/menubar.ui:384 data/ui/view-popup.ui:26 msgid "Play _Selection" msgstr "Přehrát _výběr" #: data/ui/menubar.ui:410 data/ui/view-popup.ui:30 msgid "S_eek Selection Start" msgstr "Přetočit na _začátek výběru" #: data/ui/menubar.ui:414 msgid "See_k Selection End" msgstr "Přetočit na _konec výběru" #: data/ui/menubar.ui:420 msgid "_Audio" msgstr "Zv_uk" #: data/ui/menubar.ui:423 msgid "_Language" msgstr "_Jazyk" #: data/ui/menubar.ui:430 msgid "Volume _Down" msgstr "Hlasitost _dolů" #: data/ui/menubar.ui:434 msgid "Volume _Up" msgstr "Hlasitost _nahoru" #: data/ui/menubar.ui:440 msgid "T_ools" msgstr "Nástroj_e" #: data/ui/menubar.ui:443 data/ui/text-assistant/confirmation-page.ui:97 #: data/ui/view-popup.ui:36 msgid "_Preview" msgstr "_Náhled" #: data/ui/menubar.ui:447 msgid "Select _Video…" msgstr "Vybrat _obrazový záznam…" #: data/ui/menubar.ui:453 msgid "_Check Spelling" msgstr "_Ověřit pravopis" #: data/ui/menubar.ui:457 msgid "Co_nfigure Spell-check…" msgstr "Na_stavit ověření správného psaní…" #: data/ui/menubar.ui:461 msgid "C_orrect Texts…" msgstr "O_pravit texty…" #: data/ui/menubar.ui:467 msgid "_Shift Positions…" msgstr "_Posunout polohy…" #: data/ui/menubar.ui:471 msgid "_Transform Positions…" msgstr "Pře_dělat polohy…" #: data/ui/menubar.ui:475 msgid "Adjust _Durations…" msgstr "Upravit _doby trvání…" #: data/ui/menubar.ui:479 msgid "Convert _Framerate…" msgstr "Převést rychlost opakování _obrázků…" #: data/ui/menubar.ui:485 msgid "_Append File…" msgstr "_Připojit soubor…" #: data/ui/menubar.ui:489 msgid "Spli_t Project…" msgstr "Roz_dělit projekt…" #: data/ui/menubar.ui:495 msgid "_Projects" msgstr "Proje_kty" #: data/ui/menubar.ui:498 msgid "_Save All" msgstr "_Uložit vše" #: data/ui/menubar.ui:502 msgid "Save _All As…" msgstr "Uložit _vše jako…" #: data/ui/menubar.ui:506 msgid "_Close All" msgstr "_Zavřít vše" #: data/ui/menubar.ui:512 msgid "_Previous" msgstr "_Předchozí" #: data/ui/menubar.ui:516 msgid "_Next" msgstr "_Další" #: data/ui/menubar.ui:527 msgid "_Documentation" msgstr "_Dokumentace" #: data/ui/menubar.ui:531 msgid "_Report A Bug" msgstr "_Nahlásit chybu" #: data/ui/menubar.ui:535 msgid "_About" msgstr "O _programu" #: data/ui/open-dialog.ui:39 msgid "Align _method:" msgstr "_Způsob zarovnání:" #: data/ui/preferences-dialog.ui:18 msgid "Preferences" msgstr "Nastavení" #: data/ui/preferences-dialog.ui:93 msgid "When opening files, try encodings in the following order:" msgstr "Při otevření souborů vyzkoušet kódování v následujícím pořadí:" #: data/ui/preferences-dialog.ui:104 msgid "Curr_ent locale encoding" msgstr "Nyně_jší jazykové kódování" #: data/ui/preferences-dialog.ui:130 msgid "_Fallback encodings:" msgstr "Zál_ožní kódování:" #: data/ui/preferences-dialog.ui:246 msgid "Aut_o-detection" msgstr "_Automatické rozpoznání" #: data/ui/preferences-dialog.ui:266 msgid "Encoding specified in the open dialog will always be tried first." msgstr "Kódování zadané v dialogu Otevřít bude vždy vyzkoušeno jako první." #: data/ui/preferences-dialog.ui:296 msgid "File" msgstr "Soubor" #: data/ui/preferences-dialog.ui:324 msgid "Font" msgstr "Písmo" #: data/ui/preferences-dialog.ui:344 msgid "Use _default theme fixed width font" msgstr "Použít písmo s pevnou šířkou u _výchozího motivu" #: data/ui/preferences-dialog.ui:368 msgid "_Editor font:" msgstr "Písmo _editoru:" #: data/ui/preferences-dialog.ui:425 msgid "Line Lengths" msgstr "Délky řádků" #: data/ui/preferences-dialog.ui:445 msgid "_Show line lengths in list cells" msgstr "_Ukázat délky řádků v buňkách seznamu" #: data/ui/preferences-dialog.ui:462 msgid "S_how line lengths in editable text fields" msgstr "U_kázat délky řádků v upravitelných polích" #: data/ui/preferences-dialog.ui:486 msgid "_Length unit:" msgstr "Jednotka _délky:" #: data/ui/preferences-dialog.ui:540 msgid "Spell-Check" msgstr "Ověření správného psaní" #: data/ui/preferences-dialog.ui:560 msgid "Chec_k spelling as you type" msgstr "Pravopis _ověřovat během psaní" #: data/ui/preferences-dialog.ui:598 msgid "Editor" msgstr "Editor" #: data/ui/preferences-dialog.ui:626 msgid "Fonts" msgstr "Písma" #: data/ui/preferences-dialog.ui:649 msgid "_Subtitles:" msgstr "_Titulky:" #: data/ui/preferences-dialog.ui:679 msgid "_Time:" msgstr "Č_as:" #: data/ui/preferences-dialog.ui:729 msgid "Colors" msgstr "Barvy" #: data/ui/preferences-dialog.ui:752 msgid "Su_btitles:" msgstr "Tit_ulky:" #: data/ui/preferences-dialog.ui:777 msgid "_Use a background behind text" msgstr "_Použít pozadí za textem" #: data/ui/preferences-dialog.ui:797 msgid "Ti_me:" msgstr "Ča_s:" #: data/ui/preferences-dialog.ui:822 msgid "Us_e a background behind text" msgstr "P_oužít pozadí za textem" #: data/ui/preferences-dialog.ui:862 msgid "Seek" msgstr "Přetočit" #: data/ui/preferences-dialog.ui:883 msgid "_Length:" msgstr "_Délka" #: data/ui/preferences-dialog.ui:971 msgid "Video Player" msgstr "Přehrávač obrazového záznamu" #: data/ui/preferences-dialog.ui:994 msgid "_Application:" msgstr "_Program:" #: data/ui/preferences-dialog.ui:1008 msgid "Co_mmand:" msgstr "Přík_az:" #. Translators: Only the title is to be translated, field names not. #: data/ui/preferences-dialog.ui:1033 msgid "" "Fields:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" msgstr "" "Pole:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" #: data/ui/preferences-dialog.ui:1048 msgid "Al_ways use UTF-8 character encoding" msgstr "Použít vždy kódování UTF-8" #: data/ui/preferences-dialog.ui:1089 msgid "Start Position" msgstr "Začáteční poloha" #: data/ui/preferences-dialog.ui:1111 msgid "_Offset:" msgstr "Po_sun:" #: data/ui/preferences-dialog.ui:1142 msgid "seconds before selection" msgstr "sekund před výběrem" #: data/ui/preferences-dialog.ui:1281 msgid "Extensions" msgstr "Rozšíření" #: data/ui/language-dialog.ui:8 msgid "Configure Spell-Check" msgstr "Nastavit ověřování pravopisu" #: data/ui/language-dialog.ui:50 msgid "Language" msgstr "Jazyk" #: data/ui/language-dialog.ui:128 msgid "Check _text column" msgstr "Přezkoušet _textový sloupec" #: data/ui/language-dialog.ui:146 msgid "Check t_ranslation column" msgstr "Přezkoušet _překladový sloupec" #: data/ui/language-dialog.ui:206 msgid "Check c_urrent project" msgstr "Přezkoušet _nynější projekt" #: data/ui/language-dialog.ui:224 msgid "Check _all open projects" msgstr "Přezkoušet _všechny otevřené projekty" #: data/ui/text-assistant/confirmation-page.ui:22 msgid "Acc_ept, discard or edit changes:" msgstr "_Potvrdit, zamítnout nebo upravit změny:" #: data/ui/text-assistant/confirmation-page.ui:67 msgid "_Mark All" msgstr "_Označit vše" #: data/ui/text-assistant/confirmation-page.ui:82 msgid "_Unmark All" msgstr "O_dznačit vše" #: data/ui/text-assistant/confirmation-page.ui:119 msgid "_Remove all blank subtitles" msgstr "Ode_brat všechny prázdné titulky" #: data/ui/text-assistant/join-split-page.ui:28 msgid "Spell-Check Dictionary" msgstr "Slovník pro ověřování správného psaní" #: data/ui/text-assistant/join-split-page.ui:49 #: data/ui/text-assistant/line-break-page.ui:81 #: data/ui/text-assistant/hearing-impaired-page.ui:81 #: data/ui/text-assistant/common-error-page.ui:80 #: data/ui/text-assistant/capitalization-page.ui:80 msgid "_Language:" msgstr "_Jazyk:" #: data/ui/text-assistant/join-split-page.ui:97 msgid "Corrections" msgstr "Opravy" #: data/ui/text-assistant/join-split-page.ui:117 msgid "_Join words not found in spell-check dictionary" msgstr "" "_Spojit slova, která nebyla nalezena ve slovníku pro ověřování správného " "psaní" #: data/ui/text-assistant/join-split-page.ui:134 msgid "_Split words not found in spell-check dictionary" msgstr "" "_Rozdělit slova, která nebyla nalezena ve slovníku pro ověřování správného " "psaní" #: data/ui/text-assistant/line-break-page.ui:22 msgid "S_elect preferred line-break points:" msgstr "V_ybrat upřednostňované body zalomení řádků:" #: data/ui/text-assistant/line-break-page.ui:67 #: data/ui/text-assistant/hearing-impaired-page.ui:67 #: data/ui/text-assistant/common-error-page.ui:66 #: data/ui/text-assistant/capitalization-page.ui:66 msgid "_Script:" msgstr "_Skript:" #: data/ui/text-assistant/line-break-page.ui:95 #: data/ui/text-assistant/hearing-impaired-page.ui:95 #: data/ui/text-assistant/common-error-page.ui:94 #: data/ui/text-assistant/capitalization-page.ui:94 msgid "Co_untry:" msgstr "Ze_mě:" #: data/ui/text-assistant/introduction-page.ui:28 msgid "_Select corrections to perform on texts:" msgstr "Vybrat _opravy, které se použijí na texty:" #: data/ui/text-assistant/introduction-page.ui:79 msgid "Colu_mns:" msgstr "Slou_pce:" #: data/ui/text-assistant/introduction-page.ui:93 msgid "S_ubtitles:" msgstr "T_itulky:" #: data/ui/text-assistant/line-break-options-page.ui:56 #: data/ui/duration-adjust-dialog.ui:207 msgid "Limits" msgstr "Omezení" #: data/ui/text-assistant/line-break-options-page.ui:79 msgid "_Maximum line length:" msgstr "_Největší délka řádku:" #: data/ui/text-assistant/line-break-options-page.ui:93 msgid "_Preferred maximum amount of lines:" msgstr "_Upřednostňovaný největší počet řádků:" #: data/ui/text-assistant/line-break-options-page.ui:198 msgid "_Skip subtitles with maximum line length of:" msgstr "Přeskočit _titulky, které mají následující největší délku řádku:" #: data/ui/text-assistant/line-break-options-page.ui:214 msgid "S_kip subtitles with maximum line amount of:" msgstr "Př_eskočit titulky, které mají následující největší počet řádků:" #: data/ui/text-assistant/hearing-impaired-page.ui:22 msgid "S_elect parts to remove:" msgstr "_Vybrat části, které se odstraní:" #: data/ui/text-assistant/common-error-page.ui:22 msgid "S_elect errors to correct:" msgstr "Vybrat _chyby k opravě:" #: data/ui/text-assistant/common-error-page.ui:108 msgid "Error types:" msgstr "Typy chyb:" #: data/ui/text-assistant/common-error-page.ui:158 msgid "_Human errors" msgstr "Chyby _uživatele" #: data/ui/text-assistant/common-error-page.ui:175 msgid "_Image recognition errors" msgstr "Chyby rozpoznání _obrázku" #: data/ui/text-assistant/capitalization-page.ui:22 msgid "S_elect parts to capitalize:" msgstr "Vybrat čás_ti, které se napíší velkými písmeny:" #: data/ui/duration-adjust-dialog.ui:33 msgid "Adjust Durations" msgstr "Upravit doby trvání" #: data/ui/duration-adjust-dialog.ui:73 msgid "Theoretic Duration" msgstr "Teoretická doba trvání " #: data/ui/duration-adjust-dialog.ui:101 msgid "_Reading speed:" msgstr "Rychlost čt_ení:" #: data/ui/duration-adjust-dialog.ui:133 msgid "characters per second" msgstr "znaků za sekundu" #: data/ui/duration-adjust-dialog.ui:150 msgid "_Lengthen duration to match reading speed" msgstr "P_rodloužit dobu trvání, aby odpovídala rychlosti čtení" #: data/ui/duration-adjust-dialog.ui:167 msgid "_Shorten duration to match reading speed" msgstr "_Zkrátit dobu trvání, aby odpovídala rychlosti čtení" #: data/ui/duration-adjust-dialog.ui:227 msgid "_Minimum duration:" msgstr "_Nejmenší doba trvání:" #: data/ui/duration-adjust-dialog.ui:243 msgid "Ma_ximum duration:" msgstr "Nej_větší doba trvání:" #: data/ui/duration-adjust-dialog.ui:259 msgid "_Gap between subtitles:" msgstr "_Mezera mezi titulky:" #: data/ui/duration-adjust-dialog.ui:294 msgid "s_econds" msgstr "s_ekund" #: data/ui/duration-adjust-dialog.ui:324 msgid "seco_nds" msgstr "se_kund" #: data/ui/duration-adjust-dialog.ui:354 msgid "secon_ds" msgstr "sek_und" #: data/ui/duration-adjust-dialog.ui:408 msgid "Adj_ust selected subtitles" msgstr "Up_ravit vybrané titulky" #: data/ui/duration-adjust-dialog.ui:425 msgid "Adjus_t current project" msgstr "Upr_avit nynější projekt" #: data/ui/duration-adjust-dialog.ui:442 msgid "Adjust all _open projects" msgstr "Upravit všechny _otevřené projekty" #: data/ui/tab-popup.ui:6 msgid "Move Tab _Left" msgstr "Posunout kartu do_leva" #: data/ui/tab-popup.ui:10 msgid "Move Tab _Right" msgstr "Posunout kartu do_prava" #: data/ui/insert-dialog.ui:15 msgid "Insert Subtitles" msgstr "Vložit titulky" #: data/ui/insert-dialog.ui:48 data/ui/position-shift-dialog.ui:82 msgid "_Amount:" msgstr "_Množství:" #: data/ui/insert-dialog.ui:62 msgid "_Position:" msgstr "_Poloha:" #: data/ui/position-shift-dialog.ui:14 msgid "Shift Positions" msgstr "Posunout polohy" #: data/ui/position-shift-dialog.ui:54 msgid "Shift" msgstr "Posunout" #: data/ui/position-shift-dialog.ui:135 #: data/ui/position-transform-dialog.ui:208 msgid "_Preview Changes" msgstr "_Náhled na změny" #: data/ui/position-shift-dialog.ui:200 msgid "Shift s_elected subtitles" msgstr "Posunout _vybrané titulky" #: data/ui/position-shift-dialog.ui:217 msgid "Shift su_btitles from selection to end" msgstr "Posunout _titulky z výběru na konec" #: data/ui/position-shift-dialog.ui:234 msgid "Shift c_urrent project" msgstr "Posunout _nynější projekt" #: data/ui/position-shift-dialog.ui:251 msgid "Shift all _open projects" msgstr "" #: data/ui/position-transform-dialog.ui:22 msgid "Transform Positions" msgstr "Předělat polohy" #: data/ui/position-transform-dialog.ui:62 msgid "First Point" msgstr "První bod" #: data/ui/position-transform-dialog.ui:91 msgid "_Subtitle:" msgstr "_Titulek:" #: data/ui/position-transform-dialog.ui:105 msgid "C_orrection:" msgstr "Úp_rava:" #: data/ui/position-transform-dialog.ui:119 #: data/ui/position-transform-dialog.ui:310 msgid "Text:" msgstr "Text:" #: data/ui/position-transform-dialog.ui:253 msgid "Second Point" msgstr "Druhý bod" #: data/ui/position-transform-dialog.ui:282 msgid "Su_btitle:" msgstr "_Titulek:" #: data/ui/position-transform-dialog.ui:296 msgid "Co_rrection:" msgstr "Úpr_ava:" #: data/ui/position-transform-dialog.ui:399 msgid "Pre_view Changes" msgstr "Náhled na z_měny" #: data/ui/position-transform-dialog.ui:464 msgid "Transform se_lected subtitles" msgstr "Předělat vy_brané titulky" #: data/ui/position-transform-dialog.ui:482 msgid "Transform c_urrent project" msgstr "Předělat _nynější projekt" #: data/extensions/custom-framerates/custom-framerates.extension.in:7 msgid "Custom Framerates" msgstr "Vlastní rychlosti opakování obrázků" #: data/extensions/custom-framerates/custom-framerates.extension.in:8 msgid "Allow use of non-standard framerates" msgstr "Povolit užití nestandardních rychlostí opakování obrázků" #: data/patterns/Latn-en-US.common-error.in:5 msgid "Period after title" msgstr "Tečka za titulem" #: data/patterns/Latn-en-US.common-error.in:6 msgid "Add period after a shortened title, such as \"Mr\" and \"Dr\"" msgstr "Přidat tečku za zkrácený titul, jako jsou například „Mgr“ a „Dr“" #: data/patterns/Latn-en.capitalization.in:5 msgid "First person pronoun" msgstr "Zájmeno první osoby" #: data/patterns/Latn-en.capitalization.in:6 msgid "Capitalize the first person pronoun \"I\"" msgstr "Velké písmeno u zájmena první osoby (v angličtině „I“)" #: data/patterns/Latn-en.common-error.in:5 #: data/patterns/Latn-en.common-error.in:14 #: data/patterns/Latn-en.common-error.in:23 msgid "Letter \"I\" in a lower case word" msgstr "Písmeno „I“ ve slově napsaném malými písmeny" #: data/patterns/Latn-en.common-error.in:6 #: data/patterns/Latn-en.common-error.in:15 #: data/patterns/Latn-en.common-error.in:24 msgid "Replace letter \"I\" with letter \"l\" in a lower case word" msgstr "Nahradit písmeno „I“ písmenem \"l\" ve slově napsaném malými písmeny" #: data/patterns/Latn-en.common-error.in:32 #: data/patterns/Latn-en.common-error.in:41 #: data/patterns/Latn-en.common-error.in:50 #: data/patterns/Latn-en.common-error.in:62 msgid "Letter \"l\" in an upper case word" msgstr "Písmeno „l“ ve slově napsaném velkými písmeny" #: data/patterns/Latn-en.common-error.in:33 #: data/patterns/Latn-en.common-error.in:42 #: data/patterns/Latn-en.common-error.in:51 #: data/patterns/Latn-en.common-error.in:63 msgid "Replace letter \"l\" with letter \"I\" in an upper case word" msgstr "Nahradit písmeno „l“ písmenem \"I\"ve slově napsaném velkými písmeny" #: data/patterns/Latn-en.common-error.in:73 #: data/patterns/Latn-en.common-error.in:82 msgid "Zero in an upper case word" msgstr "Nula ve slově napsaném velkými písmeny" #: data/patterns/Latn-en.common-error.in:74 #: data/patterns/Latn-en.common-error.in:83 msgid "Replace zero with letter \"O\" in an upper case word" msgstr "Nahradí nulu za písmeno „O“ ve slově napsaném velkými písmeny" #: data/patterns/Latn-en.common-error.in:91 #: data/patterns/Latn.common-error.in:108 msgid "Space between number and unit" msgstr "Mezera mezi číslem a jednotkou" #: data/patterns/Latn-en.common-error.in:92 #: data/patterns/Latn.common-error.in:109 msgid "Add or remove space between a number and the associated unit" msgstr "Přidat nebo odstranit mezeru mezi číslem a k němu patřící jednotkou" #: data/patterns/Latn-en.common-error.in:100 msgid "Spaces around an apostrophe" msgstr "Mezery kolem odsuvníků (apostrofů)" #: data/patterns/Latn-en.common-error.in:101 msgid "Remove spaces around an apostrophe" msgstr "Odstranit mezery kolem odsuvníků (apostrofů)" #: data/patterns/Latn-en.common-error.in:109 #: data/patterns/Latn-en.common-error.in:118 msgid "Okay" msgstr "Okay" #: data/patterns/Latn-en.common-error.in:110 #: data/patterns/Latn-en.common-error.in:119 msgid "Spell two-letter forms of \"okay\" in all upper case" msgstr "Napište velkými písmeny dvojpísmennou podobu slova \"okay\"" #: data/patterns/Latn-en.hearing-impaired.in:5 msgid "Uppercase speaker before a colon" msgstr "Mluvčí psaný velkými písmeny před dvojtečkou" #: data/patterns/Latn-en.hearing-impaired.in:6 msgid "" "Replace the uppercase name of the speaker before a colon with a dialogue " "dash" msgstr "" "Nahradit jméno mluvčího psané velkými písmeny před dvojtečkou začínající " "velkým písmenem za dialogovou pomlčku" #: data/patterns/Latn-en.line-break.in:5 msgid "Title" msgstr "Titul" #: data/patterns/Latn-en.line-break.in:6 msgid "Do not break after a title, e.g. \" Dr.\"" msgstr "Nezalamovat po titulu, např. \" Dr.\"" #: data/patterns/Latn-en.line-break.in:13 msgid "Article" msgstr "Článek" #: data/patterns/Latn-en.line-break.in:14 msgid "Do not break after an article" msgstr "Nezalamovat po článku" #: data/patterns/Latn-en.line-break.in:21 msgid "Preposition" msgstr "Zájmeno" #: data/patterns/Latn-en.line-break.in:22 msgid "Do not break after a preposition" msgstr "Nezalamovat po zájmenu" #: data/patterns/Latn-en.line-break.in:30 msgid "Possessive determiner" msgstr "Přivlastňovací zájmeno" #: data/patterns/Latn-en.line-break.in:31 msgid "Do not break after a possessive determiner, e.g. \"my\"" msgstr "Nezalamovat po přivlastňovacím zájmenu, např. \"my\"" #: data/patterns/Latn-fi.common-error.in:5 #: data/patterns/Latn.common-error.in:182 msgid "Space after punctuation marks" msgstr "Mezera za interpunkčními znaménky" #: data/patterns/Latn-fi.common-error.in:6 #: data/patterns/Latn.common-error.in:183 msgid "Add space after various punctuation marks" msgstr "Přidat mezeru za různá interpunkční znaménka" #: data/patterns/Latn-fr.common-error.in:5 #: data/patterns/Latn-fr.common-error.in:14 #: data/patterns/Latn-fr.common-error.in:23 #: data/patterns/Latn-fr.common-error.in:32 msgid "Spaces around guillemets" msgstr "Mezery kolem francouzských uvozovek" #: data/patterns/Latn-fr.common-error.in:6 #: data/patterns/Latn-fr.common-error.in:15 #: data/patterns/Latn-fr.common-error.in:24 #: data/patterns/Latn-fr.common-error.in:33 msgid "Add spaces around guillemets" msgstr "Přidat mezery kolem francouzských uvozovek" #: data/patterns/Latn-fr.common-error.in:41 #: data/patterns/Latn-fr.common-error.in:52 #: data/patterns/Latn.common-error.in:171 msgid "Space before punctuation marks" msgstr "Mezera před interpunkčními znaménky" #: data/patterns/Latn-fr.common-error.in:42 #: data/patterns/Latn-fr.common-error.in:53 msgid "Add or remove space before various punctuation marks" msgstr "Přidat nebo odstranit mezeru před různými interpunkčními znaménky" #: data/patterns/Latn.capitalization.in:5 msgid "Sentence" msgstr "Věta" #: data/patterns/Latn.capitalization.in:6 msgid "Capitalize the first word of a sentence" msgstr "Nastavit velké písmeno u prvního slova věty" #: data/patterns/Latn.capitalization.in:12 msgid "Ellipsis" msgstr "Výpustka" #: data/patterns/Latn.capitalization.in:13 msgid "Capitalize after an ellipsis" msgstr "Nastavit velké písmeno u slova za výpustkou" #: data/patterns/Latn.common-error.in:8 data/patterns/Latn.common-error.in:17 #: data/patterns/Latn.common-error.in:26 data/patterns/Latn.common-error.in:35 #: data/patterns/Latn.common-error.in:44 data/patterns/Latn.common-error.in:53 #: data/patterns/Latn.common-error.in:62 msgid "Ligatures" msgstr "Slitky" #: data/patterns/Latn.common-error.in:9 data/patterns/Latn.common-error.in:18 #: data/patterns/Latn.common-error.in:27 data/patterns/Latn.common-error.in:36 #: data/patterns/Latn.common-error.in:45 data/patterns/Latn.common-error.in:54 #: data/patterns/Latn.common-error.in:63 msgid "Unpack ligatures to individual characters" msgstr "Rozložit slitky na jednotlivé znaky" #: data/patterns/Latn.common-error.in:71 data/patterns/Latn.common-error.in:80 msgid "Spelling of a.m. and p.m." msgstr "Způsob psaní a.m. a p.m." #: data/patterns/Latn.common-error.in:72 data/patterns/Latn.common-error.in:81 msgid "Change the various spellings of 12-hour periods to \"a.m.\" and \"p.m.\"" msgstr "Změnit různé způsoby psaní 12 hodinových údobí na »a.m.« a »p.m.«" #: data/patterns/Latn.common-error.in:89 data/patterns/Latn.common-error.in:98 msgid "Letter \"O\" in a number" msgstr "Písmeno „O“ uprostřed čísla" #: data/patterns/Latn.common-error.in:90 data/patterns/Latn.common-error.in:99 msgid "Replace letter \"O\" with a zero in a number" msgstr "Nahradit uprostřed čísel písmeno „O“ za nulu" #: data/patterns/Latn.common-error.in:117 msgid "Double apostrophe" msgstr "Dvojitý odsuvník (apostrof)" #: data/patterns/Latn.common-error.in:118 msgid "Replace a double apostrophe with a quotation mark" msgstr "Nahradit dvojitý odsuvník (apostrof) za uvozovku" #: data/patterns/Latn.common-error.in:126 #: data/patterns/Latn.common-error.in:135 #: data/patterns/Latn.common-error.in:144 #: data/patterns/Latn.common-error.in:153 msgid "Spaces around brackets" msgstr "Mezery kolem závorek" #: data/patterns/Latn.common-error.in:127 #: data/patterns/Latn.common-error.in:136 #: data/patterns/Latn.common-error.in:145 #: data/patterns/Latn.common-error.in:154 msgid "Add or remove spaces around parantheses and square brackets" msgstr "Přidat nebo odstranit mezery kolem kulatých nebo hranatých závorek" #: data/patterns/Latn.common-error.in:162 msgid "Space after a dialogue dash" msgstr "Mezera za v dialogovou odrážkou" #: data/patterns/Latn.common-error.in:163 msgid "Add space after a dialogue dash" msgstr "Přidat mezeru za dialogovou pomlčku." #: data/patterns/Latn.common-error.in:172 msgid "Remove space before various punctuation marks" msgstr "Odstranit mezeru před různými interpunkčními znaménky" #: data/patterns/Latn.common-error.in:192 msgid "Space after an ellipsis" msgstr "Mezera za výpustkou" #: data/patterns/Latn.common-error.in:193 msgid "Add space after an ellipsis" msgstr "Přidat mezeru za výpustku" #: data/patterns/Latn.common-error.in:201 msgid "Space after a starting ellipsis" msgstr "Mezera za počáteční výpustkou" #: data/patterns/Latn.common-error.in:202 msgid "Remove space after an ellipsis that starts a line" msgstr "Odstranit mezeru za výpustkou na začátku řádku" #: data/patterns/Latn.common-error.in:210 #: data/patterns/Latn.common-error.in:221 #: data/patterns/Latn.common-error.in:232 #: data/patterns/Latn.common-error.in:242 msgid "Spaces around a quotation mark" msgstr "Mezery kolem uvozovek" #: data/patterns/Latn.common-error.in:211 #: data/patterns/Latn.common-error.in:222 #: data/patterns/Latn.common-error.in:233 #: data/patterns/Latn.common-error.in:243 msgid "Remove space after a starting- and before an ending quotation mark" msgstr "Odstranit mezeru po otevírací uvozovce a před uzavírací uvozovkou" #: data/patterns/Latn.common-error.in:252 #: data/patterns/Latn.common-error.in:261 msgid "Spaces around musical notes" msgstr "Mezery okolo hudebních not" #: data/patterns/Latn.common-error.in:253 #: data/patterns/Latn.common-error.in:262 msgid "Add spaces between musical note characters and lyrics" msgstr "Přidat mezery mezi znaky hudebních not a slova písně" #: data/patterns/Latn.common-error.in:270 #: data/patterns/Latn.common-error.in:279 msgid "Multiple question- and exclamation marks" msgstr "Více otazníků a vykřičníků najednou" #: data/patterns/Latn.common-error.in:271 #: data/patterns/Latn.common-error.in:280 msgid "" "Replace multiple consequtive question- and exclamation marks with only one" msgstr "Nahradit vícenásobné otazníky a vykřičníky za jeden" #: data/patterns/Latn.common-error.in:288 #: data/patterns/Latn.common-error.in:298 msgid "Periods around a punctuation mark" msgstr "Tečka vedle interpunkčního znaménka" #: data/patterns/Latn.common-error.in:289 #: data/patterns/Latn.common-error.in:299 msgid "Remove period before or after various punctuation marks" msgstr "Odstranit tečku před nebo za různými interpunkčními znaménky" #: data/patterns/Latn.common-error.in:308 msgid "Terminating double-dashes" msgstr "Závěrečné dvojité pomlčky" #: data/patterns/Latn.common-error.in:309 msgid "Replace a single clause-terminating dash with two dashes" msgstr "Nahradit jednu uzavírající větnou pomlčku dvěma pomlčkami" #: data/patterns/Latn.hearing-impaired.in:5 msgid "Sound in brackets" msgstr "Zvuk v hranatých závorkách" #: data/patterns/Latn.hearing-impaired.in:6 msgid "Remove description of a sound between square brackets" msgstr "Odstranit popis zvuku v hranatých závorkách" #: data/patterns/Latn.hearing-impaired.in:12 msgid "Sound in parantheses" msgstr "Zvuk v kulatých závorkách" #: data/patterns/Latn.hearing-impaired.in:13 msgid "Remove description of a sound between parantheses" msgstr "Odstranit popis zvuku v kulatých závorkách" #: data/patterns/Latn.hearing-impaired.in:19 msgid "Song lyrics between number signs" msgstr "Text písně mezi mezi dvojitými křížky" #: data/patterns/Latn.hearing-impaired.in:20 msgid "Remove song lyrics starting with or between number signs" msgstr "" "Odstranit text písně začínající nebo nacházející se mezi dvojitými křížky" #: data/patterns/Latn.hearing-impaired.in:27 msgid "One-line song lyrics between number signs" msgstr "Jednořádkový text písně mezi dvojitými křížky" #: data/patterns/Latn.hearing-impaired.in:28 msgid "Remove one-line song lyrics starting with or between number signs" msgstr "" "Odstranit jednořádkový text písně začínající nebo nacházející se mezi " "symboly dvojitých křížků" #: data/patterns/Latn.hearing-impaired.in:35 msgid "Speaker before a colon" msgstr "Mluvčí před dvojtečkou" #: data/patterns/Latn.hearing-impaired.in:36 msgid "Replace the name of the speaker before a colon with a dialogue dash" msgstr "Nahradit jméno mluvčího před dvojtečkou za dialogovou odrážku" #: data/patterns/Latn.line-break.in:5 data/patterns/Latn.line-break.in:13 msgid "Dialogue" msgstr "Dialog" #: data/patterns/Latn.line-break.in:6 data/patterns/Latn.line-break.in:14 msgid "Break according to dialogue separated by dashes" msgstr "Zalomení odpovídající dialogu odděleno pomlčkami" #: data/patterns/Latn.line-break.in:21 data/patterns/Latn.line-break.in:30 msgid "Clause" msgstr "Větný člen" #: data/patterns/Latn.line-break.in:22 data/patterns/Latn.line-break.in:31 msgid "Break according to clauses terminated by a punctuation mark" msgstr "Zalomení odpovídající větným členům ukončené interpunkčním znaménkem" #: data/patterns/Latn.line-break.in:38 msgid "Number and unit" msgstr "Číslo a jednotka" #: data/patterns/Latn.line-break.in:39 msgid "Do not break between a number and associated unit" msgstr "Nezalamovat mezi číslem a s ním spojenou jednotkou" #: data/patterns/Zyyy.common-error.in:5 data/patterns/Zyyy.common-error.in:14 msgid "Leading and trailing spaces" msgstr "Mezery na začátku a na konci" #: data/patterns/Zyyy.common-error.in:6 data/patterns/Zyyy.common-error.in:15 msgid "Remove spaces from the beginning and end of lines" msgstr "Odstranit mezery ze začátku a konce řádku" #: data/patterns/Zyyy.common-error.in:23 msgid "Multiple consecutive spaces" msgstr "Několik po sobě jdoucích mezer" #: data/patterns/Zyyy.common-error.in:24 msgid "Replace multiple consecutive spaces with only one" msgstr "Nahradit více po sobě jdoucích mezer jen jednou" #: data/patterns/Zyyy.common-error.in:32 data/patterns/Zyyy.common-error.in:45 #: data/patterns/Zyyy.common-error.in:55 data/patterns/Zyyy.common-error.in:65 msgid "Space between digits" msgstr "Mezery mezi číslicemi" #: data/patterns/Zyyy.common-error.in:33 data/patterns/Zyyy.common-error.in:46 #: data/patterns/Zyyy.common-error.in:56 data/patterns/Zyyy.common-error.in:66 msgid "Remove space between digits of a number" msgstr "Odstranit mezery mezi číslicemi v čísle" #: data/patterns/Zyyy.common-error.in:79 msgid "Musical notes" msgstr "Hudební noty" #: data/patterns/Zyyy.common-error.in:80 msgid "Replace Unicode musical note characters with number signs" msgstr "Nahradit znaky Unicode hudebních not dvojitými křížky" #: data/io.otsaloma.gaupol.appdata.xml.in:7 msgid "Editor for text-based subtitles" msgstr "Editor pro textově založené titulky" #: data/io.otsaloma.gaupol.appdata.xml.in:9 msgid "" "Gaupol is an editor for text-based subtitle files. It supports multiple " "subtitle file formats and provides means of creating subtitles, editing " "texts and timing subtitles to match video." msgstr "" "Gaupol je editor pro textově založené soubory titulků. Podporuje více " "formátů souborů titulků a poskytuje prostředky k vytváření titulků, " "upravování textů a časování titulků, aby odpovídaly obrazovému záznamu." #: data/io.otsaloma.gaupol.appdata.xml.in:40 msgid "Main window" msgstr "Hlavní okno" #: data/io.otsaloma.gaupol.desktop.in:5 msgid "Subtitle Editor" msgstr "Editor titulků" #: data/io.otsaloma.gaupol.desktop.in:6 msgid "Edit subtitle files" msgstr "Upravit soubory s titulky" #. TRANSLATORS: Search terms to find this application. Do NOT translate or #. localize the semicolons! The list MUST also end with a semicolon! #: data/io.otsaloma.gaupol.desktop.in:12 msgid "video;subtitles;captions;" msgstr "video;titulky;podtitulky;" gaupol-1.11/po/de.po000066400000000000000000002136061422217132500143000ustar00rootroot00000000000000# 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. # # Translators: # Osmo Salomaa , 2016 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-04-03 04:00+0300\n" "PO-Revision-Date: 2016-07-07 00:55+0000\n" "Last-Translator: Osmo Salomaa , 2016\n" "Language-Team: German (https://www.transifex.com/otsaloma/teams/64879/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: aeidon/enums.py:40 gaupol/enums.py:38 msgid "Subtitle number" msgstr "Untertitelnummer" #: aeidon/enums.py:43 msgid "Subtitle position" msgstr "Untertitelposition" #: aeidon/enums.py:59 msgid "23.976 fps" msgstr "23,976 fps" #: aeidon/enums.py:63 msgid "24.000 fps" msgstr "24,000 fps" #: aeidon/enums.py:67 msgid "25.000 fps" msgstr "25,000 fps" #: aeidon/enums.py:71 msgid "29.970 fps" msgstr "29,970 fps" #: aeidon/enums.py:75 data/ui/menubar.ui:248 msgid "30.000 fps" msgstr "" #: aeidon/enums.py:79 data/ui/menubar.ui:253 msgid "50.000 fps" msgstr "" #: aeidon/enums.py:83 data/ui/menubar.ui:258 msgid "59.940 fps" msgstr "" #: aeidon/enums.py:87 data/ui/menubar.ui:263 msgid "60.000 fps" msgstr "" #: aeidon/enums.py:112 msgid "Mac (classic)" msgstr "Mac (klassisch)" #. TRANSLATORS: Most of the character encoding descriptions are copied from #. gedit, which is translated to very many languages. Check the gedit .po #. files for a reference: #. . #: aeidon/encodings.py:40 aeidon/encodings.py:43 aeidon/encodings.py:46 msgid "English" msgstr "Englisch" #: aeidon/encodings.py:41 aeidon/encodings.py:42 aeidon/encodings.py:69 msgid "Chinese traditional" msgstr "Chinesisch, traditionell" #: aeidon/encodings.py:44 msgid "German" msgstr "" #: aeidon/encodings.py:45 aeidon/encodings.py:54 aeidon/encodings.py:59 #: aeidon/encodings.py:79 aeidon/encodings.py:105 msgid "Hebrew" msgstr "Hebräisch" #: aeidon/encodings.py:47 aeidon/encodings.py:51 aeidon/encodings.py:56 #: aeidon/encodings.py:73 aeidon/encodings.py:76 aeidon/encodings.py:98 #: aeidon/encodings.py:111 aeidon/encodings.py:122 msgid "Western" msgstr "Westlich" #: aeidon/encodings.py:48 aeidon/encodings.py:61 aeidon/encodings.py:80 #: aeidon/encodings.py:103 msgid "Arabic" msgstr "Arabisch" #: aeidon/encodings.py:49 aeidon/encodings.py:64 aeidon/encodings.py:66 #: aeidon/encodings.py:77 aeidon/encodings.py:104 aeidon/encodings.py:119 msgid "Greek" msgstr "Griechisch" #: aeidon/encodings.py:50 aeidon/encodings.py:81 aeidon/encodings.py:101 #: aeidon/encodings.py:109 msgid "Baltic" msgstr "Baltisch" #: aeidon/encodings.py:52 aeidon/encodings.py:74 aeidon/encodings.py:99 #: aeidon/encodings.py:121 msgid "Central European" msgstr "Zentraleuropäisch" #: aeidon/encodings.py:53 aeidon/encodings.py:75 aeidon/encodings.py:102 #: aeidon/encodings.py:118 msgid "Cyrillic" msgstr "Kyrillisch" #: aeidon/encodings.py:55 aeidon/encodings.py:71 aeidon/encodings.py:78 #: aeidon/encodings.py:106 aeidon/encodings.py:123 msgid "Turkish" msgstr "Türkisch" #: aeidon/encodings.py:57 msgid "Portuguese" msgstr "Portugiesisch" #: aeidon/encodings.py:58 aeidon/encodings.py:120 msgid "Icelandic" msgstr "Isländisch" #: aeidon/encodings.py:60 msgid "Canadian" msgstr "Kanadisch" #: aeidon/encodings.py:62 aeidon/encodings.py:107 msgid "Nordic" msgstr "Nordisch" #: aeidon/encodings.py:63 aeidon/encodings.py:114 msgid "Russian" msgstr "Russisch" #: aeidon/encodings.py:65 aeidon/encodings.py:108 msgid "Thai" msgstr "Thailändisch" #: aeidon/encodings.py:67 aeidon/encodings.py:83 aeidon/encodings.py:84 #: aeidon/encodings.py:85 aeidon/encodings.py:91 aeidon/encodings.py:92 #: aeidon/encodings.py:93 aeidon/encodings.py:94 aeidon/encodings.py:95 #: aeidon/encodings.py:96 aeidon/encodings.py:125 aeidon/encodings.py:126 #: aeidon/encodings.py:127 msgid "Japanese" msgstr "Japanisch" #: aeidon/encodings.py:68 aeidon/encodings.py:86 aeidon/encodings.py:97 #: aeidon/encodings.py:113 msgid "Korean" msgstr "Koreanisch" #: aeidon/encodings.py:70 msgid "Urdu" msgstr "Urdu" #: aeidon/encodings.py:72 aeidon/encodings.py:116 msgid "Ukrainian" msgstr "Ukrainisch" #: aeidon/encodings.py:82 msgid "Vietnamese" msgstr "Vietnamesisch" #: aeidon/encodings.py:87 aeidon/encodings.py:90 msgid "Chinese simplified" msgstr "Vereinfachtes Chinesisch" #: aeidon/encodings.py:88 aeidon/encodings.py:89 msgid "Chinese unified" msgstr "Chinesisch vereinfacht" #: aeidon/encodings.py:100 aeidon/encodings.py:112 msgid "South European" msgstr "Südeuropäisch" #: aeidon/encodings.py:110 msgid "Celtic" msgstr "Keltisch" #: aeidon/encodings.py:115 msgid "Tajik" msgstr "" #: aeidon/encodings.py:117 msgid "Kazakh" msgstr "" #: aeidon/encodings.py:124 msgid "Cyrillic Asian" msgstr "Asiatisches Kyrillisch" #: aeidon/encodings.py:128 aeidon/encodings.py:129 aeidon/encodings.py:130 #: aeidon/encodings.py:131 aeidon/encodings.py:132 aeidon/encodings.py:133 #: aeidon/encodings.py:134 aeidon/encodings.py:135 aeidon/encodings.py:136 msgid "Unicode" msgstr "Unicode" #: aeidon/encodings.py:156 #, python-brace-format msgid "{description} ({name})" msgstr "{description} ({name})" #: aeidon/encodings.py:232 msgid "Current locale ({})" msgstr "Aktuelle Locale ({})" #: aeidon/locales.py:46 #, python-brace-format msgid "{language} ({country})" msgstr "{language} ({country})" #: aeidon/agents/search.py:227 msgid "Replacing" msgstr "Ersetzen" #: aeidon/agents/search.py:256 aeidon/agents/search.py:258 msgid "Replacing all" msgstr "Alle ersetzen" #: aeidon/agents/position.py:74 msgid "Adjusting durations" msgstr "Laufzeiten anpassen" #: aeidon/agents/position.py:96 msgid "Converting framerate" msgstr "Bildwiederholfrequenz konvertieren" #: aeidon/agents/position.py:146 msgid "Setting framerate" msgstr "Bildwiederholfrequenz-Einstellung" #: aeidon/agents/position.py:168 msgid "Shifting positions" msgstr "Positionen verschieben" #: aeidon/agents/position.py:188 msgid "Transforming positions" msgstr "Positionen umwandeln" #: aeidon/agents/clipboard.py:44 msgid "Cutting texts" msgstr "Texte ausschneiden" #: aeidon/agents/clipboard.py:61 msgid "Pasting texts" msgstr "Texte einfügen" #: aeidon/agents/text.py:91 msgid "Breaking lines" msgstr "Zeilen umbrechen" #: aeidon/agents/text.py:128 msgid "Capitalizing texts" msgstr "Texte großschreiben" #: aeidon/agents/text.py:185 msgid "Correcting common errors" msgstr "Typische Fehler korrigieren" #: aeidon/agents/text.py:234 msgid "Removing hearing impaired texts" msgstr "Texte für Hörgeschädigte entfernen" #: aeidon/agents/text.py:315 msgid "Joining words by spell-check suggestions" msgstr "Wörter von Rechtschreibprüfungsvorschlägen zusammenfügen" #: aeidon/agents/text.py:354 msgid "Splitting words by spell-check suggestions" msgstr "Wörter von Rechtschreibprüfungsvorschlägen teilen" #: aeidon/agents/set.py:58 aeidon/agents/set.py:80 aeidon/agents/set.py:113 msgid "Editing position" msgstr "Positionen bearbeiten" #: aeidon/agents/set.py:129 msgid "Editing text" msgstr "Text bearbeiten" #: aeidon/agents/edit.py:35 msgid "Clearing texts" msgstr "Texte bereinigen" #: aeidon/agents/edit.py:61 aeidon/agents/edit.py:83 msgid "Inserting subtitles" msgstr "Untertitel einfügen" #: aeidon/agents/edit.py:103 msgid "Merging subtitles" msgstr "Untertitel zusammenführen" #: aeidon/agents/edit.py:114 msgid "Removing subtitles" msgstr "Untertitel entfernen" #: aeidon/agents/edit.py:131 msgid "Replacing positions" msgstr "Positionen ersetzen" #: aeidon/agents/edit.py:147 msgid "Replacing texts" msgstr "Texte ersetzen" #: aeidon/agents/edit.py:171 msgid "Splitting subtitle" msgstr "Untertitel teilen" #: aeidon/agents/format.py:49 msgid "Adding dialogue dashes" msgstr "Gedankenstriche hinzufügen" #: aeidon/agents/format.py:68 msgid "Changing case" msgstr "Groß-/Kleinschreibung ändern" #: aeidon/agents/format.py:92 msgid "Italicizing" msgstr "Kursiv setzen" #: aeidon/agents/format.py:108 msgid "Removing dialogue dashes" msgstr "Gedankenstriche entfernen" #: aeidon/agents/format.py:174 msgid "Unitalicizing" msgstr "Schrift aufrichten" #: gaupol/application.py:219 gaupol/agents/open.py:203 msgid "Open" msgstr "Öffnen" #: gaupol/application.py:223 msgid "Open main files" msgstr "Hauptdateien öffnen" #: gaupol/application.py:230 msgid "Save" msgstr "" #: gaupol/application.py:233 msgid "Save the current main document" msgstr "Das aktuelle Hauptdokument speichern" #: gaupol/application.py:238 msgid "Undo" msgstr "" #: gaupol/application.py:242 msgid "Undo the last action" msgstr "Die letzte Aktion rückgängig machen" #: gaupol/application.py:249 msgid "Redo" msgstr "" #: gaupol/application.py:252 msgid "Redo the last undone action" msgstr "Die letzte rückgängig gemachte Aktion nochmal machen" #: gaupol/application.py:260 msgid "Insert" msgstr "Einfügen" #: gaupol/application.py:262 msgid "Insert new subtitles" msgstr "Neue Untertitel einfügen" #: gaupol/application.py:266 #: data/extensions/custom-framerates/preferences-dialog.ui:78 msgid "Remove" msgstr "Entfernen" #: gaupol/application.py:268 msgid "Remove the selected subtitles" msgstr "Die ausgewählten Untertitel entfernen" #: gaupol/application.py:273 data/ui/search-dialog.ui:283 msgid "Find" msgstr "Finden" #: gaupol/application.py:275 msgid "Search for and replace text" msgstr "Suchen nach und Ersetzen von Text" #: gaupol/application.py:279 data/ui/preferences-dialog.ui:942 msgid "Video" msgstr "Video" #: gaupol/application.py:281 msgid "Show or hide the video player" msgstr "" #: gaupol/application.py:285 data/ui/preferences-dialog.ui:1173 msgid "Preview" msgstr "Vorschau" #: gaupol/application.py:287 msgid "Preview from selected position with a video player" msgstr "Vorschau von einer ausgewählten Position mit einem Video-Spieler" #: gaupol/enums.py:37 msgid "No." msgstr "Nr." #: gaupol/enums.py:43 msgid "Start" msgstr "Start" #: gaupol/enums.py:44 msgid "Start position" msgstr "Startposition" #: gaupol/enums.py:49 msgid "End" msgstr "Ende" #: gaupol/enums.py:50 msgid "End position" msgstr "Endposition" #. TRANSLATORS: 'Dur.' is short for duration. It is used in the header #. of a column that contains numbers five digits wide. #: gaupol/enums.py:57 msgid "Dur." msgstr "Laufz" #: gaupol/enums.py:58 msgid "Duration" msgstr "Laufzeit" #: gaupol/enums.py:63 gaupol/enums.py:64 msgid "Text" msgstr "" #: gaupol/enums.py:69 gaupol/enums.py:70 msgid "Translation" msgstr "" #: gaupol/enums.py:82 msgid "characters" msgstr "Zeichen" #: gaupol/enums.py:85 msgid "ems" msgstr "ems" #: gaupol/page.py:60 msgid "Untitled {:d}" msgstr "Ohne Titel {:d}" #: gaupol/page.py:133 msgid "Close project" msgstr "Projekt schließen" #: gaupol/page.py:145 msgid "{} translation" msgstr "{}-Übersetzung" #: gaupol/page.py:302 msgid "Path:" msgstr "Pfad:" #: gaupol/page.py:303 msgid "Format:" msgstr "Format:" #: gaupol/page.py:304 msgid "Encoding:" msgstr "" #: gaupol/page.py:305 msgid "Newlines:" msgstr "Zeilenumbrüche:" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:99 msgid "Tasks and Target" msgstr "" #: gaupol/assistants.py:128 msgid "Correct texts in the text column" msgstr "" #: gaupol/assistants.py:129 msgid "Correct texts in the translation column" msgstr "" #: gaupol/assistants.py:138 msgid "Correct texts in selected subtitles" msgstr "" #: gaupol/assistants.py:139 msgid "Correct texts in current project" msgstr "" #: gaupol/assistants.py:140 msgid "Correct texts in all open projects" msgstr "" #: gaupol/assistants.py:363 msgid "Other" msgstr "Anderes" #: gaupol/assistants.py:439 msgid "Capitalize texts written in lower case" msgstr "Kleingeschriebene Texte großschreiben" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:443 msgid "Capitalization Patterns" msgstr "" #: gaupol/assistants.py:445 msgid "Capitalize texts" msgstr "Texte großschreiben" #: gaupol/assistants.py:468 msgid "Correct common errors made by humans or image recognition software" msgstr "" "Fehler korrigieren, die häufig durch Menschen oder Bilderkennungssoftware " "gemacht werden" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:472 msgid "Common Error Patterns" msgstr "" #: gaupol/assistants.py:474 msgid "Correct common errors" msgstr "Häufige Fehler korrigieren" #: gaupol/assistants.py:526 msgid "Remove explanatory texts meant for the hearing impaired" msgstr "Erklärende Texte, die für Hörgeschädigte gedacht sind, entfernen" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:530 msgid "Hearing Impaired Patterns" msgstr "" #: gaupol/assistants.py:532 msgid "Remove hearing impaired texts" msgstr "Texte für Hörgeschädigte entfernen" #: gaupol/assistants.py:544 msgid "" "Use spell-check suggestions to fix whitespace detection errors of image " "recognition software" msgstr "" "Rechtschreibprüfungsvorschläge benutzen, um Leerraumabfragefehler der " "Bilderkennungs-Software zu beheben" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:548 msgid "Joining and Splitting Words" msgstr "" #: gaupol/assistants.py:550 msgid "Join or Split Words" msgstr "Wörter zusammensetzen oder trennen" #: gaupol/assistants.py:599 gaupol/agents/tools.py:45 msgid "Failed to load dictionary for language \"{}\"" msgstr "Laden des Wörterbuchs für die Sprache »{}« fehlgeschlagen." #: gaupol/assistants.py:601 gaupol/player.py:263 gaupol/player.py:381 #: gaupol/dialogs/search.py:560 gaupol/dialogs/search.py:568 #: gaupol/dialogs/text_edit.py:49 gaupol/dialogs/encoding.py:56 #: gaupol/agents/open.py:328 gaupol/agents/open.py:337 #: gaupol/agents/open.py:345 gaupol/agents/open.py:354 #: gaupol/agents/tools.py:48 gaupol/agents/save.py:197 #: gaupol/agents/save.py:205 gaupol/agents/preview.py:108 #: gaupol/agents/preview.py:116 gaupol/agents/preview.py:125 #: gaupol/agents/preview.py:133 msgid "_OK" msgstr "" #: gaupol/assistants.py:635 msgid "Break text into lines of defined length" msgstr "Text in Zeilen mit vorgegebener Länge umbrechen" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:639 msgid "Line-Break Patterns" msgstr "" #: gaupol/assistants.py:641 msgid "Break lines" msgstr "Zeilen umbrechen" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:679 msgid "Line-Break Options" msgstr "" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:763 msgid "Correcting Texts" msgstr "Texte korrigieren" #: gaupol/assistants.py:769 msgid "Each task is now being run on each project." msgstr "Jede Aufgabe wird nun für jedes Projekt ausgeführt." #: gaupol/assistants.py:793 #, python-brace-format msgid "{current:d} of {total:d} tasks complete" msgstr "{current:d} von {total:d} Aufgaben komplett" #: gaupol/assistants.py:801 msgid "Project: {}" msgstr "Projekt: {}" #: gaupol/assistants.py:807 msgid "Task: {}" msgstr "Aufgabe: {}" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:832 msgid "Confirm Changes" msgstr "Änderungen bestätigen" #: gaupol/assistants.py:892 msgid "Accept" msgstr "Akzeptieren" #: gaupol/assistants.py:898 msgid "Original Text" msgstr "Originaltext" #: gaupol/assistants.py:899 msgid "Corrected Text" msgstr "Korrigierter Text" #: gaupol/assistants.py:1048 msgid "Correct Texts" msgstr "Texte korrigieren" #: gaupol/assistants.py:1076 msgid "Correcting texts" msgstr "Texte werden korrigiert" #: gaupol/assistants.py:1092 #, python-brace-format msgid "Edited {edits:d} and removed {removals:d} subtitles" msgstr "{edits:d} Untertitel bearbeitet und {removals:d} entfernt" #: gaupol/assistants.py:1126 msgid "Confirm {:d} Change" msgid_plural "Confirm {:d} Changes" msgstr[0] "" msgstr[1] "" #: gaupol/renderers/multiline.py:86 msgid "Italic" msgstr "" #: gaupol/player.py:372 msgid "No video streams found" msgstr "" #: gaupol/player.py:379 msgid "Failed to initialize playback" msgstr "" #: gaupol/dialogs/search.py:189 data/ui/menubar.ui:524 msgid "_Help" msgstr "_Hilfe" #: gaupol/dialogs/search.py:471 msgid "Found and replaced {:d} occurence" msgid_plural "Found and replaced {:d} occurences" msgstr[0] "" msgstr[1] "" #: gaupol/dialogs/search.py:488 msgid "\"{}\" not found" msgstr "»{}« nicht gefunden" #: gaupol/dialogs/search.py:558 msgid "Error in regular expression pattern" msgstr "Fehler im regulären Ausdrucksmuster" #: gaupol/dialogs/search.py:566 msgid "Error in regular expression replacement" msgstr "Fehler in Ersetzung von regulärem Ausdruck" #: gaupol/dialogs/text_edit.py:48 gaupol/dialogs/framerate_convert.py:63 #: gaupol/dialogs/insert.py:44 gaupol/dialogs/encoding.py:55 #: gaupol/dialogs/split.py:44 gaupol/dialogs/multi_close.py:54 #: gaupol/dialogs/open.py:63 gaupol/dialogs/position_transform.py:69 #: gaupol/dialogs/position_shift.py:71 gaupol/dialogs/multi_save.py:83 #: gaupol/dialogs/multi_save.py:215 gaupol/dialogs/duration_adjust.py:86 #: gaupol/dialogs/save.py:73 gaupol/dialogs/video.py:41 #: gaupol/agents/open.py:363 gaupol/agents/open.py:375 #: gaupol/agents/open.py:387 gaupol/agents/close.py:71 #: data/extensions/custom-framerates/custom-framerates.py:39 msgid "_Cancel" msgstr "" #: gaupol/dialogs/text_edit.py:53 msgid "Edit Text" msgstr "Text bearbeiten" #: gaupol/dialogs/framerate_convert.py:64 msgid "Co_nvert" msgstr "_Konvertieren" #: gaupol/dialogs/insert.py:45 msgid "_Insert" msgstr "_Einfügen" #: gaupol/dialogs/insert.py:54 msgid "Above selection" msgstr "Auswahl oben" #: gaupol/dialogs/insert.py:55 msgid "Below selection" msgstr "Auswahl unten" #: gaupol/dialogs/encoding.py:60 data/ui/preferences-dialog.ui:70 msgid "Character Encodings" msgstr "Zeichenkodierung" #: gaupol/dialogs/encoding.py:78 gaupol/dialogs/encoding.py:125 msgid "Description" msgstr "Beschreibung" #: gaupol/dialogs/encoding.py:85 gaupol/dialogs/encoding.py:132 msgid "Encoding" msgstr "Kodierung" #: gaupol/dialogs/encoding.py:141 msgid "Show in Menu" msgstr "Im Menü anzeigen" #: gaupol/dialogs/split.py:45 msgid "_Split" msgstr "_Zerteilen" #: gaupol/dialogs/split.py:76 msgid "Splitting project" msgstr "Projekt teilen" #: gaupol/dialogs/split.py:97 #, python-brace-format msgid "Split {amount:d} subtitles to project \"{name}\"" msgstr "{amount:d} Untertitel zu Projekt »{name}« teilen" #: gaupol/dialogs/spell_check.py:269 msgid "Spell-checking" msgstr "Rechtschreibprüfung" #: gaupol/dialogs/preferences.py:217 msgid "{} Extension Website" msgstr "{}-Website-Erweiterung" #: gaupol/dialogs/preferences.py:429 msgid "Custom" msgstr "Angepasst" #: gaupol/dialogs/multi_close.py:38 msgid "Save changes to documents before closing?" msgstr "Änderungen an Dokumenten vor dem Schließen speichern?" #: gaupol/dialogs/multi_close.py:39 gaupol/agents/open.py:384 #: gaupol/agents/close.py:68 msgid "If you don't save, changes will be permanently lost." msgstr "Wenn Sie nicht speichern, sind die Änderungen für immer verloren." #: gaupol/dialogs/multi_close.py:53 gaupol/agents/close.py:70 msgid "Close _Without Saving" msgstr "Schließen _ohne zu speichern" #: gaupol/dialogs/multi_close.py:55 gaupol/dialogs/multi_save.py:84 #: gaupol/dialogs/save.py:74 gaupol/agents/open.py:388 #: gaupol/agents/close.py:72 data/ui/menubar.ui:34 msgid "_Save" msgstr "S_peichern" #: gaupol/dialogs/multi_close.py:70 msgid "Select the _main documents you want to save:" msgstr "_Wählen Sie das Hauptdokument, das Sie speichern wollen:" #: gaupol/dialogs/multi_close.py:95 msgid "Select the _translation documents you want to save:" msgstr "Wählen Sie die _Übersetzungsdokumente, die Sie speichern wollen:" #: gaupol/dialogs/open.py:64 gaupol/agents/open.py:364 #: gaupol/agents/open.py:376 msgid "_Open" msgstr "" #: gaupol/dialogs/position_transform.py:70 msgid "_Transform" msgstr "U_mwandeln" #: gaupol/dialogs/position_shift.py:72 msgid "_Shift" msgstr "_Verschieben" #: gaupol/dialogs/position_shift.py:150 msgid "frames" msgstr "Bilder" #: gaupol/dialogs/position_shift.py:168 data/ui/preferences-dialog.ui:911 msgid "seconds" msgstr "Sekunden" #: gaupol/dialogs/about.py:36 msgid "About Gaupol" msgstr "Über Gaupol" #: gaupol/dialogs/about.py:40 msgid "Subtitle editor" msgstr "Untertitel-Editor" #. TRANSLATORS: This is a special message that shouldn't be translated #. literally. It is used in the about dialog to give credits to the #. translators. Thus, you should translate it to your name and email #. address. You can also include other translators who have contributed #. to this translation; in that case, please write them on separate #. lines seperated by newlines (\n). #: gaupol/dialogs/about.py:51 msgid "translator-credits" msgstr "Chris Leick, " #: gaupol/dialogs/about.py:54 msgid "Gaupol Website" msgstr "Gaupol-Website" #: gaupol/dialogs/append.py:35 msgid "Append File" msgstr "Datei anhängen" #: gaupol/dialogs/debug.py:43 msgid "Something went wrong" msgstr "" #: gaupol/dialogs/debug.py:44 msgid "" "You have probably discovered a bug. Please report it by providing the below " "information and a description of what you were doing." msgstr "" #: gaupol/dialogs/debug.py:52 msgid "_Report Bug" msgstr "" #: gaupol/dialogs/debug.py:53 data/ui/menubar.ui:56 msgid "_Quit" msgstr "_Beenden" #: gaupol/dialogs/debug.py:54 gaupol/dialogs/preview_error.py:45 #: data/ui/menubar.ui:52 data/ui/tab-popup.ui:16 msgid "_Close" msgstr "_Schließen" #: gaupol/dialogs/multi_save.py:98 gaupol/dialogs/save.py:110 msgid "{} (recommended)" msgstr "" #: gaupol/dialogs/multi_save.py:212 msgid "" "{:d} of the files to be saved already exist. Do you want to replace them?" msgstr "" "{:d} der zu speichernden Dateien existieren bereits. Möchten Sie sie " "ersetzen?" #: gaupol/dialogs/multi_save.py:213 msgid "" "The files already exist in \"{}\". Replacing them will overwrite their " "contents." msgstr "" "Die Dateien exisiteren bereits in »{}«. Sie zu ersetzen wird ihren Inhalt " "überschreiben." #: gaupol/dialogs/multi_save.py:216 data/ui/search-dialog.ui:192 #: data/ui/spell-check-dialog.ui:122 msgid "_Replace" msgstr "Erset_zen" #: gaupol/dialogs/duration_adjust.py:70 msgid "Adjusted duration of {:d} subtitle" msgid_plural "Adjusted durations of {:d} subtitles" msgstr[0] "" msgstr[1] "" #: gaupol/dialogs/duration_adjust.py:87 msgid "_Adjust" msgstr "_Anpassen" #: gaupol/dialogs/preview_error.py:36 msgid "Preview in video player failed" msgstr "Vorschau im Video-Spieler fehlgeschlagen" #: gaupol/dialogs/preview_error.py:37 msgid "" "There is probably a problem with either the video file or the video player. " "See the preferences dialog to choose the video player or to customize the " "command." msgstr "" #: gaupol/dialogs/language.py:97 msgid "Set Language" msgstr "Sprache setzen" #: gaupol/dialogs/video.py:52 gaupol/dialogs/file.py:59 msgid "All files" msgstr "Alle Dateien" #: gaupol/dialogs/video.py:56 msgid "Video files" msgstr "Video-Dateien" #: gaupol/dialogs/file.py:63 msgid "All supported files" msgstr "Alle unterstützten Dateien" #: gaupol/dialogs/file.py:77 #, python-brace-format msgid "{format} (*{extension})" msgstr "{format} (*{extension})" #: gaupol/dialogs/file.py:120 msgid "Auto-detected" msgstr "Automatisch erkannt" #: gaupol/dialogs/file.py:122 msgid "Other…" msgstr "Andere …" #: gaupol/agents/menu.py:94 gaupol/agents/menu.py:103 #: gaupol/agents/menu.py:110 msgid "File not found" msgstr "" #: gaupol/agents/open.py:85 #, python-brace-format msgid "Appended {amount:d} subtitles from \"{basename}\"" msgstr "{amount:d} Untertitel von »{basename}« angehängt" #: gaupol/agents/open.py:96 msgid "Appending file" msgstr "Datei anhängen" #: gaupol/agents/open.py:111 msgid "File \"{}\" is already open" msgstr "Datei »{}« ist bereits geöffnet" #: gaupol/agents/open.py:214 msgid "Open Translation" msgstr "Übersetzung öffnen" #: gaupol/agents/open.py:223 msgid "Select Video" msgstr "Video auswählen" #: gaupol/agents/open.py:224 msgid "_Select" msgstr "_Auswählen" #: gaupol/agents/open.py:325 msgid "Failed to decode file \"{}\" with all attempted codecs" msgstr "Dekodierung der Datei »{}« mit allen versuchten Codecs fehlgeschlagen" #: gaupol/agents/open.py:326 msgid "Please try to open the file with a different character encoding." msgstr "" "Bitte versuchen Sie die Datei mit einer anderen Zeichenkodierung zu öffnen." #: gaupol/agents/open.py:334 msgid "Failed to recognize format of file \"{}\"" msgstr "Das Format der Datei »{}« konnte nicht erkannt werden" #: gaupol/agents/open.py:335 msgid "" "Please check that the file you are trying to open is a subtitle file of a " "format supported by Gaupol." msgstr "" "Bitte prüfen Sie, ob die Datei, die Sie zu öffnen versuchen, eine " "Untertiteldatei ist, deren Format Gaupol unterstützt." #: gaupol/agents/open.py:343 msgid "Failed to open file \"{}\"" msgstr "Öffnen der Datei »{}« fehlgeschlagen" #: gaupol/agents/open.py:351 msgid "Failed to parse file \"{}\"" msgstr "Auswerten der Datei »{}« fehlgeschlagen" #: gaupol/agents/open.py:352 msgid "Please check that the file you are trying to open is a valid {} file." msgstr "" #: gaupol/agents/open.py:360 msgid "Open abnormally large file \"{}\"?" msgstr "Außergewöhnlich große Datei »{}« öffnen?" #: gaupol/agents/open.py:361 msgid "" "Size of the file is {:.1f} MB, which is abnormally large for a text-based " "subtitle file. Please, check that you are not trying to open a binary file." msgstr "" "Die Datei ist {:.1f} MB groß, was für eine textbasierte Untertiteldatei " "außerordentlich viel ist. Bitte prüfen Sie, ob sie nicht versuchen, eine " "Binärdatei zu öffnen." #: gaupol/agents/open.py:371 msgid "Open unsorted file \"{}\"?" msgstr "Unsortierte Datei »{}« öffnen?" #: gaupol/agents/open.py:372 msgid "" "The order of {:d} subtitles needs to be changed. If {:d} sounds like a lot, " "the file may be erroneously composed." msgstr "" "Die Reihenfolge von {:d} Untertiteln muss geändert werden. Wenn {:d} klingt," " als ob es viel sei, könnte die Datei irrtümlicherweise zusammengesetzt " "worden sein." #: gaupol/agents/open.py:383 msgid "Save changes to translation document \"{}\" before opening a new one?" msgstr "" "Änderungen in der Übersetzungsdatei »{}« speichern, bevor eine neue geöffnet" " wird?" #: gaupol/agents/open.py:386 msgid "Open _Without Saving" msgstr "Öffnen _ohne zu speichern" #: gaupol/agents/close.py:66 msgid "Save changes to document \"{}\" before closing?" msgstr "" #: gaupol/agents/edit.py:101 gaupol/agents/edit.py:119 msgid "Stretching end position" msgstr "" #: gaupol/agents/edit.py:208 msgid "Inserted {:d} subtitle to fit clipboard contents" msgid_plural "Inserted {:d} subtitles to fit clipboard contents" msgstr[0] "" msgstr[1] "" #: gaupol/agents/edit.py:334 gaupol/agents/edit.py:352 msgid "Stretching start position" msgstr "" #: gaupol/agents/edit.py:411 msgid "Use Shift+Return for line-break" msgstr "Feststelltaste+Eingabetaste für Zeilenumbruch benutzen" #: gaupol/agents/save.py:129 msgid "Save As" msgstr "Speichern als" #: gaupol/agents/save.py:135 msgid "Saved main document as \"{}\"" msgstr "Hauptdokument als »{}« gespeichert" #: gaupol/agents/save.py:153 msgid "Save Translation As" msgstr "Übersetzung speichern als" #: gaupol/agents/save.py:159 msgid "Saved translation document as \"{}\"" msgstr "Übersetzungsdokument als »{}« gespeichert" #: gaupol/agents/save.py:194 #, python-brace-format msgid "Failed to encode file \"{basename}\" with codec \"{codec}\"" msgstr "Kodieren der Datei »{basename}« mit Codec »{codec}« fehlgeschlagen" #: gaupol/agents/save.py:195 msgid "Please try to save the file with a different character encoding." msgstr "" "Bitte versuchen Sie die Datei mit einer anderen ZeichenKodierung zu " "speichern" #: gaupol/agents/save.py:203 msgid "Failed to save file \"{}\"" msgstr "Speichern von Datei »{}« fehlgeschlagen" #: gaupol/agents/video.py:67 data/ui/menubar.ui:380 msgid "_Play/Pause" msgstr "" #: gaupol/agents/video.py:69 msgid "Play or pause video" msgstr "" #: gaupol/agents/video.py:75 data/ui/menubar.ui:390 msgid "Seek _Previous" msgstr "" #: gaupol/agents/video.py:77 msgid "Seek to the start of the previous subtitle" msgstr "" #: gaupol/agents/video.py:81 data/ui/menubar.ui:394 msgid "Seek _Next" msgstr "" #: gaupol/agents/video.py:83 msgid "Seek to the start of the next subtitle" msgstr "" #: gaupol/agents/video.py:88 data/ui/menubar.ui:400 msgid "Seek _Backward" msgstr "" #: gaupol/agents/video.py:90 msgid "Seek backward" msgstr "" #: gaupol/agents/video.py:94 data/ui/menubar.ui:404 msgid "Seek _Forward" msgstr "" #: gaupol/agents/video.py:96 msgid "Seek forward" msgstr "" #: gaupol/agents/video.py:109 msgid "Volume" msgstr "" #: gaupol/agents/video.py:189 msgid "Load Video" msgstr "" #: gaupol/agents/video.py:189 msgid "_Load" msgstr "" #: gaupol/agents/video.py:361 msgid "Track {:d}" msgstr "" #: gaupol/agents/preview.py:105 msgid "Failed to encode subtitle file to temporary directory \"{}\"" msgstr "" "Kodieren der Untertiteldatei in das temporäre Verzeichnis »{}« " "fehlgeschlagen" #: gaupol/agents/preview.py:106 msgid "" "Subtitle data could not be encoded to a temporary file for preview with the " "current character encoding. Please first save the subtitle file with a " "different character encoding." msgstr "" "Untertiteldaten konnten nicht für die Vorschau mit einer anderen " "Zeichenkodierung in eine temporäre Datei kodiert werden. Bitte speichern Sie" " die Untertiteldatei zuerst mit einer anderen Zeichenkodierung." #: gaupol/agents/preview.py:114 msgid "Failed to save subtitle file to temporary directory \"{}\"" msgstr "" "Speichern der Untertiteldatei in das temporäre Verzeichnis »{}« " "fehlgeschlagen" #: gaupol/agents/preview.py:122 msgid "Video player not found" msgstr "" #: gaupol/agents/preview.py:123 msgid "" "Please install one of the supported video players: mpv (recommended), " "MPlayer or VLC. See the preferences dialog to choose the video player or to " "customize the command." msgstr "" #: gaupol/agents/preview.py:131 msgid "Failed to launch video player" msgstr "Starten des Video-Spielers fehlgeschlagen" #: gaupol/applicationman.py:105 msgid "gaupol [OPTION...] [FILE...] [+[NUM]]" msgstr "gaupol [OPTION...] [DATEI...] [+[NUM]]" #: gaupol/applicationman.py:109 msgid "FILE..." msgstr "" #: gaupol/applicationman.py:112 msgid "subtitle files to open" msgstr "" #: gaupol/applicationman.py:122 msgid "ENCODING" msgstr "KODIERUNG" #: gaupol/applicationman.py:125 msgid "set the character encoding used to open files" msgstr "Zeichenkodierung setzen, die beim Öffnen von Dateien benutzt wird" #: gaupol/applicationman.py:132 msgid "list all available character encodings" msgstr "alle verfügbaren Zeichenkodierungen auflisten" #: gaupol/applicationman.py:137 gaupol/applicationman.py:154 msgid "FILE" msgstr "DATEI" #: gaupol/applicationman.py:140 msgid "open translation file" msgstr "Übersetzungsdatei öffnen" #: gaupol/applicationman.py:145 msgid "METHOD" msgstr "METHODE" #: gaupol/applicationman.py:149 msgid "method used to align translation subtitles: 'number' or 'position'" msgstr "" "Methode, die zum Ausrichten der Ersetzungsuntertitel benutzt wird: »Zahl» " "oder »Position«" #: gaupol/applicationman.py:157 msgid "select video file" msgstr "Video-Datei auswählen" #: data/extensions/custom-framerates/custom-framerates.py:40 #: data/ui/spell-check-dialog.ui:152 msgid "_Add" msgstr "_Hinzufügen" #: data/extensions/custom-framerates/custom-framerates.py:171 msgid "{:.3f} fps" msgstr "" #: data/extensions/custom-framerates/add-framerate-dialog.ui:13 msgid "Add Framerate" msgstr "" #: data/extensions/custom-framerates/add-framerate-dialog.ui:44 msgid "_Framerate:" msgstr "" #: data/extensions/custom-framerates/add-framerate-dialog.ui:73 msgid "fps" msgstr "" #: data/extensions/custom-framerates/preferences-dialog.ui:8 msgid "Framerates" msgstr "" #: data/extensions/custom-framerates/preferences-dialog.ui:64 msgid "Add" msgstr "" #: data/ui/columns-popup.ui:6 data/ui/menubar.ui:275 msgid "_No." msgstr "_Nr." #: data/ui/columns-popup.ui:10 data/ui/menubar.ui:279 msgid "_Start" msgstr "_Start" #: data/ui/columns-popup.ui:14 data/ui/menubar.ui:283 msgid "_End" msgstr "_Ende" #: data/ui/columns-popup.ui:18 data/ui/menubar.ui:287 msgid "_Duration" msgstr "_Laufzeit" #: data/ui/columns-popup.ui:22 data/ui/menubar.ui:291 data/ui/menubar.ui:303 msgid "_Text" msgstr "_Text" #: data/ui/columns-popup.ui:26 data/ui/menubar.ui:295 msgid "T_ranslation" msgstr "" #: data/ui/split-dialog.ui:15 msgid "Split Project" msgstr "Projekt zerteilen" #: data/ui/split-dialog.ui:48 msgid "_First subtitle of new project:" msgstr "_Erster Untertitel des neuen Projekts:" #: data/ui/search-dialog.ui:89 msgid "_Search for:" msgstr "_Suchen nach:" #: data/ui/search-dialog.ui:103 data/ui/spell-check-dialog.ui:193 msgid "Replace _with:" msgstr "Ersetzen _durch:" #: data/ui/search-dialog.ui:162 data/ui/menubar.ui:328 msgid "Find _Next" msgstr "_Nächsten finden" #: data/ui/search-dialog.ui:177 msgid "Find _Previous" msgstr "_Vorherigen finden" #: data/ui/search-dialog.ui:207 msgid "Replace _All" msgstr "Alle _ersetzen" #: data/ui/search-dialog.ui:241 msgid "R_egular expression" msgstr "_Regulärer Ausdruck" #: data/ui/search-dialog.ui:258 msgid "_Ignore case" msgstr "Groß-/Kleinschreibung _ignorieren" #: data/ui/search-dialog.ui:304 data/ui/language-dialog.ui:108 msgid "Columns" msgstr "Spalten" #: data/ui/search-dialog.ui:324 msgid "Find in _text column" msgstr "" #: data/ui/search-dialog.ui:341 msgid "Find in t_ranslation column" msgstr "" #: data/ui/search-dialog.ui:381 data/ui/framerate-convert-dialog.ui:144 #: data/ui/language-dialog.ui:186 #: data/ui/text-assistant/line-break-options-page.ui:178 #: data/ui/duration-adjust-dialog.ui:388 data/ui/position-shift-dialog.ui:180 #: data/ui/position-transform-dialog.ui:444 msgid "Subtitles" msgstr "Untertitel" #: data/ui/search-dialog.ui:401 msgid "Find in c_urrent project" msgstr "Im aktuellen _Projekt finden" #: data/ui/search-dialog.ui:419 msgid "Find in _all open projects" msgstr "In _allen offenen Projekten finden" #: data/ui/search-dialog.ui:452 msgid "Target" msgstr "Ziel" #: data/ui/framerate-convert-dialog.ui:8 msgid "Convert Framerate" msgstr "Bildwiederholfrequenz konvertieren" #: data/ui/framerate-convert-dialog.ui:48 msgid "Framerate" msgstr "Bildfrequenz" #: data/ui/framerate-convert-dialog.ui:71 msgid "_Input:" msgstr "_Eingabe:" #: data/ui/framerate-convert-dialog.ui:86 msgid "_Output:" msgstr "A_usgabe:" #: data/ui/framerate-convert-dialog.ui:164 msgid "Convert c_urrent project" msgstr "Aktuelles _Projekt konvertieren" #: data/ui/framerate-convert-dialog.ui:181 msgid "Convert _all open projects" msgstr "_Alle offenen Projekte konvertieren" #: data/ui/spell-check-dialog.ui:8 msgid "Check Spelling" msgstr "Rechtschreibung prüfen" #: data/ui/spell-check-dialog.ui:47 msgid "Join _Back" msgstr "_Zurück zusammenfügen" #: data/ui/spell-check-dialog.ui:62 msgid "Join _Forward" msgstr "_Vorwärts zusammenfügen" #: data/ui/spell-check-dialog.ui:77 data/ui/menubar.ui:62 msgid "_Edit" msgstr "_Bearbeiten" #: data/ui/spell-check-dialog.ui:92 msgid "_Ignore" msgstr "_Ignorieren" #: data/ui/spell-check-dialog.ui:107 msgid "Ig_nore All" msgstr "_Alle ignorieren" #: data/ui/spell-check-dialog.ui:137 msgid "Rep_lace All" msgstr "Alle _ersetzen" #: data/ui/spell-check-dialog.ui:179 msgid "_Suggestions:" msgstr "V_orschläge:" #: data/ui/multi-save-dialog.ui:8 msgid "Save All As" msgstr "Alles speichern als" #: data/ui/multi-save-dialog.ui:46 msgid "Save in _folder:" msgstr "Speichern im _Ordner:" #: data/ui/multi-save-dialog.ui:60 data/ui/save-dialog.ui:25 msgid "For_mat:" msgstr "_Format:" #: data/ui/multi-save-dialog.ui:74 data/ui/open-dialog.ui:25 #: data/ui/save-dialog.ui:39 msgid "_Encoding:" msgstr "" #: data/ui/multi-save-dialog.ui:88 data/ui/save-dialog.ui:53 msgid "Ne_wlines:" msgstr "Zeile_numbrüche:" #: data/ui/multi-save-dialog.ui:103 msgid "Select A Folder" msgstr "Wählen Sie einen Ordner" #: data/ui/multi-save-dialog.ui:150 data/ui/save-dialog.ui:102 msgid "F_ramerate:" msgstr "" #: data/ui/menubar.ui:5 msgid "_File" msgstr "_Datei" #: data/ui/menubar.ui:8 msgid "_New" msgstr "_Neu" #: data/ui/menubar.ui:12 msgid "_Open…" msgstr "_Öffnen …" #: data/ui/menubar.ui:16 msgid "Open _Translation…" msgstr "_Übersetzung öffnen …" #: data/ui/menubar.ui:22 msgid "Open _Recent" msgstr "Akt_uelles öffnen" #: data/ui/menubar.ui:27 msgid "Open R_ecent Translation" msgstr "Ak_tuelle Übersetzung öffnen" #: data/ui/menubar.ui:38 msgid "Save _As…" msgstr "Sp_eichern als …" #: data/ui/menubar.ui:42 msgid "Save Trans_lation" msgstr "Überset_zung speichern" #: data/ui/menubar.ui:46 msgid "Save Translat_ion As…" msgstr "Übersetzun_g speichern als …" #: data/ui/menubar.ui:65 msgid "_Undo" msgstr "R_ückgängig machen" #: data/ui/menubar.ui:69 msgid "_Redo" msgstr "N_ochmal machen" #: data/ui/menubar.ui:75 msgid "_Edit Cell" msgstr "_Zelle bearbeiten" #: data/ui/menubar.ui:79 msgid "Edit _Next Cell" msgstr "_Nächste Zelle bearbeiten" #: data/ui/menubar.ui:85 msgid "Stretc_h" msgstr "" #: data/ui/menubar.ui:88 msgid "_Start Earlier" msgstr "" #: data/ui/menubar.ui:92 msgid "S_tart Later" msgstr "" #: data/ui/menubar.ui:98 msgid "E_nd Earlier" msgstr "" #: data/ui/menubar.ui:102 msgid "En_d Later" msgstr "" #: data/ui/menubar.ui:108 msgid "Set St_art From Video Position" msgstr "" #: data/ui/menubar.ui:112 msgid "Set En_d From Video Position" msgstr "" #: data/ui/menubar.ui:118 data/ui/view-popup.ui:6 msgid "_Split Subtitle" msgstr "Untertitel tei_len" #: data/ui/menubar.ui:122 data/ui/view-popup.ui:10 msgid "_Merge Subtitles" msgstr "Unter_titel zusammenfügen" #: data/ui/menubar.ui:128 data/ui/view-popup.ui:16 msgid "_Insert Subtitles…" msgstr "_Untertitel einfügen …" #: data/ui/menubar.ui:132 msgid "Inser_t Subtitle At Video Position" msgstr "" #: data/ui/menubar.ui:136 data/ui/view-popup.ui:20 msgid "Rem_ove Subtitles" msgstr "Untert_itel entfernen" #: data/ui/menubar.ui:142 msgid "Sele_ction" msgstr "Auswa_hl" #: data/ui/menubar.ui:145 msgid "Select _All" msgstr "Alle ausw_ählen" #: data/ui/menubar.ui:149 msgid "_Invert Selection" msgstr "Aus_wahl umkehren" #: data/ui/menubar.ui:155 msgid "Extend To _Beginning" msgstr "Zum _Anfang ausdehnen" #: data/ui/menubar.ui:159 msgid "Extend To _End" msgstr "Zum En_de ausdehnen" #: data/ui/menubar.ui:165 msgid "_Previous From Video Position" msgstr "" #: data/ui/menubar.ui:169 msgid "_Next From Video Position" msgstr "" #: data/ui/menubar.ui:177 msgid "_Preferences" msgstr "_Einstellungen" #: data/ui/menubar.ui:183 msgid "_View" msgstr "_Ansicht" #: data/ui/menubar.ui:186 msgid "Tool_bar" msgstr "" #: data/ui/menubar.ui:190 msgid "_Video Player" msgstr "" #: data/ui/menubar.ui:196 msgid "_Layout" msgstr "" #: data/ui/menubar.ui:199 msgid "_Horizontal" msgstr "" #: data/ui/menubar.ui:204 msgid "_Vertical" msgstr "" #: data/ui/menubar.ui:213 msgid "_Times" msgstr "_Zeiten" #: data/ui/menubar.ui:218 msgid "_Frames" msgstr "Bil_der" #: data/ui/menubar.ui:225 msgid "F_ramerate" msgstr "Bildwiederholfre_quenz" #: data/ui/menubar.ui:228 msgid "2_3.976 fps" msgstr "2_3,976 fps" #: data/ui/menubar.ui:233 msgid "2_4.000 fps" msgstr "2_4,000 fps" #: data/ui/menubar.ui:238 msgid "2_5.000 fps" msgstr "2_5,000 fps" #: data/ui/menubar.ui:243 msgid "2_9.970 fps" msgstr "2_9,970 fps" #: data/ui/menubar.ui:272 msgid "_Columns" msgstr "_Spalten" #: data/ui/menubar.ui:306 msgid "Cu_t" msgstr "_Ausschneiden" #: data/ui/menubar.ui:310 msgid "_Copy" msgstr "_Kopieren" #: data/ui/menubar.ui:314 msgid "_Paste" msgstr "Ein_fügen" #: data/ui/menubar.ui:318 msgid "Cl_ear" msgstr "_Bereinigen" #: data/ui/menubar.ui:324 msgid "_Find And Replace…" msgstr "_Suchen und Ersetzen …" #: data/ui/menubar.ui:332 msgid "Find Pre_vious" msgstr "_Vorherigen finden" #: data/ui/menubar.ui:338 msgid "_Italic" msgstr "Kur_siv" #: data/ui/menubar.ui:342 msgid "_Dialogue" msgstr "_Dialog" #: data/ui/menubar.ui:348 msgid "Ca_se" msgstr "_Großgeschrieben" #: data/ui/menubar.ui:351 msgid "_Title" msgstr "_Titel" #: data/ui/menubar.ui:355 msgid "_Sentence" msgstr "S_atz" #: data/ui/menubar.ui:359 msgid "_Upper" msgstr "Gr_oß" #: data/ui/menubar.ui:363 msgid "_Lower" msgstr "_Klein" #: data/ui/menubar.ui:371 msgid "Vi_deo" msgstr "" #: data/ui/menubar.ui:374 msgid "_Load Video…" msgstr "" #: data/ui/menubar.ui:384 data/ui/view-popup.ui:26 msgid "Play _Selection" msgstr "" #: data/ui/menubar.ui:410 data/ui/view-popup.ui:30 msgid "S_eek Selection Start" msgstr "" #: data/ui/menubar.ui:414 msgid "See_k Selection End" msgstr "" #: data/ui/menubar.ui:420 msgid "_Audio" msgstr "" #: data/ui/menubar.ui:423 msgid "_Language" msgstr "" #: data/ui/menubar.ui:430 msgid "Volume _Down" msgstr "" #: data/ui/menubar.ui:434 msgid "Volume _Up" msgstr "" #: data/ui/menubar.ui:440 msgid "T_ools" msgstr "_Werkzeuge" #: data/ui/menubar.ui:443 data/ui/text-assistant/confirmation-page.ui:97 #: data/ui/view-popup.ui:36 msgid "_Preview" msgstr "_Vorschau" #: data/ui/menubar.ui:447 msgid "Select _Video…" msgstr "_Video auswählen …" #: data/ui/menubar.ui:453 msgid "_Check Spelling" msgstr "Rechtschreibung _prüfen" #: data/ui/menubar.ui:457 msgid "Co_nfigure Spell-check…" msgstr "_Rechtschreibprüfung einrichten …" #: data/ui/menubar.ui:461 msgid "C_orrect Texts…" msgstr "_Texte korrigieren …" #: data/ui/menubar.ui:467 msgid "_Shift Positions…" msgstr "Positionen _verschieben …" #: data/ui/menubar.ui:471 msgid "_Transform Positions…" msgstr "_Positionen umwandeln …" #: data/ui/menubar.ui:475 msgid "Adjust _Durations…" msgstr "_Laufzeiten anpassen …" #: data/ui/menubar.ui:479 msgid "Convert _Framerate…" msgstr "Bildwiederhol_frequenz konvertieren …" #: data/ui/menubar.ui:485 msgid "_Append File…" msgstr "_Datei anhängen …" #: data/ui/menubar.ui:489 msgid "Spli_t Project…" msgstr "Pr_ojekt teilen …" #: data/ui/menubar.ui:495 msgid "_Projects" msgstr "_Projekte" #: data/ui/menubar.ui:498 msgid "_Save All" msgstr "Alle spei_chern" #: data/ui/menubar.ui:502 msgid "Save _All As…" msgstr "A_lle speichern als …" #: data/ui/menubar.ui:506 msgid "_Close All" msgstr "_Alle schließen" #: data/ui/menubar.ui:512 msgid "_Previous" msgstr "_Vorheriger" #: data/ui/menubar.ui:516 msgid "_Next" msgstr "_Nächster" #: data/ui/menubar.ui:527 msgid "_Documentation" msgstr "" #: data/ui/menubar.ui:531 msgid "_Report A Bug" msgstr "Einen _Fehler berichten" #: data/ui/menubar.ui:535 msgid "_About" msgstr "_Über" #: data/ui/open-dialog.ui:39 msgid "Align _method:" msgstr "Ausrichtungs_methode:" #: data/ui/preferences-dialog.ui:18 msgid "Preferences" msgstr "Einstellungen" #: data/ui/preferences-dialog.ui:93 msgid "When opening files, try encodings in the following order:" msgstr "" "Beim Öffnen von Dateien kodierungen in folgender Reihenfolge probieren:" #: data/ui/preferences-dialog.ui:104 msgid "Curr_ent locale encoding" msgstr "_Aktuelle Locale-Kodierung" #: data/ui/preferences-dialog.ui:130 msgid "_Fallback encodings:" msgstr "Aus_weichkodierungen:" #: data/ui/preferences-dialog.ui:246 msgid "Aut_o-detection" msgstr "Auto_matische Erkennung" #: data/ui/preferences-dialog.ui:266 msgid "Encoding specified in the open dialog will always be tried first." msgstr "" "Die im Öffnen-Dialog angegebenen Kodierung wird immer zuerst probiert." #: data/ui/preferences-dialog.ui:296 msgid "File" msgstr "Datei" #: data/ui/preferences-dialog.ui:324 msgid "Font" msgstr "Schrift" #: data/ui/preferences-dialog.ui:344 msgid "Use _default theme fixed width font" msgstr "" #: data/ui/preferences-dialog.ui:368 msgid "_Editor font:" msgstr "_Editorschrift:" #: data/ui/preferences-dialog.ui:425 msgid "Line Lengths" msgstr "Zeilenlängen" #: data/ui/preferences-dialog.ui:445 msgid "_Show line lengths in list cells" msgstr "_Zeilenlängen in Listenzellen anzeigen" #: data/ui/preferences-dialog.ui:462 msgid "S_how line lengths in editable text fields" msgstr "Zeilen_länge in bearbeitbaren Feldern anzeigen" #: data/ui/preferences-dialog.ui:486 msgid "_Length unit:" msgstr "L_ängeneinheit:" #: data/ui/preferences-dialog.ui:540 msgid "Spell-Check" msgstr "Rechtschreibprüfung" #: data/ui/preferences-dialog.ui:560 msgid "Chec_k spelling as you type" msgstr "Recht_schreibung während des Tippens prüfen" #: data/ui/preferences-dialog.ui:598 msgid "Editor" msgstr "Editor" #: data/ui/preferences-dialog.ui:626 msgid "Fonts" msgstr "" #: data/ui/preferences-dialog.ui:649 msgid "_Subtitles:" msgstr "" #: data/ui/preferences-dialog.ui:679 msgid "_Time:" msgstr "" #: data/ui/preferences-dialog.ui:729 msgid "Colors" msgstr "" #: data/ui/preferences-dialog.ui:752 msgid "Su_btitles:" msgstr "" #: data/ui/preferences-dialog.ui:777 msgid "_Use a background behind text" msgstr "" #: data/ui/preferences-dialog.ui:797 msgid "Ti_me:" msgstr "" #: data/ui/preferences-dialog.ui:822 msgid "Us_e a background behind text" msgstr "" #: data/ui/preferences-dialog.ui:862 msgid "Seek" msgstr "" #: data/ui/preferences-dialog.ui:883 msgid "_Length:" msgstr "" #: data/ui/preferences-dialog.ui:971 msgid "Video Player" msgstr "Video-Spieler" #: data/ui/preferences-dialog.ui:994 msgid "_Application:" msgstr "A_nwendung:" #: data/ui/preferences-dialog.ui:1008 msgid "Co_mmand:" msgstr "_Befehl:" #. Translators: Only the title is to be translated, field names not. #: data/ui/preferences-dialog.ui:1033 msgid "" "Fields:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" msgstr "" #: data/ui/preferences-dialog.ui:1048 msgid "Al_ways use UTF-8 character encoding" msgstr "_Immer Zeichenkodierung UTF-8 verwenden" #: data/ui/preferences-dialog.ui:1089 msgid "Start Position" msgstr "Startposition" #: data/ui/preferences-dialog.ui:1111 msgid "_Offset:" msgstr "Ve_rsatz:" #: data/ui/preferences-dialog.ui:1142 msgid "seconds before selection" msgstr "Sekunden vor Auswahl" #: data/ui/preferences-dialog.ui:1281 msgid "Extensions" msgstr "Erweiterungen" #: data/ui/language-dialog.ui:8 msgid "Configure Spell-Check" msgstr "Rechtschreibprüfung konfigurieren" #: data/ui/language-dialog.ui:50 msgid "Language" msgstr "Sprache" #: data/ui/language-dialog.ui:128 msgid "Check _text column" msgstr "" #: data/ui/language-dialog.ui:146 msgid "Check t_ranslation column" msgstr "" #: data/ui/language-dialog.ui:206 msgid "Check c_urrent project" msgstr "A_ktuelles Projekt prüfen" #: data/ui/language-dialog.ui:224 msgid "Check _all open projects" msgstr "_Alle offenen Projekte prüfen" #: data/ui/text-assistant/confirmation-page.ui:22 msgid "Acc_ept, discard or edit changes:" msgstr "_Änderungen übernehmen, bestätigen oder bearbeiten:" #: data/ui/text-assistant/confirmation-page.ui:67 msgid "_Mark All" msgstr "Alle _markieren" #: data/ui/text-assistant/confirmation-page.ui:82 msgid "_Unmark All" msgstr "Alle Mark_ierungen aufheben" #: data/ui/text-assistant/confirmation-page.ui:119 msgid "_Remove all blank subtitles" msgstr "Alle leeren _Untertitel entfernen" #: data/ui/text-assistant/join-split-page.ui:28 msgid "Spell-Check Dictionary" msgstr "Rechtschreibprüfungswörterbuch" #: data/ui/text-assistant/join-split-page.ui:49 #: data/ui/text-assistant/line-break-page.ui:81 #: data/ui/text-assistant/hearing-impaired-page.ui:81 #: data/ui/text-assistant/common-error-page.ui:80 #: data/ui/text-assistant/capitalization-page.ui:80 msgid "_Language:" msgstr "_Sprache:" #: data/ui/text-assistant/join-split-page.ui:97 msgid "Corrections" msgstr "Korrekturen" #: data/ui/text-assistant/join-split-page.ui:117 msgid "_Join words not found in spell-check dictionary" msgstr "" "W_örter zusammenfügen, die nicht im Wörterbuch für die Rechtschreibprüfung " "gefunden wurden" #: data/ui/text-assistant/join-split-page.ui:134 msgid "_Split words not found in spell-check dictionary" msgstr "" "Wö_rter teilen, die nicht im Wörterbuch für die Rechtschreibprüfung gefunden" " wurden" #: data/ui/text-assistant/line-break-page.ui:22 msgid "S_elect preferred line-break points:" msgstr "B_evorzugte Zeilenumbruchpunkte auswählen:" #: data/ui/text-assistant/line-break-page.ui:67 #: data/ui/text-assistant/hearing-impaired-page.ui:67 #: data/ui/text-assistant/common-error-page.ui:66 #: data/ui/text-assistant/capitalization-page.ui:66 msgid "_Script:" msgstr "S_kript:" #: data/ui/text-assistant/line-break-page.ui:95 #: data/ui/text-assistant/hearing-impaired-page.ui:95 #: data/ui/text-assistant/common-error-page.ui:94 #: data/ui/text-assistant/capitalization-page.ui:94 msgid "Co_untry:" msgstr "" #: data/ui/text-assistant/introduction-page.ui:28 msgid "_Select corrections to perform on texts:" msgstr "K_orrekturen auswählen, die auf Texte angewandt werden:" #: data/ui/text-assistant/introduction-page.ui:79 msgid "Colu_mns:" msgstr "" #: data/ui/text-assistant/introduction-page.ui:93 msgid "S_ubtitles:" msgstr "" #: data/ui/text-assistant/line-break-options-page.ui:56 #: data/ui/duration-adjust-dialog.ui:207 msgid "Limits" msgstr "Einschränkungen" #: data/ui/text-assistant/line-break-options-page.ui:79 msgid "_Maximum line length:" msgstr "Maximale Zeilenlän_ge:" #: data/ui/text-assistant/line-break-options-page.ui:93 msgid "_Preferred maximum amount of lines:" msgstr "Bevorzugte maximale Zeile_nanzahl:" #: data/ui/text-assistant/line-break-options-page.ui:198 msgid "_Skip subtitles with maximum line length of:" msgstr "Unte_rtitel überspringen, die folgende maximale _Zeilenlänge haben:" #: data/ui/text-assistant/line-break-options-page.ui:214 msgid "S_kip subtitles with maximum line amount of:" msgstr "Untertitel überspringen, die folgende maximale _Zeilenzahl haben:" #: data/ui/text-assistant/hearing-impaired-page.ui:22 msgid "S_elect parts to remove:" msgstr "Teile zum _Entfernen auswählen:" #: data/ui/text-assistant/common-error-page.ui:22 msgid "S_elect errors to correct:" msgstr "_Fehler zum Korrigieren auswählen:" #: data/ui/text-assistant/common-error-page.ui:108 msgid "Error types:" msgstr "Fehlertypen:" #: data/ui/text-assistant/common-error-page.ui:158 msgid "_Human errors" msgstr "_Anwenderfehler" #: data/ui/text-assistant/common-error-page.ui:175 msgid "_Image recognition errors" msgstr "_Bilderkennungsfehler" #: data/ui/text-assistant/capitalization-page.ui:22 msgid "S_elect parts to capitalize:" msgstr "_Teile auswählen, die groß geschrieben werden:" #: data/ui/duration-adjust-dialog.ui:33 msgid "Adjust Durations" msgstr "Laufzeiten anpassen" #: data/ui/duration-adjust-dialog.ui:73 msgid "Theoretic Duration" msgstr "Theoretische Laufzeit" #: data/ui/duration-adjust-dialog.ui:101 msgid "_Reading speed:" msgstr "Lesegesch_windigkeit" #: data/ui/duration-adjust-dialog.ui:133 msgid "characters per second" msgstr "Zeichen pro Sekunde" #: data/ui/duration-adjust-dialog.ui:150 msgid "_Lengthen duration to match reading speed" msgstr "_Laufzeit zur Anpassung an Lesegeschwindigkeit verlängern" #: data/ui/duration-adjust-dialog.ui:167 msgid "_Shorten duration to match reading speed" msgstr "Lauf_zeit zur Anpassung an Lesegeschwindigkeit verkürzen" #: data/ui/duration-adjust-dialog.ui:227 msgid "_Minimum duration:" msgstr "_MindestLaufzeit:" #: data/ui/duration-adjust-dialog.ui:243 msgid "Ma_ximum duration:" msgstr "Ma_ximale Laufzeit:" #: data/ui/duration-adjust-dialog.ui:259 msgid "_Gap between subtitles:" msgstr "A_bstand zwischen Untertiteln:" #: data/ui/duration-adjust-dialog.ui:294 msgid "s_econds" msgstr "S_ekunden" #: data/ui/duration-adjust-dialog.ui:324 msgid "seco_nds" msgstr "Seku_nden" #: data/ui/duration-adjust-dialog.ui:354 msgid "secon_ds" msgstr "Se_kunden" #: data/ui/duration-adjust-dialog.ui:408 msgid "Adj_ust selected subtitles" msgstr "Ausgewählte Unte_rtitel anpassen" #: data/ui/duration-adjust-dialog.ui:425 msgid "Adjus_t current project" msgstr "Aktuelles Pro_jekt anpassen" #: data/ui/duration-adjust-dialog.ui:442 msgid "Adjust all _open projects" msgstr "Alle _offenen Projekte anpassen" #: data/ui/tab-popup.ui:6 msgid "Move Tab _Left" msgstr "Reiter nach links _verschieben" #: data/ui/tab-popup.ui:10 msgid "Move Tab _Right" msgstr "Reiter nach rechts verschie_ben" #: data/ui/insert-dialog.ui:15 msgid "Insert Subtitles" msgstr "Untertitel einfügen" #: data/ui/insert-dialog.ui:48 data/ui/position-shift-dialog.ui:82 msgid "_Amount:" msgstr "_Betrag:" #: data/ui/insert-dialog.ui:62 msgid "_Position:" msgstr "_Position:" #: data/ui/position-shift-dialog.ui:14 msgid "Shift Positions" msgstr "Positionen verschieben" #: data/ui/position-shift-dialog.ui:54 msgid "Shift" msgstr "Verschieben" #: data/ui/position-shift-dialog.ui:135 #: data/ui/position-transform-dialog.ui:208 msgid "_Preview Changes" msgstr "_Änderungsvorschau" #: data/ui/position-shift-dialog.ui:200 msgid "Shift s_elected subtitles" msgstr "Ausge_wählte Untertitel verschieben" #: data/ui/position-shift-dialog.ui:217 msgid "Shift su_btitles from selection to end" msgstr "" #: data/ui/position-shift-dialog.ui:234 msgid "Shift c_urrent project" msgstr "Aktuelles _Projekt verschieben" #: data/ui/position-shift-dialog.ui:251 msgid "Shift all _open projects" msgstr "" #: data/ui/position-transform-dialog.ui:22 msgid "Transform Positions" msgstr "Positionen umwandeln" #: data/ui/position-transform-dialog.ui:62 msgid "First Point" msgstr "Erster Punkt" #: data/ui/position-transform-dialog.ui:91 msgid "_Subtitle:" msgstr "U_ntertitel:" #: data/ui/position-transform-dialog.ui:105 msgid "C_orrection:" msgstr "K_orrektur:" #: data/ui/position-transform-dialog.ui:119 #: data/ui/position-transform-dialog.ui:310 msgid "Text:" msgstr "Text:" #: data/ui/position-transform-dialog.ui:253 msgid "Second Point" msgstr "Zweiter Punkt" #: data/ui/position-transform-dialog.ui:282 msgid "Su_btitle:" msgstr "_Untertitel:" #: data/ui/position-transform-dialog.ui:296 msgid "Co_rrection:" msgstr "Ko_rrektur:" #: data/ui/position-transform-dialog.ui:399 msgid "Pre_view Changes" msgstr "_Änderungsvorschau" #: data/ui/position-transform-dialog.ui:464 msgid "Transform se_lected subtitles" msgstr "_Ausgewählte Untertitel umwandeln" #: data/ui/position-transform-dialog.ui:482 msgid "Transform c_urrent project" msgstr "A_ktuelles Projekt umwandeln" #: data/extensions/custom-framerates/custom-framerates.extension.in:7 msgid "Custom Framerates" msgstr "" #: data/extensions/custom-framerates/custom-framerates.extension.in:8 msgid "Allow use of non-standard framerates" msgstr "" #: data/patterns/Latn-en-US.common-error.in:5 msgid "Period after title" msgstr "Punkt nach Titel" #: data/patterns/Latn-en-US.common-error.in:6 msgid "Add period after a shortened title, such as \"Mr\" and \"Dr\"" msgstr "Punkt hinter einem gekürzten Titel, wie z.B »Fr« oder »Dr« hinzufügen" #: data/patterns/Latn-en.capitalization.in:5 msgid "First person pronoun" msgstr "Pronomen für die erste Person" #: data/patterns/Latn-en.capitalization.in:6 msgid "Capitalize the first person pronoun \"I\"" msgstr "Das Pronomen für die erste Person »I« großschreiben" #: data/patterns/Latn-en.common-error.in:5 #: data/patterns/Latn-en.common-error.in:14 #: data/patterns/Latn-en.common-error.in:23 msgid "Letter \"I\" in a lower case word" msgstr "Buchstabe »I« in einem kleingeschriebenen Wort" #: data/patterns/Latn-en.common-error.in:6 #: data/patterns/Latn-en.common-error.in:15 #: data/patterns/Latn-en.common-error.in:24 msgid "Replace letter \"I\" with letter \"l\" in a lower case word" msgstr "" "Den Buchstaben »I« durch den Buchstaben »l« in einem kleingeschriebenen Wort" " ersetzen" #: data/patterns/Latn-en.common-error.in:32 #: data/patterns/Latn-en.common-error.in:41 #: data/patterns/Latn-en.common-error.in:50 #: data/patterns/Latn-en.common-error.in:62 msgid "Letter \"l\" in an upper case word" msgstr "Buchstabe »l« in einem großgeschriebenen Wort" #: data/patterns/Latn-en.common-error.in:33 #: data/patterns/Latn-en.common-error.in:42 #: data/patterns/Latn-en.common-error.in:51 #: data/patterns/Latn-en.common-error.in:63 msgid "Replace letter \"l\" with letter \"I\" in an upper case word" msgstr "" "Den Buchstaben »l« durch den Buchstaben »I« in einem großgeschriebenen Wort " "ersetzen" #: data/patterns/Latn-en.common-error.in:73 #: data/patterns/Latn-en.common-error.in:82 msgid "Zero in an upper case word" msgstr "Null in einem großgeschriebenen Wort" #: data/patterns/Latn-en.common-error.in:74 #: data/patterns/Latn-en.common-error.in:83 msgid "Replace zero with letter \"O\" in an upper case word" msgstr "" "Null durch den Buchstaben »O« in einem großgeschriebenen Wort ersetzen" #: data/patterns/Latn-en.common-error.in:91 #: data/patterns/Latn.common-error.in:108 msgid "Space between number and unit" msgstr "Leerzeichen zwischen Zahl und Einheit" #: data/patterns/Latn-en.common-error.in:92 #: data/patterns/Latn.common-error.in:109 msgid "Add or remove space between a number and the associated unit" msgstr "" "Leerzeichen zwischen einer Zahl und der dazugehörigen Einheit hinzufügen " "oder entfernen" #: data/patterns/Latn-en.common-error.in:100 msgid "Spaces around an apostrophe" msgstr "Leerzeichen um einen Apostroph" #: data/patterns/Latn-en.common-error.in:101 msgid "Remove spaces around an apostrophe" msgstr "Leerzeichen um einen Apostroph entfernen" #: data/patterns/Latn-en.common-error.in:109 #: data/patterns/Latn-en.common-error.in:118 msgid "Okay" msgstr "Okay" #: data/patterns/Latn-en.common-error.in:110 #: data/patterns/Latn-en.common-error.in:119 msgid "Spell two-letter forms of \"okay\" in all upper case" msgstr "" #: data/patterns/Latn-en.hearing-impaired.in:5 msgid "Uppercase speaker before a colon" msgstr "Großgeschriebener Sprecher vor einem Doppelpunkt" #: data/patterns/Latn-en.hearing-impaired.in:6 msgid "" "Replace the uppercase name of the speaker before a colon with a dialogue " "dash" msgstr "" "Den großgeschriebenen Namen des Sprechers vor einem Doppelpunkt mit einem " "Dialog-Halbgeviertstrich ersetzen" #: data/patterns/Latn-en.line-break.in:5 msgid "Title" msgstr "" #: data/patterns/Latn-en.line-break.in:6 msgid "Do not break after a title, e.g. \" Dr.\"" msgstr "" #: data/patterns/Latn-en.line-break.in:13 msgid "Article" msgstr "" #: data/patterns/Latn-en.line-break.in:14 msgid "Do not break after an article" msgstr "" #: data/patterns/Latn-en.line-break.in:21 msgid "Preposition" msgstr "" #: data/patterns/Latn-en.line-break.in:22 msgid "Do not break after a preposition" msgstr "" #: data/patterns/Latn-en.line-break.in:30 msgid "Possessive determiner" msgstr "" #: data/patterns/Latn-en.line-break.in:31 msgid "Do not break after a possessive determiner, e.g. \"my\"" msgstr "" #: data/patterns/Latn-fi.common-error.in:5 #: data/patterns/Latn.common-error.in:182 msgid "Space after punctuation marks" msgstr "Leerzeichen nach Satzzeichen" #: data/patterns/Latn-fi.common-error.in:6 #: data/patterns/Latn.common-error.in:183 msgid "Add space after various punctuation marks" msgstr "Leerzeichen hinter verschiedenen Satzzeichen hinzufügen" #: data/patterns/Latn-fr.common-error.in:5 #: data/patterns/Latn-fr.common-error.in:14 #: data/patterns/Latn-fr.common-error.in:23 #: data/patterns/Latn-fr.common-error.in:32 msgid "Spaces around guillemets" msgstr "" #: data/patterns/Latn-fr.common-error.in:6 #: data/patterns/Latn-fr.common-error.in:15 #: data/patterns/Latn-fr.common-error.in:24 #: data/patterns/Latn-fr.common-error.in:33 msgid "Add spaces around guillemets" msgstr "" #: data/patterns/Latn-fr.common-error.in:41 #: data/patterns/Latn-fr.common-error.in:52 #: data/patterns/Latn.common-error.in:171 msgid "Space before punctuation marks" msgstr "Leerzeichen vor Satzzeichen" #: data/patterns/Latn-fr.common-error.in:42 #: data/patterns/Latn-fr.common-error.in:53 msgid "Add or remove space before various punctuation marks" msgstr "" #: data/patterns/Latn.capitalization.in:5 msgid "Sentence" msgstr "Satz" #: data/patterns/Latn.capitalization.in:6 msgid "Capitalize the first word of a sentence" msgstr "Das erste Wort eines Satzes großschreiben" #: data/patterns/Latn.capitalization.in:12 msgid "Ellipsis" msgstr "" #: data/patterns/Latn.capitalization.in:13 msgid "Capitalize after an ellipsis" msgstr "" #: data/patterns/Latn.common-error.in:8 data/patterns/Latn.common-error.in:17 #: data/patterns/Latn.common-error.in:26 data/patterns/Latn.common-error.in:35 #: data/patterns/Latn.common-error.in:44 data/patterns/Latn.common-error.in:53 #: data/patterns/Latn.common-error.in:62 msgid "Ligatures" msgstr "" #: data/patterns/Latn.common-error.in:9 data/patterns/Latn.common-error.in:18 #: data/patterns/Latn.common-error.in:27 data/patterns/Latn.common-error.in:36 #: data/patterns/Latn.common-error.in:45 data/patterns/Latn.common-error.in:54 #: data/patterns/Latn.common-error.in:63 msgid "Unpack ligatures to individual characters" msgstr "" #: data/patterns/Latn.common-error.in:71 data/patterns/Latn.common-error.in:80 msgid "Spelling of a.m. and p.m." msgstr "Schreibweise von a.m. und p.m." #: data/patterns/Latn.common-error.in:72 data/patterns/Latn.common-error.in:81 msgid "Change the various spellings of 12-hour periods to \"a.m.\" and \"p.m.\"" msgstr "" "Die verschiedenen Schreibweisen von Perioden à 12 Stunden auf »a.m.« und " "»p.m.« ändern" #: data/patterns/Latn.common-error.in:89 data/patterns/Latn.common-error.in:98 msgid "Letter \"O\" in a number" msgstr "Buchstabe »O« in einer Zahl" #: data/patterns/Latn.common-error.in:90 data/patterns/Latn.common-error.in:99 msgid "Replace letter \"O\" with a zero in a number" msgstr "»O« innerhalb einer Zahl durch Null ersetzen" #: data/patterns/Latn.common-error.in:117 msgid "Double apostrophe" msgstr "Doppelter Apostroph" #: data/patterns/Latn.common-error.in:118 msgid "Replace a double apostrophe with a quotation mark" msgstr "Einen doppelten Apostroph durch ein Anführungszeichen ersetzen" #: data/patterns/Latn.common-error.in:126 #: data/patterns/Latn.common-error.in:135 #: data/patterns/Latn.common-error.in:144 #: data/patterns/Latn.common-error.in:153 msgid "Spaces around brackets" msgstr "Leerzeichen um Klammern" #: data/patterns/Latn.common-error.in:127 #: data/patterns/Latn.common-error.in:136 #: data/patterns/Latn.common-error.in:145 #: data/patterns/Latn.common-error.in:154 msgid "Add or remove spaces around parantheses and square brackets" msgstr "Leerzeichen um runde oder eckige Klammern hinzufügen oder entfernen" #: data/patterns/Latn.common-error.in:162 msgid "Space after a dialogue dash" msgstr "Leerzeichen nach einem Dialog-Bindestrich" #: data/patterns/Latn.common-error.in:163 msgid "Add space after a dialogue dash" msgstr "Leerzeichen hinter einem Dialog-Halbgeviertstrich hinzufügen" #: data/patterns/Latn.common-error.in:172 msgid "Remove space before various punctuation marks" msgstr "Leerzeichen vor verschiedenen Satzzeichen entfernen" #: data/patterns/Latn.common-error.in:192 msgid "Space after an ellipsis" msgstr "Leerzeichen nach einer Auslassung" #: data/patterns/Latn.common-error.in:193 msgid "Add space after an ellipsis" msgstr "Leerzeichen hinter einer Auslassung hinzufügen" #: data/patterns/Latn.common-error.in:201 msgid "Space after a starting ellipsis" msgstr "Leerzeichen nach einer Anfangsauslassung" #: data/patterns/Latn.common-error.in:202 msgid "Remove space after an ellipsis that starts a line" msgstr "Leerzeichen nach einer Auslassung am Anfang eine Zeile entfernen" #: data/patterns/Latn.common-error.in:210 #: data/patterns/Latn.common-error.in:221 #: data/patterns/Latn.common-error.in:232 #: data/patterns/Latn.common-error.in:242 msgid "Spaces around a quotation mark" msgstr "Leerzeichen um Anführungszeichen" #: data/patterns/Latn.common-error.in:211 #: data/patterns/Latn.common-error.in:222 #: data/patterns/Latn.common-error.in:233 #: data/patterns/Latn.common-error.in:243 msgid "Remove space after a starting- and before an ending quotation mark" msgstr "" "Leerzeichen hinter einem öffnenden und vor einem schließenden " "Anführungszeichen entfernen" #: data/patterns/Latn.common-error.in:252 #: data/patterns/Latn.common-error.in:261 msgid "Spaces around musical notes" msgstr "" #: data/patterns/Latn.common-error.in:253 #: data/patterns/Latn.common-error.in:262 msgid "Add spaces between musical note characters and lyrics" msgstr "" #: data/patterns/Latn.common-error.in:270 #: data/patterns/Latn.common-error.in:279 msgid "Multiple question- and exclamation marks" msgstr "Mehrere Frage- und Ausrufezeichen" #: data/patterns/Latn.common-error.in:271 #: data/patterns/Latn.common-error.in:280 msgid "" "Replace multiple consequtive question- and exclamation marks with only one" msgstr "" "Mehrere aufeinander folgende Frage- und Ausrufezeichen mit durch nur eines " "ersetzen" #: data/patterns/Latn.common-error.in:288 #: data/patterns/Latn.common-error.in:298 msgid "Periods around a punctuation mark" msgstr "Punkte um ein Satzzeichen herum" #: data/patterns/Latn.common-error.in:289 #: data/patterns/Latn.common-error.in:299 msgid "Remove period before or after various punctuation marks" msgstr "Punkte vor oder nach verschiedenen Satzzeichen entfernen" #: data/patterns/Latn.common-error.in:308 msgid "Terminating double-dashes" msgstr "Abschließende Doppelbindestriche" #: data/patterns/Latn.common-error.in:309 msgid "Replace a single clause-terminating dash with two dashes" msgstr "Einen einzelnen Satzende-Strich durch zwei Striche ersetzen" #: data/patterns/Latn.hearing-impaired.in:5 msgid "Sound in brackets" msgstr "Ton in Klammern" #: data/patterns/Latn.hearing-impaired.in:6 msgid "Remove description of a sound between square brackets" msgstr "Beschreibung eines Tons zwischen eckigen Klammern entfernen" #: data/patterns/Latn.hearing-impaired.in:12 msgid "Sound in parantheses" msgstr "Ton in runden Klammern" #: data/patterns/Latn.hearing-impaired.in:13 msgid "Remove description of a sound between parantheses" msgstr "Beschreibung eines Tons zwischen Klammern entfernen" #: data/patterns/Latn.hearing-impaired.in:19 msgid "Song lyrics between number signs" msgstr "Liedtexte zwischen Rauten" #: data/patterns/Latn.hearing-impaired.in:20 msgid "Remove song lyrics starting with or between number signs" msgstr "Liedtexte entfernen, die mit oder zwischen Rauten beginnen" #: data/patterns/Latn.hearing-impaired.in:27 msgid "One-line song lyrics between number signs" msgstr "Einzeilige Liedtexte zwischen Rauten" #: data/patterns/Latn.hearing-impaired.in:28 msgid "Remove one-line song lyrics starting with or between number signs" msgstr "Einzeilige Liedtexte entfernen, die mit oder zwischen Rauten beginnen" #: data/patterns/Latn.hearing-impaired.in:35 msgid "Speaker before a colon" msgstr "Sprecher vor einem Doppelpunkt" #: data/patterns/Latn.hearing-impaired.in:36 msgid "Replace the name of the speaker before a colon with a dialogue dash" msgstr "" "Den Namen des Sprechers vor einem Doppelpunkt mit einem Gedankenstrich " "ersetzen" #: data/patterns/Latn.line-break.in:5 data/patterns/Latn.line-break.in:13 msgid "Dialogue" msgstr "Dialog" #: data/patterns/Latn.line-break.in:6 data/patterns/Latn.line-break.in:14 msgid "Break according to dialogue separated by dashes" msgstr "" "Unterbrechung entsprechend dem Dialog getrennt durch Halbgeviertstriche" #: data/patterns/Latn.line-break.in:21 data/patterns/Latn.line-break.in:30 msgid "Clause" msgstr "Satzteil" #: data/patterns/Latn.line-break.in:22 data/patterns/Latn.line-break.in:31 msgid "Break according to clauses terminated by a punctuation mark" msgstr "" "Unterbrechung entsprechend den Satzteilen von einem Satzzeichen beendet" #: data/patterns/Latn.line-break.in:38 msgid "Number and unit" msgstr "" #: data/patterns/Latn.line-break.in:39 msgid "Do not break between a number and associated unit" msgstr "" #: data/patterns/Zyyy.common-error.in:5 data/patterns/Zyyy.common-error.in:14 msgid "Leading and trailing spaces" msgstr "Führende und abschließende Leerzeichen" #: data/patterns/Zyyy.common-error.in:6 data/patterns/Zyyy.common-error.in:15 msgid "Remove spaces from the beginning and end of lines" msgstr "Leerzeichen am Anfang und Ende einer Zeile entfernen" #: data/patterns/Zyyy.common-error.in:23 msgid "Multiple consecutive spaces" msgstr "Mehrere aufeinander folgende Leerzeichen" #: data/patterns/Zyyy.common-error.in:24 msgid "Replace multiple consecutive spaces with only one" msgstr "Mehrere aufeinander folgende Leerzeichen durch nur eines ersetzen" #: data/patterns/Zyyy.common-error.in:32 data/patterns/Zyyy.common-error.in:45 #: data/patterns/Zyyy.common-error.in:55 data/patterns/Zyyy.common-error.in:65 msgid "Space between digits" msgstr "Leerzeichen zwischen Ziffern" #: data/patterns/Zyyy.common-error.in:33 data/patterns/Zyyy.common-error.in:46 #: data/patterns/Zyyy.common-error.in:56 data/patterns/Zyyy.common-error.in:66 msgid "Remove space between digits of a number" msgstr "Leerzeichen zwischen Ziffern einer Nummer entfernen" #: data/patterns/Zyyy.common-error.in:79 msgid "Musical notes" msgstr "" #: data/patterns/Zyyy.common-error.in:80 msgid "Replace Unicode musical note characters with number signs" msgstr "" #: data/io.otsaloma.gaupol.appdata.xml.in:7 msgid "Editor for text-based subtitles" msgstr "" #: data/io.otsaloma.gaupol.appdata.xml.in:9 msgid "" "Gaupol is an editor for text-based subtitle files. It supports multiple " "subtitle file formats and provides means of creating subtitles, editing " "texts and timing subtitles to match video." msgstr "" #: data/io.otsaloma.gaupol.appdata.xml.in:40 msgid "Main window" msgstr "" #: data/io.otsaloma.gaupol.desktop.in:5 msgid "Subtitle Editor" msgstr "Untertiteleditor" #: data/io.otsaloma.gaupol.desktop.in:6 msgid "Edit subtitle files" msgstr "Untertiteldateien bearbeiten" #. TRANSLATORS: Search terms to find this application. Do NOT translate or #. localize the semicolons! The list MUST also end with a semicolon! #: data/io.otsaloma.gaupol.desktop.in:12 msgid "video;subtitles;captions;" msgstr "" gaupol-1.11/po/es.po000066400000000000000000002255311422217132500143170ustar00rootroot00000000000000# 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. # # Translators: # Carlos Mella , 2021 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-04-03 04:00+0300\n" "PO-Revision-Date: 2016-07-07 00:55+0000\n" "Last-Translator: Carlos Mella , 2021\n" "Language-Team: Spanish (https://www.transifex.com/otsaloma/teams/64879/es/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: aeidon/enums.py:40 gaupol/enums.py:38 msgid "Subtitle number" msgstr "Número del subtítulo" #: aeidon/enums.py:43 msgid "Subtitle position" msgstr "Posición del subtítulo" #: aeidon/enums.py:59 msgid "23.976 fps" msgstr "23,976 fps" #: aeidon/enums.py:63 msgid "24.000 fps" msgstr "24,000 fps" #: aeidon/enums.py:67 msgid "25.000 fps" msgstr "25,000 fps" #: aeidon/enums.py:71 msgid "29.970 fps" msgstr "29,970 fps" #: aeidon/enums.py:75 data/ui/menubar.ui:248 msgid "30.000 fps" msgstr "30,000 fps" #: aeidon/enums.py:79 data/ui/menubar.ui:253 msgid "50.000 fps" msgstr "50,000 fps" #: aeidon/enums.py:83 data/ui/menubar.ui:258 msgid "59.940 fps" msgstr "59,940 fps" #: aeidon/enums.py:87 data/ui/menubar.ui:263 msgid "60.000 fps" msgstr "60,000 fps" #: aeidon/enums.py:112 msgid "Mac (classic)" msgstr "Mac (clásico)" #. TRANSLATORS: Most of the character encoding descriptions are copied from #. gedit, which is translated to very many languages. Check the gedit .po #. files for a reference: #. . #: aeidon/encodings.py:40 aeidon/encodings.py:43 aeidon/encodings.py:46 msgid "English" msgstr "Inglés" #: aeidon/encodings.py:41 aeidon/encodings.py:42 aeidon/encodings.py:69 msgid "Chinese traditional" msgstr "Chino tradicional" #: aeidon/encodings.py:44 msgid "German" msgstr "Alemán" #: aeidon/encodings.py:45 aeidon/encodings.py:54 aeidon/encodings.py:59 #: aeidon/encodings.py:79 aeidon/encodings.py:105 msgid "Hebrew" msgstr "Hebreo" #: aeidon/encodings.py:47 aeidon/encodings.py:51 aeidon/encodings.py:56 #: aeidon/encodings.py:73 aeidon/encodings.py:76 aeidon/encodings.py:98 #: aeidon/encodings.py:111 aeidon/encodings.py:122 msgid "Western" msgstr "Occidental" #: aeidon/encodings.py:48 aeidon/encodings.py:61 aeidon/encodings.py:80 #: aeidon/encodings.py:103 msgid "Arabic" msgstr "Árabe" #: aeidon/encodings.py:49 aeidon/encodings.py:64 aeidon/encodings.py:66 #: aeidon/encodings.py:77 aeidon/encodings.py:104 aeidon/encodings.py:119 msgid "Greek" msgstr "Griego" #: aeidon/encodings.py:50 aeidon/encodings.py:81 aeidon/encodings.py:101 #: aeidon/encodings.py:109 msgid "Baltic" msgstr "Báltico" #: aeidon/encodings.py:52 aeidon/encodings.py:74 aeidon/encodings.py:99 #: aeidon/encodings.py:121 msgid "Central European" msgstr "Centroeuropeo" #: aeidon/encodings.py:53 aeidon/encodings.py:75 aeidon/encodings.py:102 #: aeidon/encodings.py:118 msgid "Cyrillic" msgstr "Cirílico" #: aeidon/encodings.py:55 aeidon/encodings.py:71 aeidon/encodings.py:78 #: aeidon/encodings.py:106 aeidon/encodings.py:123 msgid "Turkish" msgstr "Turco" #: aeidon/encodings.py:57 msgid "Portuguese" msgstr "Portugués" #: aeidon/encodings.py:58 aeidon/encodings.py:120 msgid "Icelandic" msgstr "Islandés" #: aeidon/encodings.py:60 msgid "Canadian" msgstr "Canadiense" #: aeidon/encodings.py:62 aeidon/encodings.py:107 msgid "Nordic" msgstr "Nórdico" #: aeidon/encodings.py:63 aeidon/encodings.py:114 msgid "Russian" msgstr "Ruso" #: aeidon/encodings.py:65 aeidon/encodings.py:108 msgid "Thai" msgstr "Tailandés" #: aeidon/encodings.py:67 aeidon/encodings.py:83 aeidon/encodings.py:84 #: aeidon/encodings.py:85 aeidon/encodings.py:91 aeidon/encodings.py:92 #: aeidon/encodings.py:93 aeidon/encodings.py:94 aeidon/encodings.py:95 #: aeidon/encodings.py:96 aeidon/encodings.py:125 aeidon/encodings.py:126 #: aeidon/encodings.py:127 msgid "Japanese" msgstr "Japonés" #: aeidon/encodings.py:68 aeidon/encodings.py:86 aeidon/encodings.py:97 #: aeidon/encodings.py:113 msgid "Korean" msgstr "Coreano" #: aeidon/encodings.py:70 msgid "Urdu" msgstr "Urdú" #: aeidon/encodings.py:72 aeidon/encodings.py:116 msgid "Ukrainian" msgstr "Ucraniano" #: aeidon/encodings.py:82 msgid "Vietnamese" msgstr "Vietnamita" #: aeidon/encodings.py:87 aeidon/encodings.py:90 msgid "Chinese simplified" msgstr "Chino simplificado" #: aeidon/encodings.py:88 aeidon/encodings.py:89 msgid "Chinese unified" msgstr "Chino unificado" #: aeidon/encodings.py:100 aeidon/encodings.py:112 msgid "South European" msgstr "Sureuropeo" #: aeidon/encodings.py:110 msgid "Celtic" msgstr "Céltico" #: aeidon/encodings.py:115 msgid "Tajik" msgstr "Tayiko" #: aeidon/encodings.py:117 msgid "Kazakh" msgstr "Kazajo" #: aeidon/encodings.py:124 msgid "Cyrillic Asian" msgstr "Cirílico asiático" #: aeidon/encodings.py:128 aeidon/encodings.py:129 aeidon/encodings.py:130 #: aeidon/encodings.py:131 aeidon/encodings.py:132 aeidon/encodings.py:133 #: aeidon/encodings.py:134 aeidon/encodings.py:135 aeidon/encodings.py:136 msgid "Unicode" msgstr "Unicode" #: aeidon/encodings.py:156 #, python-brace-format msgid "{description} ({name})" msgstr "{description} ({name})" #: aeidon/encodings.py:232 msgid "Current locale ({})" msgstr "Configuración regional actual ({})" #: aeidon/locales.py:46 #, python-brace-format msgid "{language} ({country})" msgstr "{language} ({country})" #: aeidon/agents/search.py:227 msgid "Replacing" msgstr "Reemplazar" #: aeidon/agents/search.py:256 aeidon/agents/search.py:258 msgid "Replacing all" msgstr "Reemplazar todo" #: aeidon/agents/position.py:74 msgid "Adjusting durations" msgstr "Ajustar posiciones" #: aeidon/agents/position.py:96 msgid "Converting framerate" msgstr "Cambiar frecuencia de fotogramas" #: aeidon/agents/position.py:146 msgid "Setting framerate" msgstr "Definir frecuencia de fotogramas" #: aeidon/agents/position.py:168 msgid "Shifting positions" msgstr "Desplazar posiciones" #: aeidon/agents/position.py:188 msgid "Transforming positions" msgstr "Ajustar posiciones" #: aeidon/agents/clipboard.py:44 msgid "Cutting texts" msgstr "Cortar texto" #: aeidon/agents/clipboard.py:61 msgid "Pasting texts" msgstr "Pegar texto" #: aeidon/agents/text.py:91 msgid "Breaking lines" msgstr "Dividir líneas" #: aeidon/agents/text.py:128 msgid "Capitalizing texts" msgstr "Capitalizar texto" #: aeidon/agents/text.py:185 msgid "Correcting common errors" msgstr "Corregir errores frecuentes" #: aeidon/agents/text.py:234 msgid "Removing hearing impaired texts" msgstr "Eliminar texto para sordos" #: aeidon/agents/text.py:315 msgid "Joining words by spell-check suggestions" msgstr "Unir palabras según sugerencias del corrector ortográfico" #: aeidon/agents/text.py:354 msgid "Splitting words by spell-check suggestions" msgstr "Dividir palabras según sugerencias del corrector ortográfico" #: aeidon/agents/set.py:58 aeidon/agents/set.py:80 aeidon/agents/set.py:113 msgid "Editing position" msgstr "Editar posición" #: aeidon/agents/set.py:129 msgid "Editing text" msgstr "Editar texto" #: aeidon/agents/edit.py:35 msgid "Clearing texts" msgstr "Borrar texto" #: aeidon/agents/edit.py:61 aeidon/agents/edit.py:83 msgid "Inserting subtitles" msgstr "Insertar subtítulos" #: aeidon/agents/edit.py:103 msgid "Merging subtitles" msgstr "Combinar subtítulos" #: aeidon/agents/edit.py:114 msgid "Removing subtitles" msgstr "Eliminar subtítulos" #: aeidon/agents/edit.py:131 msgid "Replacing positions" msgstr "Reemplazar posiciones" #: aeidon/agents/edit.py:147 msgid "Replacing texts" msgstr "Reemplazar texto" #: aeidon/agents/edit.py:171 msgid "Splitting subtitle" msgstr "Dividir subtítulo" #: aeidon/agents/format.py:49 msgid "Adding dialogue dashes" msgstr "Agregar rayas de diálogo" #: aeidon/agents/format.py:68 msgid "Changing case" msgstr "Cambiar capitalización" #: aeidon/agents/format.py:92 msgid "Italicizing" msgstr "Aplicar cursiva" #: aeidon/agents/format.py:108 msgid "Removing dialogue dashes" msgstr "Quitar rayas de diálogo" #: aeidon/agents/format.py:174 msgid "Unitalicizing" msgstr "Quitar cursiva" #: gaupol/application.py:219 gaupol/agents/open.py:203 msgid "Open" msgstr "Abrir" #: gaupol/application.py:223 msgid "Open main files" msgstr "Abre archivos de subtítulos" #: gaupol/application.py:230 msgid "Save" msgstr "Guardar" #: gaupol/application.py:233 msgid "Save the current main document" msgstr "Guarda el documento principal actual" #: gaupol/application.py:238 msgid "Undo" msgstr "Deshacer" #: gaupol/application.py:242 msgid "Undo the last action" msgstr "Deshace los efectos de la última acción" #: gaupol/application.py:249 msgid "Redo" msgstr "Rehacer" #: gaupol/application.py:252 msgid "Redo the last undone action" msgstr "Rehace la última acción deshecha" #: gaupol/application.py:260 msgid "Insert" msgstr "Insertar" #: gaupol/application.py:262 msgid "Insert new subtitles" msgstr "Inserta subtítulos nuevos" #: gaupol/application.py:266 #: data/extensions/custom-framerates/preferences-dialog.ui:78 msgid "Remove" msgstr "Eliminar" #: gaupol/application.py:268 msgid "Remove the selected subtitles" msgstr "Elimina los subtítulos seleccionados" #: gaupol/application.py:273 data/ui/search-dialog.ui:283 msgid "Find" msgstr "Buscar" #: gaupol/application.py:275 msgid "Search for and replace text" msgstr "Busca y reemplaza texto" #: gaupol/application.py:279 data/ui/preferences-dialog.ui:942 msgid "Video" msgstr "Vídeo" #: gaupol/application.py:281 msgid "Show or hide the video player" msgstr "Muestra u oculta el vídeo integrado" #: gaupol/application.py:285 data/ui/preferences-dialog.ui:1173 msgid "Preview" msgstr "Vista previa" #: gaupol/application.py:287 msgid "Preview from selected position with a video player" msgstr "" "Reproduce el vídeo en un reproductor externo desde la posición seleccionada" #: gaupol/enums.py:37 msgid "No." msgstr "Nº" #: gaupol/enums.py:43 msgid "Start" msgstr "Inicio" #: gaupol/enums.py:44 msgid "Start position" msgstr "Posición inicial" #: gaupol/enums.py:49 msgid "End" msgstr "Fin" #: gaupol/enums.py:50 msgid "End position" msgstr "Posición final" #. TRANSLATORS: 'Dur.' is short for duration. It is used in the header #. of a column that contains numbers five digits wide. #: gaupol/enums.py:57 msgid "Dur." msgstr "Dur." #: gaupol/enums.py:58 msgid "Duration" msgstr "Duración" #: gaupol/enums.py:63 gaupol/enums.py:64 msgid "Text" msgstr "Texto" #: gaupol/enums.py:69 gaupol/enums.py:70 msgid "Translation" msgstr "Traducción" #: gaupol/enums.py:82 msgid "characters" msgstr "caracteres" #: gaupol/enums.py:85 msgid "ems" msgstr "ems" #: gaupol/page.py:60 msgid "Untitled {:d}" msgstr "Sin título {:d}" #: gaupol/page.py:133 msgid "Close project" msgstr "Cerrar proyecto" #: gaupol/page.py:145 msgid "{} translation" msgstr "traducción de {}" #: gaupol/page.py:302 msgid "Path:" msgstr "Ruta:" #: gaupol/page.py:303 msgid "Format:" msgstr "Formato:" #: gaupol/page.py:304 msgid "Encoding:" msgstr "Codificación:" #: gaupol/page.py:305 msgid "Newlines:" msgstr "Salto de línea:" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:99 msgid "Tasks and Target" msgstr "Tareas y alcance" #: gaupol/assistants.py:128 msgid "Correct texts in the text column" msgstr "Corregir en la columna texto" #: gaupol/assistants.py:129 msgid "Correct texts in the translation column" msgstr "Corregir en la columna traducción" #: gaupol/assistants.py:138 msgid "Correct texts in selected subtitles" msgstr "Corregir en los subtítulos seleccionados" #: gaupol/assistants.py:139 msgid "Correct texts in current project" msgstr "Corregir en el proyecto actual" #: gaupol/assistants.py:140 msgid "Correct texts in all open projects" msgstr "Corregir en todos los proyectos abiertos" #: gaupol/assistants.py:363 msgid "Other" msgstr "Otro" #: gaupol/assistants.py:439 msgid "Capitalize texts written in lower case" msgstr "Capitaliza el texto escrito en minúsculas" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:443 msgid "Capitalization Patterns" msgstr "Reglas de capitalización" #: gaupol/assistants.py:445 msgid "Capitalize texts" msgstr "Capitalizar texto" #: gaupol/assistants.py:468 msgid "Correct common errors made by humans or image recognition software" msgstr "" "Corrige diversos errores frecuentes propios de un humano o de un\n" "software reconocedor de imágenes" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:472 msgid "Common Error Patterns" msgstr "Reglas de errores frecuentes" #: gaupol/assistants.py:474 msgid "Correct common errors" msgstr "Corregir errores frecuentes" #: gaupol/assistants.py:526 msgid "Remove explanatory texts meant for the hearing impaired" msgstr "Elimina el texto explicativo para personas con problemas de audición" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:530 msgid "Hearing Impaired Patterns" msgstr "Reglas de texto para sordos" #: gaupol/assistants.py:532 msgid "Remove hearing impaired texts" msgstr "Eliminar texto para sordos" #: gaupol/assistants.py:544 msgid "" "Use spell-check suggestions to fix whitespace detection errors of image " "recognition software" msgstr "" "Usa sugerencias del corrector ortográfico para corregir los espacios en\n" "blanco detectados por un software reconocedor de imágenes" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:548 msgid "Joining and Splitting Words" msgstr "Unir o dividir palabras" #: gaupol/assistants.py:550 msgid "Join or Split Words" msgstr "Unir o dividir palabras" #: gaupol/assistants.py:599 gaupol/agents/tools.py:45 msgid "Failed to load dictionary for language \"{}\"" msgstr "No fue posible abrir el diccionario para el idioma «{}»" #: gaupol/assistants.py:601 gaupol/player.py:263 gaupol/player.py:381 #: gaupol/dialogs/search.py:560 gaupol/dialogs/search.py:568 #: gaupol/dialogs/text_edit.py:49 gaupol/dialogs/encoding.py:56 #: gaupol/agents/open.py:328 gaupol/agents/open.py:337 #: gaupol/agents/open.py:345 gaupol/agents/open.py:354 #: gaupol/agents/tools.py:48 gaupol/agents/save.py:197 #: gaupol/agents/save.py:205 gaupol/agents/preview.py:108 #: gaupol/agents/preview.py:116 gaupol/agents/preview.py:125 #: gaupol/agents/preview.py:133 msgid "_OK" msgstr "_Aceptar" #: gaupol/assistants.py:635 msgid "Break text into lines of defined length" msgstr "Divide el texto en líneas de un largo máximo especificado" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:639 msgid "Line-Break Patterns" msgstr "Reglas de dividir líneas" #: gaupol/assistants.py:641 msgid "Break lines" msgstr "Dividir líneas" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:679 msgid "Line-Break Options" msgstr "Opciones de dividir líneas" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:763 msgid "Correcting Texts" msgstr "Corrigiendo textos" #: gaupol/assistants.py:769 msgid "Each task is now being run on each project." msgstr "Aplicando las tareas seleccionadas a cada proyecto." #: gaupol/assistants.py:793 #, python-brace-format msgid "{current:d} of {total:d} tasks complete" msgstr "{current:d} de {total:d} tareas completadas" #: gaupol/assistants.py:801 msgid "Project: {}" msgstr "Proyecto: {}" #: gaupol/assistants.py:807 msgid "Task: {}" msgstr "Tarea: {}" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:832 msgid "Confirm Changes" msgstr "Confirmar cambios" #: gaupol/assistants.py:892 msgid "Accept" msgstr "Aceptar" #: gaupol/assistants.py:898 msgid "Original Text" msgstr "Texto original" #: gaupol/assistants.py:899 msgid "Corrected Text" msgstr "Texto corregido" #: gaupol/assistants.py:1048 msgid "Correct Texts" msgstr "Corregir Texto" #: gaupol/assistants.py:1076 msgid "Correcting texts" msgstr "Corregir texto" #: gaupol/assistants.py:1092 #, python-brace-format msgid "Edited {edits:d} and removed {removals:d} subtitles" msgstr "{edits:d} subtítulos editados, {removals:d} eliminados" #: gaupol/assistants.py:1126 msgid "Confirm {:d} Change" msgid_plural "Confirm {:d} Changes" msgstr[0] "Confirmar {:d} cambio" msgstr[1] "Confirmar {:d} cambios" #: gaupol/renderers/multiline.py:86 msgid "Italic" msgstr "Cursiva" #: gaupol/player.py:372 msgid "No video streams found" msgstr "No se encontró ningún canal de vídeo" #: gaupol/player.py:379 msgid "Failed to initialize playback" msgstr "No fue posible iniciar la reproducción" #: gaupol/dialogs/search.py:189 data/ui/menubar.ui:524 msgid "_Help" msgstr "Ay_uda" #: gaupol/dialogs/search.py:471 msgid "Found and replaced {:d} occurence" msgid_plural "Found and replaced {:d} occurences" msgstr[0] "{:d} ocurrencia encontrada y reemplazada" msgstr[1] "{:d} ocurrencias encontradas y reemplazadas" #: gaupol/dialogs/search.py:488 msgid "\"{}\" not found" msgstr "No se encontró «{}»" #: gaupol/dialogs/search.py:558 msgid "Error in regular expression pattern" msgstr "Error con la expresión regular de búsqueda" #: gaupol/dialogs/search.py:566 msgid "Error in regular expression replacement" msgstr "Error con la expresión regular de reemplazo" #: gaupol/dialogs/text_edit.py:48 gaupol/dialogs/framerate_convert.py:63 #: gaupol/dialogs/insert.py:44 gaupol/dialogs/encoding.py:55 #: gaupol/dialogs/split.py:44 gaupol/dialogs/multi_close.py:54 #: gaupol/dialogs/open.py:63 gaupol/dialogs/position_transform.py:69 #: gaupol/dialogs/position_shift.py:71 gaupol/dialogs/multi_save.py:83 #: gaupol/dialogs/multi_save.py:215 gaupol/dialogs/duration_adjust.py:86 #: gaupol/dialogs/save.py:73 gaupol/dialogs/video.py:41 #: gaupol/agents/open.py:363 gaupol/agents/open.py:375 #: gaupol/agents/open.py:387 gaupol/agents/close.py:71 #: data/extensions/custom-framerates/custom-framerates.py:39 msgid "_Cancel" msgstr "_Cancelar" #: gaupol/dialogs/text_edit.py:53 msgid "Edit Text" msgstr "Editar texto" #: gaupol/dialogs/framerate_convert.py:64 msgid "Co_nvert" msgstr "Co_nvertir" #: gaupol/dialogs/insert.py:45 msgid "_Insert" msgstr "_Insertar" #: gaupol/dialogs/insert.py:54 msgid "Above selection" msgstr "Sobre la selección" #: gaupol/dialogs/insert.py:55 msgid "Below selection" msgstr "Bajo la selección" #: gaupol/dialogs/encoding.py:60 data/ui/preferences-dialog.ui:70 msgid "Character Encodings" msgstr "Codificación de caracteres" #: gaupol/dialogs/encoding.py:78 gaupol/dialogs/encoding.py:125 msgid "Description" msgstr "Descripción" #: gaupol/dialogs/encoding.py:85 gaupol/dialogs/encoding.py:132 msgid "Encoding" msgstr "Codificación" #: gaupol/dialogs/encoding.py:141 msgid "Show in Menu" msgstr "Mostrar en el menú" #: gaupol/dialogs/split.py:45 msgid "_Split" msgstr "_Dividir" #: gaupol/dialogs/split.py:76 msgid "Splitting project" msgstr "Dividiendo proyecto" #: gaupol/dialogs/split.py:97 #, python-brace-format msgid "Split {amount:d} subtitles to project \"{name}\"" msgstr "{amount:d} subtítulos movidos al proyecto nuevo «{name}»" #: gaupol/dialogs/spell_check.py:269 msgid "Spell-checking" msgstr "Corrigiendo ortografía" #: gaupol/dialogs/preferences.py:217 msgid "{} Extension Website" msgstr "Sitio web de {}" #: gaupol/dialogs/preferences.py:429 msgid "Custom" msgstr "Personalizado" #: gaupol/dialogs/multi_close.py:38 msgid "Save changes to documents before closing?" msgstr "¿Guardar los cambios en los documentos antes de salir?" #: gaupol/dialogs/multi_close.py:39 gaupol/agents/open.py:384 #: gaupol/agents/close.py:68 msgid "If you don't save, changes will be permanently lost." msgstr "Si no guarda, todos los cambios se perderán." #: gaupol/dialogs/multi_close.py:53 gaupol/agents/close.py:70 msgid "Close _Without Saving" msgstr "Cerrar _sin guardar" #: gaupol/dialogs/multi_close.py:55 gaupol/dialogs/multi_save.py:84 #: gaupol/dialogs/save.py:74 gaupol/agents/open.py:388 #: gaupol/agents/close.py:72 data/ui/menubar.ui:34 msgid "_Save" msgstr "_Guardar" #: gaupol/dialogs/multi_close.py:70 msgid "Select the _main documents you want to save:" msgstr "Seleccione los docu_mentos que quiera guardar:" #: gaupol/dialogs/multi_close.py:95 msgid "Select the _translation documents you want to save:" msgstr "Seleccione los documentos de _traducción que quiera guardar:" #: gaupol/dialogs/open.py:64 gaupol/agents/open.py:364 #: gaupol/agents/open.py:376 msgid "_Open" msgstr "_Abrir" #: gaupol/dialogs/position_transform.py:70 msgid "_Transform" msgstr "_Ajustar" #: gaupol/dialogs/position_shift.py:72 msgid "_Shift" msgstr "_Desplazar" #: gaupol/dialogs/position_shift.py:150 msgid "frames" msgstr "fotogramas" #: gaupol/dialogs/position_shift.py:168 data/ui/preferences-dialog.ui:911 msgid "seconds" msgstr "segundos" #: gaupol/dialogs/about.py:36 msgid "About Gaupol" msgstr "Acerca de Gaupol" #: gaupol/dialogs/about.py:40 msgid "Subtitle editor" msgstr "Editor de subtítulos" #. TRANSLATORS: This is a special message that shouldn't be translated #. literally. It is used in the about dialog to give credits to the #. translators. Thus, you should translate it to your name and email #. address. You can also include other translators who have contributed #. to this translation; in that case, please write them on separate #. lines seperated by newlines (\n). #: gaupol/dialogs/about.py:51 msgid "translator-credits" msgstr "" "Carlos Mella \n" "Miguel Latorre " #: gaupol/dialogs/about.py:54 msgid "Gaupol Website" msgstr "Sitio web de Gaupol" #: gaupol/dialogs/append.py:35 msgid "Append File" msgstr "Añadir desde archivo" #: gaupol/dialogs/debug.py:43 msgid "Something went wrong" msgstr "Algo salió mal" #: gaupol/dialogs/debug.py:44 msgid "" "You have probably discovered a bug. Please report it by providing the below " "information and a description of what you were doing." msgstr "" "Probablemente ha descubierto un error en Gaupol. Por favor informe de esto " "describiendo la tarea que estaba realizando, y adjunte la siguiente " "información:" #: gaupol/dialogs/debug.py:52 msgid "_Report Bug" msgstr "_Informar de este error" #: gaupol/dialogs/debug.py:53 data/ui/menubar.ui:56 msgid "_Quit" msgstr "_Salir" #: gaupol/dialogs/debug.py:54 gaupol/dialogs/preview_error.py:45 #: data/ui/menubar.ui:52 data/ui/tab-popup.ui:16 msgid "_Close" msgstr "_Cerrar" #: gaupol/dialogs/multi_save.py:98 gaupol/dialogs/save.py:110 msgid "{} (recommended)" msgstr "{} (recomendado)" #: gaupol/dialogs/multi_save.py:212 msgid "" "{:d} of the files to be saved already exist. Do you want to replace them?" msgstr "{:d} de los archivos por guardarse ya existen. ¿Desea reemplazarlos?" #: gaupol/dialogs/multi_save.py:213 msgid "" "The files already exist in \"{}\". Replacing them will overwrite their " "contents." msgstr "" "Los archivos ya existen en «{}». Al reemplazarlos sobreescribirá sus " "contenidos." #: gaupol/dialogs/multi_save.py:216 data/ui/search-dialog.ui:192 #: data/ui/spell-check-dialog.ui:122 msgid "_Replace" msgstr "_Reemplazar" #: gaupol/dialogs/duration_adjust.py:70 msgid "Adjusted duration of {:d} subtitle" msgid_plural "Adjusted durations of {:d} subtitles" msgstr[0] "{:d} subtítulo ajustado en su duración" msgstr[1] "{:d} subtítulos ajustados en su duración" #: gaupol/dialogs/duration_adjust.py:87 msgid "_Adjust" msgstr "_Ajustar" #: gaupol/dialogs/preview_error.py:36 msgid "Preview in video player failed" msgstr "" "No fue posible ejecutar la vista previa en el reproductor externo de vídeo" #: gaupol/dialogs/preview_error.py:37 msgid "" "There is probably a problem with either the video file or the video player. " "See the preferences dialog to choose the video player or to customize the " "command." msgstr "" "Probablemente hay un problema con el archivo o el reproductor de vídeo. " "Puede elegir un nuevo reproductor o personalizar el comando en el diálogo de" " preferencias de Gaupol." #: gaupol/dialogs/language.py:97 msgid "Set Language" msgstr "Definir idioma" #: gaupol/dialogs/video.py:52 gaupol/dialogs/file.py:59 msgid "All files" msgstr "Todos los archivos" #: gaupol/dialogs/video.py:56 msgid "Video files" msgstr "Archivos de vídeo" #: gaupol/dialogs/file.py:63 msgid "All supported files" msgstr "Todos los archivos soportados" #: gaupol/dialogs/file.py:77 #, python-brace-format msgid "{format} (*{extension})" msgstr "{format} (*{extension})" #: gaupol/dialogs/file.py:120 msgid "Auto-detected" msgstr "Detectar automáticamente" #: gaupol/dialogs/file.py:122 msgid "Other…" msgstr "Otro…" #: gaupol/agents/menu.py:94 gaupol/agents/menu.py:103 #: gaupol/agents/menu.py:110 msgid "File not found" msgstr "No se encontró el archivo" #: gaupol/agents/open.py:85 #, python-brace-format msgid "Appended {amount:d} subtitles from \"{basename}\"" msgstr "{amount:d} subtítulos añadidos desde «{basename}»" #: gaupol/agents/open.py:96 msgid "Appending file" msgstr "Añadiendo archivo" #: gaupol/agents/open.py:111 msgid "File \"{}\" is already open" msgstr "El archivo «{}» ya está abierto" #: gaupol/agents/open.py:214 msgid "Open Translation" msgstr "Abrir traducción" #: gaupol/agents/open.py:223 msgid "Select Video" msgstr "Seleccionar el archivo de vídeo" #: gaupol/agents/open.py:224 msgid "_Select" msgstr "_Seleccionar" #: gaupol/agents/open.py:325 msgid "Failed to decode file \"{}\" with all attempted codecs" msgstr "No fue posible decodificar el archivo «{}» con los códecs disponibles" #: gaupol/agents/open.py:326 msgid "Please try to open the file with a different character encoding." msgstr "" "Intente abrir el archivo usando una codificación de caracteres diferente." #: gaupol/agents/open.py:334 msgid "Failed to recognize format of file \"{}\"" msgstr "No fue posible reconocer el formato del archivo «{}»" #: gaupol/agents/open.py:335 msgid "" "Please check that the file you are trying to open is a subtitle file of a " "format supported by Gaupol." msgstr "" "Verifique que el archivo que intenta abrir está en un formato soportado por " "Gaupol." #: gaupol/agents/open.py:343 msgid "Failed to open file \"{}\"" msgstr "No fue posible abrir el archivo «{}»" #: gaupol/agents/open.py:351 msgid "Failed to parse file \"{}\"" msgstr "No fue posible analizar el archivo «{}»" #: gaupol/agents/open.py:352 msgid "Please check that the file you are trying to open is a valid {} file." msgstr "Verifique que el archivo que intenta abrir es un archivo {} válido." #: gaupol/agents/open.py:360 msgid "Open abnormally large file \"{}\"?" msgstr "¿Abrir el archivo de gran tamaño «{}»?" #: gaupol/agents/open.py:361 msgid "" "Size of the file is {:.1f} MB, which is abnormally large for a text-based " "subtitle file. Please, check that you are not trying to open a binary file." msgstr "" "El tamaño del archivo es {:.1f} MB, que es excesivamente grande para un " "archivo de subtítulos. Verifique que no sea un archivo binario." #: gaupol/agents/open.py:371 msgid "Open unsorted file \"{}\"?" msgstr "¿Abrir el archivo desordenado «{}»?" #: gaupol/agents/open.py:372 msgid "" "The order of {:d} subtitles needs to be changed. If {:d} sounds like a lot, " "the file may be erroneously composed." msgstr "" "Es necesario cambiar el orden de {:d} subtítulos. Si considera que {:d} es " "una gran cantidad, es posible que el archivo fuera creado de forma " "incorrecta." #: gaupol/agents/open.py:383 msgid "Save changes to translation document \"{}\" before opening a new one?" msgstr "" "¿Guardar cambios en el documento de traducción «{}» antes de abrir uno " "nuevo?" #: gaupol/agents/open.py:386 msgid "Open _Without Saving" msgstr "Abrir _sin guardar" #: gaupol/agents/close.py:66 msgid "Save changes to document \"{}\" before closing?" msgstr "¿Guardar los cambios al documento «{}» antes de salir?" #: gaupol/agents/edit.py:101 gaupol/agents/edit.py:119 msgid "Stretching end position" msgstr "Ajustar posición final" #: gaupol/agents/edit.py:208 msgid "Inserted {:d} subtitle to fit clipboard contents" msgid_plural "Inserted {:d} subtitles to fit clipboard contents" msgstr[0] "" "{:d} subtítulo insertado para adaptarse a los contenidos del portapapeles" msgstr[1] "" "{:d} subtítulos insertados para adaptarse a los contenidos del portapapeles" #: gaupol/agents/edit.py:334 gaupol/agents/edit.py:352 msgid "Stretching start position" msgstr "Ajustar posición inicial" #: gaupol/agents/edit.py:411 msgid "Use Shift+Return for line-break" msgstr "Use Mayús+Intro para insertar un salto de línea" #: gaupol/agents/save.py:129 msgid "Save As" msgstr "Guardar como" #: gaupol/agents/save.py:135 msgid "Saved main document as \"{}\"" msgstr "Documento principal guardado como «{}»" #: gaupol/agents/save.py:153 msgid "Save Translation As" msgstr "Guardar traducción como" #: gaupol/agents/save.py:159 msgid "Saved translation document as \"{}\"" msgstr "Documento de traducción guardado como «{}»" #: gaupol/agents/save.py:194 #, python-brace-format msgid "Failed to encode file \"{basename}\" with codec \"{codec}\"" msgstr "" "No fue posible codificar el archivo «{basename}» usando el códec «{codec}»" #: gaupol/agents/save.py:195 msgid "Please try to save the file with a different character encoding." msgstr "" "Intente guardar el archivo usando una codificación de caracteres diferente." #: gaupol/agents/save.py:203 msgid "Failed to save file \"{}\"" msgstr "No fue posible guardar el archivo «{}»" #: gaupol/agents/video.py:67 data/ui/menubar.ui:380 msgid "_Play/Pause" msgstr "_Reproducir o pausar" #: gaupol/agents/video.py:69 msgid "Play or pause video" msgstr "Reproduce o pausa el vídeo" #: gaupol/agents/video.py:75 data/ui/menubar.ui:390 msgid "Seek _Previous" msgstr "Saltar al _anterior" #: gaupol/agents/video.py:77 msgid "Seek to the start of the previous subtitle" msgstr "Salta al inicio del subtítulo anterior" #: gaupol/agents/video.py:81 data/ui/menubar.ui:394 msgid "Seek _Next" msgstr "Saltar al _siguiente" #: gaupol/agents/video.py:83 msgid "Seek to the start of the next subtitle" msgstr "Salta al inicio del subtítulo siguiente" #: gaupol/agents/video.py:88 data/ui/menubar.ui:400 msgid "Seek _Backward" msgstr "Saltar hacia a_trás" #: gaupol/agents/video.py:90 msgid "Seek backward" msgstr "Salta hacia atrás" #: gaupol/agents/video.py:94 data/ui/menubar.ui:404 msgid "Seek _Forward" msgstr "Saltar hacia a_delante" #: gaupol/agents/video.py:96 msgid "Seek forward" msgstr "Salta hacia adelante" #: gaupol/agents/video.py:109 msgid "Volume" msgstr "Volumen" #: gaupol/agents/video.py:189 msgid "Load Video" msgstr "Abrir vídeo" #: gaupol/agents/video.py:189 msgid "_Load" msgstr "_Abrir" #: gaupol/agents/video.py:361 msgid "Track {:d}" msgstr "Pista {:d}" #: gaupol/agents/preview.py:105 msgid "Failed to encode subtitle file to temporary directory \"{}\"" msgstr "" "No fue posible codificar el archivo de subtítulos en el directorio temporal " "«{}»" #: gaupol/agents/preview.py:106 msgid "" "Subtitle data could not be encoded to a temporary file for preview with the " "current character encoding. Please first save the subtitle file with a " "different character encoding." msgstr "" "No fue posible codificar los subtítulos en un archivo temporal para su vista" " previa usando la codificación de caracteres actual. Intente guardar el " "archivo de subtítulos con una codificación de caracteres diferente." #: gaupol/agents/preview.py:114 msgid "Failed to save subtitle file to temporary directory \"{}\"" msgstr "" "No fue posible guardar el archivo de subtítulos en el directorio temporal " "«{}»" #: gaupol/agents/preview.py:122 msgid "Video player not found" msgstr "No se encontró el reproductor externo de vídeo" #: gaupol/agents/preview.py:123 msgid "" "Please install one of the supported video players: mpv (recommended), " "MPlayer or VLC. See the preferences dialog to choose the video player or to " "customize the command." msgstr "" "Instale uno de los reproductores de vídeo soportados: mpv (recomendado), " "MPlayer o VLC. Puede elegir el reproductor o personalizar el comando en el " "diálogo de preferencias de Gaupol." #: gaupol/agents/preview.py:131 msgid "Failed to launch video player" msgstr "No fue posible ejecutar el reproductor externo de vídeo" #: gaupol/applicationman.py:105 msgid "gaupol [OPTION...] [FILE...] [+[NUM]]" msgstr "gaupol [OPCIÓN...] [ARCHIVO...] [+[NUM]]" #: gaupol/applicationman.py:109 msgid "FILE..." msgstr "ARCHIVO..." #: gaupol/applicationman.py:112 msgid "subtitle files to open" msgstr "archivos de subtítulos a abrir" #: gaupol/applicationman.py:122 msgid "ENCODING" msgstr "CODIFICACIÓN" #: gaupol/applicationman.py:125 msgid "set the character encoding used to open files" msgstr "establece la codificación de caracteres usada para abrir archivos" #: gaupol/applicationman.py:132 msgid "list all available character encodings" msgstr "lista todas las codificaciones de caracteres disponibles" #: gaupol/applicationman.py:137 gaupol/applicationman.py:154 msgid "FILE" msgstr "ARCHIVO" #: gaupol/applicationman.py:140 msgid "open translation file" msgstr "abre el archivo de traducción" #: gaupol/applicationman.py:145 msgid "METHOD" msgstr "MÉTODO" #: gaupol/applicationman.py:149 msgid "method used to align translation subtitles: 'number' or 'position'" msgstr "" "método usado para ajustar los subtítulos de traducción: 'number' o " "'position'" #: gaupol/applicationman.py:157 msgid "select video file" msgstr "selecciona el archivo de vídeo" #: data/extensions/custom-framerates/custom-framerates.py:40 #: data/ui/spell-check-dialog.ui:152 msgid "_Add" msgstr "Aña_dir" #: data/extensions/custom-framerates/custom-framerates.py:171 msgid "{:.3f} fps" msgstr "{:.3f} fps" #: data/extensions/custom-framerates/add-framerate-dialog.ui:13 msgid "Add Framerate" msgstr "Añadir frecuencia de fotogramas" #: data/extensions/custom-framerates/add-framerate-dialog.ui:44 msgid "_Framerate:" msgstr "_Frecuencia de fotogramas:" #: data/extensions/custom-framerates/add-framerate-dialog.ui:73 msgid "fps" msgstr "fps" #: data/extensions/custom-framerates/preferences-dialog.ui:8 msgid "Framerates" msgstr "Frecuencias de fotogramas" #: data/extensions/custom-framerates/preferences-dialog.ui:64 msgid "Add" msgstr "Añadir" #: data/ui/columns-popup.ui:6 data/ui/menubar.ui:275 msgid "_No." msgstr "_Nº" #: data/ui/columns-popup.ui:10 data/ui/menubar.ui:279 msgid "_Start" msgstr "_Inicio" #: data/ui/columns-popup.ui:14 data/ui/menubar.ui:283 msgid "_End" msgstr "_Fin" #: data/ui/columns-popup.ui:18 data/ui/menubar.ui:287 msgid "_Duration" msgstr "_Duración" #: data/ui/columns-popup.ui:22 data/ui/menubar.ui:291 data/ui/menubar.ui:303 msgid "_Text" msgstr "_Texto" #: data/ui/columns-popup.ui:26 data/ui/menubar.ui:295 msgid "T_ranslation" msgstr "T_raducción" #: data/ui/split-dialog.ui:15 msgid "Split Project" msgstr "Dividir proyecto" #: data/ui/split-dialog.ui:48 msgid "_First subtitle of new project:" msgstr "_Primer subtítulo del proyecto nuevo:" #: data/ui/search-dialog.ui:89 msgid "_Search for:" msgstr "_Buscar por:" #: data/ui/search-dialog.ui:103 data/ui/spell-check-dialog.ui:193 msgid "Replace _with:" msgstr "Ree_mplazar con:" #: data/ui/search-dialog.ui:162 data/ui/menubar.ui:328 msgid "Find _Next" msgstr "Buscar _siguiente" #: data/ui/search-dialog.ui:177 msgid "Find _Previous" msgstr "Buscar _anterior" #: data/ui/search-dialog.ui:207 msgid "Replace _All" msgstr "Reemplazar _todo" #: data/ui/search-dialog.ui:241 msgid "R_egular expression" msgstr "_Expresión regular" #: data/ui/search-dialog.ui:258 msgid "_Ignore case" msgstr "Ignorar _capitalización" #: data/ui/search-dialog.ui:304 data/ui/language-dialog.ui:108 msgid "Columns" msgstr "Columnas" #: data/ui/search-dialog.ui:324 msgid "Find in _text column" msgstr "Buscar en la columna t_exto" #: data/ui/search-dialog.ui:341 msgid "Find in t_ranslation column" msgstr "Buscar en la columna t_raducción" #: data/ui/search-dialog.ui:381 data/ui/framerate-convert-dialog.ui:144 #: data/ui/language-dialog.ui:186 #: data/ui/text-assistant/line-break-options-page.ui:178 #: data/ui/duration-adjust-dialog.ui:388 data/ui/position-shift-dialog.ui:180 #: data/ui/position-transform-dialog.ui:444 msgid "Subtitles" msgstr "Subtítulos" #: data/ui/search-dialog.ui:401 msgid "Find in c_urrent project" msgstr "Buscar en el proyecto act_ual" #: data/ui/search-dialog.ui:419 msgid "Find in _all open projects" msgstr "Buscar en _todos los proyectos abiertos" #: data/ui/search-dialog.ui:452 msgid "Target" msgstr "Objetivo" #: data/ui/framerate-convert-dialog.ui:8 msgid "Convert Framerate" msgstr "Cambiar framerate" #: data/ui/framerate-convert-dialog.ui:48 msgid "Framerate" msgstr "Frecuencia de fotogramas" #: data/ui/framerate-convert-dialog.ui:71 msgid "_Input:" msgstr "_Entrada:" #: data/ui/framerate-convert-dialog.ui:86 msgid "_Output:" msgstr "_Salida:" #: data/ui/framerate-convert-dialog.ui:164 msgid "Convert c_urrent project" msgstr "Cambiar en el proyecto act_ual" #: data/ui/framerate-convert-dialog.ui:181 msgid "Convert _all open projects" msgstr "Cambiar en _todos los proyectos abiertos" #: data/ui/spell-check-dialog.ui:8 msgid "Check Spelling" msgstr "Comprobar ortografía" #: data/ui/spell-check-dialog.ui:47 msgid "Join _Back" msgstr "Unir con _anterior" #: data/ui/spell-check-dialog.ui:62 msgid "Join _Forward" msgstr "Unir con _siguiente" #: data/ui/spell-check-dialog.ui:77 data/ui/menubar.ui:62 msgid "_Edit" msgstr "_Editar" #: data/ui/spell-check-dialog.ui:92 msgid "_Ignore" msgstr "_Ignorar" #: data/ui/spell-check-dialog.ui:107 msgid "Ig_nore All" msgstr "Ig_norar todo" #: data/ui/spell-check-dialog.ui:137 msgid "Rep_lace All" msgstr "Reemplazar _todo" #: data/ui/spell-check-dialog.ui:179 msgid "_Suggestions:" msgstr "S_ugerencias:" #: data/ui/multi-save-dialog.ui:8 msgid "Save All As" msgstr "Guardar todo como" #: data/ui/multi-save-dialog.ui:46 msgid "Save in _folder:" msgstr "G_uardar en la carpeta:" #: data/ui/multi-save-dialog.ui:60 data/ui/save-dialog.ui:25 msgid "For_mat:" msgstr "_Formato:" #: data/ui/multi-save-dialog.ui:74 data/ui/open-dialog.ui:25 #: data/ui/save-dialog.ui:39 msgid "_Encoding:" msgstr "Co_dificación:" #: data/ui/multi-save-dialog.ui:88 data/ui/save-dialog.ui:53 msgid "Ne_wlines:" msgstr "Salto de _línea:" #: data/ui/multi-save-dialog.ui:103 msgid "Select A Folder" msgstr "Seleccionar carpeta" #: data/ui/multi-save-dialog.ui:150 data/ui/save-dialog.ui:102 msgid "F_ramerate:" msgstr "F_recuencia de fotogramas:" #: data/ui/menubar.ui:5 msgid "_File" msgstr "_Archivo" #: data/ui/menubar.ui:8 msgid "_New" msgstr "_Nuevo" #: data/ui/menubar.ui:12 msgid "_Open…" msgstr "_Abrir…" #: data/ui/menubar.ui:16 msgid "Open _Translation…" msgstr "Abrir _traducción…" #: data/ui/menubar.ui:22 msgid "Open _Recent" msgstr "Abrir _reciente" #: data/ui/menubar.ui:27 msgid "Open R_ecent Translation" msgstr "Abrir traducción rec_iente" #: data/ui/menubar.ui:38 msgid "Save _As…" msgstr "Gu_ardar como…" #: data/ui/menubar.ui:42 msgid "Save Trans_lation" msgstr "Guardar tra_ducción" #: data/ui/menubar.ui:46 msgid "Save Translat_ion As…" msgstr "Guardar traducción c_omo…" #: data/ui/menubar.ui:65 msgid "_Undo" msgstr "_Deshacer" #: data/ui/menubar.ui:69 msgid "_Redo" msgstr "_Rehacer" #: data/ui/menubar.ui:75 msgid "_Edit Cell" msgstr "_Editar celda" #: data/ui/menubar.ui:79 msgid "Edit _Next Cell" msgstr "Edi_tar la siguiente celda" #: data/ui/menubar.ui:85 msgid "Stretc_h" msgstr "_Ajustar posición" #: data/ui/menubar.ui:88 msgid "_Start Earlier" msgstr "_Iniciar antes" #: data/ui/menubar.ui:92 msgid "S_tart Later" msgstr "I_niciar después" #: data/ui/menubar.ui:98 msgid "E_nd Earlier" msgstr "_Finalizar antes" #: data/ui/menubar.ui:102 msgid "En_d Later" msgstr "Fin_alizar después" #: data/ui/menubar.ui:108 msgid "Set St_art From Video Position" msgstr "Definir p_osición inicial según la posición del vídeo" #: data/ui/menubar.ui:112 msgid "Set En_d From Video Position" msgstr "De_finir posición final según la posición del vídeo" #: data/ui/menubar.ui:118 data/ui/view-popup.ui:6 msgid "_Split Subtitle" msgstr "Dividir _subtítulo" #: data/ui/menubar.ui:122 data/ui/view-popup.ui:10 msgid "_Merge Subtitles" msgstr "Co_mbinar subtítulos" #: data/ui/menubar.ui:128 data/ui/view-popup.ui:16 msgid "_Insert Subtitles…" msgstr "_Insertar subtítulos…" #: data/ui/menubar.ui:132 msgid "Inser_t Subtitle At Video Position" msgstr "Insertar s_ubtítulo según la posición del vídeo" #: data/ui/menubar.ui:136 data/ui/view-popup.ui:20 msgid "Rem_ove Subtitles" msgstr "E_liminar subtítulos" #: data/ui/menubar.ui:142 msgid "Sele_ction" msgstr "Sele_cción" #: data/ui/menubar.ui:145 msgid "Select _All" msgstr "Seleccionar _todo" #: data/ui/menubar.ui:149 msgid "_Invert Selection" msgstr "I_nvertir selección" #: data/ui/menubar.ui:155 msgid "Extend To _Beginning" msgstr "Extender desde el _inicio" #: data/ui/menubar.ui:159 msgid "Extend To _End" msgstr "Extender hasta el _final" #: data/ui/menubar.ui:165 msgid "_Previous From Video Position" msgstr "_Anterior según la posición del vídeo" #: data/ui/menubar.ui:169 msgid "_Next From Video Position" msgstr "_Siguiente según la posición del vídeo" #: data/ui/menubar.ui:177 msgid "_Preferences" msgstr "Prefere_ncias" #: data/ui/menubar.ui:183 msgid "_View" msgstr "_Ver" #: data/ui/menubar.ui:186 msgid "Tool_bar" msgstr "Barra de _herramientas" #: data/ui/menubar.ui:190 msgid "_Video Player" msgstr "Ví_deo integrado" #: data/ui/menubar.ui:196 msgid "_Layout" msgstr "Disp_osición" #: data/ui/menubar.ui:199 msgid "_Horizontal" msgstr "_Horizontal" #: data/ui/menubar.ui:204 msgid "_Vertical" msgstr "_Vertical" #: data/ui/menubar.ui:213 msgid "_Times" msgstr "_Tiempos" #: data/ui/menubar.ui:218 msgid "_Frames" msgstr "_Fotogramas" #: data/ui/menubar.ui:225 msgid "F_ramerate" msgstr "F_recuencia de fotogramas" #: data/ui/menubar.ui:228 msgid "2_3.976 fps" msgstr "2_3,976 fps" #: data/ui/menubar.ui:233 msgid "2_4.000 fps" msgstr "2_4,000 fps" #: data/ui/menubar.ui:238 msgid "2_5.000 fps" msgstr "2_5,000 fps" #: data/ui/menubar.ui:243 msgid "2_9.970 fps" msgstr "2_9,970 fps" #: data/ui/menubar.ui:272 msgid "_Columns" msgstr "_Columnas" #: data/ui/menubar.ui:306 msgid "Cu_t" msgstr "Cor_tar" #: data/ui/menubar.ui:310 msgid "_Copy" msgstr "_Copiar" #: data/ui/menubar.ui:314 msgid "_Paste" msgstr "_Pegar" #: data/ui/menubar.ui:318 msgid "Cl_ear" msgstr "_Borrar" #: data/ui/menubar.ui:324 msgid "_Find And Replace…" msgstr "Buscar y _reemplazar…" #: data/ui/menubar.ui:332 msgid "Find Pre_vious" msgstr "Buscar _anterior" #: data/ui/menubar.ui:338 msgid "_Italic" msgstr "Curs_iva" #: data/ui/menubar.ui:342 msgid "_Dialogue" msgstr "_Diálogo" #: data/ui/menubar.ui:348 msgid "Ca_se" msgstr "Capitali_zación" #: data/ui/menubar.ui:351 msgid "_Title" msgstr "_Título" #: data/ui/menubar.ui:355 msgid "_Sentence" msgstr "_Frase" #: data/ui/menubar.ui:359 msgid "_Upper" msgstr "M_ayúsculas" #: data/ui/menubar.ui:363 msgid "_Lower" msgstr "M_inúsculas" #: data/ui/menubar.ui:371 msgid "Vi_deo" msgstr "Vi_deo" #: data/ui/menubar.ui:374 msgid "_Load Video…" msgstr "Abrir _vídeo…" #: data/ui/menubar.ui:384 data/ui/view-popup.ui:26 msgid "Play _Selection" msgstr "Reproducir sele_cción" #: data/ui/menubar.ui:410 data/ui/view-popup.ui:30 msgid "S_eek Selection Start" msgstr "Saltar al _inicio de la selección" #: data/ui/menubar.ui:414 msgid "See_k Selection End" msgstr "Saltar al _fin de la selección" #: data/ui/menubar.ui:420 msgid "_Audio" msgstr "Audi_o" #: data/ui/menubar.ui:423 msgid "_Language" msgstr "_Idioma" #: data/ui/menubar.ui:430 msgid "Volume _Down" msgstr "_Bajar volumen" #: data/ui/menubar.ui:434 msgid "Volume _Up" msgstr "_Subir volumen" #: data/ui/menubar.ui:440 msgid "T_ools" msgstr "_Herramientas" #: data/ui/menubar.ui:443 data/ui/text-assistant/confirmation-page.ui:97 #: data/ui/view-popup.ui:36 msgid "_Preview" msgstr "_Vista previa" #: data/ui/menubar.ui:447 msgid "Select _Video…" msgstr "Seleccionar _vídeo…" #: data/ui/menubar.ui:453 msgid "_Check Spelling" msgstr "Comprobar _ortografía" #: data/ui/menubar.ui:457 msgid "Co_nfigure Spell-check…" msgstr "_Configurar corrector ortográfico…" #: data/ui/menubar.ui:461 msgid "C_orrect Texts…" msgstr "Corregir _texto…" #: data/ui/menubar.ui:467 msgid "_Shift Positions…" msgstr "_Desplazar posiciones…" #: data/ui/menubar.ui:471 msgid "_Transform Positions…" msgstr "Ajustar po_siciones…" #: data/ui/menubar.ui:475 msgid "Adjust _Durations…" msgstr "Ajustar _duraciones…" #: data/ui/menubar.ui:479 msgid "Convert _Framerate…" msgstr "Cambiar _frecuencia de fotogramas…" #: data/ui/menubar.ui:485 msgid "_Append File…" msgstr "_Añadir desde archivo…" #: data/ui/menubar.ui:489 msgid "Spli_t Project…" msgstr "D_ividir proyecto…" #: data/ui/menubar.ui:495 msgid "_Projects" msgstr "_Proyectos" #: data/ui/menubar.ui:498 msgid "_Save All" msgstr "Guardar _todo" #: data/ui/menubar.ui:502 msgid "Save _All As…" msgstr "Guardar todo c_omo…" #: data/ui/menubar.ui:506 msgid "_Close All" msgstr "_Cerrar todo" #: data/ui/menubar.ui:512 msgid "_Previous" msgstr "_Anterior" #: data/ui/menubar.ui:516 msgid "_Next" msgstr "_Siguiente" #: data/ui/menubar.ui:527 msgid "_Documentation" msgstr "Do_cumentación" #: data/ui/menubar.ui:531 msgid "_Report A Bug" msgstr "Informar de un _error" #: data/ui/menubar.ui:535 msgid "_About" msgstr "Acerca _de" #: data/ui/open-dialog.ui:39 msgid "Align _method:" msgstr "Aj_ustar según:" #: data/ui/preferences-dialog.ui:18 msgid "Preferences" msgstr "Preferencias" #: data/ui/preferences-dialog.ui:93 msgid "When opening files, try encodings in the following order:" msgstr "Al abrir archivos, probar con las siguientes codificaciones:" #: data/ui/preferences-dialog.ui:104 msgid "Curr_ent locale encoding" msgstr "La c_odificación dada por la configuración regional actual" #: data/ui/preferences-dialog.ui:130 msgid "_Fallback encodings:" msgstr "Codificacio_nes alternativas:" #: data/ui/preferences-dialog.ui:246 msgid "Aut_o-detection" msgstr "_Detectar automáticamente" #: data/ui/preferences-dialog.ui:266 msgid "Encoding specified in the open dialog will always be tried first." msgstr "" "La codificación especificada en el diálogo «Abrir» será siempre la primera " "en probarse." #: data/ui/preferences-dialog.ui:296 msgid "File" msgstr "Archivo" #: data/ui/preferences-dialog.ui:324 msgid "Font" msgstr "Tipografía" #: data/ui/preferences-dialog.ui:344 msgid "Use _default theme fixed width font" msgstr "Usar la _tipografía de ancho fijo por omisión del sistema" #: data/ui/preferences-dialog.ui:368 msgid "_Editor font:" msgstr "Tipografía del e_ditor:" #: data/ui/preferences-dialog.ui:425 msgid "Line Lengths" msgstr "Largo de líneas" #: data/ui/preferences-dialog.ui:445 msgid "_Show line lengths in list cells" msgstr "_Mostrar el largo de las líneas en las celdas" #: data/ui/preferences-dialog.ui:462 msgid "S_how line lengths in editable text fields" msgstr "" "Mo_strar el largo de las líneas en los campos de texto mientras se escribe" #: data/ui/preferences-dialog.ui:486 msgid "_Length unit:" msgstr "_Unidad de medida:" #: data/ui/preferences-dialog.ui:540 msgid "Spell-Check" msgstr "Corrector ortográfico" #: data/ui/preferences-dialog.ui:560 msgid "Chec_k spelling as you type" msgstr "Revisar _ortografía mientras se escribe" #: data/ui/preferences-dialog.ui:598 msgid "Editor" msgstr "Editor" #: data/ui/preferences-dialog.ui:626 msgid "Fonts" msgstr "Tipografías" #: data/ui/preferences-dialog.ui:649 msgid "_Subtitles:" msgstr "_Subtítulos:" #: data/ui/preferences-dialog.ui:679 msgid "_Time:" msgstr "_Tiempo:" #: data/ui/preferences-dialog.ui:729 msgid "Colors" msgstr "Colores" #: data/ui/preferences-dialog.ui:752 msgid "Su_btitles:" msgstr "S_ubtítulos:" #: data/ui/preferences-dialog.ui:777 msgid "_Use a background behind text" msgstr "_Mostrar un fondo tras el texto" #: data/ui/preferences-dialog.ui:797 msgid "Ti_me:" msgstr "T_iempo:" #: data/ui/preferences-dialog.ui:822 msgid "Us_e a background behind text" msgstr "M_ostrar un fondo tras el texto" #: data/ui/preferences-dialog.ui:862 msgid "Seek" msgstr "Saltos" #: data/ui/preferences-dialog.ui:883 msgid "_Length:" msgstr "_Largo:" #: data/ui/preferences-dialog.ui:971 msgid "Video Player" msgstr "Reproductor externo de vídeo" #: data/ui/preferences-dialog.ui:994 msgid "_Application:" msgstr "_Aplicación:" #: data/ui/preferences-dialog.ui:1008 msgid "Co_mmand:" msgstr "Co_mando:" #. Translators: Only the title is to be translated, field names not. #: data/ui/preferences-dialog.ui:1033 msgid "" "Fields:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" msgstr "" "Campos:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" #: data/ui/preferences-dialog.ui:1048 msgid "Al_ways use UTF-8 character encoding" msgstr "Usar _siempre la codificación de caracteres UTF-8" #: data/ui/preferences-dialog.ui:1089 msgid "Start Position" msgstr "Posición inicial" #: data/ui/preferences-dialog.ui:1111 msgid "_Offset:" msgstr "_Desplazamiento:" #: data/ui/preferences-dialog.ui:1142 msgid "seconds before selection" msgstr "segundos antes de la selección" #: data/ui/preferences-dialog.ui:1281 msgid "Extensions" msgstr "Complementos" #: data/ui/language-dialog.ui:8 msgid "Configure Spell-Check" msgstr "Configurar corrector ortográfico" #: data/ui/language-dialog.ui:50 msgid "Language" msgstr "Idioma" #: data/ui/language-dialog.ui:128 msgid "Check _text column" msgstr "Comprobar la columna t_exto" #: data/ui/language-dialog.ui:146 msgid "Check t_ranslation column" msgstr "Comprobar la columna t_raducción" #: data/ui/language-dialog.ui:206 msgid "Check c_urrent project" msgstr "Comprobar el proyecto act_ual" #: data/ui/language-dialog.ui:224 msgid "Check _all open projects" msgstr "Comprobar _todos los proyectos abiertos" #: data/ui/text-assistant/confirmation-page.ui:22 msgid "Acc_ept, discard or edit changes:" msgstr "Acepte, rechace o edite cada cam_bio propuesto:" #: data/ui/text-assistant/confirmation-page.ui:67 msgid "_Mark All" msgstr "_Marcar todo" #: data/ui/text-assistant/confirmation-page.ui:82 msgid "_Unmark All" msgstr "_Desmarcar todo" #: data/ui/text-assistant/confirmation-page.ui:119 msgid "_Remove all blank subtitles" msgstr "" "_Eliminar\n" "subtítulos en blanco" #: data/ui/text-assistant/join-split-page.ui:28 msgid "Spell-Check Dictionary" msgstr "Diccionario del corrector ortográfico" #: data/ui/text-assistant/join-split-page.ui:49 #: data/ui/text-assistant/line-break-page.ui:81 #: data/ui/text-assistant/hearing-impaired-page.ui:81 #: data/ui/text-assistant/common-error-page.ui:80 #: data/ui/text-assistant/capitalization-page.ui:80 msgid "_Language:" msgstr "_Idioma:" #: data/ui/text-assistant/join-split-page.ui:97 msgid "Corrections" msgstr "Correcciones" #: data/ui/text-assistant/join-split-page.ui:117 msgid "_Join words not found in spell-check dictionary" msgstr "" "_Unir palabras no encontradas en el diccionario del corrector ortográfico" #: data/ui/text-assistant/join-split-page.ui:134 msgid "_Split words not found in spell-check dictionary" msgstr "" "Di_vidir palabras no encontradas en el diccionario del corrector ortográfico" #: data/ui/text-assistant/line-break-page.ui:22 msgid "S_elect preferred line-break points:" msgstr "S_eleccione los puntos de división de líneas preferidos:" #: data/ui/text-assistant/line-break-page.ui:67 #: data/ui/text-assistant/hearing-impaired-page.ui:67 #: data/ui/text-assistant/common-error-page.ui:66 #: data/ui/text-assistant/capitalization-page.ui:66 msgid "_Script:" msgstr "_Script:" #: data/ui/text-assistant/line-break-page.ui:95 #: data/ui/text-assistant/hearing-impaired-page.ui:95 #: data/ui/text-assistant/common-error-page.ui:94 #: data/ui/text-assistant/capitalization-page.ui:94 msgid "Co_untry:" msgstr "_País:" #: data/ui/text-assistant/introduction-page.ui:28 msgid "_Select corrections to perform on texts:" msgstr "_Seleccione las tareas de corrección que quiera aplicar:" #: data/ui/text-assistant/introduction-page.ui:79 msgid "Colu_mns:" msgstr "Colu_mnas:" #: data/ui/text-assistant/introduction-page.ui:93 msgid "S_ubtitles:" msgstr "S_ubtítulos:" #: data/ui/text-assistant/line-break-options-page.ui:56 #: data/ui/duration-adjust-dialog.ui:207 msgid "Limits" msgstr "Límites" #: data/ui/text-assistant/line-break-options-page.ui:79 msgid "_Maximum line length:" msgstr "_Largo máximo de cada línea:" #: data/ui/text-assistant/line-break-options-page.ui:93 msgid "_Preferred maximum amount of lines:" msgstr "_Número preferido máximo de líneas:" #: data/ui/text-assistant/line-break-options-page.ui:198 msgid "_Skip subtitles with maximum line length of:" msgstr "_Ignorar subtítulos con líneas de un largo menor o igual a:" #: data/ui/text-assistant/line-break-options-page.ui:214 msgid "S_kip subtitles with maximum line amount of:" msgstr "Ign_orar subtítulos con un número de líneas menor o igual a:" #: data/ui/text-assistant/hearing-impaired-page.ui:22 msgid "S_elect parts to remove:" msgstr "S_eleccione los elementos que quiera eliminar:" #: data/ui/text-assistant/common-error-page.ui:22 msgid "S_elect errors to correct:" msgstr "S_eleccione los errores que quiera corregir:" #: data/ui/text-assistant/common-error-page.ui:108 msgid "Error types:" msgstr "Tipos de errores:" #: data/ui/text-assistant/common-error-page.ui:158 msgid "_Human errors" msgstr "Errores _humanos" #: data/ui/text-assistant/common-error-page.ui:175 msgid "_Image recognition errors" msgstr "Errores de _reconocedores de imágenes" #: data/ui/text-assistant/capitalization-page.ui:22 msgid "S_elect parts to capitalize:" msgstr "S_eleccione los casos donde quiera capitalizar:" #: data/ui/duration-adjust-dialog.ui:33 msgid "Adjust Durations" msgstr "Ajustar duración" #: data/ui/duration-adjust-dialog.ui:73 msgid "Theoretic Duration" msgstr "Duración teórica" #: data/ui/duration-adjust-dialog.ui:101 msgid "_Reading speed:" msgstr "_Velocidad de lectura:" #: data/ui/duration-adjust-dialog.ui:133 msgid "characters per second" msgstr "caracteres por segundo" #: data/ui/duration-adjust-dialog.ui:150 msgid "_Lengthen duration to match reading speed" msgstr "Au_mentar duración hasta alcanzar la velocidad de lectura" #: data/ui/duration-adjust-dialog.ui:167 msgid "_Shorten duration to match reading speed" msgstr "_Reducir duración hasta alcanzar la velocidad de lectura" #: data/ui/duration-adjust-dialog.ui:227 msgid "_Minimum duration:" msgstr "Duración mí_nima:" #: data/ui/duration-adjust-dialog.ui:243 msgid "Ma_ximum duration:" msgstr "Duración má_xima:" #: data/ui/duration-adjust-dialog.ui:259 msgid "_Gap between subtitles:" msgstr "_Pausa entre subtítulos:" #: data/ui/duration-adjust-dialog.ui:294 msgid "s_econds" msgstr "segun_dos" #: data/ui/duration-adjust-dialog.ui:324 msgid "seco_nds" msgstr "segund_os" #: data/ui/duration-adjust-dialog.ui:354 msgid "secon_ds" msgstr "segundo_s" #: data/ui/duration-adjust-dialog.ui:408 msgid "Adj_ust selected subtitles" msgstr "Ajustar los subtítulos s_eleccionados" #: data/ui/duration-adjust-dialog.ui:425 msgid "Adjus_t current project" msgstr "Ajustar en el proyecto act_ual" #: data/ui/duration-adjust-dialog.ui:442 msgid "Adjust all _open projects" msgstr "Ajustar en _todos los proyectos abiertos" #: data/ui/tab-popup.ui:6 msgid "Move Tab _Left" msgstr "Mover solapa a la _izquierda" #: data/ui/tab-popup.ui:10 msgid "Move Tab _Right" msgstr "Mover solapa a la _derecha" #: data/ui/insert-dialog.ui:15 msgid "Insert Subtitles" msgstr "Insertar subtítulos" #: data/ui/insert-dialog.ui:48 data/ui/position-shift-dialog.ui:82 msgid "_Amount:" msgstr "C_antidad:" #: data/ui/insert-dialog.ui:62 msgid "_Position:" msgstr "_Posición:" #: data/ui/position-shift-dialog.ui:14 msgid "Shift Positions" msgstr "Desplazar posiciones" #: data/ui/position-shift-dialog.ui:54 msgid "Shift" msgstr "Desplazamiento" #: data/ui/position-shift-dialog.ui:135 #: data/ui/position-transform-dialog.ui:208 msgid "_Preview Changes" msgstr "_Vista previa" #: data/ui/position-shift-dialog.ui:200 msgid "Shift s_elected subtitles" msgstr "Desplazar los subtítulos s_eleccionados" #: data/ui/position-shift-dialog.ui:217 msgid "Shift su_btitles from selection to end" msgstr "De_splazar a partir de los subtítulos seleccionados" #: data/ui/position-shift-dialog.ui:234 msgid "Shift c_urrent project" msgstr "Desplazar en el proyecto act_ual" #: data/ui/position-shift-dialog.ui:251 msgid "Shift all _open projects" msgstr "Desplazar en _todos los proyectos abiertos" #: data/ui/position-transform-dialog.ui:22 msgid "Transform Positions" msgstr "Ajustar posiciones" #: data/ui/position-transform-dialog.ui:62 msgid "First Point" msgstr "Primer punto" #: data/ui/position-transform-dialog.ui:91 msgid "_Subtitle:" msgstr "_Subtítulo:" #: data/ui/position-transform-dialog.ui:105 msgid "C_orrection:" msgstr "Ajus_te:" #: data/ui/position-transform-dialog.ui:119 #: data/ui/position-transform-dialog.ui:310 msgid "Text:" msgstr "Texto:" #: data/ui/position-transform-dialog.ui:253 msgid "Second Point" msgstr "Segundo punto" #: data/ui/position-transform-dialog.ui:282 msgid "Su_btitle:" msgstr "_Subtítulo:" #: data/ui/position-transform-dialog.ui:296 msgid "Co_rrection:" msgstr "Ajus_te:" #: data/ui/position-transform-dialog.ui:399 msgid "Pre_view Changes" msgstr "_Vista previa" #: data/ui/position-transform-dialog.ui:464 msgid "Transform se_lected subtitles" msgstr "Ajustar los subtítulos s_eleccionados" #: data/ui/position-transform-dialog.ui:482 msgid "Transform c_urrent project" msgstr "Ajustar en el proyecto act_ual" #: data/extensions/custom-framerates/custom-framerates.extension.in:7 msgid "Custom Framerates" msgstr "Frecuencias de fotogramas personalizadas" #: data/extensions/custom-framerates/custom-framerates.extension.in:8 msgid "Allow use of non-standard framerates" msgstr "" "Permite el uso de frecuencias de fotogramas («framerates») poco frecuentes" #: data/patterns/Latn-en-US.common-error.in:5 msgid "Period after title" msgstr "Punto después de títulos personales" #: data/patterns/Latn-en-US.common-error.in:6 msgid "Add period after a shortened title, such as \"Mr\" and \"Dr\"" msgstr "" "Agrega un punto después de un título personal abreviado, tal como «Mr» o " "«Dr»" #: data/patterns/Latn-en.capitalization.in:5 msgid "First person pronoun" msgstr "Pronombre en primera persona" #: data/patterns/Latn-en.capitalization.in:6 msgid "Capitalize the first person pronoun \"I\"" msgstr "Capitaliza el pronombre en primera persona «I»" #: data/patterns/Latn-en.common-error.in:5 #: data/patterns/Latn-en.common-error.in:14 #: data/patterns/Latn-en.common-error.in:23 msgid "Letter \"I\" in a lower case word" msgstr "Letra «I» en palabras en minúsculas" #: data/patterns/Latn-en.common-error.in:6 #: data/patterns/Latn-en.common-error.in:15 #: data/patterns/Latn-en.common-error.in:24 msgid "Replace letter \"I\" with letter \"l\" in a lower case word" msgstr "" "Reemplaza la vocal «I» dentro de una palabra en minúsculas por la consonante" " «l»" #: data/patterns/Latn-en.common-error.in:32 #: data/patterns/Latn-en.common-error.in:41 #: data/patterns/Latn-en.common-error.in:50 #: data/patterns/Latn-en.common-error.in:62 msgid "Letter \"l\" in an upper case word" msgstr "Letra «l» en palabras en mayúsculas" #: data/patterns/Latn-en.common-error.in:33 #: data/patterns/Latn-en.common-error.in:42 #: data/patterns/Latn-en.common-error.in:51 #: data/patterns/Latn-en.common-error.in:63 msgid "Replace letter \"l\" with letter \"I\" in an upper case word" msgstr "" "Reemplaza la consonante «l» dentro de una palabra en mayúsculas por la vocal" " «I»" #: data/patterns/Latn-en.common-error.in:73 #: data/patterns/Latn-en.common-error.in:82 msgid "Zero in an upper case word" msgstr "Cero en palabras en mayúsculas" #: data/patterns/Latn-en.common-error.in:74 #: data/patterns/Latn-en.common-error.in:83 msgid "Replace zero with letter \"O\" in an upper case word" msgstr "" "Reemplaza el número cero dentro de una palabra en mayúsculas por la vocal " "«O»" #: data/patterns/Latn-en.common-error.in:91 #: data/patterns/Latn.common-error.in:108 msgid "Space between number and unit" msgstr "Espacio entre números y unidades de medida" #: data/patterns/Latn-en.common-error.in:92 #: data/patterns/Latn.common-error.in:109 msgid "Add or remove space between a number and the associated unit" msgstr "" "Ajusta el espacio en blanco entre un número y su unidad de medida asociada" #: data/patterns/Latn-en.common-error.in:100 msgid "Spaces around an apostrophe" msgstr "Espacios alrededor de apóstrofes" #: data/patterns/Latn-en.common-error.in:101 msgid "Remove spaces around an apostrophe" msgstr "Elimina el espacio en blanco alrededor de un apóstrofe" #: data/patterns/Latn-en.common-error.in:109 #: data/patterns/Latn-en.common-error.in:118 msgid "Okay" msgstr "Okay" #: data/patterns/Latn-en.common-error.in:110 #: data/patterns/Latn-en.common-error.in:119 msgid "Spell two-letter forms of \"okay\" in all upper case" msgstr "Convierte varias formas abreviadas de la palabra «okay» a «OK»" #: data/patterns/Latn-en.hearing-impaired.in:5 msgid "Uppercase speaker before a colon" msgstr "Hablante en mayúsculas antes de dos puntos" #: data/patterns/Latn-en.hearing-impaired.in:6 msgid "" "Replace the uppercase name of the speaker before a colon with a dialogue " "dash" msgstr "" "Reemplaza el nombre en mayúsculas del hablante antes de dos puntos por una " "raya de diálogo" #: data/patterns/Latn-en.line-break.in:5 msgid "Title" msgstr "Título personal" #: data/patterns/Latn-en.line-break.in:6 msgid "Do not break after a title, e.g. \" Dr.\"" msgstr "No divide después de un título personal, como «Dr.»" #: data/patterns/Latn-en.line-break.in:13 msgid "Article" msgstr "Artículo" #: data/patterns/Latn-en.line-break.in:14 msgid "Do not break after an article" msgstr "No divide después de un artículo" #: data/patterns/Latn-en.line-break.in:21 msgid "Preposition" msgstr "Preposición" #: data/patterns/Latn-en.line-break.in:22 msgid "Do not break after a preposition" msgstr "No divide después de una preposición" #: data/patterns/Latn-en.line-break.in:30 msgid "Possessive determiner" msgstr "Determinante posesivo" #: data/patterns/Latn-en.line-break.in:31 msgid "Do not break after a possessive determiner, e.g. \"my\"" msgstr "No divide después de un determinante posesivo, tal como «mi»" #: data/patterns/Latn-fi.common-error.in:5 #: data/patterns/Latn.common-error.in:182 msgid "Space after punctuation marks" msgstr "Espacio a continuación de signos de puntuación" #: data/patterns/Latn-fi.common-error.in:6 #: data/patterns/Latn.common-error.in:183 msgid "Add space after various punctuation marks" msgstr "Agrega un espacio en blanco después de diversos signos de puntuación" #: data/patterns/Latn-fr.common-error.in:5 #: data/patterns/Latn-fr.common-error.in:14 #: data/patterns/Latn-fr.common-error.in:23 #: data/patterns/Latn-fr.common-error.in:32 msgid "Spaces around guillemets" msgstr "Espacios alrededor de comillas angulares" #: data/patterns/Latn-fr.common-error.in:6 #: data/patterns/Latn-fr.common-error.in:15 #: data/patterns/Latn-fr.common-error.in:24 #: data/patterns/Latn-fr.common-error.in:33 msgid "Add spaces around guillemets" msgstr "Agrega espacios en blanco alrededor de comillas angulares" #: data/patterns/Latn-fr.common-error.in:41 #: data/patterns/Latn-fr.common-error.in:52 #: data/patterns/Latn.common-error.in:171 msgid "Space before punctuation marks" msgstr "Espacio antes de signos de puntuación" #: data/patterns/Latn-fr.common-error.in:42 #: data/patterns/Latn-fr.common-error.in:53 msgid "Add or remove space before various punctuation marks" msgstr "Ajusta el espacio en blanco antes de diversos signos de puntuación" #: data/patterns/Latn.capitalization.in:5 msgid "Sentence" msgstr "Frase" #: data/patterns/Latn.capitalization.in:6 msgid "Capitalize the first word of a sentence" msgstr "Capitaliza la primera palabra de cada oración" #: data/patterns/Latn.capitalization.in:12 msgid "Ellipsis" msgstr "Puntos suspensivos" #: data/patterns/Latn.capitalization.in:13 msgid "Capitalize after an ellipsis" msgstr "Capitaliza después de puntos suspensivos" #: data/patterns/Latn.common-error.in:8 data/patterns/Latn.common-error.in:17 #: data/patterns/Latn.common-error.in:26 data/patterns/Latn.common-error.in:35 #: data/patterns/Latn.common-error.in:44 data/patterns/Latn.common-error.in:53 #: data/patterns/Latn.common-error.in:62 msgid "Ligatures" msgstr "Ligaduras" #: data/patterns/Latn.common-error.in:9 data/patterns/Latn.common-error.in:18 #: data/patterns/Latn.common-error.in:27 data/patterns/Latn.common-error.in:36 #: data/patterns/Latn.common-error.in:45 data/patterns/Latn.common-error.in:54 #: data/patterns/Latn.common-error.in:63 msgid "Unpack ligatures to individual characters" msgstr "" "Reemplaza diversas ligaduras tipográficas por sus caracteres individuales" #: data/patterns/Latn.common-error.in:71 data/patterns/Latn.common-error.in:80 msgid "Spelling of a.m. and p.m." msgstr "«a.m.» y «p.m.»" #: data/patterns/Latn.common-error.in:72 data/patterns/Latn.common-error.in:81 msgid "Change the various spellings of 12-hour periods to \"a.m.\" and \"p.m.\"" msgstr "" "Convierte varias formas de escribir períodos de 12 horas a «a.m.» y «p.m.»" #: data/patterns/Latn.common-error.in:89 data/patterns/Latn.common-error.in:98 msgid "Letter \"O\" in a number" msgstr "Letra «O» en números" #: data/patterns/Latn.common-error.in:90 data/patterns/Latn.common-error.in:99 msgid "Replace letter \"O\" with a zero in a number" msgstr "Reemplaza la vocal «O» dentro de un número por un cero" #: data/patterns/Latn.common-error.in:117 msgid "Double apostrophe" msgstr "Doble comilla simple" #: data/patterns/Latn.common-error.in:118 msgid "Replace a double apostrophe with a quotation mark" msgstr "Reemplaza dos comillas simples por una comilla doble" #: data/patterns/Latn.common-error.in:126 #: data/patterns/Latn.common-error.in:135 #: data/patterns/Latn.common-error.in:144 #: data/patterns/Latn.common-error.in:153 msgid "Spaces around brackets" msgstr "Espacios alrededor de paréntesis" #: data/patterns/Latn.common-error.in:127 #: data/patterns/Latn.common-error.in:136 #: data/patterns/Latn.common-error.in:145 #: data/patterns/Latn.common-error.in:154 msgid "Add or remove spaces around parantheses and square brackets" msgstr "" "Ajusta los espacios en blanco alrededor de paréntesis y corchetes cuadrados" #: data/patterns/Latn.common-error.in:162 msgid "Space after a dialogue dash" msgstr "Espacio a continuación de rayas de diálogo" #: data/patterns/Latn.common-error.in:163 msgid "Add space after a dialogue dash" msgstr "Agrega un espacio en blanco después de una raya de diálogo" #: data/patterns/Latn.common-error.in:172 msgid "Remove space before various punctuation marks" msgstr "Elimina el espacio en blanco antes de diversos signos de puntuación" #: data/patterns/Latn.common-error.in:192 msgid "Space after an ellipsis" msgstr "Espacio a continuación de puntos suspensivos" #: data/patterns/Latn.common-error.in:193 msgid "Add space after an ellipsis" msgstr "Agrega un espacio en blanco después de puntos suspensivos" #: data/patterns/Latn.common-error.in:201 msgid "Space after a starting ellipsis" msgstr "Espacio a continuación de puntos suspensivos iniciales" #: data/patterns/Latn.common-error.in:202 msgid "Remove space after an ellipsis that starts a line" msgstr "" "Elimina el espacio en blanco después de puntos suspensivos al inicio de " "línea" #: data/patterns/Latn.common-error.in:210 #: data/patterns/Latn.common-error.in:221 #: data/patterns/Latn.common-error.in:232 #: data/patterns/Latn.common-error.in:242 msgid "Spaces around a quotation mark" msgstr "Espacios alrededor de comillas" #: data/patterns/Latn.common-error.in:211 #: data/patterns/Latn.common-error.in:222 #: data/patterns/Latn.common-error.in:233 #: data/patterns/Latn.common-error.in:243 msgid "Remove space after a starting- and before an ending quotation mark" msgstr "" "Elimina el espacio en blanco después de una comilla inicial y previo a una " "final" #: data/patterns/Latn.common-error.in:252 #: data/patterns/Latn.common-error.in:261 msgid "Spaces around musical notes" msgstr "Espacios alrededor de notas musicales" #: data/patterns/Latn.common-error.in:253 #: data/patterns/Latn.common-error.in:262 msgid "Add spaces between musical note characters and lyrics" msgstr "" "Agrega espacios en blanco entre caracteres de notas musicales y letras de " "canciones" #: data/patterns/Latn.common-error.in:270 #: data/patterns/Latn.common-error.in:279 msgid "Multiple question- and exclamation marks" msgstr "Múltiples signos de exclamación e interrogación" #: data/patterns/Latn.common-error.in:271 #: data/patterns/Latn.common-error.in:280 msgid "" "Replace multiple consequtive question- and exclamation marks with only one" msgstr "" "Reduce a uno múltiples signos de interrogación o exclamación consecutivos" #: data/patterns/Latn.common-error.in:288 #: data/patterns/Latn.common-error.in:298 msgid "Periods around a punctuation mark" msgstr "Puntos alrededor de signos de puntuación" #: data/patterns/Latn.common-error.in:289 #: data/patterns/Latn.common-error.in:299 msgid "Remove period before or after various punctuation marks" msgstr "Elimina el punto antes o después de diversos signos de puntuación" #: data/patterns/Latn.common-error.in:308 msgid "Terminating double-dashes" msgstr "Fin de oraciones con dos rayas" #: data/patterns/Latn.common-error.in:309 msgid "Replace a single clause-terminating dash with two dashes" msgstr "" "Agrega una segunda raya al fin de una oración ya terminada por una raya" #: data/patterns/Latn.hearing-impaired.in:5 msgid "Sound in brackets" msgstr "Sonido entre corchetes cuadrados" #: data/patterns/Latn.hearing-impaired.in:6 msgid "Remove description of a sound between square brackets" msgstr "Elimina la descripción entre corchetes cuadrados de un sonido" #: data/patterns/Latn.hearing-impaired.in:12 msgid "Sound in parantheses" msgstr "Sonido entre paréntesis" #: data/patterns/Latn.hearing-impaired.in:13 msgid "Remove description of a sound between parantheses" msgstr "Elimina la descripción entre paréntesis de un sonido" #: data/patterns/Latn.hearing-impaired.in:19 msgid "Song lyrics between number signs" msgstr "Letras de canciones entre almohadillas" #: data/patterns/Latn.hearing-impaired.in:20 msgid "Remove song lyrics starting with or between number signs" msgstr "" "Elimina letras de canciones que comienzan o se encuentran entre almohadillas" " (#)" #: data/patterns/Latn.hearing-impaired.in:27 msgid "One-line song lyrics between number signs" msgstr "Letras de canciones entre almohadillas por línea" #: data/patterns/Latn.hearing-impaired.in:28 msgid "Remove one-line song lyrics starting with or between number signs" msgstr "" "Elimina letras de canciones que comienzan o se encuentran por línea entre " "almohadillas (#)" #: data/patterns/Latn.hearing-impaired.in:35 msgid "Speaker before a colon" msgstr "Hablante antes de dos puntos" #: data/patterns/Latn.hearing-impaired.in:36 msgid "Replace the name of the speaker before a colon with a dialogue dash" msgstr "" "Reemplaza el nombre del hablante antes de dos puntos por una raya de diálogo" #: data/patterns/Latn.line-break.in:5 data/patterns/Latn.line-break.in:13 msgid "Dialogue" msgstr "Diálogo" #: data/patterns/Latn.line-break.in:6 data/patterns/Latn.line-break.in:14 msgid "Break according to dialogue separated by dashes" msgstr "Divide en base a rayas separando un diálogo" #: data/patterns/Latn.line-break.in:21 data/patterns/Latn.line-break.in:30 msgid "Clause" msgstr "Oración" #: data/patterns/Latn.line-break.in:22 data/patterns/Latn.line-break.in:31 msgid "Break according to clauses terminated by a punctuation mark" msgstr "Divide en base a oraciones finalizadas por un signo de puntuación" #: data/patterns/Latn.line-break.in:38 msgid "Number and unit" msgstr "Número y unidad de medida" #: data/patterns/Latn.line-break.in:39 msgid "Do not break between a number and associated unit" msgstr "No divide entre un número y su unidad de medida respectiva" #: data/patterns/Zyyy.common-error.in:5 data/patterns/Zyyy.common-error.in:14 msgid "Leading and trailing spaces" msgstr "Espacios iniciales y finales" #: data/patterns/Zyyy.common-error.in:6 data/patterns/Zyyy.common-error.in:15 msgid "Remove spaces from the beginning and end of lines" msgstr "Elimina el espacio en blanco al inicio y fin de cada línea" #: data/patterns/Zyyy.common-error.in:23 msgid "Multiple consecutive spaces" msgstr "Múltiples espacios en blanco" #: data/patterns/Zyyy.common-error.in:24 msgid "Replace multiple consecutive spaces with only one" msgstr "Reduce a uno múltiples espacios en blanco consecutivos" #: data/patterns/Zyyy.common-error.in:32 data/patterns/Zyyy.common-error.in:45 #: data/patterns/Zyyy.common-error.in:55 data/patterns/Zyyy.common-error.in:65 msgid "Space between digits" msgstr "Espacio entre dígitos" #: data/patterns/Zyyy.common-error.in:33 data/patterns/Zyyy.common-error.in:46 #: data/patterns/Zyyy.common-error.in:56 data/patterns/Zyyy.common-error.in:66 msgid "Remove space between digits of a number" msgstr "Elimina el espacio en blanco entre los dígitos de un número" #: data/patterns/Zyyy.common-error.in:79 msgid "Musical notes" msgstr "Notas musicales" #: data/patterns/Zyyy.common-error.in:80 msgid "Replace Unicode musical note characters with number signs" msgstr "Reemplaza caracteres Unicode de notas musicales por signos numéricos" #: data/io.otsaloma.gaupol.appdata.xml.in:7 msgid "Editor for text-based subtitles" msgstr "Editor de archivos de subtítulos basados en texto" #: data/io.otsaloma.gaupol.appdata.xml.in:9 msgid "" "Gaupol is an editor for text-based subtitle files. It supports multiple " "subtitle file formats and provides means of creating subtitles, editing " "texts and timing subtitles to match video." msgstr "" "Gaupol es un editor de archivos de subtítulos basados en texto. Con soporte " "para diversos formatos de archivos, proporciona los medios para crear " "subtítulos, manipular líneas y sincronizar subtítulos a un vídeo." #: data/io.otsaloma.gaupol.appdata.xml.in:40 msgid "Main window" msgstr "Ventana principal" #: data/io.otsaloma.gaupol.desktop.in:5 msgid "Subtitle Editor" msgstr "Editor de subtítulos" #: data/io.otsaloma.gaupol.desktop.in:6 msgid "Edit subtitle files" msgstr "Edite archivos de subtítulos" #. TRANSLATORS: Search terms to find this application. Do NOT translate or #. localize the semicolons! The list MUST also end with a semicolon! #: data/io.otsaloma.gaupol.desktop.in:12 msgid "video;subtitles;captions;" msgstr "vídeo;subtítulos;" gaupol-1.11/po/fi.po000066400000000000000000002207331422217132500143050ustar00rootroot00000000000000# 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. # # Translators: # Osmo Salomaa , 2020 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-04-03 04:00+0300\n" "PO-Revision-Date: 2022-04-03 04:00+0300\n" "Last-Translator: Osmo Salomaa , 2020\n" "Language-Team: Finnish (https://www.transifex.com/otsaloma/teams/64879/fi/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fi\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: aeidon/enums.py:40 gaupol/enums.py:38 msgid "Subtitle number" msgstr "Kappaleen numero" #: aeidon/enums.py:43 msgid "Subtitle position" msgstr "Kappaleen kohta" #: aeidon/enums.py:59 msgid "23.976 fps" msgstr "23,976 fps" #: aeidon/enums.py:63 msgid "24.000 fps" msgstr "24,000 fps" #: aeidon/enums.py:67 msgid "25.000 fps" msgstr "25,000 fps" #: aeidon/enums.py:71 msgid "29.970 fps" msgstr "29,970 fps" #: aeidon/enums.py:75 data/ui/menubar.ui:248 msgid "30.000 fps" msgstr "30,000 fps" #: aeidon/enums.py:79 data/ui/menubar.ui:253 msgid "50.000 fps" msgstr "50,000 fps" #: aeidon/enums.py:83 data/ui/menubar.ui:258 msgid "59.940 fps" msgstr "59,940 fps" #: aeidon/enums.py:87 data/ui/menubar.ui:263 msgid "60.000 fps" msgstr "60,000 fps" #: aeidon/enums.py:112 msgid "Mac (classic)" msgstr "Mac (klassinen)" #. TRANSLATORS: Most of the character encoding descriptions are copied from #. gedit, which is translated to very many languages. Check the gedit .po #. files for a reference: #. . #: aeidon/encodings.py:40 aeidon/encodings.py:43 aeidon/encodings.py:46 msgid "English" msgstr "Englanti" #: aeidon/encodings.py:41 aeidon/encodings.py:42 aeidon/encodings.py:69 msgid "Chinese traditional" msgstr "Kiina, perinteinen" #: aeidon/encodings.py:44 msgid "German" msgstr "Saksa" #: aeidon/encodings.py:45 aeidon/encodings.py:54 aeidon/encodings.py:59 #: aeidon/encodings.py:79 aeidon/encodings.py:105 msgid "Hebrew" msgstr "Heprea" #: aeidon/encodings.py:47 aeidon/encodings.py:51 aeidon/encodings.py:56 #: aeidon/encodings.py:73 aeidon/encodings.py:76 aeidon/encodings.py:98 #: aeidon/encodings.py:111 aeidon/encodings.py:122 msgid "Western" msgstr "Länsimainen" #: aeidon/encodings.py:48 aeidon/encodings.py:61 aeidon/encodings.py:80 #: aeidon/encodings.py:103 msgid "Arabic" msgstr "Arabia" #: aeidon/encodings.py:49 aeidon/encodings.py:64 aeidon/encodings.py:66 #: aeidon/encodings.py:77 aeidon/encodings.py:104 aeidon/encodings.py:119 msgid "Greek" msgstr "Kreikka" #: aeidon/encodings.py:50 aeidon/encodings.py:81 aeidon/encodings.py:101 #: aeidon/encodings.py:109 msgid "Baltic" msgstr "Balttilainen" #: aeidon/encodings.py:52 aeidon/encodings.py:74 aeidon/encodings.py:99 #: aeidon/encodings.py:121 msgid "Central European" msgstr "Keski-Eurooppalainen" #: aeidon/encodings.py:53 aeidon/encodings.py:75 aeidon/encodings.py:102 #: aeidon/encodings.py:118 msgid "Cyrillic" msgstr "Kyrillinen" #: aeidon/encodings.py:55 aeidon/encodings.py:71 aeidon/encodings.py:78 #: aeidon/encodings.py:106 aeidon/encodings.py:123 msgid "Turkish" msgstr "Turkki" #: aeidon/encodings.py:57 msgid "Portuguese" msgstr "Portugali" #: aeidon/encodings.py:58 aeidon/encodings.py:120 msgid "Icelandic" msgstr "Islanti" #: aeidon/encodings.py:60 msgid "Canadian" msgstr "Kanadalainen" #: aeidon/encodings.py:62 aeidon/encodings.py:107 msgid "Nordic" msgstr "Pohjoismainen" #: aeidon/encodings.py:63 aeidon/encodings.py:114 msgid "Russian" msgstr "Venäjä" #: aeidon/encodings.py:65 aeidon/encodings.py:108 msgid "Thai" msgstr "Thai" #: aeidon/encodings.py:67 aeidon/encodings.py:83 aeidon/encodings.py:84 #: aeidon/encodings.py:85 aeidon/encodings.py:91 aeidon/encodings.py:92 #: aeidon/encodings.py:93 aeidon/encodings.py:94 aeidon/encodings.py:95 #: aeidon/encodings.py:96 aeidon/encodings.py:125 aeidon/encodings.py:126 #: aeidon/encodings.py:127 msgid "Japanese" msgstr "Japani" #: aeidon/encodings.py:68 aeidon/encodings.py:86 aeidon/encodings.py:97 #: aeidon/encodings.py:113 msgid "Korean" msgstr "Korea" #: aeidon/encodings.py:70 msgid "Urdu" msgstr "Urdu" #: aeidon/encodings.py:72 aeidon/encodings.py:116 msgid "Ukrainian" msgstr "Ukraina" #: aeidon/encodings.py:82 msgid "Vietnamese" msgstr "Vietnam" #: aeidon/encodings.py:87 aeidon/encodings.py:90 msgid "Chinese simplified" msgstr "Kiina, yksinkertaistettu" #: aeidon/encodings.py:88 aeidon/encodings.py:89 msgid "Chinese unified" msgstr "Kiina, yhdistetty" #: aeidon/encodings.py:100 aeidon/encodings.py:112 msgid "South European" msgstr "Eteläeurooppalainen" #: aeidon/encodings.py:110 msgid "Celtic" msgstr "Kelttiläinen" #: aeidon/encodings.py:115 msgid "Tajik" msgstr "Tadžikki" #: aeidon/encodings.py:117 msgid "Kazakh" msgstr "Kazakki" #: aeidon/encodings.py:124 msgid "Cyrillic Asian" msgstr "Aasian kyrillinen" #: aeidon/encodings.py:128 aeidon/encodings.py:129 aeidon/encodings.py:130 #: aeidon/encodings.py:131 aeidon/encodings.py:132 aeidon/encodings.py:133 #: aeidon/encodings.py:134 aeidon/encodings.py:135 aeidon/encodings.py:136 msgid "Unicode" msgstr "Unicode" #: aeidon/encodings.py:156 #, python-brace-format msgid "{description} ({name})" msgstr "{description} ({name})" #: aeidon/encodings.py:232 msgid "Current locale ({})" msgstr "Nykyinen maa-asetusto ({})" #: aeidon/locales.py:46 #, python-brace-format msgid "{language} ({country})" msgstr "{language} ({country})" #: aeidon/agents/search.py:227 msgid "Replacing" msgstr "korvaaminen" #: aeidon/agents/search.py:256 aeidon/agents/search.py:258 msgid "Replacing all" msgstr "kaikkien korvaaminen" #: aeidon/agents/position.py:74 msgid "Adjusting durations" msgstr "kestojen säätäminen" #: aeidon/agents/position.py:96 msgid "Converting framerate" msgstr "ruutunopeuden muuntaminen" #: aeidon/agents/position.py:146 msgid "Setting framerate" msgstr "ruutunopeuden asettaminen" #: aeidon/agents/position.py:168 msgid "Shifting positions" msgstr "kohtien siirtäminen" #: aeidon/agents/position.py:188 msgid "Transforming positions" msgstr "kohtien muuntaminen" #: aeidon/agents/clipboard.py:44 msgid "Cutting texts" msgstr "tekstien leikkaaminen" #: aeidon/agents/clipboard.py:61 msgid "Pasting texts" msgstr "tekstien liittäminen" #: aeidon/agents/text.py:91 msgid "Breaking lines" msgstr "rivien katkaiseminen" #: aeidon/agents/text.py:128 msgid "Capitalizing texts" msgstr "tekstien kirjainkokojen muuttaminen" #: aeidon/agents/text.py:185 msgid "Correcting common errors" msgstr "yleisten virheiden korjaaminen" #: aeidon/agents/text.py:234 msgid "Removing hearing impaired texts" msgstr "kuulovammaisten tekstien poistaminen" #: aeidon/agents/text.py:315 msgid "Joining words by spell-check suggestions" msgstr "sanojen yhdistäminen oikoluvun ehdotusten mukaan" #: aeidon/agents/text.py:354 msgid "Splitting words by spell-check suggestions" msgstr "sanojen jakaminen oikoluvun ehdotusten mukaan" #: aeidon/agents/set.py:58 aeidon/agents/set.py:80 aeidon/agents/set.py:113 msgid "Editing position" msgstr "kohdan muokkaaminen" #: aeidon/agents/set.py:129 msgid "Editing text" msgstr "tekstin muokkaaminen" #: aeidon/agents/edit.py:35 msgid "Clearing texts" msgstr "tekstien tyhjentäminen" #: aeidon/agents/edit.py:61 aeidon/agents/edit.py:83 msgid "Inserting subtitles" msgstr "kappaleiden lisääminen" #: aeidon/agents/edit.py:103 msgid "Merging subtitles" msgstr "kappaleiden yhdistäminen" #: aeidon/agents/edit.py:114 msgid "Removing subtitles" msgstr "kappaleiden poistaminen" #: aeidon/agents/edit.py:131 msgid "Replacing positions" msgstr "kohtien korvaaminen" #: aeidon/agents/edit.py:147 msgid "Replacing texts" msgstr "tekstien korvaaminen" #: aeidon/agents/edit.py:171 msgid "Splitting subtitle" msgstr "kappaleen jakaminen" #: aeidon/agents/format.py:49 msgid "Adding dialogue dashes" msgstr "vuoropuheluviivojen lisääminen" #: aeidon/agents/format.py:68 msgid "Changing case" msgstr "kirjainkoon muuttaminen" #: aeidon/agents/format.py:92 msgid "Italicizing" msgstr "kursivointi" #: aeidon/agents/format.py:108 msgid "Removing dialogue dashes" msgstr "vuoropuheluviivojen lisääminen" #: aeidon/agents/format.py:174 msgid "Unitalicizing" msgstr "kursivoinnin poistaminen" #: gaupol/application.py:219 gaupol/agents/open.py:203 msgid "Open" msgstr "Avaa" #: gaupol/application.py:223 msgid "Open main files" msgstr "Avaa päätiedostoja" #: gaupol/application.py:230 msgid "Save" msgstr "Tallenna" #: gaupol/application.py:233 msgid "Save the current main document" msgstr "Tallenna nykyinen pääasiakirja" #: gaupol/application.py:238 msgid "Undo" msgstr "Kumoa" #: gaupol/application.py:242 msgid "Undo the last action" msgstr "Kumoa viimeisin toiminto" #: gaupol/application.py:249 msgid "Redo" msgstr "Tee uudelleen" #: gaupol/application.py:252 msgid "Redo the last undone action" msgstr "Tee uudestaan viimeisin kumottu toiminto" #: gaupol/application.py:260 msgid "Insert" msgstr "Lisää" #: gaupol/application.py:262 msgid "Insert new subtitles" msgstr "Lisää uusia kappaleita" #: gaupol/application.py:266 #: data/extensions/custom-framerates/preferences-dialog.ui:78 msgid "Remove" msgstr "Poista" #: gaupol/application.py:268 msgid "Remove the selected subtitles" msgstr "Poista valitut kappaleet" #: gaupol/application.py:273 data/ui/search-dialog.ui:283 msgid "Find" msgstr "Etsi" #: gaupol/application.py:275 msgid "Search for and replace text" msgstr "Etsi ja korvaa tekstiä" #: gaupol/application.py:279 data/ui/preferences-dialog.ui:942 msgid "Video" msgstr "Video" #: gaupol/application.py:281 msgid "Show or hide the video player" msgstr "Näytä tai piilota videosoitin" #: gaupol/application.py:285 data/ui/preferences-dialog.ui:1173 msgid "Preview" msgstr "Esikatselu" #: gaupol/application.py:287 msgid "Preview from selected position with a video player" msgstr "Esikatsele valitusta kohdasta videosoittimella" #: gaupol/enums.py:37 msgid "No." msgstr "Nro." #: gaupol/enums.py:43 msgid "Start" msgstr "Alku" #: gaupol/enums.py:44 msgid "Start position" msgstr "Alkukohta" #: gaupol/enums.py:49 msgid "End" msgstr "Loppu" #: gaupol/enums.py:50 msgid "End position" msgstr "Loppukohta" #. TRANSLATORS: 'Dur.' is short for duration. It is used in the header #. of a column that contains numbers five digits wide. #: gaupol/enums.py:57 msgid "Dur." msgstr "Kesto" #: gaupol/enums.py:58 msgid "Duration" msgstr "Kesto" #: gaupol/enums.py:63 gaupol/enums.py:64 msgid "Text" msgstr "Teksti" #: gaupol/enums.py:69 gaupol/enums.py:70 msgid "Translation" msgstr "Käännös" #: gaupol/enums.py:82 msgid "characters" msgstr "merkkiä" #: gaupol/enums.py:85 msgid "ems" msgstr "em" #: gaupol/page.py:60 msgid "Untitled {:d}" msgstr "Nimetön {:d}" #: gaupol/page.py:133 msgid "Close project" msgstr "Sulje projekti" #: gaupol/page.py:145 msgid "{} translation" msgstr "{} käännös" #: gaupol/page.py:302 msgid "Path:" msgstr "Polku:" #: gaupol/page.py:303 msgid "Format:" msgstr "Tiedostomuoto:" #: gaupol/page.py:304 msgid "Encoding:" msgstr "Koodaus:" #: gaupol/page.py:305 msgid "Newlines:" msgstr "Rivinvaihdot:" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:99 msgid "Tasks and Target" msgstr "Tehtävät ja kohde" #: gaupol/assistants.py:128 msgid "Correct texts in the text column" msgstr "Korjaa tekstit tekstisarakkeessa" #: gaupol/assistants.py:129 msgid "Correct texts in the translation column" msgstr "Korjaa tekstit käännössarakkeessa" #: gaupol/assistants.py:138 msgid "Correct texts in selected subtitles" msgstr "Korjaa valittujen kappaleiden tekstit" #: gaupol/assistants.py:139 msgid "Correct texts in current project" msgstr "Korjaa nykyisen projektin tekstit" #: gaupol/assistants.py:140 msgid "Correct texts in all open projects" msgstr "Korjaa kaikkien avoimien projektien tekstit" #: gaupol/assistants.py:363 msgid "Other" msgstr "Muu" #: gaupol/assistants.py:439 msgid "Capitalize texts written in lower case" msgstr "Muunna kokonaan pienellä kirjoitetun tekstin kirjainkoko" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:443 msgid "Capitalization Patterns" msgstr "Kirjainkoon lausekkeet" #: gaupol/assistants.py:445 msgid "Capitalize texts" msgstr "Muunna kirjainkoko" #: gaupol/assistants.py:468 msgid "Correct common errors made by humans or image recognition software" msgstr "" "Korjaa joko ihmisten tai kuvantunnistusohjelmien tekemiä yleisiä virheitä" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:472 msgid "Common Error Patterns" msgstr "Yleisten virheiden lausekkeet" #: gaupol/assistants.py:474 msgid "Correct common errors" msgstr "Korjaa yleisiä virheitä" #: gaupol/assistants.py:526 msgid "Remove explanatory texts meant for the hearing impaired" msgstr "Poista kuulovammaisille tarkoitetut selittävät tekstit" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:530 msgid "Hearing Impaired Patterns" msgstr "Kuulovammaistekstien lausekkeet" #: gaupol/assistants.py:532 msgid "Remove hearing impaired texts" msgstr "Poista kuulovammaistekstit" #: gaupol/assistants.py:544 msgid "" "Use spell-check suggestions to fix whitespace detection errors of image " "recognition software" msgstr "" "Käytä oikoluvun ehdotuksia kuvantunnistusohjelmien tekemien " "välientunnistusvirheiden korjaamiseen" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:548 msgid "Joining and Splitting Words" msgstr "Sanojen yhdistäminen ja jakaminen" #: gaupol/assistants.py:550 msgid "Join or Split Words" msgstr "Yhdistä tai jaa sanoja" #: gaupol/assistants.py:599 gaupol/agents/tools.py:45 msgid "Failed to load dictionary for language \"{}\"" msgstr "Sanakirjan lataaminen kielelle \"{}\" epäonnistui" #: gaupol/assistants.py:601 gaupol/player.py:263 gaupol/player.py:381 #: gaupol/dialogs/search.py:560 gaupol/dialogs/search.py:568 #: gaupol/dialogs/text_edit.py:49 gaupol/dialogs/encoding.py:56 #: gaupol/agents/open.py:328 gaupol/agents/open.py:337 #: gaupol/agents/open.py:345 gaupol/agents/open.py:354 #: gaupol/agents/tools.py:48 gaupol/agents/save.py:197 #: gaupol/agents/save.py:205 gaupol/agents/preview.py:108 #: gaupol/agents/preview.py:116 gaupol/agents/preview.py:125 #: gaupol/agents/preview.py:133 msgid "_OK" msgstr "_OK" #: gaupol/assistants.py:635 msgid "Break text into lines of defined length" msgstr "Katkaise teksti määritellyn pituisiin riveihin" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:639 msgid "Line-Break Patterns" msgstr "Rivien katkaisun lausekkeet" #: gaupol/assistants.py:641 msgid "Break lines" msgstr "Katkaise rivejä" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:679 msgid "Line-Break Options" msgstr "Rivien katkaisun asetukset" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:763 msgid "Correcting Texts" msgstr "Korjataan tekstejä" #: gaupol/assistants.py:769 msgid "Each task is now being run on each project." msgstr "Jokaista tehtävää ajetaan nyt jokaiselle projektille." #: gaupol/assistants.py:793 #, python-brace-format msgid "{current:d} of {total:d} tasks complete" msgstr "{current:d} / {total:d} tehtävästä valmiina" #: gaupol/assistants.py:801 msgid "Project: {}" msgstr "Projekti: {}" #: gaupol/assistants.py:807 msgid "Task: {}" msgstr "Tehtävä: {}" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:832 msgid "Confirm Changes" msgstr "Vahvista muutokset" #: gaupol/assistants.py:892 msgid "Accept" msgstr "Hyväksy" #: gaupol/assistants.py:898 msgid "Original Text" msgstr "Alkuperäinen teksti" #: gaupol/assistants.py:899 msgid "Corrected Text" msgstr "Korjattu teksti" #: gaupol/assistants.py:1048 msgid "Correct Texts" msgstr "Korjaa tekstejä" #: gaupol/assistants.py:1076 msgid "Correcting texts" msgstr "tekstien korjaaminen" #: gaupol/assistants.py:1092 #, python-brace-format msgid "Edited {edits:d} and removed {removals:d} subtitles" msgstr "Muokattiin {edits:d} ja poistettiin {removals:d} kappaletta" #: gaupol/assistants.py:1126 msgid "Confirm {:d} Change" msgid_plural "Confirm {:d} Changes" msgstr[0] "Vahvista {:d} muutos" msgstr[1] "Vahvista {:d} muutosta" #: gaupol/renderers/multiline.py:86 msgid "Italic" msgstr "Kursiivi" #: gaupol/player.py:372 msgid "No video streams found" msgstr "Ei löytynyt videosisältöä" #: gaupol/player.py:379 msgid "Failed to initialize playback" msgstr "Toiston aloitus epäonnistui" #: gaupol/dialogs/search.py:189 data/ui/menubar.ui:524 msgid "_Help" msgstr "_Ohje" #: gaupol/dialogs/search.py:471 msgid "Found and replaced {:d} occurence" msgid_plural "Found and replaced {:d} occurences" msgstr[0] "Löydettiin ja korvattiin {:d} tapaus" msgstr[1] "Löydettiin ja korvattiin {:d} tapausta" #: gaupol/dialogs/search.py:488 msgid "\"{}\" not found" msgstr "Lauseketta \"{}\" ei löytynyt" #: gaupol/dialogs/search.py:558 msgid "Error in regular expression pattern" msgstr "Virhe säännöllisessä lausekkeessa" #: gaupol/dialogs/search.py:566 msgid "Error in regular expression replacement" msgstr "Virhe säännöllisen lausekkeen korvaajassa" #: gaupol/dialogs/text_edit.py:48 gaupol/dialogs/framerate_convert.py:63 #: gaupol/dialogs/insert.py:44 gaupol/dialogs/encoding.py:55 #: gaupol/dialogs/split.py:44 gaupol/dialogs/multi_close.py:54 #: gaupol/dialogs/open.py:63 gaupol/dialogs/position_transform.py:69 #: gaupol/dialogs/position_shift.py:71 gaupol/dialogs/multi_save.py:83 #: gaupol/dialogs/multi_save.py:215 gaupol/dialogs/duration_adjust.py:86 #: gaupol/dialogs/save.py:73 gaupol/dialogs/video.py:41 #: gaupol/agents/open.py:363 gaupol/agents/open.py:375 #: gaupol/agents/open.py:387 gaupol/agents/close.py:71 #: data/extensions/custom-framerates/custom-framerates.py:39 msgid "_Cancel" msgstr "_Peruuta" #: gaupol/dialogs/text_edit.py:53 msgid "Edit Text" msgstr "Muokkaa tekstiä" #: gaupol/dialogs/framerate_convert.py:64 msgid "Co_nvert" msgstr "_Muunna" #: gaupol/dialogs/insert.py:45 msgid "_Insert" msgstr "_Lisää" #: gaupol/dialogs/insert.py:54 msgid "Above selection" msgstr "Valinnan yläpuolelle" #: gaupol/dialogs/insert.py:55 msgid "Below selection" msgstr "Valinnan alapuolelle" #: gaupol/dialogs/encoding.py:60 data/ui/preferences-dialog.ui:70 msgid "Character Encodings" msgstr "Merkistökoodaukset" #: gaupol/dialogs/encoding.py:78 gaupol/dialogs/encoding.py:125 msgid "Description" msgstr "Kuvaus" #: gaupol/dialogs/encoding.py:85 gaupol/dialogs/encoding.py:132 msgid "Encoding" msgstr "Koodaus" #: gaupol/dialogs/encoding.py:141 msgid "Show in Menu" msgstr "Näytä valikossa" #: gaupol/dialogs/split.py:45 msgid "_Split" msgstr "_Jaa" #: gaupol/dialogs/split.py:76 msgid "Splitting project" msgstr "projektin jakaminen" #: gaupol/dialogs/split.py:97 #, python-brace-format msgid "Split {amount:d} subtitles to project \"{name}\"" msgstr "Jaettiin {amount:d} kappaletta projektiin \"{name}\"" #: gaupol/dialogs/spell_check.py:269 msgid "Spell-checking" msgstr "oikeinkirjoituksen tarkistaminen" #: gaupol/dialogs/preferences.py:217 msgid "{} Extension Website" msgstr "{} laajennuksen WWW-sivut" #: gaupol/dialogs/preferences.py:429 msgid "Custom" msgstr "Oma" #: gaupol/dialogs/multi_close.py:38 msgid "Save changes to documents before closing?" msgstr "Tallennetaanko muutokset asiakirjoihin ennen sulkemista?" #: gaupol/dialogs/multi_close.py:39 gaupol/agents/open.py:384 #: gaupol/agents/close.py:68 msgid "If you don't save, changes will be permanently lost." msgstr "Jos et tallenna, muutokset hukataan pysyvästi." #: gaupol/dialogs/multi_close.py:53 gaupol/agents/close.py:70 msgid "Close _Without Saving" msgstr "_Sulje tallentamatta" #: gaupol/dialogs/multi_close.py:55 gaupol/dialogs/multi_save.py:84 #: gaupol/dialogs/save.py:74 gaupol/agents/open.py:388 #: gaupol/agents/close.py:72 data/ui/menubar.ui:34 msgid "_Save" msgstr "_Tallenna" #: gaupol/dialogs/multi_close.py:70 msgid "Select the _main documents you want to save:" msgstr "Valitse pää_asiakirjat, jotka haluat tallentaa:" #: gaupol/dialogs/multi_close.py:95 msgid "Select the _translation documents you want to save:" msgstr "Valitse _käännösasiakirjat, jotka haluat tallentaa:" #: gaupol/dialogs/open.py:64 gaupol/agents/open.py:364 #: gaupol/agents/open.py:376 msgid "_Open" msgstr "_Avaa" #: gaupol/dialogs/position_transform.py:70 msgid "_Transform" msgstr "_Muunna" #: gaupol/dialogs/position_shift.py:72 msgid "_Shift" msgstr "_Siirrä" #: gaupol/dialogs/position_shift.py:150 msgid "frames" msgstr "ruutua" #: gaupol/dialogs/position_shift.py:168 data/ui/preferences-dialog.ui:911 msgid "seconds" msgstr "sekuntia" #: gaupol/dialogs/about.py:36 msgid "About Gaupol" msgstr "Tietoja Gaupolista" #: gaupol/dialogs/about.py:40 msgid "Subtitle editor" msgstr "Tekstitysmuokkain" #. TRANSLATORS: This is a special message that shouldn't be translated #. literally. It is used in the about dialog to give credits to the #. translators. Thus, you should translate it to your name and email #. address. You can also include other translators who have contributed #. to this translation; in that case, please write them on separate #. lines seperated by newlines (\n). #: gaupol/dialogs/about.py:51 msgid "translator-credits" msgstr "Osmo Salomaa " #: gaupol/dialogs/about.py:54 msgid "Gaupol Website" msgstr "Gaupolin WWW-sivut" #: gaupol/dialogs/append.py:35 msgid "Append File" msgstr "Lisää tiedosto perään" #: gaupol/dialogs/debug.py:43 msgid "Something went wrong" msgstr "Jotain meni vikaan" #: gaupol/dialogs/debug.py:44 msgid "" "You have probably discovered a bug. Please report it by providing the below " "information and a description of what you were doing." msgstr "" "Olet luultavasti löytänyt ohjelmointivirheen. Voit ilmoittaa virheen " "antamalla alla olevat tiedot ja kuvauksen siitä mitä olit tekemässä." #: gaupol/dialogs/debug.py:52 msgid "_Report Bug" msgstr "_Lähetä vikailmoitus" #: gaupol/dialogs/debug.py:53 data/ui/menubar.ui:56 msgid "_Quit" msgstr "_Lopeta" #: gaupol/dialogs/debug.py:54 gaupol/dialogs/preview_error.py:45 #: data/ui/menubar.ui:52 data/ui/tab-popup.ui:16 msgid "_Close" msgstr "_Sulje" #: gaupol/dialogs/multi_save.py:98 gaupol/dialogs/save.py:110 msgid "{} (recommended)" msgstr "{} (suositeltu)" #: gaupol/dialogs/multi_save.py:212 msgid "" "{:d} of the files to be saved already exist. Do you want to replace them?" msgstr "Tiedostoista {:d} on jo olemassa. Haluatko korvata ne?" #: gaupol/dialogs/multi_save.py:213 msgid "" "The files already exist in \"{}\". Replacing them will overwrite their " "contents." msgstr "" "Tiedostot ovat jo olemassa kansiossa \"{}\". Tiedostojen korvaus " "ylikirjoittaa niiden sisällön." #: gaupol/dialogs/multi_save.py:216 data/ui/search-dialog.ui:192 #: data/ui/spell-check-dialog.ui:122 msgid "_Replace" msgstr "_Korvaa" #: gaupol/dialogs/duration_adjust.py:70 msgid "Adjusted duration of {:d} subtitle" msgid_plural "Adjusted durations of {:d} subtitles" msgstr[0] "Säädettiin {:d} kappaleen kestoa" msgstr[1] "Säädettiin {:d} kappaleen kestoa" #: gaupol/dialogs/duration_adjust.py:87 msgid "_Adjust" msgstr "_Säädä" #: gaupol/dialogs/preview_error.py:36 msgid "Preview in video player failed" msgstr "Esikatselu videosoittimessa epäonnistui" #: gaupol/dialogs/preview_error.py:37 msgid "" "There is probably a problem with either the video file or the video player. " "See the preferences dialog to choose the video player or to customize the " "command." msgstr "" "Joko videotiedostossa tai videosoittimessa on todennäköisesti vikaa. Voit " "valita videosoittimen ja muokata esikatselukomentoa asetusikkunan kautta." #: gaupol/dialogs/language.py:97 msgid "Set Language" msgstr "Aseta kieli" #: gaupol/dialogs/video.py:52 gaupol/dialogs/file.py:59 msgid "All files" msgstr "Kaikki tiedostot" #: gaupol/dialogs/video.py:56 msgid "Video files" msgstr "Videotiedostot" #: gaupol/dialogs/file.py:63 msgid "All supported files" msgstr "Kaikki tuetut tiedostot" #: gaupol/dialogs/file.py:77 #, python-brace-format msgid "{format} (*{extension})" msgstr "{format} (*{extension})" #: gaupol/dialogs/file.py:120 msgid "Auto-detected" msgstr "Automaattisesti tunnistettu" #: gaupol/dialogs/file.py:122 msgid "Other…" msgstr "Muu…" #: gaupol/agents/menu.py:94 gaupol/agents/menu.py:103 #: gaupol/agents/menu.py:110 msgid "File not found" msgstr "Tiedostoa ei löytynyt" #: gaupol/agents/open.py:85 #, python-brace-format msgid "Appended {amount:d} subtitles from \"{basename}\"" msgstr "Lisättiin {amount:d} kappaletta perään tiedostosta \"{basename}\"" #: gaupol/agents/open.py:96 msgid "Appending file" msgstr "tiedoston lisääminen perään" #: gaupol/agents/open.py:111 msgid "File \"{}\" is already open" msgstr "Tiedosto \"{}\" on jo auki" #: gaupol/agents/open.py:214 msgid "Open Translation" msgstr "Avaa käännös" #: gaupol/agents/open.py:223 msgid "Select Video" msgstr "Valitse video" #: gaupol/agents/open.py:224 msgid "_Select" msgstr "_Valitse" #: gaupol/agents/open.py:325 msgid "Failed to decode file \"{}\" with all attempted codecs" msgstr "Tiedoston \"{}\" purkaminen epäonnistui kaikilla kokeilluilla koodekeilla" #: gaupol/agents/open.py:326 msgid "Please try to open the file with a different character encoding." msgstr "Yritä avata tiedosto eri merkistökoodauksella." #: gaupol/agents/open.py:334 msgid "Failed to recognize format of file \"{}\"" msgstr "Tiedoston \"{}\" muodon tunnistus epäonnistui" #: gaupol/agents/open.py:335 msgid "" "Please check that the file you are trying to open is a subtitle file of a " "format supported by Gaupol." msgstr "" "Tarkista että tiedosto, jota yrität avata on tekstitystiedosto, jonka muotoa" " Gaupol tukee." #: gaupol/agents/open.py:343 msgid "Failed to open file \"{}\"" msgstr "Tiedoston \"{}\" avaaminen epäonnistui" #: gaupol/agents/open.py:351 msgid "Failed to parse file \"{}\"" msgstr "Tiedoston \"{}\" tulkinta epäonnistui" #: gaupol/agents/open.py:352 msgid "Please check that the file you are trying to open is a valid {} file." msgstr "" "Tarkista, että tiedosto, jota yrität avata on kelvollinen {} tiedosto." #: gaupol/agents/open.py:360 msgid "Open abnormally large file \"{}\"?" msgstr "Avaa epätavallisen suuri tiedosto \"{}\"?" #: gaupol/agents/open.py:361 msgid "" "Size of the file is {:.1f} MB, which is abnormally large for a text-based " "subtitle file. Please, check that you are not trying to open a binary file." msgstr "" "Tiedoston koko on {:.1f} Mt, mikä on epätavallisen suuri koko " "tekstimuotoiselle tekstitystiedostolle. Tarkista ettet yritä avata " "binääritiedostoa." #: gaupol/agents/open.py:371 msgid "Open unsorted file \"{}\"?" msgstr "Avaa lajittelematon tiedosto \"{}\"?" #: gaupol/agents/open.py:372 msgid "" "The order of {:d} subtitles needs to be changed. If {:d} sounds like a lot, " "the file may be erroneously composed." msgstr "" "{:d} kappaleen järjestys täytyy muuttaa. Jos {:d} kuulostaa paljolta, " "tiedosto voi olla virheellisesti muodostettu." #: gaupol/agents/open.py:383 msgid "Save changes to translation document \"{}\" before opening a new one?" msgstr "Tallenna muutokset käännösasiakirjaan \"{}\" ennen uuden avaamista?" #: gaupol/agents/open.py:386 msgid "Open _Without Saving" msgstr "_Avaa tallentamatta" #: gaupol/agents/close.py:66 msgid "Save changes to document \"{}\" before closing?" msgstr "Tallenna muutokset asiakirjaan \"{}\" ennen sulkemista?" #: gaupol/agents/edit.py:101 gaupol/agents/edit.py:119 msgid "Stretching end position" msgstr "lopun venyttäminen" #: gaupol/agents/edit.py:208 msgid "Inserted {:d} subtitle to fit clipboard contents" msgid_plural "Inserted {:d} subtitles to fit clipboard contents" msgstr[0] "Lisättiin {:d} kappale, jotta leikepöydän sisältö mahtui" msgstr[1] "Lisättiin {:d} kappaletta, jotta leikepöydän sisältö mahtui" #: gaupol/agents/edit.py:334 gaupol/agents/edit.py:352 msgid "Stretching start position" msgstr "alun venyttäminen" #: gaupol/agents/edit.py:411 msgid "Use Shift+Return for line-break" msgstr "Käytä näppäimiä Shift+Return rivinvaihtoa varten" #: gaupol/agents/save.py:129 msgid "Save As" msgstr "Tallenna nimellä" #: gaupol/agents/save.py:135 msgid "Saved main document as \"{}\"" msgstr "Tallennettiin pääasiakirja nimellä \"{}\"" #: gaupol/agents/save.py:153 msgid "Save Translation As" msgstr "Tallenna käännös nimellä" #: gaupol/agents/save.py:159 msgid "Saved translation document as \"{}\"" msgstr "Tallennettiin käännösasiakirja nimellä \"{}\"" #: gaupol/agents/save.py:194 #, python-brace-format msgid "Failed to encode file \"{basename}\" with codec \"{codec}\"" msgstr "Tiedoston \"{basename}\" koodaaminen koodekilla \"{codec}\" epäonnistui" #: gaupol/agents/save.py:195 msgid "Please try to save the file with a different character encoding." msgstr "Yritä tallentaa tiedosto eri merkistökoodauksella." #: gaupol/agents/save.py:203 msgid "Failed to save file \"{}\"" msgstr "Tiedoston \"{}\" tallentaminen epäonnistui" #: gaupol/agents/video.py:67 data/ui/menubar.ui:380 msgid "_Play/Pause" msgstr "_Toista/Tauota" #: gaupol/agents/video.py:69 msgid "Play or pause video" msgstr "Toista tai tauota video" #: gaupol/agents/video.py:75 data/ui/menubar.ui:390 msgid "Seek _Previous" msgstr "Kelaa _edelliseen" #: gaupol/agents/video.py:77 msgid "Seek to the start of the previous subtitle" msgstr "Kelaa edellisen kappaleen alkuun" #: gaupol/agents/video.py:81 data/ui/menubar.ui:394 msgid "Seek _Next" msgstr "Kelaa _seuraavaan" #: gaupol/agents/video.py:83 msgid "Seek to the start of the next subtitle" msgstr "Kelaa seuraavan kappaleen alkuun" #: gaupol/agents/video.py:88 data/ui/menubar.ui:400 msgid "Seek _Backward" msgstr "_Kelaa taaksepäin" #: gaupol/agents/video.py:90 msgid "Seek backward" msgstr "Kelaa taaksepäin" #: gaupol/agents/video.py:94 data/ui/menubar.ui:404 msgid "Seek _Forward" msgstr "Kel_aa eteenpäin" #: gaupol/agents/video.py:96 msgid "Seek forward" msgstr "Kelaa eteenpäin" #: gaupol/agents/video.py:109 msgid "Volume" msgstr "Äänenvoimakkuus" #: gaupol/agents/video.py:189 msgid "Load Video" msgstr "Lataa video" #: gaupol/agents/video.py:189 msgid "_Load" msgstr "_Lataa" #: gaupol/agents/video.py:361 msgid "Track {:d}" msgstr "Raita {:d}" #: gaupol/agents/preview.py:105 msgid "Failed to encode subtitle file to temporary directory \"{}\"" msgstr "Tekstitystiedoston koodaaminen väliaikaishakemistoon \"{}\" epäonnistui" #: gaupol/agents/preview.py:106 msgid "" "Subtitle data could not be encoded to a temporary file for preview with the " "current character encoding. Please first save the subtitle file with a " "different character encoding." msgstr "" "Tekstitysdataa ei voitu koodata väliaikaistiedostoon esikatselua varten " "nykyisellä merkistökoodauksella. Tallenna tekstitystiedosto ensin eri " "merkistökoodauksella." #: gaupol/agents/preview.py:114 msgid "Failed to save subtitle file to temporary directory \"{}\"" msgstr "Tekstitystiedoston tallentaminen väliaikaishakemistoon \"{}\" epäonnistui" #: gaupol/agents/preview.py:122 msgid "Video player not found" msgstr "Videosoitinta ei löytynyt" #: gaupol/agents/preview.py:123 msgid "" "Please install one of the supported video players: mpv (recommended), " "MPlayer or VLC. See the preferences dialog to choose the video player or to " "customize the command." msgstr "" "Asenna joku seuraavista videosoittimista: mpv (suositeltu), MPlayer tai VLC." " Voit valita videosoittimen ja muokata esikatselukomentoa asetusikkunan " "kautta." #: gaupol/agents/preview.py:131 msgid "Failed to launch video player" msgstr "Videosoittimen käynnistäminen epäonnistui" #: gaupol/applicationman.py:105 msgid "gaupol [OPTION...] [FILE...] [+[NUM]]" msgstr "gaupol [VALITSIN...] [TIEDOSTO...] [+[NRO]]" #: gaupol/applicationman.py:109 msgid "FILE..." msgstr "TIEDOSTO..." #: gaupol/applicationman.py:112 msgid "subtitle files to open" msgstr "avattavat tekstitystiedostot" #: gaupol/applicationman.py:122 msgid "ENCODING" msgstr "KOODAUS" #: gaupol/applicationman.py:125 msgid "set the character encoding used to open files" msgstr "aseta tiedostojen avaamiseen käytettävä merkistökoodaus" #: gaupol/applicationman.py:132 msgid "list all available character encodings" msgstr "luettele kaikki käytettävissä olevat merkistökoodaukset" #: gaupol/applicationman.py:137 gaupol/applicationman.py:154 msgid "FILE" msgstr "TIEDOSTO" #: gaupol/applicationman.py:140 msgid "open translation file" msgstr "avaa käännöstiedosto" #: gaupol/applicationman.py:145 msgid "METHOD" msgstr "MENETELMÄ" #: gaupol/applicationman.py:149 msgid "method used to align translation subtitles: 'number' or 'position'" msgstr "" "käännöksen kappaleiden tasaamiseen käytettävä menetelmä: 'number' " "(numero)tai 'position' (kohta)" #: gaupol/applicationman.py:157 msgid "select video file" msgstr "valitse videotiedosto" #: data/extensions/custom-framerates/custom-framerates.py:40 #: data/ui/spell-check-dialog.ui:152 msgid "_Add" msgstr "_Lisää" #: data/extensions/custom-framerates/custom-framerates.py:171 msgid "{:.3f} fps" msgstr "{:.3f} fps" #: data/extensions/custom-framerates/add-framerate-dialog.ui:13 msgid "Add Framerate" msgstr "Lisää ruutunopeus" #: data/extensions/custom-framerates/add-framerate-dialog.ui:44 msgid "_Framerate:" msgstr "_Ruutunopeus:" #: data/extensions/custom-framerates/add-framerate-dialog.ui:73 msgid "fps" msgstr "fps" #: data/extensions/custom-framerates/preferences-dialog.ui:8 msgid "Framerates" msgstr "Ruutunopeudet" #: data/extensions/custom-framerates/preferences-dialog.ui:64 msgid "Add" msgstr "Lisää" #: data/ui/columns-popup.ui:6 data/ui/menubar.ui:275 msgid "_No." msgstr "_Nro." #: data/ui/columns-popup.ui:10 data/ui/menubar.ui:279 msgid "_Start" msgstr "_Alku" #: data/ui/columns-popup.ui:14 data/ui/menubar.ui:283 msgid "_End" msgstr "_Loppu" #: data/ui/columns-popup.ui:18 data/ui/menubar.ui:287 msgid "_Duration" msgstr "_Kesto" #: data/ui/columns-popup.ui:22 data/ui/menubar.ui:291 data/ui/menubar.ui:303 msgid "_Text" msgstr "T_eksti" #: data/ui/columns-popup.ui:26 data/ui/menubar.ui:295 msgid "T_ranslation" msgstr "Käännö_s" #: data/ui/split-dialog.ui:15 msgid "Split Project" msgstr "Jaa projekti" #: data/ui/split-dialog.ui:48 msgid "_First subtitle of new project:" msgstr "_Uuden projektin ensimmäinen kappale:" #: data/ui/search-dialog.ui:89 msgid "_Search for:" msgstr "Ets_i:" #: data/ui/search-dialog.ui:103 data/ui/spell-check-dialog.ui:193 msgid "Replace _with:" msgstr "Ko_rvaa:" #: data/ui/search-dialog.ui:162 data/ui/menubar.ui:328 msgid "Find _Next" msgstr "_Etsi seuraava" #: data/ui/search-dialog.ui:177 msgid "Find _Previous" msgstr "E_tsi edellinen" #: data/ui/search-dialog.ui:207 msgid "Replace _All" msgstr "Korv_aa kaikki" #: data/ui/search-dialog.ui:241 msgid "R_egular expression" msgstr "S_äännöllinen lauseke" #: data/ui/search-dialog.ui:258 msgid "_Ignore case" msgstr "_Jätä kirjainkoko huomiotta" #: data/ui/search-dialog.ui:304 data/ui/language-dialog.ui:108 msgid "Columns" msgstr "Sarakkeet" #: data/ui/search-dialog.ui:324 msgid "Find in _text column" msgstr "Etsi _tekstisarakkeesta" #: data/ui/search-dialog.ui:341 msgid "Find in t_ranslation column" msgstr "Etsi _käännössarakkeesta" #: data/ui/search-dialog.ui:381 data/ui/framerate-convert-dialog.ui:144 #: data/ui/language-dialog.ui:186 #: data/ui/text-assistant/line-break-options-page.ui:178 #: data/ui/duration-adjust-dialog.ui:388 data/ui/position-shift-dialog.ui:180 #: data/ui/position-transform-dialog.ui:444 msgid "Subtitles" msgstr "Kappaleet" #: data/ui/search-dialog.ui:401 msgid "Find in c_urrent project" msgstr "Etsi _nykyisestä projektista" #: data/ui/search-dialog.ui:419 msgid "Find in _all open projects" msgstr "Etsi k_aikista avoimista projekteista" #: data/ui/search-dialog.ui:452 msgid "Target" msgstr "Kohde" #: data/ui/framerate-convert-dialog.ui:8 msgid "Convert Framerate" msgstr "Muunna ruutunopeus" #: data/ui/framerate-convert-dialog.ui:48 msgid "Framerate" msgstr "Ruutunopeus" #: data/ui/framerate-convert-dialog.ui:71 msgid "_Input:" msgstr "_Sisään:" #: data/ui/framerate-convert-dialog.ui:86 msgid "_Output:" msgstr "_Ulos:" #: data/ui/framerate-convert-dialog.ui:164 msgid "Convert c_urrent project" msgstr "Muunna _nykyinen projekti" #: data/ui/framerate-convert-dialog.ui:181 msgid "Convert _all open projects" msgstr "Muunna _kaikki avoimet projektit" #: data/ui/spell-check-dialog.ui:8 msgid "Check Spelling" msgstr "Tarkista oikeinkirjoitus" #: data/ui/spell-check-dialog.ui:47 msgid "Join _Back" msgstr "Yhdistä _taakse" #: data/ui/spell-check-dialog.ui:62 msgid "Join _Forward" msgstr "Yhdistä _eteen" #: data/ui/spell-check-dialog.ui:77 data/ui/menubar.ui:62 msgid "_Edit" msgstr "_Muokkaa" #: data/ui/spell-check-dialog.ui:92 msgid "_Ignore" msgstr "_Ohita" #: data/ui/spell-check-dialog.ui:107 msgid "Ig_nore All" msgstr "O_hita kaikki" #: data/ui/spell-check-dialog.ui:137 msgid "Rep_lace All" msgstr "Ko_rvaa kaikki" #: data/ui/spell-check-dialog.ui:179 msgid "_Suggestions:" msgstr "Eh_dotukset:" #: data/ui/multi-save-dialog.ui:8 msgid "Save All As" msgstr "Tallenna kaikki muodossa" #: data/ui/multi-save-dialog.ui:46 msgid "Save in _folder:" msgstr "Tallenna _kansioon:" #: data/ui/multi-save-dialog.ui:60 data/ui/save-dialog.ui:25 msgid "For_mat:" msgstr "T_iedostomuoto:" #: data/ui/multi-save-dialog.ui:74 data/ui/open-dialog.ui:25 #: data/ui/save-dialog.ui:39 msgid "_Encoding:" msgstr "_Koodaus:" #: data/ui/multi-save-dialog.ui:88 data/ui/save-dialog.ui:53 msgid "Ne_wlines:" msgstr "_Rivinvaihdot:" #: data/ui/multi-save-dialog.ui:103 msgid "Select A Folder" msgstr "Valitse kansio" #: data/ui/multi-save-dialog.ui:150 data/ui/save-dialog.ui:102 msgid "F_ramerate:" msgstr "Ruutu_nopeus:" #: data/ui/menubar.ui:5 msgid "_File" msgstr "_Tiedosto" #: data/ui/menubar.ui:8 msgid "_New" msgstr "_Uusi" #: data/ui/menubar.ui:12 msgid "_Open…" msgstr "_Avaa…" #: data/ui/menubar.ui:16 msgid "Open _Translation…" msgstr "Avaa _käännös…" #: data/ui/menubar.ui:22 msgid "Open _Recent" msgstr "Avaa v_iimeaikainen" #: data/ui/menubar.ui:27 msgid "Open R_ecent Translation" msgstr "Avaa vii_meaikainen käännös" #: data/ui/menubar.ui:38 msgid "Save _As…" msgstr "Tall_enna nimellä…" #: data/ui/menubar.ui:42 msgid "Save Trans_lation" msgstr "Talle_nna käännös" #: data/ui/menubar.ui:46 msgid "Save Translat_ion As…" msgstr "Tallenna k_äännös nimellä…" #: data/ui/menubar.ui:65 msgid "_Undo" msgstr "_Kumoa" #: data/ui/menubar.ui:69 msgid "_Redo" msgstr "_Tee uudelleen" #: data/ui/menubar.ui:75 msgid "_Edit Cell" msgstr "_Muokkaa solua" #: data/ui/menubar.ui:79 msgid "Edit _Next Cell" msgstr "M_uokkaa seuraavaa solua" #: data/ui/menubar.ui:85 msgid "Stretc_h" msgstr "V_enytä" #: data/ui/menubar.ui:88 msgid "_Start Earlier" msgstr "_Aloita aiemmin" #: data/ui/menubar.ui:92 msgid "S_tart Later" msgstr "Al_oita myöhemmin" #: data/ui/menubar.ui:98 msgid "E_nd Earlier" msgstr "_Lopeta aiemmin" #: data/ui/menubar.ui:102 msgid "En_d Later" msgstr "Lop_eta myöhemmin" #: data/ui/menubar.ui:108 msgid "Set St_art From Video Position" msgstr "Aseta alk_u videon kohdasta" #: data/ui/menubar.ui:112 msgid "Set En_d From Video Position" msgstr "Aseta l_oppu videon kohdasta" #: data/ui/menubar.ui:118 data/ui/view-popup.ui:6 msgid "_Split Subtitle" msgstr "_Jaa kappale" #: data/ui/menubar.ui:122 data/ui/view-popup.ui:10 msgid "_Merge Subtitles" msgstr "_Yhdistä kappaleet" #: data/ui/menubar.ui:128 data/ui/view-popup.ui:16 msgid "_Insert Subtitles…" msgstr "_Lisää kappaleita…" #: data/ui/menubar.ui:132 msgid "Inser_t Subtitle At Video Position" msgstr "Li_sää kappale videon kohtaan" #: data/ui/menubar.ui:136 data/ui/view-popup.ui:20 msgid "Rem_ove Subtitles" msgstr "_Poista kappaleet" #: data/ui/menubar.ui:142 msgid "Sele_ction" msgstr "_Valinta" #: data/ui/menubar.ui:145 msgid "Select _All" msgstr "_Valitse kaikki" #: data/ui/menubar.ui:149 msgid "_Invert Selection" msgstr "_Käännä valinta" #: data/ui/menubar.ui:155 msgid "Extend To _Beginning" msgstr "Laajenna _alkuun" #: data/ui/menubar.ui:159 msgid "Extend To _End" msgstr "Laajenna _loppuun" #: data/ui/menubar.ui:165 msgid "_Previous From Video Position" msgstr "_Edellinen videon kohdasta" #: data/ui/menubar.ui:169 msgid "_Next From Video Position" msgstr "Seuraava videon kohdasta" #: data/ui/menubar.ui:177 msgid "_Preferences" msgstr "_Asetukset" #: data/ui/menubar.ui:183 msgid "_View" msgstr "_Näytä" #: data/ui/menubar.ui:186 msgid "Tool_bar" msgstr "_Työkalurivi" #: data/ui/menubar.ui:190 msgid "_Video Player" msgstr "_Videosoitin" #: data/ui/menubar.ui:196 msgid "_Layout" msgstr "As_ettelu" #: data/ui/menubar.ui:199 msgid "_Horizontal" msgstr "_Vaaka" #: data/ui/menubar.ui:204 msgid "_Vertical" msgstr "_Pysty" #: data/ui/menubar.ui:213 msgid "_Times" msgstr "_Ajat" #: data/ui/menubar.ui:218 msgid "_Frames" msgstr "_Ruudut" #: data/ui/menubar.ui:225 msgid "F_ramerate" msgstr "Ruutu_nopeus" #: data/ui/menubar.ui:228 msgid "2_3.976 fps" msgstr "2_3,976 fps" #: data/ui/menubar.ui:233 msgid "2_4.000 fps" msgstr "2_4,000 fps" #: data/ui/menubar.ui:238 msgid "2_5.000 fps" msgstr "2_5,000 fps" #: data/ui/menubar.ui:243 msgid "2_9.970 fps" msgstr "2_9,970 fps" #: data/ui/menubar.ui:272 msgid "_Columns" msgstr "_Sarakkeet" #: data/ui/menubar.ui:306 msgid "Cu_t" msgstr "_Leikkaa" #: data/ui/menubar.ui:310 msgid "_Copy" msgstr "_Kopioi" #: data/ui/menubar.ui:314 msgid "_Paste" msgstr "L_iitä" #: data/ui/menubar.ui:318 msgid "Cl_ear" msgstr "_Tyhjennä" #: data/ui/menubar.ui:324 msgid "_Find And Replace…" msgstr "_Etsi ja korvaa…" #: data/ui/menubar.ui:332 msgid "Find Pre_vious" msgstr "Etsi e_dellinen" #: data/ui/menubar.ui:338 msgid "_Italic" msgstr "K_ursiivi" #: data/ui/menubar.ui:342 msgid "_Dialogue" msgstr "_Vuoropuhelu" #: data/ui/menubar.ui:348 msgid "Ca_se" msgstr "Ki_rjainkoko" #: data/ui/menubar.ui:351 msgid "_Title" msgstr "_Otsikko" #: data/ui/menubar.ui:355 msgid "_Sentence" msgstr "_Lause" #: data/ui/menubar.ui:359 msgid "_Upper" msgstr "_Iso" #: data/ui/menubar.ui:363 msgid "_Lower" msgstr "_Pieni" #: data/ui/menubar.ui:371 msgid "Vi_deo" msgstr "Vi_deo" #: data/ui/menubar.ui:374 msgid "_Load Video…" msgstr "_Lataa Video…" #: data/ui/menubar.ui:384 data/ui/view-popup.ui:26 msgid "Play _Selection" msgstr "Toista _valinta" #: data/ui/menubar.ui:410 data/ui/view-popup.ui:30 msgid "S_eek Selection Start" msgstr "Kelaa vali_nnan alkuun" #: data/ui/menubar.ui:414 msgid "See_k Selection End" msgstr "Kelaa valinnan l_oppuun" #: data/ui/menubar.ui:420 msgid "_Audio" msgstr "_Ääni" #: data/ui/menubar.ui:423 msgid "_Language" msgstr "Ki_eli" #: data/ui/menubar.ui:430 msgid "Volume _Down" msgstr "_Hiljemmalle" #: data/ui/menubar.ui:434 msgid "Volume _Up" msgstr "_Kovemmalle" #: data/ui/menubar.ui:440 msgid "T_ools" msgstr "Ty_ökalut" #: data/ui/menubar.ui:443 data/ui/text-assistant/confirmation-page.ui:97 #: data/ui/view-popup.ui:36 msgid "_Preview" msgstr "_Esikatsele" #: data/ui/menubar.ui:447 msgid "Select _Video…" msgstr "_Valitse video…" #: data/ui/menubar.ui:453 msgid "_Check Spelling" msgstr "_Tarkista oikeinkirjoitus" #: data/ui/menubar.ui:457 msgid "Co_nfigure Spell-check…" msgstr "_Oikoluvun asetukset…" #: data/ui/menubar.ui:461 msgid "C_orrect Texts…" msgstr "_Korjaa tekstejä…" #: data/ui/menubar.ui:467 msgid "_Shift Positions…" msgstr "_Siirrä kohtia…" #: data/ui/menubar.ui:471 msgid "_Transform Positions…" msgstr "_Muunna kohtia…" #: data/ui/menubar.ui:475 msgid "Adjust _Durations…" msgstr "S_äädä kestoja…" #: data/ui/menubar.ui:479 msgid "Convert _Framerate…" msgstr "M_uunna ruutunopeus…" #: data/ui/menubar.ui:485 msgid "_Append File…" msgstr "_Lisää tiedosto perään…" #: data/ui/menubar.ui:489 msgid "Spli_t Project…" msgstr "_Jaa projekti…" #: data/ui/menubar.ui:495 msgid "_Projects" msgstr "_Projektit" #: data/ui/menubar.ui:498 msgid "_Save All" msgstr "_Tallenna kaikki" #: data/ui/menubar.ui:502 msgid "Save _All As…" msgstr "Tallenna _kaikki muodossa…" #: data/ui/menubar.ui:506 msgid "_Close All" msgstr "_Sulje kaikki" #: data/ui/menubar.ui:512 msgid "_Previous" msgstr "_Edellinen" #: data/ui/menubar.ui:516 msgid "_Next" msgstr "_Seuraava" #: data/ui/menubar.ui:527 msgid "_Documentation" msgstr "_Ohjeet" #: data/ui/menubar.ui:531 msgid "_Report A Bug" msgstr "_Lähetä vikailmoitus" #: data/ui/menubar.ui:535 msgid "_About" msgstr "_Tietoja" #: data/ui/open-dialog.ui:39 msgid "Align _method:" msgstr "_Tasausmenetelmä:" #: data/ui/preferences-dialog.ui:18 msgid "Preferences" msgstr "Asetukset" #: data/ui/preferences-dialog.ui:93 msgid "When opening files, try encodings in the following order:" msgstr "Tiedostoja avatessa, kokeile koodauksia järjestyksessä:" #: data/ui/preferences-dialog.ui:104 msgid "Curr_ent locale encoding" msgstr "_Nykyisen maa-asetuston koodaus" #: data/ui/preferences-dialog.ui:130 msgid "_Fallback encodings:" msgstr "_Toissijaiset koodaukset:" #: data/ui/preferences-dialog.ui:246 msgid "Aut_o-detection" msgstr "A_utomaattitunnistus" #: data/ui/preferences-dialog.ui:266 msgid "Encoding specified in the open dialog will always be tried first." msgstr "Avausikkunassa määriteltyä koodausta kokeillaan aina ensin." #: data/ui/preferences-dialog.ui:296 msgid "File" msgstr "Tiedosto" #: data/ui/preferences-dialog.ui:324 msgid "Font" msgstr "Kirjasin" #: data/ui/preferences-dialog.ui:344 msgid "Use _default theme fixed width font" msgstr "Käytä _oletusteeman tasalevyistä kirjasinta" #: data/ui/preferences-dialog.ui:368 msgid "_Editor font:" msgstr "_Muokkaimen kirjasin:" #: data/ui/preferences-dialog.ui:425 msgid "Line Lengths" msgstr "Rivien pituudet" #: data/ui/preferences-dialog.ui:445 msgid "_Show line lengths in list cells" msgstr "_Näytä rivien pituudet listan soluissa" #: data/ui/preferences-dialog.ui:462 msgid "S_how line lengths in editable text fields" msgstr "N_äytä rivien pituudet muokattavissa tekstikentissä" #: data/ui/preferences-dialog.ui:486 msgid "_Length unit:" msgstr "_Pituusyksikkö:" #: data/ui/preferences-dialog.ui:540 msgid "Spell-Check" msgstr "Oikoluku" #: data/ui/preferences-dialog.ui:560 msgid "Chec_k spelling as you type" msgstr "_Tarkista oikeinkirjoitus kirjoittaessa" #: data/ui/preferences-dialog.ui:598 msgid "Editor" msgstr "Muokkain" #: data/ui/preferences-dialog.ui:626 msgid "Fonts" msgstr "Kirjasimet" #: data/ui/preferences-dialog.ui:649 msgid "_Subtitles:" msgstr "_Tekstitykset:" #: data/ui/preferences-dialog.ui:679 msgid "_Time:" msgstr "_Aika:" #: data/ui/preferences-dialog.ui:729 msgid "Colors" msgstr "Värit" #: data/ui/preferences-dialog.ui:752 msgid "Su_btitles:" msgstr "T_ekstitykset:" #: data/ui/preferences-dialog.ui:777 msgid "_Use a background behind text" msgstr "K_äytä taustaa tekstin takana" #: data/ui/preferences-dialog.ui:797 msgid "Ti_me:" msgstr "Ai_ka:" #: data/ui/preferences-dialog.ui:822 msgid "Us_e a background behind text" msgstr "Käytä ta_ustaa tekstin takana" #: data/ui/preferences-dialog.ui:862 msgid "Seek" msgstr "Kelaus" #: data/ui/preferences-dialog.ui:883 msgid "_Length:" msgstr "_Pituus:" #: data/ui/preferences-dialog.ui:971 msgid "Video Player" msgstr "Videosoitin" #: data/ui/preferences-dialog.ui:994 msgid "_Application:" msgstr "So_vellus:" #: data/ui/preferences-dialog.ui:1008 msgid "Co_mmand:" msgstr "_Komento:" #. Translators: Only the title is to be translated, field names not. #: data/ui/preferences-dialog.ui:1033 msgid "" "Fields:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" msgstr "" "Kentät:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" #: data/ui/preferences-dialog.ui:1048 msgid "Al_ways use UTF-8 character encoding" msgstr "Käytä aina _UTF-8 -merkistökoodausta" #: data/ui/preferences-dialog.ui:1089 msgid "Start Position" msgstr "Aloituskohta" #: data/ui/preferences-dialog.ui:1111 msgid "_Offset:" msgstr "Sii_rtymä:" #: data/ui/preferences-dialog.ui:1142 msgid "seconds before selection" msgstr "sekuntia ennen valintaa" #: data/ui/preferences-dialog.ui:1281 msgid "Extensions" msgstr "Laajennukset" #: data/ui/language-dialog.ui:8 msgid "Configure Spell-Check" msgstr "Oikoluvun asetukset" #: data/ui/language-dialog.ui:50 msgid "Language" msgstr "Kieli" #: data/ui/language-dialog.ui:128 msgid "Check _text column" msgstr "Tarkista _tekstisarake" #: data/ui/language-dialog.ui:146 msgid "Check t_ranslation column" msgstr "Tarkista _käännössarake" #: data/ui/language-dialog.ui:206 msgid "Check c_urrent project" msgstr "Tarkista _nykyinen projekti" #: data/ui/language-dialog.ui:224 msgid "Check _all open projects" msgstr "Tarkista k_aikki avoimet projektit" #: data/ui/text-assistant/confirmation-page.ui:22 msgid "Acc_ept, discard or edit changes:" msgstr "_Hyväksy, hylkää tai muokkaa muutoksia:" #: data/ui/text-assistant/confirmation-page.ui:67 msgid "_Mark All" msgstr "_Merkitse kaikki" #: data/ui/text-assistant/confirmation-page.ui:82 msgid "_Unmark All" msgstr "_Poista merkinnät" #: data/ui/text-assistant/confirmation-page.ui:119 msgid "_Remove all blank subtitles" msgstr "P_oista kaikki tyhjät kappaleet" #: data/ui/text-assistant/join-split-page.ui:28 msgid "Spell-Check Dictionary" msgstr "Oikoluvun sanakirja" #: data/ui/text-assistant/join-split-page.ui:49 #: data/ui/text-assistant/line-break-page.ui:81 #: data/ui/text-assistant/hearing-impaired-page.ui:81 #: data/ui/text-assistant/common-error-page.ui:80 #: data/ui/text-assistant/capitalization-page.ui:80 msgid "_Language:" msgstr "K_ieli:" #: data/ui/text-assistant/join-split-page.ui:97 msgid "Corrections" msgstr "Korjaukset" #: data/ui/text-assistant/join-split-page.ui:117 msgid "_Join words not found in spell-check dictionary" msgstr "_Yhdistä sanat, joita ei löydy sanakirjasta" #: data/ui/text-assistant/join-split-page.ui:134 msgid "_Split words not found in spell-check dictionary" msgstr "_Jaa sanat, joita ei löydy sanakirjasta" #: data/ui/text-assistant/line-break-page.ui:22 msgid "S_elect preferred line-break points:" msgstr "_Valitse mieluisimmat rivinvaihtokohdat:" #: data/ui/text-assistant/line-break-page.ui:67 #: data/ui/text-assistant/hearing-impaired-page.ui:67 #: data/ui/text-assistant/common-error-page.ui:66 #: data/ui/text-assistant/capitalization-page.ui:66 msgid "_Script:" msgstr "_Kirjoitusasu:" #: data/ui/text-assistant/line-break-page.ui:95 #: data/ui/text-assistant/hearing-impaired-page.ui:95 #: data/ui/text-assistant/common-error-page.ui:94 #: data/ui/text-assistant/capitalization-page.ui:94 msgid "Co_untry:" msgstr "_Maa:" #: data/ui/text-assistant/introduction-page.ui:28 msgid "_Select corrections to perform on texts:" msgstr "_Valitse suoritettavat korjaukset:" #: data/ui/text-assistant/introduction-page.ui:79 msgid "Colu_mns:" msgstr "_Sarakkeet:" #: data/ui/text-assistant/introduction-page.ui:93 msgid "S_ubtitles:" msgstr "_Kappaleet:" #: data/ui/text-assistant/line-break-options-page.ui:56 #: data/ui/duration-adjust-dialog.ui:207 msgid "Limits" msgstr "Rajat" #: data/ui/text-assistant/line-break-options-page.ui:79 msgid "_Maximum line length:" msgstr "_Rivipituuden maksimi:" #: data/ui/text-assistant/line-break-options-page.ui:93 msgid "_Preferred maximum amount of lines:" msgstr "_Mieluisin rivien maksimimäärä:" #: data/ui/text-assistant/line-break-options-page.ui:198 msgid "_Skip subtitles with maximum line length of:" msgstr "_Ohita kappaleet, joiden rivipituus on korkeintaan:" #: data/ui/text-assistant/line-break-options-page.ui:214 msgid "S_kip subtitles with maximum line amount of:" msgstr "O_hita kappaleet, joiden rivimäärä on korkeintaan:" #: data/ui/text-assistant/hearing-impaired-page.ui:22 msgid "S_elect parts to remove:" msgstr "_Valitse poistettavat osat:" #: data/ui/text-assistant/common-error-page.ui:22 msgid "S_elect errors to correct:" msgstr "_Valitse korjattavat virheet:" #: data/ui/text-assistant/common-error-page.ui:108 msgid "Error types:" msgstr "Virhetyypit:" #: data/ui/text-assistant/common-error-page.ui:158 msgid "_Human errors" msgstr "I_hmisten virheet" #: data/ui/text-assistant/common-error-page.ui:175 msgid "_Image recognition errors" msgstr "K_uvantunnistusvirheet" #: data/ui/text-assistant/capitalization-page.ui:22 msgid "S_elect parts to capitalize:" msgstr "_Valitse isolla kirjaimella alkavaksi muutettavat osat:" #: data/ui/duration-adjust-dialog.ui:33 msgid "Adjust Durations" msgstr "Säädä kestoja" #: data/ui/duration-adjust-dialog.ui:73 msgid "Theoretic Duration" msgstr "Teoreettinen kesto" #: data/ui/duration-adjust-dialog.ui:101 msgid "_Reading speed:" msgstr "_Lukunopeus:" #: data/ui/duration-adjust-dialog.ui:133 msgid "characters per second" msgstr "merkkiä sekunnissa" #: data/ui/duration-adjust-dialog.ui:150 msgid "_Lengthen duration to match reading speed" msgstr "_Pidennä kesto vastaamaan lukunopeutta" #: data/ui/duration-adjust-dialog.ui:167 msgid "_Shorten duration to match reading speed" msgstr "Ly_hennä kesto vastaamaan lukunopeutta" #: data/ui/duration-adjust-dialog.ui:227 msgid "_Minimum duration:" msgstr "_Minimikesto:" #: data/ui/duration-adjust-dialog.ui:243 msgid "Ma_ximum duration:" msgstr "M_aksimikesto:" #: data/ui/duration-adjust-dialog.ui:259 msgid "_Gap between subtitles:" msgstr "Kappaleiden _väli:" #: data/ui/duration-adjust-dialog.ui:294 msgid "s_econds" msgstr "s_ekuntia" #: data/ui/duration-adjust-dialog.ui:324 msgid "seco_nds" msgstr "sek_untia" #: data/ui/duration-adjust-dialog.ui:354 msgid "secon_ds" msgstr "sekun_tia" #: data/ui/duration-adjust-dialog.ui:408 msgid "Adj_ust selected subtitles" msgstr "Sää_dä valitut kappaleet" #: data/ui/duration-adjust-dialog.ui:425 msgid "Adjus_t current project" msgstr "Säädä _nykyinen projekti" #: data/ui/duration-adjust-dialog.ui:442 msgid "Adjust all _open projects" msgstr "Säädä ka_ikki avoimet projektit" #: data/ui/tab-popup.ui:6 msgid "Move Tab _Left" msgstr "Siirrä välilehti _vasemmalle" #: data/ui/tab-popup.ui:10 msgid "Move Tab _Right" msgstr "Siirrä välilehti _oikealle" #: data/ui/insert-dialog.ui:15 msgid "Insert Subtitles" msgstr "Lisää kappaleita" #: data/ui/insert-dialog.ui:48 data/ui/position-shift-dialog.ui:82 msgid "_Amount:" msgstr "_Määrä:" #: data/ui/insert-dialog.ui:62 msgid "_Position:" msgstr "_Sijainti:" #: data/ui/position-shift-dialog.ui:14 msgid "Shift Positions" msgstr "Siirrä kohtia" #: data/ui/position-shift-dialog.ui:54 msgid "Shift" msgstr "Siirrä" #: data/ui/position-shift-dialog.ui:135 #: data/ui/position-transform-dialog.ui:208 msgid "_Preview Changes" msgstr "_Esikatsele muutoksia" #: data/ui/position-shift-dialog.ui:200 msgid "Shift s_elected subtitles" msgstr "Siirrä _valitut kappaleet" #: data/ui/position-shift-dialog.ui:217 msgid "Shift su_btitles from selection to end" msgstr "Siirrä v_alinnasta loppuun" #: data/ui/position-shift-dialog.ui:234 msgid "Shift c_urrent project" msgstr "Siirrä _nykyinen projekti" #: data/ui/position-shift-dialog.ui:251 msgid "Shift all _open projects" msgstr "Siirrä _kaikki avoimet projektit" #: data/ui/position-transform-dialog.ui:22 msgid "Transform Positions" msgstr "Muunna kohdat" #: data/ui/position-transform-dialog.ui:62 msgid "First Point" msgstr "Ensimmäinen piste" #: data/ui/position-transform-dialog.ui:91 msgid "_Subtitle:" msgstr "_Kappale:" #: data/ui/position-transform-dialog.ui:105 msgid "C_orrection:" msgstr "K_orjaus:" #: data/ui/position-transform-dialog.ui:119 #: data/ui/position-transform-dialog.ui:310 msgid "Text:" msgstr "Teksti:" #: data/ui/position-transform-dialog.ui:253 msgid "Second Point" msgstr "Toinen piste" #: data/ui/position-transform-dialog.ui:282 msgid "Su_btitle:" msgstr "K_appale:" #: data/ui/position-transform-dialog.ui:296 msgid "Co_rrection:" msgstr "Ko_rjaus:" #: data/ui/position-transform-dialog.ui:399 msgid "Pre_view Changes" msgstr "Es_ikatsele muutoksia:" #: data/ui/position-transform-dialog.ui:464 msgid "Transform se_lected subtitles" msgstr "Muunna _valitut kappaleet" #: data/ui/position-transform-dialog.ui:482 msgid "Transform c_urrent project" msgstr "Muunna _nykyinen projekti" #: data/extensions/custom-framerates/custom-framerates.extension.in:7 msgid "Custom Framerates" msgstr "Omat ruutunopeudet" #: data/extensions/custom-framerates/custom-framerates.extension.in:8 msgid "Allow use of non-standard framerates" msgstr "Salli epästandardien ruutunopeuksien käyttö" #: data/patterns/Latn-en-US.common-error.in:5 msgid "Period after title" msgstr "Piste tittelin jälkeen" #: data/patterns/Latn-en-US.common-error.in:6 msgid "Add period after a shortened title, such as \"Mr\" and \"Dr\"" msgstr "Lisää piste lyhennetyn tittelin, kuten \"Mr\" ja \"Dr\", jälkeen" #: data/patterns/Latn-en.capitalization.in:5 msgid "First person pronoun" msgstr "Ensimmäisen persoonan pronomini" #: data/patterns/Latn-en.capitalization.in:6 msgid "Capitalize the first person pronoun \"I\"" msgstr "Muunna ensimmäisen persoonan pronominin \"I\" kirjainkoko" #: data/patterns/Latn-en.common-error.in:5 #: data/patterns/Latn-en.common-error.in:14 #: data/patterns/Latn-en.common-error.in:23 msgid "Letter \"I\" in a lower case word" msgstr "Kirjain \"I\" pienellä kirjoitetussa sanassa" #: data/patterns/Latn-en.common-error.in:6 #: data/patterns/Latn-en.common-error.in:15 #: data/patterns/Latn-en.common-error.in:24 msgid "Replace letter \"I\" with letter \"l\" in a lower case word" msgstr "Korvaa kirjain \"I\" kirjaimella \"l\" pienellä kirjoitetussa sanassa" #: data/patterns/Latn-en.common-error.in:32 #: data/patterns/Latn-en.common-error.in:41 #: data/patterns/Latn-en.common-error.in:50 #: data/patterns/Latn-en.common-error.in:62 msgid "Letter \"l\" in an upper case word" msgstr "Kirjain \"l\" isolla kirjoitetussa sanassa" #: data/patterns/Latn-en.common-error.in:33 #: data/patterns/Latn-en.common-error.in:42 #: data/patterns/Latn-en.common-error.in:51 #: data/patterns/Latn-en.common-error.in:63 msgid "Replace letter \"l\" with letter \"I\" in an upper case word" msgstr "Korvaa kirjain \"l\" kirjaimella \"I\" isolla kirjoitetussa sanassa" #: data/patterns/Latn-en.common-error.in:73 #: data/patterns/Latn-en.common-error.in:82 msgid "Zero in an upper case word" msgstr "Nolla isolla kirjoitetussa sanassa" #: data/patterns/Latn-en.common-error.in:74 #: data/patterns/Latn-en.common-error.in:83 msgid "Replace zero with letter \"O\" in an upper case word" msgstr "Korvaa nolla kirjaimella \"O\" isolla kirjoitetussa sanassa" #: data/patterns/Latn-en.common-error.in:91 #: data/patterns/Latn.common-error.in:108 msgid "Space between number and unit" msgstr "Väli luvun ja yksikön välissä" #: data/patterns/Latn-en.common-error.in:92 #: data/patterns/Latn.common-error.in:109 msgid "Add or remove space between a number and the associated unit" msgstr "Lisää tai poista väli luvun ja sen yksikön välistä" #: data/patterns/Latn-en.common-error.in:100 msgid "Spaces around an apostrophe" msgstr "Välit heittomerkin ympärillä" #: data/patterns/Latn-en.common-error.in:101 msgid "Remove spaces around an apostrophe" msgstr "Poista välit heittomerkin ympäriltä" #: data/patterns/Latn-en.common-error.in:109 #: data/patterns/Latn-en.common-error.in:118 msgid "Okay" msgstr "Okay" #: data/patterns/Latn-en.common-error.in:110 #: data/patterns/Latn-en.common-error.in:119 msgid "Spell two-letter forms of \"okay\" in all upper case" msgstr "Muunna okay:n kaksikirjaimiset kirjoitusasut isolla kirjoitetuksi" #: data/patterns/Latn-en.hearing-impaired.in:5 msgid "Uppercase speaker before a colon" msgstr "Isolla kirjoitettu puhuja ennen kaksoispistettä" #: data/patterns/Latn-en.hearing-impaired.in:6 msgid "" "Replace the uppercase name of the speaker before a colon with a dialogue " "dash" msgstr "" "Korvaa kokonaan isolla kirjoitettu puhujan nimi ennen kaksoispistettä " "vuoropuheluviivalla" #: data/patterns/Latn-en.line-break.in:5 msgid "Title" msgstr "Titteli" #: data/patterns/Latn-en.line-break.in:6 msgid "Do not break after a title, e.g. \" Dr.\"" msgstr "Älä katkaise tittelin, esim. \"Dr.\", jälkeen" #: data/patterns/Latn-en.line-break.in:13 msgid "Article" msgstr "Artikkeli" #: data/patterns/Latn-en.line-break.in:14 msgid "Do not break after an article" msgstr "Älä katkaise artikkelin jälkeen" #: data/patterns/Latn-en.line-break.in:21 msgid "Preposition" msgstr "Prepositio" #: data/patterns/Latn-en.line-break.in:22 msgid "Do not break after a preposition" msgstr "Älä katkaise preposition jälkeen" #: data/patterns/Latn-en.line-break.in:30 msgid "Possessive determiner" msgstr "Possessivimääre" #: data/patterns/Latn-en.line-break.in:31 msgid "Do not break after a possessive determiner, e.g. \"my\"" msgstr "Älä katkaise possessiivimääreen, esim. \"my\", jälkeen" #: data/patterns/Latn-fi.common-error.in:5 #: data/patterns/Latn.common-error.in:182 msgid "Space after punctuation marks" msgstr "Väli välimerkkien jälkeen" #: data/patterns/Latn-fi.common-error.in:6 #: data/patterns/Latn.common-error.in:183 msgid "Add space after various punctuation marks" msgstr "Lisää väli tiettyjen välimerkkien jälkeen" #: data/patterns/Latn-fr.common-error.in:5 #: data/patterns/Latn-fr.common-error.in:14 #: data/patterns/Latn-fr.common-error.in:23 #: data/patterns/Latn-fr.common-error.in:32 msgid "Spaces around guillemets" msgstr "Välit kulmalainausmerkkien ympärillä" #: data/patterns/Latn-fr.common-error.in:6 #: data/patterns/Latn-fr.common-error.in:15 #: data/patterns/Latn-fr.common-error.in:24 #: data/patterns/Latn-fr.common-error.in:33 msgid "Add spaces around guillemets" msgstr "Lisää välit kulmalainausmerkkien ympärille" #: data/patterns/Latn-fr.common-error.in:41 #: data/patterns/Latn-fr.common-error.in:52 #: data/patterns/Latn.common-error.in:171 msgid "Space before punctuation marks" msgstr "Väli ennen välimerkkejä" #: data/patterns/Latn-fr.common-error.in:42 #: data/patterns/Latn-fr.common-error.in:53 msgid "Add or remove space before various punctuation marks" msgstr "Lisää tai poista väli ennen tiettyjä välimerkkejä" #: data/patterns/Latn.capitalization.in:5 msgid "Sentence" msgstr "Lause" #: data/patterns/Latn.capitalization.in:6 msgid "Capitalize the first word of a sentence" msgstr "Kirjoita lauseen ensimmäinen sana isolla alkukirjaimella" #: data/patterns/Latn.capitalization.in:12 msgid "Ellipsis" msgstr "Kolme pistettä" #: data/patterns/Latn.capitalization.in:13 msgid "Capitalize after an ellipsis" msgstr "Aloita isolla alkukirjaimella kolmen pisteen jälkeen" #: data/patterns/Latn.common-error.in:8 data/patterns/Latn.common-error.in:17 #: data/patterns/Latn.common-error.in:26 data/patterns/Latn.common-error.in:35 #: data/patterns/Latn.common-error.in:44 data/patterns/Latn.common-error.in:53 #: data/patterns/Latn.common-error.in:62 msgid "Ligatures" msgstr "Ligatuuri" #: data/patterns/Latn.common-error.in:9 data/patterns/Latn.common-error.in:18 #: data/patterns/Latn.common-error.in:27 data/patterns/Latn.common-error.in:36 #: data/patterns/Latn.common-error.in:45 data/patterns/Latn.common-error.in:54 #: data/patterns/Latn.common-error.in:63 msgid "Unpack ligatures to individual characters" msgstr "Pura ligatuurit yksittäisiksi merkeiksi" #: data/patterns/Latn.common-error.in:71 data/patterns/Latn.common-error.in:80 msgid "Spelling of a.m. and p.m." msgstr "Aamu- ja iltapäivien kirjoitusasu" #: data/patterns/Latn.common-error.in:72 data/patterns/Latn.common-error.in:81 msgid "Change the various spellings of 12-hour periods to \"a.m.\" and \"p.m.\"" msgstr "Muuta 12 tunnin jaksojen kirjoitusasu muotoon \"a.m.\" ja \"p.m.\"" #: data/patterns/Latn.common-error.in:89 data/patterns/Latn.common-error.in:98 msgid "Letter \"O\" in a number" msgstr "Kirjain \"O\" luvussa" #: data/patterns/Latn.common-error.in:90 data/patterns/Latn.common-error.in:99 msgid "Replace letter \"O\" with a zero in a number" msgstr "Korvaa kirjain \"O\" nollalla luvussa" #: data/patterns/Latn.common-error.in:117 msgid "Double apostrophe" msgstr "Kaksoisheittomerkki" #: data/patterns/Latn.common-error.in:118 msgid "Replace a double apostrophe with a quotation mark" msgstr "Korvaa kaksoisheittomerkki lainausmerkillä" #: data/patterns/Latn.common-error.in:126 #: data/patterns/Latn.common-error.in:135 #: data/patterns/Latn.common-error.in:144 #: data/patterns/Latn.common-error.in:153 msgid "Spaces around brackets" msgstr "Välit sulkeiden ympärillä" #: data/patterns/Latn.common-error.in:127 #: data/patterns/Latn.common-error.in:136 #: data/patterns/Latn.common-error.in:145 #: data/patterns/Latn.common-error.in:154 msgid "Add or remove spaces around parantheses and square brackets" msgstr "Lisää tai poista välit kaari- ja hakasulkeiden ympäriltä" #: data/patterns/Latn.common-error.in:162 msgid "Space after a dialogue dash" msgstr "Väli vuoropuheluviivan jälkeen" #: data/patterns/Latn.common-error.in:163 msgid "Add space after a dialogue dash" msgstr "Lisää väli vuoropuheluviivan jälkeen" #: data/patterns/Latn.common-error.in:172 msgid "Remove space before various punctuation marks" msgstr "Poista väli ennen tiettyjä välimerkkejä" #: data/patterns/Latn.common-error.in:192 msgid "Space after an ellipsis" msgstr "Väli kolmen pisteen jälkeen" #: data/patterns/Latn.common-error.in:193 msgid "Add space after an ellipsis" msgstr "Lisää väli kolmen pisteen jälkeen" #: data/patterns/Latn.common-error.in:201 msgid "Space after a starting ellipsis" msgstr "Väli aloittavan kolmen pisteen jälkeen" #: data/patterns/Latn.common-error.in:202 msgid "Remove space after an ellipsis that starts a line" msgstr "Poista väli rivin aloittavan kolmen pisteen jälkeen" #: data/patterns/Latn.common-error.in:210 #: data/patterns/Latn.common-error.in:221 #: data/patterns/Latn.common-error.in:232 #: data/patterns/Latn.common-error.in:242 msgid "Spaces around a quotation mark" msgstr "Välit lainausmerkin ympärillä" #: data/patterns/Latn.common-error.in:211 #: data/patterns/Latn.common-error.in:222 #: data/patterns/Latn.common-error.in:233 #: data/patterns/Latn.common-error.in:243 msgid "Remove space after a starting- and before an ending quotation mark" msgstr "" "Poista väli aloittavan lainausmerkin jälkeen ja ennen päättävää " "lainausmerkkiä" #: data/patterns/Latn.common-error.in:252 #: data/patterns/Latn.common-error.in:261 msgid "Spaces around musical notes" msgstr "Välit nuottien ympärillä" #: data/patterns/Latn.common-error.in:253 #: data/patterns/Latn.common-error.in:262 msgid "Add spaces between musical note characters and lyrics" msgstr "Lisää välit nuottimerkkien ja lyriikoiden väliin" #: data/patterns/Latn.common-error.in:270 #: data/patterns/Latn.common-error.in:279 msgid "Multiple question- and exclamation marks" msgstr "Useat kysymys- ja huutomerkit" #: data/patterns/Latn.common-error.in:271 #: data/patterns/Latn.common-error.in:280 msgid "" "Replace multiple consequtive question- and exclamation marks with only one" msgstr "Korvaa useat peräkkäiset kysymys- ja heittomerkit yhdellä" #: data/patterns/Latn.common-error.in:288 #: data/patterns/Latn.common-error.in:298 msgid "Periods around a punctuation mark" msgstr "Pisteet välimerkin ympärillä" #: data/patterns/Latn.common-error.in:289 #: data/patterns/Latn.common-error.in:299 msgid "Remove period before or after various punctuation marks" msgstr "Poista piste tiettyjen välimerkkien edeltä tai jäljestä" #: data/patterns/Latn.common-error.in:308 msgid "Terminating double-dashes" msgstr "Päättävät kaksoisviivat" #: data/patterns/Latn.common-error.in:309 msgid "Replace a single clause-terminating dash with two dashes" msgstr "Korvaa yksi virkkeen päättävä viiva kahdella" #: data/patterns/Latn.hearing-impaired.in:5 msgid "Sound in brackets" msgstr "Ääni hakasulkeissa" #: data/patterns/Latn.hearing-impaired.in:6 msgid "Remove description of a sound between square brackets" msgstr "Poista hakasulkeissa oleva äänen kuvaus" #: data/patterns/Latn.hearing-impaired.in:12 msgid "Sound in parantheses" msgstr "Ääni kaarisulkeissa" #: data/patterns/Latn.hearing-impaired.in:13 msgid "Remove description of a sound between parantheses" msgstr "Poista kaarisulkeissa oleva äänen kuvaus" #: data/patterns/Latn.hearing-impaired.in:19 msgid "Song lyrics between number signs" msgstr "Laulun sanat numeromerkkien välissä" #: data/patterns/Latn.hearing-impaired.in:20 msgid "Remove song lyrics starting with or between number signs" msgstr "Poista laulun sanat alkaen numeromerkeillä tai niiden välissä" #: data/patterns/Latn.hearing-impaired.in:27 msgid "One-line song lyrics between number signs" msgstr "Yksiriviset laulun sanat numeromerkkien välissä" #: data/patterns/Latn.hearing-impaired.in:28 msgid "Remove one-line song lyrics starting with or between number signs" msgstr "" "Poista yksiriviset laulun sanat alkaen numeromerkeillä tai niiden välissä" #: data/patterns/Latn.hearing-impaired.in:35 msgid "Speaker before a colon" msgstr "Puhuja ennen kaksoispistettä" #: data/patterns/Latn.hearing-impaired.in:36 msgid "Replace the name of the speaker before a colon with a dialogue dash" msgstr "Korvaa puhujan nimi ennen kaksoispistettä vuoropuheluviivalla" #: data/patterns/Latn.line-break.in:5 data/patterns/Latn.line-break.in:13 msgid "Dialogue" msgstr "Vuoropuhelu" #: data/patterns/Latn.line-break.in:6 data/patterns/Latn.line-break.in:14 msgid "Break according to dialogue separated by dashes" msgstr "Katkaise viivoilla erotetun vuoropuhelun mukaan" #: data/patterns/Latn.line-break.in:21 data/patterns/Latn.line-break.in:30 msgid "Clause" msgstr "Virke" #: data/patterns/Latn.line-break.in:22 data/patterns/Latn.line-break.in:31 msgid "Break according to clauses terminated by a punctuation mark" msgstr "Katkaise välimerkkiin päättyvien virkkeiden mukaan" #: data/patterns/Latn.line-break.in:38 msgid "Number and unit" msgstr "Lukuarvo ja yksikkö" #: data/patterns/Latn.line-break.in:39 msgid "Do not break between a number and associated unit" msgstr "Älä katkaise lukuarvon ja sen yksikön välistä" #: data/patterns/Zyyy.common-error.in:5 data/patterns/Zyyy.common-error.in:14 msgid "Leading and trailing spaces" msgstr "Välit rivien päissä" #: data/patterns/Zyyy.common-error.in:6 data/patterns/Zyyy.common-error.in:15 msgid "Remove spaces from the beginning and end of lines" msgstr "Poista välit rivien alusta ja lopusta" #: data/patterns/Zyyy.common-error.in:23 msgid "Multiple consecutive spaces" msgstr "Useat peräkkäiset välit" #: data/patterns/Zyyy.common-error.in:24 msgid "Replace multiple consecutive spaces with only one" msgstr "Korvaa useat peräkkäiset välit yhdellä" #: data/patterns/Zyyy.common-error.in:32 data/patterns/Zyyy.common-error.in:45 #: data/patterns/Zyyy.common-error.in:55 data/patterns/Zyyy.common-error.in:65 msgid "Space between digits" msgstr "Väli numeroiden välissä" #: data/patterns/Zyyy.common-error.in:33 data/patterns/Zyyy.common-error.in:46 #: data/patterns/Zyyy.common-error.in:56 data/patterns/Zyyy.common-error.in:66 msgid "Remove space between digits of a number" msgstr "Poista väli luvun numeroiden välissä" #: data/patterns/Zyyy.common-error.in:79 msgid "Musical notes" msgstr "Musiikkinuotit" #: data/patterns/Zyyy.common-error.in:80 msgid "Replace Unicode musical note characters with number signs" msgstr "Korvaa Unicode musiikkinuotit numeromerkeillä" #: data/io.otsaloma.gaupol.appdata.xml.in:7 msgid "Editor for text-based subtitles" msgstr "Muokkain tekstimuotoisille tekstityksille" #: data/io.otsaloma.gaupol.appdata.xml.in:9 msgid "" "Gaupol is an editor for text-based subtitle files. It supports multiple " "subtitle file formats and provides means of creating subtitles, editing " "texts and timing subtitles to match video." msgstr "" "Gaupol on muokkain tekstimuotoisille tekstitystiedostoille. Se tukee useita " "eri tekstitystiedostomuotoja ja tarjoaa toimintoja tekstitysten luomiseen, " "tekstien muokkaamiseen ja tekstitysten ajoittamiseen videoon sovittaen." #: data/io.otsaloma.gaupol.appdata.xml.in:40 msgid "Main window" msgstr "Pääikkuna" #: data/io.otsaloma.gaupol.desktop.in:5 msgid "Subtitle Editor" msgstr "Tekstitysmuokkain" #: data/io.otsaloma.gaupol.desktop.in:6 msgid "Edit subtitle files" msgstr "Muokkaa tekstitystiedostoja" #. TRANSLATORS: Search terms to find this application. Do NOT translate or #. localize the semicolons! The list MUST also end with a semicolon! #: data/io.otsaloma.gaupol.desktop.in:12 msgid "video;subtitles;captions;" msgstr "video;tekstitys;" gaupol-1.11/po/fr.po000066400000000000000000002254431422217132500143210ustar00rootroot00000000000000# 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. # # Translators: # Osmo Salomaa , 2016 # Yann Domingo, 2017 # Guillaume , 2017 # Erwan Amans , 2019 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-04-03 04:00+0300\n" "PO-Revision-Date: 2016-07-07 00:55+0000\n" "Last-Translator: Erwan Amans , 2019\n" "Language-Team: French (https://www.transifex.com/otsaloma/teams/64879/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fr\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: aeidon/enums.py:40 gaupol/enums.py:38 msgid "Subtitle number" msgstr "Numéro de sous-titre" #: aeidon/enums.py:43 msgid "Subtitle position" msgstr "Position de sous-titre" #: aeidon/enums.py:59 msgid "23.976 fps" msgstr "23.976 ips" #: aeidon/enums.py:63 msgid "24.000 fps" msgstr "24.000 ips" #: aeidon/enums.py:67 msgid "25.000 fps" msgstr "25.000 ips" #: aeidon/enums.py:71 msgid "29.970 fps" msgstr "29.970 ips" #: aeidon/enums.py:75 data/ui/menubar.ui:248 msgid "30.000 fps" msgstr "" #: aeidon/enums.py:79 data/ui/menubar.ui:253 msgid "50.000 fps" msgstr "" #: aeidon/enums.py:83 data/ui/menubar.ui:258 msgid "59.940 fps" msgstr "" #: aeidon/enums.py:87 data/ui/menubar.ui:263 msgid "60.000 fps" msgstr "" #: aeidon/enums.py:112 msgid "Mac (classic)" msgstr "Mac (classique)" #. TRANSLATORS: Most of the character encoding descriptions are copied from #. gedit, which is translated to very many languages. Check the gedit .po #. files for a reference: #. . #: aeidon/encodings.py:40 aeidon/encodings.py:43 aeidon/encodings.py:46 msgid "English" msgstr "Anglais" #: aeidon/encodings.py:41 aeidon/encodings.py:42 aeidon/encodings.py:69 msgid "Chinese traditional" msgstr "Chinois (traditionnel)" #: aeidon/encodings.py:44 msgid "German" msgstr "Allemand" #: aeidon/encodings.py:45 aeidon/encodings.py:54 aeidon/encodings.py:59 #: aeidon/encodings.py:79 aeidon/encodings.py:105 msgid "Hebrew" msgstr "Hébreu" #: aeidon/encodings.py:47 aeidon/encodings.py:51 aeidon/encodings.py:56 #: aeidon/encodings.py:73 aeidon/encodings.py:76 aeidon/encodings.py:98 #: aeidon/encodings.py:111 aeidon/encodings.py:122 msgid "Western" msgstr "Occidental" #: aeidon/encodings.py:48 aeidon/encodings.py:61 aeidon/encodings.py:80 #: aeidon/encodings.py:103 msgid "Arabic" msgstr "Arabe" #: aeidon/encodings.py:49 aeidon/encodings.py:64 aeidon/encodings.py:66 #: aeidon/encodings.py:77 aeidon/encodings.py:104 aeidon/encodings.py:119 msgid "Greek" msgstr "Grec" #: aeidon/encodings.py:50 aeidon/encodings.py:81 aeidon/encodings.py:101 #: aeidon/encodings.py:109 msgid "Baltic" msgstr "Baltique" #: aeidon/encodings.py:52 aeidon/encodings.py:74 aeidon/encodings.py:99 #: aeidon/encodings.py:121 msgid "Central European" msgstr "Europe centrale" #: aeidon/encodings.py:53 aeidon/encodings.py:75 aeidon/encodings.py:102 #: aeidon/encodings.py:118 msgid "Cyrillic" msgstr "Cyrillique" #: aeidon/encodings.py:55 aeidon/encodings.py:71 aeidon/encodings.py:78 #: aeidon/encodings.py:106 aeidon/encodings.py:123 msgid "Turkish" msgstr "Turc" #: aeidon/encodings.py:57 msgid "Portuguese" msgstr "Portugais" #: aeidon/encodings.py:58 aeidon/encodings.py:120 msgid "Icelandic" msgstr "Islandais" #: aeidon/encodings.py:60 msgid "Canadian" msgstr "Canadian" #: aeidon/encodings.py:62 aeidon/encodings.py:107 msgid "Nordic" msgstr "Nordique" #: aeidon/encodings.py:63 aeidon/encodings.py:114 msgid "Russian" msgstr "Russe" #: aeidon/encodings.py:65 aeidon/encodings.py:108 msgid "Thai" msgstr "Thaï" #: aeidon/encodings.py:67 aeidon/encodings.py:83 aeidon/encodings.py:84 #: aeidon/encodings.py:85 aeidon/encodings.py:91 aeidon/encodings.py:92 #: aeidon/encodings.py:93 aeidon/encodings.py:94 aeidon/encodings.py:95 #: aeidon/encodings.py:96 aeidon/encodings.py:125 aeidon/encodings.py:126 #: aeidon/encodings.py:127 msgid "Japanese" msgstr "Japonais" #: aeidon/encodings.py:68 aeidon/encodings.py:86 aeidon/encodings.py:97 #: aeidon/encodings.py:113 msgid "Korean" msgstr "Coréen" #: aeidon/encodings.py:70 msgid "Urdu" msgstr "Urdu" #: aeidon/encodings.py:72 aeidon/encodings.py:116 msgid "Ukrainian" msgstr "Ukrainien" #: aeidon/encodings.py:82 msgid "Vietnamese" msgstr "Vietnamien" #: aeidon/encodings.py:87 aeidon/encodings.py:90 msgid "Chinese simplified" msgstr "Chinois (simplifié)" #: aeidon/encodings.py:88 aeidon/encodings.py:89 msgid "Chinese unified" msgstr "Chinois (unifié)" #: aeidon/encodings.py:100 aeidon/encodings.py:112 msgid "South European" msgstr "Europe du sud" #: aeidon/encodings.py:110 msgid "Celtic" msgstr "Celtique" #: aeidon/encodings.py:115 msgid "Tajik" msgstr "Tadjik" #: aeidon/encodings.py:117 msgid "Kazakh" msgstr "Kazakh" #: aeidon/encodings.py:124 msgid "Cyrillic Asian" msgstr "Cyrillique (Asie)" #: aeidon/encodings.py:128 aeidon/encodings.py:129 aeidon/encodings.py:130 #: aeidon/encodings.py:131 aeidon/encodings.py:132 aeidon/encodings.py:133 #: aeidon/encodings.py:134 aeidon/encodings.py:135 aeidon/encodings.py:136 msgid "Unicode" msgstr "Unicode" #: aeidon/encodings.py:156 #, python-brace-format msgid "{description} ({name})" msgstr "{description} ({name})" #: aeidon/encodings.py:232 msgid "Current locale ({})" msgstr "Région actuelle ({})" #: aeidon/locales.py:46 #, python-brace-format msgid "{language} ({country})" msgstr "{language} ({country})" #: aeidon/agents/search.py:227 msgid "Replacing" msgstr "Remplacement" #: aeidon/agents/search.py:256 aeidon/agents/search.py:258 msgid "Replacing all" msgstr "Remplacement (tous)" #: aeidon/agents/position.py:74 msgid "Adjusting durations" msgstr "Ajustement des durées" #: aeidon/agents/position.py:96 msgid "Converting framerate" msgstr "Conversion de la fréquence d'image" #: aeidon/agents/position.py:146 msgid "Setting framerate" msgstr "Mise en place de la fréquence d'image" #: aeidon/agents/position.py:168 msgid "Shifting positions" msgstr "Décalage des positions" #: aeidon/agents/position.py:188 msgid "Transforming positions" msgstr "Transformation des positions" #: aeidon/agents/clipboard.py:44 msgid "Cutting texts" msgstr "Coupage de textes" #: aeidon/agents/clipboard.py:61 msgid "Pasting texts" msgstr "Collage de textes" #: aeidon/agents/text.py:91 msgid "Breaking lines" msgstr "Passage à la ligne" #: aeidon/agents/text.py:128 msgid "Capitalizing texts" msgstr "Capitalisation des textes" #: aeidon/agents/text.py:185 msgid "Correcting common errors" msgstr "Correction des erreurs habituelles" #: aeidon/agents/text.py:234 msgid "Removing hearing impaired texts" msgstr "Suppression des textes pour malentendants" #: aeidon/agents/text.py:315 msgid "Joining words by spell-check suggestions" msgstr "Jonction des mots d'après les suggestions orthographiques" #: aeidon/agents/text.py:354 msgid "Splitting words by spell-check suggestions" msgstr "Séparation des mots d'après les suggestions orthographiques" #: aeidon/agents/set.py:58 aeidon/agents/set.py:80 aeidon/agents/set.py:113 msgid "Editing position" msgstr "Édition de position" #: aeidon/agents/set.py:129 msgid "Editing text" msgstr "Édition du texte" #: aeidon/agents/edit.py:35 msgid "Clearing texts" msgstr "Effacement de textes" #: aeidon/agents/edit.py:61 aeidon/agents/edit.py:83 msgid "Inserting subtitles" msgstr "Insertion de sous-titres" #: aeidon/agents/edit.py:103 msgid "Merging subtitles" msgstr "Fusion de sous-titres" #: aeidon/agents/edit.py:114 msgid "Removing subtitles" msgstr "Suppression de sous-titres" #: aeidon/agents/edit.py:131 msgid "Replacing positions" msgstr "Remplacement de positions" #: aeidon/agents/edit.py:147 msgid "Replacing texts" msgstr "Remplacement de textes" #: aeidon/agents/edit.py:171 msgid "Splitting subtitle" msgstr "Séparation de sous-titre" #: aeidon/agents/format.py:49 msgid "Adding dialogue dashes" msgstr "Ajout de tirets de dialogue" #: aeidon/agents/format.py:68 msgid "Changing case" msgstr "Modification de la casse" #: aeidon/agents/format.py:92 msgid "Italicizing" msgstr "Mise en italiques" #: aeidon/agents/format.py:108 msgid "Removing dialogue dashes" msgstr "Suppression de tirets de dialogue" #: aeidon/agents/format.py:174 msgid "Unitalicizing" msgstr "Annulation des italiques" #: gaupol/application.py:219 gaupol/agents/open.py:203 msgid "Open" msgstr "Ouvrir" #: gaupol/application.py:223 msgid "Open main files" msgstr "Ouvrir" #: gaupol/application.py:230 msgid "Save" msgstr "Enregistrer" #: gaupol/application.py:233 msgid "Save the current main document" msgstr "Enregistrer le document principal actuel" #: gaupol/application.py:238 msgid "Undo" msgstr "Annuler" #: gaupol/application.py:242 msgid "Undo the last action" msgstr "Annuler la dernière action" #: gaupol/application.py:249 msgid "Redo" msgstr "Refaire" #: gaupol/application.py:252 msgid "Redo the last undone action" msgstr "Rétablir la dernière opération annulée" #: gaupol/application.py:260 msgid "Insert" msgstr "Insérer" #: gaupol/application.py:262 msgid "Insert new subtitles" msgstr "Insérer des nouveaux sous-titres" #: gaupol/application.py:266 #: data/extensions/custom-framerates/preferences-dialog.ui:78 msgid "Remove" msgstr "Supprimer" #: gaupol/application.py:268 msgid "Remove the selected subtitles" msgstr "Supprimer les sous-titres sélectionnés" #: gaupol/application.py:273 data/ui/search-dialog.ui:283 msgid "Find" msgstr "Rechercher" #: gaupol/application.py:275 msgid "Search for and replace text" msgstr "Rechercher et remplacer du texte" #: gaupol/application.py:279 data/ui/preferences-dialog.ui:942 msgid "Video" msgstr "Vidéo" #: gaupol/application.py:281 msgid "Show or hide the video player" msgstr "Afficher ou masquer le lecteur vidéo" #: gaupol/application.py:285 data/ui/preferences-dialog.ui:1173 msgid "Preview" msgstr "Aperçu" #: gaupol/application.py:287 msgid "Preview from selected position with a video player" msgstr "Aperçu de la position sélectionnée dans un lecteur vidéo" #: gaupol/enums.py:37 msgid "No." msgstr "N°" #: gaupol/enums.py:43 msgid "Start" msgstr "Début" #: gaupol/enums.py:44 msgid "Start position" msgstr "Position de début" #: gaupol/enums.py:49 msgid "End" msgstr "Fin" #: gaupol/enums.py:50 msgid "End position" msgstr "Position de fin" #. TRANSLATORS: 'Dur.' is short for duration. It is used in the header #. of a column that contains numbers five digits wide. #: gaupol/enums.py:57 msgid "Dur." msgstr "Dur." #: gaupol/enums.py:58 msgid "Duration" msgstr "Durée" #: gaupol/enums.py:63 gaupol/enums.py:64 msgid "Text" msgstr "Texte" #: gaupol/enums.py:69 gaupol/enums.py:70 msgid "Translation" msgstr "Traduction" #: gaupol/enums.py:82 msgid "characters" msgstr "caractères" #: gaupol/enums.py:85 msgid "ems" msgstr "em" #: gaupol/page.py:60 msgid "Untitled {:d}" msgstr "Sans titre {:d}" #: gaupol/page.py:133 msgid "Close project" msgstr "Fermer le projet" #: gaupol/page.py:145 msgid "{} translation" msgstr "Traduction en {}" #: gaupol/page.py:302 msgid "Path:" msgstr "Chemin :" #: gaupol/page.py:303 msgid "Format:" msgstr "Format :" #: gaupol/page.py:304 msgid "Encoding:" msgstr "Encodage :" #: gaupol/page.py:305 msgid "Newlines:" msgstr "Fins de ligne :" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:99 msgid "Tasks and Target" msgstr "Tâches et cibles" #: gaupol/assistants.py:128 msgid "Correct texts in the text column" msgstr "Corriger les textes dans la colonne de texte" #: gaupol/assistants.py:129 msgid "Correct texts in the translation column" msgstr "Corriger les textes dans la colonne de traduction" #: gaupol/assistants.py:138 msgid "Correct texts in selected subtitles" msgstr "Corriger les textes dans les sous-titres sélectionnés" #: gaupol/assistants.py:139 msgid "Correct texts in current project" msgstr "Corriger les textes dans le projet actuel" #: gaupol/assistants.py:140 msgid "Correct texts in all open projects" msgstr "Corriger les textes dans tous les projets ouverts" #: gaupol/assistants.py:363 msgid "Other" msgstr "Autre" #: gaupol/assistants.py:439 msgid "Capitalize texts written in lower case" msgstr "Capitaliser les textes en minuscule" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:443 msgid "Capitalization Patterns" msgstr "Modèles de capitalisation" #: gaupol/assistants.py:445 msgid "Capitalize texts" msgstr "Capitaliser les textes" #: gaupol/assistants.py:468 msgid "Correct common errors made by humans or image recognition software" msgstr "" "Corriger les erreurs fréquentes ou dues à une mauvaise reconnaissance " "d'image" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:472 msgid "Common Error Patterns" msgstr "Modèles d'erreur fréquente" #: gaupol/assistants.py:474 msgid "Correct common errors" msgstr "Corriger les erreurs fréquentes" #: gaupol/assistants.py:526 msgid "Remove explanatory texts meant for the hearing impaired" msgstr "Enlever les textes explicatifs destinés aux malentendants" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:530 msgid "Hearing Impaired Patterns" msgstr "Modèles pour malentendants" #: gaupol/assistants.py:532 msgid "Remove hearing impaired texts" msgstr "Enlever les textes pour malentendants" #: gaupol/assistants.py:544 msgid "" "Use spell-check suggestions to fix whitespace detection errors of image " "recognition software" msgstr "" "Utiliser les suggestions orthographiques pour corriger les erreurs de " "détection des espaces causés par les logiciels de reconnaissance d'image" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:548 msgid "Joining and Splitting Words" msgstr "Jonction/scission de mots" #: gaupol/assistants.py:550 msgid "Join or Split Words" msgstr "Joindre ou scinder des mots" #: gaupol/assistants.py:599 gaupol/agents/tools.py:45 msgid "Failed to load dictionary for language \"{}\"" msgstr "Échec du chargement du dictionnaire pour la langue \"{}\"" #: gaupol/assistants.py:601 gaupol/player.py:263 gaupol/player.py:381 #: gaupol/dialogs/search.py:560 gaupol/dialogs/search.py:568 #: gaupol/dialogs/text_edit.py:49 gaupol/dialogs/encoding.py:56 #: gaupol/agents/open.py:328 gaupol/agents/open.py:337 #: gaupol/agents/open.py:345 gaupol/agents/open.py:354 #: gaupol/agents/tools.py:48 gaupol/agents/save.py:197 #: gaupol/agents/save.py:205 gaupol/agents/preview.py:108 #: gaupol/agents/preview.py:116 gaupol/agents/preview.py:125 #: gaupol/agents/preview.py:133 msgid "_OK" msgstr "_OK" #: gaupol/assistants.py:635 msgid "Break text into lines of defined length" msgstr "Diviser le texte en lignes d'un longueur prédéfinie" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:639 msgid "Line-Break Patterns" msgstr "Modèles de passage à la ligne" #: gaupol/assistants.py:641 msgid "Break lines" msgstr "Passages à la ligne" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:679 msgid "Line-Break Options" msgstr "Options de passage à la ligne" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:763 msgid "Correcting Texts" msgstr "Correction des textes" #: gaupol/assistants.py:769 msgid "Each task is now being run on each project." msgstr "Chaque tâche est maintenant en cours d'exécution dans chaque projet." #: gaupol/assistants.py:793 #, python-brace-format msgid "{current:d} of {total:d} tasks complete" msgstr "{current:d} tâches complétées sur {total:d}" #: gaupol/assistants.py:801 msgid "Project: {}" msgstr "Projet : {}" #: gaupol/assistants.py:807 msgid "Task: {}" msgstr "Tâche : {}" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:832 msgid "Confirm Changes" msgstr "Confirmer les changements" #: gaupol/assistants.py:892 msgid "Accept" msgstr "Accepter" #: gaupol/assistants.py:898 msgid "Original Text" msgstr "Texte original" #: gaupol/assistants.py:899 msgid "Corrected Text" msgstr "Textes corrigés" #: gaupol/assistants.py:1048 msgid "Correct Texts" msgstr "Textes corrects" #: gaupol/assistants.py:1076 msgid "Correcting texts" msgstr "Correction de textes" #: gaupol/assistants.py:1092 #, python-brace-format msgid "Edited {edits:d} and removed {removals:d} subtitles" msgstr "{edits:d} sous-titres édités et {removals:d} supprimés" #: gaupol/assistants.py:1126 msgid "Confirm {:d} Change" msgid_plural "Confirm {:d} Changes" msgstr[0] "Confirmer {:d} changement" msgstr[1] "Confirmer {:d} changements" #: gaupol/renderers/multiline.py:86 msgid "Italic" msgstr "Italique" #: gaupol/player.py:372 msgid "No video streams found" msgstr "" #: gaupol/player.py:379 msgid "Failed to initialize playback" msgstr "Échec du lancement du lecteur vidéo" #: gaupol/dialogs/search.py:189 data/ui/menubar.ui:524 msgid "_Help" msgstr "_Aide" #: gaupol/dialogs/search.py:471 msgid "Found and replaced {:d} occurence" msgid_plural "Found and replaced {:d} occurences" msgstr[0] "Terme remplacé {:d} fois" msgstr[1] "Terme remplacé {:d} fois" #: gaupol/dialogs/search.py:488 msgid "\"{}\" not found" msgstr "\"{}\" non trouvé" #: gaupol/dialogs/search.py:558 msgid "Error in regular expression pattern" msgstr "Erreur dans le modèle d'expression régulière" #: gaupol/dialogs/search.py:566 msgid "Error in regular expression replacement" msgstr "Erreur dans le replacement par expression régulière" #: gaupol/dialogs/text_edit.py:48 gaupol/dialogs/framerate_convert.py:63 #: gaupol/dialogs/insert.py:44 gaupol/dialogs/encoding.py:55 #: gaupol/dialogs/split.py:44 gaupol/dialogs/multi_close.py:54 #: gaupol/dialogs/open.py:63 gaupol/dialogs/position_transform.py:69 #: gaupol/dialogs/position_shift.py:71 gaupol/dialogs/multi_save.py:83 #: gaupol/dialogs/multi_save.py:215 gaupol/dialogs/duration_adjust.py:86 #: gaupol/dialogs/save.py:73 gaupol/dialogs/video.py:41 #: gaupol/agents/open.py:363 gaupol/agents/open.py:375 #: gaupol/agents/open.py:387 gaupol/agents/close.py:71 #: data/extensions/custom-framerates/custom-framerates.py:39 msgid "_Cancel" msgstr "_Annuler" #: gaupol/dialogs/text_edit.py:53 msgid "Edit Text" msgstr "Éditer le texte" #: gaupol/dialogs/framerate_convert.py:64 msgid "Co_nvert" msgstr "Co_nvertir" #: gaupol/dialogs/insert.py:45 msgid "_Insert" msgstr "_Insérer" #: gaupol/dialogs/insert.py:54 msgid "Above selection" msgstr "Au-dessus de la sélection" #: gaupol/dialogs/insert.py:55 msgid "Below selection" msgstr "En-dessous de la sélection" #: gaupol/dialogs/encoding.py:60 data/ui/preferences-dialog.ui:70 msgid "Character Encodings" msgstr "Encodages de caractère" #: gaupol/dialogs/encoding.py:78 gaupol/dialogs/encoding.py:125 msgid "Description" msgstr "Description" #: gaupol/dialogs/encoding.py:85 gaupol/dialogs/encoding.py:132 msgid "Encoding" msgstr "Encodage" #: gaupol/dialogs/encoding.py:141 msgid "Show in Menu" msgstr "Montrer dans le menu" #: gaupol/dialogs/split.py:45 msgid "_Split" msgstr "_Scinder" #: gaupol/dialogs/split.py:76 msgid "Splitting project" msgstr "Séparation du projet" #: gaupol/dialogs/split.py:97 #, python-brace-format msgid "Split {amount:d} subtitles to project \"{name}\"" msgstr "Séparer {amount:d} sous-titres dans le projet \"{name}\"" #: gaupol/dialogs/spell_check.py:269 msgid "Spell-checking" msgstr "Vérification orthographique" #: gaupol/dialogs/preferences.py:217 msgid "{} Extension Website" msgstr "Site de l'extension {}" #: gaupol/dialogs/preferences.py:429 msgid "Custom" msgstr "Personnalisé" #: gaupol/dialogs/multi_close.py:38 msgid "Save changes to documents before closing?" msgstr "Voulez-vous enregistrer les modifications avant de quitter ?" #: gaupol/dialogs/multi_close.py:39 gaupol/agents/open.py:384 #: gaupol/agents/close.py:68 msgid "If you don't save, changes will be permanently lost." msgstr "" "Si vous n'enregistrez pas, les modifications seront définitivement perdues." #: gaupol/dialogs/multi_close.py:53 gaupol/agents/close.py:70 msgid "Close _Without Saving" msgstr "Fermer _sans enregistrer" #: gaupol/dialogs/multi_close.py:55 gaupol/dialogs/multi_save.py:84 #: gaupol/dialogs/save.py:74 gaupol/agents/open.py:388 #: gaupol/agents/close.py:72 data/ui/menubar.ui:34 msgid "_Save" msgstr "_Enregistrer" #: gaupol/dialogs/multi_close.py:70 msgid "Select the _main documents you want to save:" msgstr "Sélectionnez les documents _principaux que vous voulez enregistrer :" #: gaupol/dialogs/multi_close.py:95 msgid "Select the _translation documents you want to save:" msgstr "Sélectionnez les _traductions que vous voulez enregistrer :" #: gaupol/dialogs/open.py:64 gaupol/agents/open.py:364 #: gaupol/agents/open.py:376 msgid "_Open" msgstr "_Ouvrir" #: gaupol/dialogs/position_transform.py:70 msgid "_Transform" msgstr "_Transformer" #: gaupol/dialogs/position_shift.py:72 msgid "_Shift" msgstr "_Décaler" #: gaupol/dialogs/position_shift.py:150 msgid "frames" msgstr "images" #: gaupol/dialogs/position_shift.py:168 data/ui/preferences-dialog.ui:911 msgid "seconds" msgstr "secondes" #: gaupol/dialogs/about.py:36 msgid "About Gaupol" msgstr "À propos de Gaupol" #: gaupol/dialogs/about.py:40 msgid "Subtitle editor" msgstr "Éditeur de sous-titres" #. TRANSLATORS: This is a special message that shouldn't be translated #. literally. It is used in the about dialog to give credits to the #. translators. Thus, you should translate it to your name and email #. address. You can also include other translators who have contributed #. to this translation; in that case, please write them on separate #. lines seperated by newlines (\n). #: gaupol/dialogs/about.py:51 msgid "translator-credits" msgstr "" "Jean van Kasteel \n" "Spanti Nicola (RyDroid) " #: gaupol/dialogs/about.py:54 msgid "Gaupol Website" msgstr "Site web de Gaupol" #: gaupol/dialogs/append.py:35 msgid "Append File" msgstr "Ajouter un fichier..." #: gaupol/dialogs/debug.py:43 msgid "Something went wrong" msgstr "Quelque chose s'est mal passé" #: gaupol/dialogs/debug.py:44 msgid "" "You have probably discovered a bug. Please report it by providing the below " "information and a description of what you were doing." msgstr "" "Il semble que vous ayez découvert un problème. Veuillez le signaler en nous " "transmettant les informations, affichées ci-dessous ainsi qu'une description" " de ce que vous étiez en train de faire lorsque le problème est apparu." #: gaupol/dialogs/debug.py:52 msgid "_Report Bug" msgstr "_Signaler un Problème" #: gaupol/dialogs/debug.py:53 data/ui/menubar.ui:56 msgid "_Quit" msgstr "_Quitter" #: gaupol/dialogs/debug.py:54 gaupol/dialogs/preview_error.py:45 #: data/ui/menubar.ui:52 data/ui/tab-popup.ui:16 msgid "_Close" msgstr "_Fermer" #: gaupol/dialogs/multi_save.py:98 gaupol/dialogs/save.py:110 msgid "{} (recommended)" msgstr "{} (recommandé)" #: gaupol/dialogs/multi_save.py:212 msgid "" "{:d} of the files to be saved already exist. Do you want to replace them?" msgstr "" "{:d} des fichiers en cours d'enregistrement existent déjà. Voulez-vous les " "remplacer ?" #: gaupol/dialogs/multi_save.py:213 msgid "" "The files already exist in \"{}\". Replacing them will overwrite their " "contents." msgstr "" "Les fichiers existent déjà dans \"{}\". Les remplacer écrasera ce qu'ils " "contiennent." #: gaupol/dialogs/multi_save.py:216 data/ui/search-dialog.ui:192 #: data/ui/spell-check-dialog.ui:122 msgid "_Replace" msgstr "_Remplacer" #: gaupol/dialogs/duration_adjust.py:70 msgid "Adjusted duration of {:d} subtitle" msgid_plural "Adjusted durations of {:d} subtitles" msgstr[0] "Durée ajustée pour {:d} sous-titre" msgstr[1] "Durée ajustée pour {:d} sous-titres" #: gaupol/dialogs/duration_adjust.py:87 msgid "_Adjust" msgstr "_Ajuster" #: gaupol/dialogs/preview_error.py:36 msgid "Preview in video player failed" msgstr "Échec de l'aperçu dans le lecteur vidéo" #: gaupol/dialogs/preview_error.py:37 msgid "" "There is probably a problem with either the video file or the video player. " "See the preferences dialog to choose the video player or to customize the " "command." msgstr "" "Il y a probablement un problème avec le fichier vidéo ou le lecteur. " "Consultez les préférences pour choisir le lecteur vidéo ou customiser sa " "commande." #: gaupol/dialogs/language.py:97 msgid "Set Language" msgstr "Définir la langue" #: gaupol/dialogs/video.py:52 gaupol/dialogs/file.py:59 msgid "All files" msgstr "Tous les fichiers" #: gaupol/dialogs/video.py:56 msgid "Video files" msgstr "Fichiers vidéo" #: gaupol/dialogs/file.py:63 msgid "All supported files" msgstr "Tous les fichiers supportés" #: gaupol/dialogs/file.py:77 #, python-brace-format msgid "{format} (*{extension})" msgstr "{format} (*{extension})" #: gaupol/dialogs/file.py:120 msgid "Auto-detected" msgstr "Auto-détecté" #: gaupol/dialogs/file.py:122 msgid "Other…" msgstr "_Autre…" #: gaupol/agents/menu.py:94 gaupol/agents/menu.py:103 #: gaupol/agents/menu.py:110 msgid "File not found" msgstr "" #: gaupol/agents/open.py:85 #, python-brace-format msgid "Appended {amount:d} subtitles from \"{basename}\"" msgstr "{amount:d} sous-titres ajoutés depuis \"{basename}\"" #: gaupol/agents/open.py:96 msgid "Appending file" msgstr "Ajout du fichier" #: gaupol/agents/open.py:111 msgid "File \"{}\" is already open" msgstr "Le fichier \"{}\" est déjà ouvert" #: gaupol/agents/open.py:214 msgid "Open Translation" msgstr "Ouvrir une traduction" #: gaupol/agents/open.py:223 msgid "Select Video" msgstr "Sélectionner une vidéo" #: gaupol/agents/open.py:224 msgid "_Select" msgstr "_Sélectionner" #: gaupol/agents/open.py:325 msgid "Failed to decode file \"{}\" with all attempted codecs" msgstr "Impossible de décoder le fichier \"{}\", tous les codecs ont été essayés" #: gaupol/agents/open.py:326 msgid "Please try to open the file with a different character encoding." msgstr "" "Veuillez réessayer d'ouvrir le fichier avec un encodage de caractères " "différent." #: gaupol/agents/open.py:334 msgid "Failed to recognize format of file \"{}\"" msgstr "Échec de la reconnaissance du format du fichier \"{}\"" #: gaupol/agents/open.py:335 msgid "" "Please check that the file you are trying to open is a subtitle file of a " "format supported by Gaupol." msgstr "" "Vérifiez que le fichier que vous essayez d'ouvrir est un fichier de sous-" "titres dans un format supporté par Gaupol." #: gaupol/agents/open.py:343 msgid "Failed to open file \"{}\"" msgstr "Échec de l'ouverture du fichier \"{}\"" #: gaupol/agents/open.py:351 msgid "Failed to parse file \"{}\"" msgstr "Impossible d'analyser le fichier \"{}\"" #: gaupol/agents/open.py:352 msgid "Please check that the file you are trying to open is a valid {} file." msgstr "" "Vérifiez que le fichier que vous essayez d'ouvrir est un fichier {} valide." #: gaupol/agents/open.py:360 msgid "Open abnormally large file \"{}\"?" msgstr "Ouvrir le fichier anormalement lourd \"{}\" ?" #: gaupol/agents/open.py:361 msgid "" "Size of the file is {:.1f} MB, which is abnormally large for a text-based " "subtitle file. Please, check that you are not trying to open a binary file." msgstr "" "La taille du fichier est {:.1f} Mo, ce qui est anormalement lourd pour un " "fichier de sous-titres textuels. Veuillez vérifier que vous n'êtes pas en " "train d'essayer d'ouvrir un fichier binaire." #: gaupol/agents/open.py:371 msgid "Open unsorted file \"{}\"?" msgstr "Ouvrir le fichier non-trié \"{}\" ?" #: gaupol/agents/open.py:372 msgid "" "The order of {:d} subtitles needs to be changed. If {:d} sounds like a lot, " "the file may be erroneously composed." msgstr "" "L'ordre de {:d} sous-titres doit être changé. Si {:d} vous semble être " "beaucoup, le fichier pourrait être mal composé." #: gaupol/agents/open.py:383 msgid "Save changes to translation document \"{}\" before opening a new one?" msgstr "" "Enregistrer les modifications de la traduction \"{}\" avant d'ouvrir un " "nouveau document ?" #: gaupol/agents/open.py:386 msgid "Open _Without Saving" msgstr "Ouvrir _sans enregistrer" #: gaupol/agents/close.py:66 msgid "Save changes to document \"{}\" before closing?" msgstr "Voulez-vous enregistrer les modifications dans \"{}\" avant de quitter ?" #: gaupol/agents/edit.py:101 gaupol/agents/edit.py:119 msgid "Stretching end position" msgstr "Modification de la position de fin" #: gaupol/agents/edit.py:208 msgid "Inserted {:d} subtitle to fit clipboard contents" msgid_plural "Inserted {:d} subtitles to fit clipboard contents" msgstr[0] "" "{:d} sous-titre inséré pour correspondre au contenu du presse-papier" msgstr[1] "" "{:d} sous-titres insérés pour correspondre au contenu du presse-papier" #: gaupol/agents/edit.py:334 gaupol/agents/edit.py:352 msgid "Stretching start position" msgstr "Modification de la position de début" #: gaupol/agents/edit.py:411 msgid "Use Shift+Return for line-break" msgstr "Utilise Maj+Entrée pour passer à la ligne" #: gaupol/agents/save.py:129 msgid "Save As" msgstr "Enregistrer sous" #: gaupol/agents/save.py:135 msgid "Saved main document as \"{}\"" msgstr "Document principal enregistré en \"{}\"" #: gaupol/agents/save.py:153 msgid "Save Translation As" msgstr "Enregistrer la traduction sous" #: gaupol/agents/save.py:159 msgid "Saved translation document as \"{}\"" msgstr "Traduction enregistrée en \"{}\"" #: gaupol/agents/save.py:194 #, python-brace-format msgid "Failed to encode file \"{basename}\" with codec \"{codec}\"" msgstr "Impossible d'encoder le fichier \"{basename}\" avec le codec \"{codec}\"" #: gaupol/agents/save.py:195 msgid "Please try to save the file with a different character encoding." msgstr "" "Veuillez essayer d'enregistrer le fichier avec un encodage de caractères " "différent." #: gaupol/agents/save.py:203 msgid "Failed to save file \"{}\"" msgstr "Échec de l'enregistrement du fichier \"{}\"" #: gaupol/agents/video.py:67 data/ui/menubar.ui:380 msgid "_Play/Pause" msgstr "_Lecture/Pause" #: gaupol/agents/video.py:69 msgid "Play or pause video" msgstr "Jouer ou mettre en pause la vidéo" #: gaupol/agents/video.py:75 data/ui/menubar.ui:390 msgid "Seek _Previous" msgstr "_Précédent" #: gaupol/agents/video.py:77 msgid "Seek to the start of the previous subtitle" msgstr "Reculer jusqu'au sous-titre précédent" #: gaupol/agents/video.py:81 data/ui/menubar.ui:394 msgid "Seek _Next" msgstr "_Suivant" #: gaupol/agents/video.py:83 msgid "Seek to the start of the next subtitle" msgstr "Avancer jusqu'au sous-titre suivant" #: gaupol/agents/video.py:88 data/ui/menubar.ui:400 msgid "Seek _Backward" msgstr "_Reculer" #: gaupol/agents/video.py:90 msgid "Seek backward" msgstr "Reculer" #: gaupol/agents/video.py:94 data/ui/menubar.ui:404 msgid "Seek _Forward" msgstr "_Avancer" #: gaupol/agents/video.py:96 msgid "Seek forward" msgstr "Avancer" #: gaupol/agents/video.py:109 msgid "Volume" msgstr "Volume" #: gaupol/agents/video.py:189 msgid "Load Video" msgstr "Charger la vidéo" #: gaupol/agents/video.py:189 msgid "_Load" msgstr "_Charger" #: gaupol/agents/video.py:361 msgid "Track {:d}" msgstr "" #: gaupol/agents/preview.py:105 msgid "Failed to encode subtitle file to temporary directory \"{}\"" msgstr "" "Impossible d'encoder le fichier de sous-titres dans le dossier temporaire " "\"{}\"" #: gaupol/agents/preview.py:106 msgid "" "Subtitle data could not be encoded to a temporary file for preview with the " "current character encoding. Please first save the subtitle file with a " "different character encoding." msgstr "" "Les données des sous-titres n'ont pas pu être encodées dans un fichier " "temporaire (pour aperçu) avec l'encodage de caractère actuel. Veuillez " "d'abord enregistrer le fichier de sous-titres avec un encodage différent." #: gaupol/agents/preview.py:114 msgid "Failed to save subtitle file to temporary directory \"{}\"" msgstr "" "Impossible de sauvegarder le fichier de sous-titres dans le dossier " "temporaire \"{}\"" #: gaupol/agents/preview.py:122 msgid "Video player not found" msgstr "Lecteur vidéo introuvable" #: gaupol/agents/preview.py:123 msgid "" "Please install one of the supported video players: mpv (recommended), " "MPlayer or VLC. See the preferences dialog to choose the video player or to " "customize the command." msgstr "" "Veuillez installer l'un des lecteurs vidéos supportés : mpv (recommandé), " "MPlayer ou VLC. Consultez les préférences pour choisir un lecteur vidéo ou " "customiser sa commande." #: gaupol/agents/preview.py:131 msgid "Failed to launch video player" msgstr "Échec du lancement du lecteur vidéo" #: gaupol/applicationman.py:105 msgid "gaupol [OPTION...] [FILE...] [+[NUM]]" msgstr "gaupol [OPTION...] [FICHIER...] [+[NUM]]" #: gaupol/applicationman.py:109 msgid "FILE..." msgstr "FICHIER..." #: gaupol/applicationman.py:112 msgid "subtitle files to open" msgstr "fichiers de sous-titres à ouvrir" #: gaupol/applicationman.py:122 msgid "ENCODING" msgstr "ENCODAGE" #: gaupol/applicationman.py:125 msgid "set the character encoding used to open files" msgstr "définir l'encodage de caractère utilisé pour ouvrir les fichiers" #: gaupol/applicationman.py:132 msgid "list all available character encodings" msgstr "lister tous les encodages de caractères disponibles" #: gaupol/applicationman.py:137 gaupol/applicationman.py:154 msgid "FILE" msgstr "FICHIER" #: gaupol/applicationman.py:140 msgid "open translation file" msgstr "ouvrir un fichier de traduction" #: gaupol/applicationman.py:145 msgid "METHOD" msgstr "MÉTHODE" #: gaupol/applicationman.py:149 msgid "method used to align translation subtitles: 'number' or 'position'" msgstr "" "Méthode utilisée pour aligner les sous-titres traduits : 'numéro' ou " "'position'" #: gaupol/applicationman.py:157 msgid "select video file" msgstr "choisir un fichier vidéo" #: data/extensions/custom-framerates/custom-framerates.py:40 #: data/ui/spell-check-dialog.ui:152 msgid "_Add" msgstr "_Ajouter" #: data/extensions/custom-framerates/custom-framerates.py:171 msgid "{:.3f} fps" msgstr "{:.3f} ips" #: data/extensions/custom-framerates/add-framerate-dialog.ui:13 msgid "Add Framerate" msgstr "Ajouter la fréquence d'image" #: data/extensions/custom-framerates/add-framerate-dialog.ui:44 msgid "_Framerate:" msgstr "_Fréquence d'image :" #: data/extensions/custom-framerates/add-framerate-dialog.ui:73 msgid "fps" msgstr "ips" #: data/extensions/custom-framerates/preferences-dialog.ui:8 msgid "Framerates" msgstr "Fréquences d'images" #: data/extensions/custom-framerates/preferences-dialog.ui:64 msgid "Add" msgstr "_Ajouter" #: data/ui/columns-popup.ui:6 data/ui/menubar.ui:275 msgid "_No." msgstr "_N°" #: data/ui/columns-popup.ui:10 data/ui/menubar.ui:279 msgid "_Start" msgstr "_Début" #: data/ui/columns-popup.ui:14 data/ui/menubar.ui:283 msgid "_End" msgstr "_Fin" #: data/ui/columns-popup.ui:18 data/ui/menubar.ui:287 msgid "_Duration" msgstr "_Durée" #: data/ui/columns-popup.ui:22 data/ui/menubar.ui:291 data/ui/menubar.ui:303 msgid "_Text" msgstr "_Texte" #: data/ui/columns-popup.ui:26 data/ui/menubar.ui:295 msgid "T_ranslation" msgstr "_Traduction" #: data/ui/split-dialog.ui:15 msgid "Split Project" msgstr "Scinder le projet" #: data/ui/split-dialog.ui:48 msgid "_First subtitle of new project:" msgstr "_Premier sous-titre du nouveau projet :" #: data/ui/search-dialog.ui:89 msgid "_Search for:" msgstr "_Rechercher :" #: data/ui/search-dialog.ui:103 data/ui/spell-check-dialog.ui:193 msgid "Replace _with:" msgstr "Remplacer _par :" #: data/ui/search-dialog.ui:162 data/ui/menubar.ui:328 msgid "Find _Next" msgstr "Rechercher le _suivant" #: data/ui/search-dialog.ui:177 msgid "Find _Previous" msgstr "Rechercher le _précédent" #: data/ui/search-dialog.ui:207 msgid "Replace _All" msgstr "_Tout remplacer" #: data/ui/search-dialog.ui:241 msgid "R_egular expression" msgstr "Expression r_égulière" #: data/ui/search-dialog.ui:258 msgid "_Ignore case" msgstr "_Ignorer la casse" #: data/ui/search-dialog.ui:304 data/ui/language-dialog.ui:108 msgid "Columns" msgstr "Colonnes" #: data/ui/search-dialog.ui:324 msgid "Find in _text column" msgstr "Trouver dans la colonne de _texte" #: data/ui/search-dialog.ui:341 msgid "Find in t_ranslation column" msgstr "Trouver dans la colonne de t_raduction" #: data/ui/search-dialog.ui:381 data/ui/framerate-convert-dialog.ui:144 #: data/ui/language-dialog.ui:186 #: data/ui/text-assistant/line-break-options-page.ui:178 #: data/ui/duration-adjust-dialog.ui:388 data/ui/position-shift-dialog.ui:180 #: data/ui/position-transform-dialog.ui:444 msgid "Subtitles" msgstr "Sous-titres" #: data/ui/search-dialog.ui:401 msgid "Find in c_urrent project" msgstr "Trouver dans le projet act_uel" #: data/ui/search-dialog.ui:419 msgid "Find in _all open projects" msgstr "Trouver dans tou_s les projets ouverts" #: data/ui/search-dialog.ui:452 msgid "Target" msgstr "Cible" #: data/ui/framerate-convert-dialog.ui:8 msgid "Convert Framerate" msgstr "Convertir la fréquence d'image" #: data/ui/framerate-convert-dialog.ui:48 msgid "Framerate" msgstr "Fréquence d'image" #: data/ui/framerate-convert-dialog.ui:71 msgid "_Input:" msgstr "_Entrée :" #: data/ui/framerate-convert-dialog.ui:86 msgid "_Output:" msgstr "_Sortie :" #: data/ui/framerate-convert-dialog.ui:164 msgid "Convert c_urrent project" msgstr "Convertir le projet act_uel" #: data/ui/framerate-convert-dialog.ui:181 msgid "Convert _all open projects" msgstr "Convertir t_ous les projets ouverts" #: data/ui/spell-check-dialog.ui:8 msgid "Check Spelling" msgstr "Vérifier l'orthographe" #: data/ui/spell-check-dialog.ui:47 msgid "Join _Back" msgstr "Joindre au _précédent" #: data/ui/spell-check-dialog.ui:62 msgid "Join _Forward" msgstr "Joindre au _suivant" #: data/ui/spell-check-dialog.ui:77 data/ui/menubar.ui:62 msgid "_Edit" msgstr "_Éditer" #: data/ui/spell-check-dialog.ui:92 msgid "_Ignore" msgstr "_Ignorer" #: data/ui/spell-check-dialog.ui:107 msgid "Ig_nore All" msgstr "Tout ig_norer" #: data/ui/spell-check-dialog.ui:137 msgid "Rep_lace All" msgstr "Tout remp_lacer" #: data/ui/spell-check-dialog.ui:179 msgid "_Suggestions:" msgstr "S_uggestions :" #: data/ui/multi-save-dialog.ui:8 msgid "Save All As" msgstr "Tout enregistrer sous" #: data/ui/multi-save-dialog.ui:46 msgid "Save in _folder:" msgstr "Enregistrer dans le _dossier :" #: data/ui/multi-save-dialog.ui:60 data/ui/save-dialog.ui:25 msgid "For_mat:" msgstr "For_mat :" #: data/ui/multi-save-dialog.ui:74 data/ui/open-dialog.ui:25 #: data/ui/save-dialog.ui:39 msgid "_Encoding:" msgstr "_Encodage :" #: data/ui/multi-save-dialog.ui:88 data/ui/save-dialog.ui:53 msgid "Ne_wlines:" msgstr "Fins de _lignes :" #: data/ui/multi-save-dialog.ui:103 msgid "Select A Folder" msgstr "Choisissez un dossier" #: data/ui/multi-save-dialog.ui:150 data/ui/save-dialog.ui:102 msgid "F_ramerate:" msgstr "F_réquence d'image :" #: data/ui/menubar.ui:5 msgid "_File" msgstr "_Fichier" #: data/ui/menubar.ui:8 msgid "_New" msgstr "_Nouveau" #: data/ui/menubar.ui:12 msgid "_Open…" msgstr "_Ouvrir…" #: data/ui/menubar.ui:16 msgid "Open _Translation…" msgstr "Ouvrir une _traduction…" #: data/ui/menubar.ui:22 msgid "Open _Recent" msgstr "Ouvrir un document _récent" #: data/ui/menubar.ui:27 msgid "Open R_ecent Translation" msgstr "Ouvrir une traduction réc_ente" #: data/ui/menubar.ui:38 msgid "Save _As…" msgstr "Enregistrer _sous…" #: data/ui/menubar.ui:42 msgid "Save Trans_lation" msgstr "Enregistrer _la traduction" #: data/ui/menubar.ui:46 msgid "Save Translat_ion As…" msgstr "Enregistrer la traduct_ion sous…" #: data/ui/menubar.ui:65 msgid "_Undo" msgstr "_Annuler" #: data/ui/menubar.ui:69 msgid "_Redo" msgstr "_Rétablir" #: data/ui/menubar.ui:75 msgid "_Edit Cell" msgstr "Édit_er la cellule" #: data/ui/menubar.ui:79 msgid "Edit _Next Cell" msgstr "Éditer la cellule suiva_nte" #: data/ui/menubar.ui:85 msgid "Stretc_h" msgstr "Stretc_h" #: data/ui/menubar.ui:88 msgid "_Start Earlier" msgstr "Commencer plus _tôt" #: data/ui/menubar.ui:92 msgid "S_tart Later" msgstr "Commencer _plus tard" #: data/ui/menubar.ui:98 msgid "E_nd Earlier" msgstr "Arrêter plus _tôt" #: data/ui/menubar.ui:102 msgid "En_d Later" msgstr "Arrêter _plus tard" #: data/ui/menubar.ui:108 msgid "Set St_art From Video Position" msgstr "" #: data/ui/menubar.ui:112 msgid "Set En_d From Video Position" msgstr "_Définir la fin depuis la position de la vidéo" #: data/ui/menubar.ui:118 data/ui/view-popup.ui:6 msgid "_Split Subtitle" msgstr "_Scinder le sous-titre" #: data/ui/menubar.ui:122 data/ui/view-popup.ui:10 msgid "_Merge Subtitles" msgstr "_Fusionner les sous-titres" #: data/ui/menubar.ui:128 data/ui/view-popup.ui:16 msgid "_Insert Subtitles…" msgstr "_Insérer des sous-titres…" #: data/ui/menubar.ui:132 msgid "Inser_t Subtitle At Video Position" msgstr "Insérer un sous-_titre à la position de la vidéo" #: data/ui/menubar.ui:136 data/ui/view-popup.ui:20 msgid "Rem_ove Subtitles" msgstr "Supprimer les s_ous-titres" #: data/ui/menubar.ui:142 msgid "Sele_ction" msgstr "Séle_ction" #: data/ui/menubar.ui:145 msgid "Select _All" msgstr "Sélectionner _tout" #: data/ui/menubar.ui:149 msgid "_Invert Selection" msgstr "_Inverser la sélection" #: data/ui/menubar.ui:155 msgid "Extend To _Beginning" msgstr "Étendre au dé_but" #: data/ui/menubar.ui:159 msgid "Extend To _End" msgstr "Étendr_e à la fin" #: data/ui/menubar.ui:165 msgid "_Previous From Video Position" msgstr "" #: data/ui/menubar.ui:169 msgid "_Next From Video Position" msgstr "" #: data/ui/menubar.ui:177 msgid "_Preferences" msgstr "_Préférences" #: data/ui/menubar.ui:183 msgid "_View" msgstr "_Affichage" #: data/ui/menubar.ui:186 msgid "Tool_bar" msgstr "_Barre d'outils" #: data/ui/menubar.ui:190 msgid "_Video Player" msgstr "Lecteur _vidéo" #: data/ui/menubar.ui:196 msgid "_Layout" msgstr "_Disposition" #: data/ui/menubar.ui:199 msgid "_Horizontal" msgstr "_Horizontal" #: data/ui/menubar.ui:204 msgid "_Vertical" msgstr "_Vertical" #: data/ui/menubar.ui:213 msgid "_Times" msgstr "_Temps" #: data/ui/menubar.ui:218 msgid "_Frames" msgstr "_Images" #: data/ui/menubar.ui:225 msgid "F_ramerate" msgstr "F_réquence d'image" #: data/ui/menubar.ui:228 msgid "2_3.976 fps" msgstr "2_3.976 ips" #: data/ui/menubar.ui:233 msgid "2_4.000 fps" msgstr "2_4.000 ips" #: data/ui/menubar.ui:238 msgid "2_5.000 fps" msgstr "2_5.000 ips" #: data/ui/menubar.ui:243 msgid "2_9.970 fps" msgstr "2_9.970 ips" #: data/ui/menubar.ui:272 msgid "_Columns" msgstr "_Colonnes" #: data/ui/menubar.ui:306 msgid "Cu_t" msgstr "Co_uper" #: data/ui/menubar.ui:310 msgid "_Copy" msgstr "_Copier" #: data/ui/menubar.ui:314 msgid "_Paste" msgstr "_Coller" #: data/ui/menubar.ui:318 msgid "Cl_ear" msgstr "_Effacer" #: data/ui/menubar.ui:324 msgid "_Find And Replace…" msgstr "_Rechercher et remplacer…" #: data/ui/menubar.ui:332 msgid "Find Pre_vious" msgstr "Rechercher _précédent" #: data/ui/menubar.ui:338 msgid "_Italic" msgstr "_Italique" #: data/ui/menubar.ui:342 msgid "_Dialogue" msgstr "_Dialogue" #: data/ui/menubar.ui:348 msgid "Ca_se" msgstr "Ca_sse" #: data/ui/menubar.ui:351 msgid "_Title" msgstr "_Titre" #: data/ui/menubar.ui:355 msgid "_Sentence" msgstr "_Phrase" #: data/ui/menubar.ui:359 msgid "_Upper" msgstr "_Majuscule" #: data/ui/menubar.ui:363 msgid "_Lower" msgstr "_Minuscule" #: data/ui/menubar.ui:371 msgid "Vi_deo" msgstr "Vi_déo" #: data/ui/menubar.ui:374 msgid "_Load Video…" msgstr "_Charger une vidéo…" #: data/ui/menubar.ui:384 data/ui/view-popup.ui:26 msgid "Play _Selection" msgstr "Jouer la _sélection" #: data/ui/menubar.ui:410 data/ui/view-popup.ui:30 msgid "S_eek Selection Start" msgstr "All_er au début de la sélection" #: data/ui/menubar.ui:414 msgid "See_k Selection End" msgstr "Aller à la f_in de la sélection" #: data/ui/menubar.ui:420 msgid "_Audio" msgstr "_Audio" #: data/ui/menubar.ui:423 msgid "_Language" msgstr "_Langue" #: data/ui/menubar.ui:430 msgid "Volume _Down" msgstr "_Diminuer le volume" #: data/ui/menubar.ui:434 msgid "Volume _Up" msgstr "_Augmenter le volume" #: data/ui/menubar.ui:440 msgid "T_ools" msgstr "_Outils" #: data/ui/menubar.ui:443 data/ui/text-assistant/confirmation-page.ui:97 #: data/ui/view-popup.ui:36 msgid "_Preview" msgstr "_Aperçu" #: data/ui/menubar.ui:447 msgid "Select _Video…" msgstr "Choisir une _vidéo…" #: data/ui/menubar.ui:453 msgid "_Check Spelling" msgstr "_Vérifier l'orthographe" #: data/ui/menubar.ui:457 msgid "Co_nfigure Spell-check…" msgstr "Co_nfigurer le correcteur orthographique…" #: data/ui/menubar.ui:461 msgid "C_orrect Texts…" msgstr "C_orriger les textes…" #: data/ui/menubar.ui:467 msgid "_Shift Positions…" msgstr "Décaler les po_sitions…" #: data/ui/menubar.ui:471 msgid "_Transform Positions…" msgstr "_Transformer les positions…" #: data/ui/menubar.ui:475 msgid "Adjust _Durations…" msgstr "Ajuster les _durées…" #: data/ui/menubar.ui:479 msgid "Convert _Framerate…" msgstr "Convertir la _fréquence d'image…" #: data/ui/menubar.ui:485 msgid "_Append File…" msgstr "_Ajouter un fichier…" #: data/ui/menubar.ui:489 msgid "Spli_t Project…" msgstr "Scinder le proje_t…" #: data/ui/menubar.ui:495 msgid "_Projects" msgstr "_Projets" #: data/ui/menubar.ui:498 msgid "_Save All" msgstr "Tout _enregistrer" #: data/ui/menubar.ui:502 msgid "Save _All As…" msgstr "Enregistrer _tout sous…" #: data/ui/menubar.ui:506 msgid "_Close All" msgstr "Tout _fermer" #: data/ui/menubar.ui:512 msgid "_Previous" msgstr "_Précédent" #: data/ui/menubar.ui:516 msgid "_Next" msgstr "_Suivant" #: data/ui/menubar.ui:527 msgid "_Documentation" msgstr "_Documentation" #: data/ui/menubar.ui:531 msgid "_Report A Bug" msgstr "_Signaler un problème" #: data/ui/menubar.ui:535 msgid "_About" msgstr "À _propos" #: data/ui/open-dialog.ui:39 msgid "Align _method:" msgstr "_Méthode d'alignement :" #: data/ui/preferences-dialog.ui:18 msgid "Preferences" msgstr "Préférences" #: data/ui/preferences-dialog.ui:93 msgid "When opening files, try encodings in the following order:" msgstr "" "À l'ouverture de fichiers, tester les encodages dans l'ordre suivant :" #: data/ui/preferences-dialog.ui:104 msgid "Curr_ent locale encoding" msgstr "_Encodage de la région actuelle" #: data/ui/preferences-dialog.ui:130 msgid "_Fallback encodings:" msgstr "Encodage de _secours :" #: data/ui/preferences-dialog.ui:246 msgid "Aut_o-detection" msgstr "Détection _automatique" #: data/ui/preferences-dialog.ui:266 msgid "Encoding specified in the open dialog will always be tried first." msgstr "" "L'encodage spécifié dans le dialogue d'ouverture sera toujours testé en " "premier." #: data/ui/preferences-dialog.ui:296 msgid "File" msgstr "_Fichier" #: data/ui/preferences-dialog.ui:324 msgid "Font" msgstr "Police de caractères" #: data/ui/preferences-dialog.ui:344 msgid "Use _default theme fixed width font" msgstr "Utilisez la largeur de police fixée par le thème _default " #: data/ui/preferences-dialog.ui:368 msgid "_Editor font:" msgstr "_Police de l'éditeur :" #: data/ui/preferences-dialog.ui:425 msgid "Line Lengths" msgstr "Longueurs de ligne" #: data/ui/preferences-dialog.ui:445 msgid "_Show line lengths in list cells" msgstr "_Afficher la longueur des lignes dans les cellules" #: data/ui/preferences-dialog.ui:462 msgid "S_how line lengths in editable text fields" msgstr "Afficher la longueur des lignes dans les _champs de texte éditables" #: data/ui/preferences-dialog.ui:486 msgid "_Length unit:" msgstr "Unité de _longueur :" #: data/ui/preferences-dialog.ui:540 msgid "Spell-Check" msgstr "Vérifier l'orthographe" #: data/ui/preferences-dialog.ui:560 msgid "Chec_k spelling as you type" msgstr "Vérifier l'_orthographe lors de la frappe" #: data/ui/preferences-dialog.ui:598 msgid "Editor" msgstr "Éditeur" #: data/ui/preferences-dialog.ui:626 msgid "Fonts" msgstr "Police de caractères" #: data/ui/preferences-dialog.ui:649 msgid "_Subtitles:" msgstr "_Sous-titres :" #: data/ui/preferences-dialog.ui:679 msgid "_Time:" msgstr "_Temps :" #: data/ui/preferences-dialog.ui:729 msgid "Colors" msgstr "Couleurs" #: data/ui/preferences-dialog.ui:752 msgid "Su_btitles:" msgstr "Sous-t_itres :" #: data/ui/preferences-dialog.ui:777 msgid "_Use a background behind text" msgstr "_Utiliser un fond derrière le texte" #: data/ui/preferences-dialog.ui:797 msgid "Ti_me:" msgstr "_Temps :" #: data/ui/preferences-dialog.ui:822 msgid "Us_e a background behind text" msgstr "Utilis_er un fond derrière le texte" #: data/ui/preferences-dialog.ui:862 msgid "Seek" msgstr "Chercher" #: data/ui/preferences-dialog.ui:883 msgid "_Length:" msgstr "_Longueur:" #: data/ui/preferences-dialog.ui:971 msgid "Video Player" msgstr "Lecteur vidéo" #: data/ui/preferences-dialog.ui:994 msgid "_Application:" msgstr "_Application :" #: data/ui/preferences-dialog.ui:1008 msgid "Co_mmand:" msgstr "_Commande :" #. Translators: Only the title is to be translated, field names not. #: data/ui/preferences-dialog.ui:1033 msgid "" "Fields:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" msgstr "" "Champs:\n" "\n" "$MILLISECONDS\n" "\n" "$SECONDS\n" "\n" "$SUBFILE\n" "\n" "$VIDEOFILE" #: data/ui/preferences-dialog.ui:1048 msgid "Al_ways use UTF-8 character encoding" msgstr "_Toujours utiliser l'encodage UTF-8" #: data/ui/preferences-dialog.ui:1089 msgid "Start Position" msgstr "Position de départ" #: data/ui/preferences-dialog.ui:1111 msgid "_Offset:" msgstr "_Décalage :" #: data/ui/preferences-dialog.ui:1142 msgid "seconds before selection" msgstr "secondes avant la sélection" #: data/ui/preferences-dialog.ui:1281 msgid "Extensions" msgstr "Extensions" #: data/ui/language-dialog.ui:8 msgid "Configure Spell-Check" msgstr "Configurer le correcteur orthographique" #: data/ui/language-dialog.ui:50 msgid "Language" msgstr "Langue" #: data/ui/language-dialog.ui:128 msgid "Check _text column" msgstr "Vérifier la colonne de _texte" #: data/ui/language-dialog.ui:146 msgid "Check t_ranslation column" msgstr "Vérifier la colonne de t_raduction" #: data/ui/language-dialog.ui:206 msgid "Check c_urrent project" msgstr "Vérifier le projet act_uel" #: data/ui/language-dialog.ui:224 msgid "Check _all open projects" msgstr "Vérifier t_ous les projets ouverts" #: data/ui/text-assistant/confirmation-page.ui:22 msgid "Acc_ept, discard or edit changes:" msgstr "Accept_er, rejeter ou éditer les changements :" #: data/ui/text-assistant/confirmation-page.ui:67 msgid "_Mark All" msgstr "Tout _marquer" #: data/ui/text-assistant/confirmation-page.ui:82 msgid "_Unmark All" msgstr "_Supprimer toutes les marques" #: data/ui/text-assistant/confirmation-page.ui:119 msgid "_Remove all blank subtitles" msgstr "Enleve_r les sous-titres vides" #: data/ui/text-assistant/join-split-page.ui:28 msgid "Spell-Check Dictionary" msgstr "Dictionnaire de la vérification orthographique" #: data/ui/text-assistant/join-split-page.ui:49 #: data/ui/text-assistant/line-break-page.ui:81 #: data/ui/text-assistant/hearing-impaired-page.ui:81 #: data/ui/text-assistant/common-error-page.ui:80 #: data/ui/text-assistant/capitalization-page.ui:80 msgid "_Language:" msgstr "_Langue :" #: data/ui/text-assistant/join-split-page.ui:97 msgid "Corrections" msgstr "Corrections" #: data/ui/text-assistant/join-split-page.ui:117 msgid "_Join words not found in spell-check dictionary" msgstr "" "_Joindre les mots non trouvés dans le dictionnaire de correction " "orthographique" #: data/ui/text-assistant/join-split-page.ui:134 msgid "_Split words not found in spell-check dictionary" msgstr "" "_Scinder les mots non trouvés dans le dictionnaire de correction " "orthographique" #: data/ui/text-assistant/line-break-page.ui:22 msgid "S_elect preferred line-break points:" msgstr "Sél_ectionner les endroits préférés pour passer à la ligne :" #: data/ui/text-assistant/line-break-page.ui:67 #: data/ui/text-assistant/hearing-impaired-page.ui:67 #: data/ui/text-assistant/common-error-page.ui:66 #: data/ui/text-assistant/capitalization-page.ui:66 msgid "_Script:" msgstr "_Script :" #: data/ui/text-assistant/line-break-page.ui:95 #: data/ui/text-assistant/hearing-impaired-page.ui:95 #: data/ui/text-assistant/common-error-page.ui:94 #: data/ui/text-assistant/capitalization-page.ui:94 msgid "Co_untry:" msgstr "_Pays :" #: data/ui/text-assistant/introduction-page.ui:28 msgid "_Select corrections to perform on texts:" msgstr "_Sélectionner les corrections à apporter au texte :" #: data/ui/text-assistant/introduction-page.ui:79 msgid "Colu_mns:" msgstr "_Colonnes :" #: data/ui/text-assistant/introduction-page.ui:93 msgid "S_ubtitles:" msgstr "_Sous-titres :" #: data/ui/text-assistant/line-break-options-page.ui:56 #: data/ui/duration-adjust-dialog.ui:207 msgid "Limits" msgstr "Limites" #: data/ui/text-assistant/line-break-options-page.ui:79 msgid "_Maximum line length:" msgstr "Longueur _maximum des lignes :" #: data/ui/text-assistant/line-break-options-page.ui:93 msgid "_Preferred maximum amount of lines:" msgstr "Nombre de ligne maximum _préféré :" #: data/ui/text-assistant/line-break-options-page.ui:198 msgid "_Skip subtitles with maximum line length of:" msgstr "Ignorer les _sous-titres ayant une longueur de ligne maximum de :" #: data/ui/text-assistant/line-break-options-page.ui:214 msgid "S_kip subtitles with maximum line amount of:" msgstr "Ignorer les sous-titres a_yant un nombre maximum de lignes de :" #: data/ui/text-assistant/hearing-impaired-page.ui:22 msgid "S_elect parts to remove:" msgstr "Sél_ectionner les parties à enlever :" #: data/ui/text-assistant/common-error-page.ui:22 msgid "S_elect errors to correct:" msgstr "_Sélectionner les erreurs à corriger :" #: data/ui/text-assistant/common-error-page.ui:108 msgid "Error types:" msgstr "Types d'erreur :" #: data/ui/text-assistant/common-error-page.ui:158 msgid "_Human errors" msgstr "Erreurs _humaines" #: data/ui/text-assistant/common-error-page.ui:175 msgid "_Image recognition errors" msgstr "Erreurs de reconnaissance d'_image" #: data/ui/text-assistant/capitalization-page.ui:22 msgid "S_elect parts to capitalize:" msgstr "Sél_ectionner les parties à capitaliser :" #: data/ui/duration-adjust-dialog.ui:33 msgid "Adjust Durations" msgstr "Ajuster les durées" #: data/ui/duration-adjust-dialog.ui:73 msgid "Theoretic Duration" msgstr "Durée théorique" #: data/ui/duration-adjust-dialog.ui:101 msgid "_Reading speed:" msgstr "Vitesse de _lecture :" #: data/ui/duration-adjust-dialog.ui:133 msgid "characters per second" msgstr "caractères par seconde" #: data/ui/duration-adjust-dialog.ui:150 msgid "_Lengthen duration to match reading speed" msgstr "Allonger _la durée pour correspondre à la vitesse de lecture" #: data/ui/duration-adjust-dialog.ui:167 msgid "_Shorten duration to match reading speed" msgstr "Réduire la durée pour corre_spondre à la vitesse de lecture" #: data/ui/duration-adjust-dialog.ui:227 msgid "_Minimum duration:" msgstr "Durée _minimum :" #: data/ui/duration-adjust-dialog.ui:243 msgid "Ma_ximum duration:" msgstr "Durée ma_ximum :" #: data/ui/duration-adjust-dialog.ui:259 msgid "_Gap between subtitles:" msgstr "_Intervalle entre les sous-titres :" #: data/ui/duration-adjust-dialog.ui:294 msgid "s_econds" msgstr "s_econdes" #: data/ui/duration-adjust-dialog.ui:324 msgid "seco_nds" msgstr "seco_ndes" #: data/ui/duration-adjust-dialog.ui:354 msgid "secon_ds" msgstr "secon_des" #: data/ui/duration-adjust-dialog.ui:408 msgid "Adj_ust selected subtitles" msgstr "Aj_uster les sous-titres sélectionnés" #: data/ui/duration-adjust-dialog.ui:425 msgid "Adjus_t current project" msgstr "Ajus_ter le projet actuel" #: data/ui/duration-adjust-dialog.ui:442 msgid "Adjust all _open projects" msgstr "Ajuster tous les projets _ouverts" #: data/ui/tab-popup.ui:6 msgid "Move Tab _Left" msgstr "Déplacer l'onglet à _gauche" #: data/ui/tab-popup.ui:10 msgid "Move Tab _Right" msgstr "Déplacer l'onglet à _droite" #: data/ui/insert-dialog.ui:15 msgid "Insert Subtitles" msgstr "Insérer des sous-titres" #: data/ui/insert-dialog.ui:48 data/ui/position-shift-dialog.ui:82 msgid "_Amount:" msgstr "_Quantité :" #: data/ui/insert-dialog.ui:62 msgid "_Position:" msgstr "_Position :" #: data/ui/position-shift-dialog.ui:14 msgid "Shift Positions" msgstr "Décaler les positions" #: data/ui/position-shift-dialog.ui:54 msgid "Shift" msgstr "Décaler" #: data/ui/position-shift-dialog.ui:135 #: data/ui/position-transform-dialog.ui:208 msgid "_Preview Changes" msgstr "_Aperçu des changements" #: data/ui/position-shift-dialog.ui:200 msgid "Shift s_elected subtitles" msgstr "Décaler l_es sous-titres sélectionnés" #: data/ui/position-shift-dialog.ui:217 msgid "Shift su_btitles from selection to end" msgstr "Dé_caler les sous-titres depuis la sélection à la fin" #: data/ui/position-shift-dialog.ui:234 msgid "Shift c_urrent project" msgstr "Décaler le projet act_uel" #: data/ui/position-shift-dialog.ui:251 msgid "Shift all _open projects" msgstr "" #: data/ui/position-transform-dialog.ui:22 msgid "Transform Positions" msgstr "Transformer les positions" #: data/ui/position-transform-dialog.ui:62 msgid "First Point" msgstr "Première entrée" #: data/ui/position-transform-dialog.ui:91 msgid "_Subtitle:" msgstr "_Sous-titre :" #: data/ui/position-transform-dialog.ui:105 msgid "C_orrection:" msgstr "C_orrection :" #: data/ui/position-transform-dialog.ui:119 #: data/ui/position-transform-dialog.ui:310 msgid "Text:" msgstr "Texte :" #: data/ui/position-transform-dialog.ui:253 msgid "Second Point" msgstr "Deuxième entrée" #: data/ui/position-transform-dialog.ui:282 msgid "Su_btitle:" msgstr "_Sous-titre :" #: data/ui/position-transform-dialog.ui:296 msgid "Co_rrection:" msgstr "Co_rrection :" #: data/ui/position-transform-dialog.ui:399 msgid "Pre_view Changes" msgstr "_Aperçu des changements" #: data/ui/position-transform-dialog.ui:464 msgid "Transform se_lected subtitles" msgstr "Transformer les sous-titres sé_lectionnés" #: data/ui/position-transform-dialog.ui:482 msgid "Transform c_urrent project" msgstr "Transformer le projet act_uel" #: data/extensions/custom-framerates/custom-framerates.extension.in:7 msgid "Custom Framerates" msgstr "Fréquences d'image personnalisées" #: data/extensions/custom-framerates/custom-framerates.extension.in:8 msgid "Allow use of non-standard framerates" msgstr "Autoriser l'utilisation de fréquences d'image non standards" #: data/patterns/Latn-en-US.common-error.in:5 msgid "Period after title" msgstr "Point après un titre" #: data/patterns/Latn-en-US.common-error.in:6 msgid "Add period after a shortened title, such as \"Mr\" and \"Dr\"" msgstr "Ajouter un point après un titre raccourci, comme \"M\" et \"Dr\"" #: data/patterns/Latn-en.capitalization.in:5 msgid "First person pronoun" msgstr "Pronom personnel, première personne" #: data/patterns/Latn-en.capitalization.in:6 msgid "Capitalize the first person pronoun \"I\"" msgstr "Mettre en majuscule le pronom personnel de la première personne \"I\"" #: data/patterns/Latn-en.common-error.in:5 #: data/patterns/Latn-en.common-error.in:14 #: data/patterns/Latn-en.common-error.in:23 msgid "Letter \"I\" in a lower case word" msgstr "Lettre \"I\" dans un mot en minuscules" #: data/patterns/Latn-en.common-error.in:6 #: data/patterns/Latn-en.common-error.in:15 #: data/patterns/Latn-en.common-error.in:24 msgid "Replace letter \"I\" with letter \"l\" in a lower case word" msgstr "Remplacer la lettre \"I\" par la lettre \"l\" dans un mot en minuscules" #: data/patterns/Latn-en.common-error.in:32 #: data/patterns/Latn-en.common-error.in:41 #: data/patterns/Latn-en.common-error.in:50 #: data/patterns/Latn-en.common-error.in:62 msgid "Letter \"l\" in an upper case word" msgstr "Lettre \"l\" dans un mot en majuscules" #: data/patterns/Latn-en.common-error.in:33 #: data/patterns/Latn-en.common-error.in:42 #: data/patterns/Latn-en.common-error.in:51 #: data/patterns/Latn-en.common-error.in:63 msgid "Replace letter \"l\" with letter \"I\" in an upper case word" msgstr "Remplacer la lettre \"l\" par la lettre \"I\" dans un mot en majuscules" #: data/patterns/Latn-en.common-error.in:73 #: data/patterns/Latn-en.common-error.in:82 msgid "Zero in an upper case word" msgstr "Zéro dans un mot en majuscules" #: data/patterns/Latn-en.common-error.in:74 #: data/patterns/Latn-en.common-error.in:83 msgid "Replace zero with letter \"O\" in an upper case word" msgstr "Remplacer le zéro par la lettre \"O\" dans un mot en majuscules" #: data/patterns/Latn-en.common-error.in:91 #: data/patterns/Latn.common-error.in:108 msgid "Space between number and unit" msgstr "Espace entre nombre et unité" #: data/patterns/Latn-en.common-error.in:92 #: data/patterns/Latn.common-error.in:109 msgid "Add or remove space between a number and the associated unit" msgstr "Ajouter ou retirer l'espace entre un nombre et son unité" #: data/patterns/Latn-en.common-error.in:100 msgid "Spaces around an apostrophe" msgstr "Espaces autour d'un apostrophe" #: data/patterns/Latn-en.common-error.in:101 msgid "Remove spaces around an apostrophe" msgstr "Retirer les espaces autour des apostrophes" #: data/patterns/Latn-en.common-error.in:109 #: data/patterns/Latn-en.common-error.in:118 msgid "Okay" msgstr "Ok" #: data/patterns/Latn-en.common-error.in:110 #: data/patterns/Latn-en.common-error.in:119 msgid "Spell two-letter forms of \"okay\" in all upper case" msgstr "" "Épeler les formes de \"okay\" en deux lettres, en utilisant des majuscules" #: data/patterns/Latn-en.hearing-impaired.in:5 msgid "Uppercase speaker before a colon" msgstr "Nom en majuscules avant un deux-points" #: data/patterns/Latn-en.hearing-impaired.in:6 msgid "" "Replace the uppercase name of the speaker before a colon with a dialogue " "dash" msgstr "" "Remplacer le nom de l'intervenant en majuscules précédant un deux-points par" " un tiret de dialogue" #: data/patterns/Latn-en.line-break.in:5 msgid "Title" msgstr "Titre" #: data/patterns/Latn-en.line-break.in:6 msgid "Do not break after a title, e.g. \" Dr.\"" msgstr "Ne pas passer à la ligne après un titre, ex : \"Dr.\"" #: data/patterns/Latn-en.line-break.in:13 msgid "Article" msgstr "Article" #: data/patterns/Latn-en.line-break.in:14 msgid "Do not break after an article" msgstr "Ne pas passer à la ligne après un article" #: data/patterns/Latn-en.line-break.in:21 msgid "Preposition" msgstr "Préposition" #: data/patterns/Latn-en.line-break.in:22 msgid "Do not break after a preposition" msgstr "Ne pas passer à la ligne après une préposition" #: data/patterns/Latn-en.line-break.in:30 msgid "Possessive determiner" msgstr "Déterminant possessif" #: data/patterns/Latn-en.line-break.in:31 msgid "Do not break after a possessive determiner, e.g. \"my\"" msgstr "Ne pas passer à la ligne après un déterminant possessif, ex : \"mon\"" #: data/patterns/Latn-fi.common-error.in:5 #: data/patterns/Latn.common-error.in:182 msgid "Space after punctuation marks" msgstr "Espaces après des marques de ponctuation" #: data/patterns/Latn-fi.common-error.in:6 #: data/patterns/Latn.common-error.in:183 msgid "Add space after various punctuation marks" msgstr "Ajouter un espace après les différentes marques de ponctuation" #: data/patterns/Latn-fr.common-error.in:5 #: data/patterns/Latn-fr.common-error.in:14 #: data/patterns/Latn-fr.common-error.in:23 #: data/patterns/Latn-fr.common-error.in:32 msgid "Spaces around guillemets" msgstr "Espaces autour des guillemets" #: data/patterns/Latn-fr.common-error.in:6 #: data/patterns/Latn-fr.common-error.in:15 #: data/patterns/Latn-fr.common-error.in:24 #: data/patterns/Latn-fr.common-error.in:33 msgid "Add spaces around guillemets" msgstr "Ajouter des espaces autour des guillemets" #: data/patterns/Latn-fr.common-error.in:41 #: data/patterns/Latn-fr.common-error.in:52 #: data/patterns/Latn.common-error.in:171 msgid "Space before punctuation marks" msgstr "Espace avant les marques de ponctuation" #: data/patterns/Latn-fr.common-error.in:42 #: data/patterns/Latn-fr.common-error.in:53 msgid "Add or remove space before various punctuation marks" msgstr "" "Ajouter ou supprimer l'espace avant les différentes marques de ponctuation" #: data/patterns/Latn.capitalization.in:5 msgid "Sentence" msgstr "Phrase" #: data/patterns/Latn.capitalization.in:6 msgid "Capitalize the first word of a sentence" msgstr "Mettre une majuscule au premier mot d'une phrase" #: data/patterns/Latn.capitalization.in:12 msgid "Ellipsis" msgstr "Ellipse" #: data/patterns/Latn.capitalization.in:13 msgid "Capitalize after an ellipsis" msgstr "Utiliser une majuscule après une ellipse" #: data/patterns/Latn.common-error.in:8 data/patterns/Latn.common-error.in:17 #: data/patterns/Latn.common-error.in:26 data/patterns/Latn.common-error.in:35 #: data/patterns/Latn.common-error.in:44 data/patterns/Latn.common-error.in:53 #: data/patterns/Latn.common-error.in:62 msgid "Ligatures" msgstr "Ligatures" #: data/patterns/Latn.common-error.in:9 data/patterns/Latn.common-error.in:18 #: data/patterns/Latn.common-error.in:27 data/patterns/Latn.common-error.in:36 #: data/patterns/Latn.common-error.in:45 data/patterns/Latn.common-error.in:54 #: data/patterns/Latn.common-error.in:63 msgid "Unpack ligatures to individual characters" msgstr "" #: data/patterns/Latn.common-error.in:71 data/patterns/Latn.common-error.in:80 msgid "Spelling of a.m. and p.m." msgstr "Façon d'épeler a.m. et p.m." #: data/patterns/Latn.common-error.in:72 data/patterns/Latn.common-error.in:81 msgid "Change the various spellings of 12-hour periods to \"a.m.\" and \"p.m.\"" msgstr "" "Modifier les différentes façons d'épeler les périodes de 12 heures en " "\"a.m.\" et \"p.m.\"" #: data/patterns/Latn.common-error.in:89 data/patterns/Latn.common-error.in:98 msgid "Letter \"O\" in a number" msgstr "Lettre \"O\" dans un nombre" #: data/patterns/Latn.common-error.in:90 data/patterns/Latn.common-error.in:99 msgid "Replace letter \"O\" with a zero in a number" msgstr "Remplacer la lettre \"O\" par un zéro dans un nombre" #: data/patterns/Latn.common-error.in:117 msgid "Double apostrophe" msgstr "Double apostrophe" #: data/patterns/Latn.common-error.in:118 msgid "Replace a double apostrophe with a quotation mark" msgstr "Remplacer les doubles apostrophes par des guillemets" #: data/patterns/Latn.common-error.in:126 #: data/patterns/Latn.common-error.in:135 #: data/patterns/Latn.common-error.in:144 #: data/patterns/Latn.common-error.in:153 msgid "Spaces around brackets" msgstr "Espaces autour des crochets" #: data/patterns/Latn.common-error.in:127 #: data/patterns/Latn.common-error.in:136 #: data/patterns/Latn.common-error.in:145 #: data/patterns/Latn.common-error.in:154 msgid "Add or remove spaces around parantheses and square brackets" msgstr "Ajouter ou supprimer les espaces autour des parenthèses et crochets" #: data/patterns/Latn.common-error.in:162 msgid "Space after a dialogue dash" msgstr "Espace après un tiret de dialogue" #: data/patterns/Latn.common-error.in:163 msgid "Add space after a dialogue dash" msgstr "Ajouter un espace après un tiret de dialogue" #: data/patterns/Latn.common-error.in:172 msgid "Remove space before various punctuation marks" msgstr "Enlever l'espace avant les différentes marques de ponctuation" #: data/patterns/Latn.common-error.in:192 msgid "Space after an ellipsis" msgstr "Espace après une ellipse" #: data/patterns/Latn.common-error.in:193 msgid "Add space after an ellipsis" msgstr "Ajouter un espace après une ellipse" #: data/patterns/Latn.common-error.in:201 msgid "Space after a starting ellipsis" msgstr "Espace après une ellipse de début" #: data/patterns/Latn.common-error.in:202 msgid "Remove space after an ellipsis that starts a line" msgstr "Enlever l'espace après une ellipse qui commence une ligne" #: data/patterns/Latn.common-error.in:210 #: data/patterns/Latn.common-error.in:221 #: data/patterns/Latn.common-error.in:232 #: data/patterns/Latn.common-error.in:242 msgid "Spaces around a quotation mark" msgstr "Espaces autour d'un guillemet" #: data/patterns/Latn.common-error.in:211 #: data/patterns/Latn.common-error.in:222 #: data/patterns/Latn.common-error.in:233 #: data/patterns/Latn.common-error.in:243 msgid "Remove space after a starting- and before an ending quotation mark" msgstr "" "Ajouter un espace après un guillemet ouvrant et avant un guillemet fermant" #: data/patterns/Latn.common-error.in:252 #: data/patterns/Latn.common-error.in:261 msgid "Spaces around musical notes" msgstr "Espaces autour des notes de musique" #: data/patterns/Latn.common-error.in:253 #: data/patterns/Latn.common-error.in:262 msgid "Add spaces between musical note characters and lyrics" msgstr "" "Ajouter des espaces entre les caractères de notes de musique et les paroles" #: data/patterns/Latn.common-error.in:270 #: data/patterns/Latn.common-error.in:279 msgid "Multiple question- and exclamation marks" msgstr "Points d'interrogation et d'exclamation multiples" #: data/patterns/Latn.common-error.in:271 #: data/patterns/Latn.common-error.in:280 msgid "" "Replace multiple consequtive question- and exclamation marks with only one" msgstr "" "Remplacer plusieurs points d'interrogation et d'exclamation qui se suivent " "par un seul uniquement" #: data/patterns/Latn.common-error.in:288 #: data/patterns/Latn.common-error.in:298 msgid "Periods around a punctuation mark" msgstr "Points autour d'une marque de ponctuation" #: data/patterns/Latn.common-error.in:289 #: data/patterns/Latn.common-error.in:299 msgid "Remove period before or after various punctuation marks" msgstr "" "Enlever les points avant et après les différentes marques de ponctuation" #: data/patterns/Latn.common-error.in:308 msgid "Terminating double-dashes" msgstr "Doubles tirets à la fin" #: data/patterns/Latn.common-error.in:309 msgid "Replace a single clause-terminating dash with two dashes" msgstr "Remplacer un tiret unique qui termine une phrase par un double tiret" #: data/patterns/Latn.hearing-impaired.in:5 msgid "Sound in brackets" msgstr "Son entre crochets" #: data/patterns/Latn.hearing-impaired.in:6 msgid "Remove description of a sound between square brackets" msgstr "Enlever la description d'un son entre crochets" #: data/patterns/Latn.hearing-impaired.in:12 msgid "Sound in parantheses" msgstr "Son entre parenthèses" #: data/patterns/Latn.hearing-impaired.in:13 msgid "Remove description of a sound between parantheses" msgstr "Enlever la description d'un son entre parenthèses" #: data/patterns/Latn.hearing-impaired.in:19 msgid "Song lyrics between number signs" msgstr "Paroles de chanson entre des nombres" #: data/patterns/Latn.hearing-impaired.in:20 msgid "Remove song lyrics starting with or between number signs" msgstr "" "Enlever les paroles de chanson qui commencent par ou qui sont entre des " "nombres" #: data/patterns/Latn.hearing-impaired.in:27 msgid "One-line song lyrics between number signs" msgstr "Paroles de chanson (ligne seule) entre des nombres" #: data/patterns/Latn.hearing-impaired.in:28 msgid "Remove one-line song lyrics starting with or between number signs" msgstr "" "Enlever les paroles de chanson (sur une seule ligne) qui commencent par ou " "qui sont entre des nombres" #: data/patterns/Latn.hearing-impaired.in:35 msgid "Speaker before a colon" msgstr "Nom avant un deux-points" #: data/patterns/Latn.hearing-impaired.in:36 msgid "Replace the name of the speaker before a colon with a dialogue dash" msgstr "" "Remplacer le nom de l'intervenant précédant un deux-points par un tiret de " "dialogue" #: data/patterns/Latn.line-break.in:5 data/patterns/Latn.line-break.in:13 msgid "Dialogue" msgstr "Dialogue" #: data/patterns/Latn.line-break.in:6 data/patterns/Latn.line-break.in:14 msgid "Break according to dialogue separated by dashes" msgstr "Passer à la ligne pour chaque dialogue séparé par des tirets" #: data/patterns/Latn.line-break.in:21 data/patterns/Latn.line-break.in:30 msgid "Clause" msgstr "Phrases" #: data/patterns/Latn.line-break.in:22 data/patterns/Latn.line-break.in:31 msgid "Break according to clauses terminated by a punctuation mark" msgstr "" "Passer à la ligne en fonction des phrases terminées par une marque de " "ponctuation" #: data/patterns/Latn.line-break.in:38 msgid "Number and unit" msgstr "Nombre et unité" #: data/patterns/Latn.line-break.in:39 msgid "Do not break between a number and associated unit" msgstr "Ne pas passer à la ligne entre un nombre et son unité associée" #: data/patterns/Zyyy.common-error.in:5 data/patterns/Zyyy.common-error.in:14 msgid "Leading and trailing spaces" msgstr "Espaces de début et de fin" #: data/patterns/Zyyy.common-error.in:6 data/patterns/Zyyy.common-error.in:15 msgid "Remove spaces from the beginning and end of lines" msgstr "Supprimer les espaces au début et à la fin des lignes" #: data/patterns/Zyyy.common-error.in:23 msgid "Multiple consecutive spaces" msgstr "Plusieurs espaces consécutifs" #: data/patterns/Zyyy.common-error.in:24 msgid "Replace multiple consecutive spaces with only one" msgstr "Remplacer plusieurs espaces consécutifs par un seul espace" #: data/patterns/Zyyy.common-error.in:32 data/patterns/Zyyy.common-error.in:45 #: data/patterns/Zyyy.common-error.in:55 data/patterns/Zyyy.common-error.in:65 msgid "Space between digits" msgstr "Espace entre les chiffres" #: data/patterns/Zyyy.common-error.in:33 data/patterns/Zyyy.common-error.in:46 #: data/patterns/Zyyy.common-error.in:56 data/patterns/Zyyy.common-error.in:66 msgid "Remove space between digits of a number" msgstr "Supprimer les espaces entre chiffres d'un même nombre" #: data/patterns/Zyyy.common-error.in:79 msgid "Musical notes" msgstr "Notes musicales" #: data/patterns/Zyyy.common-error.in:80 msgid "Replace Unicode musical note characters with number signs" msgstr "Remplacer les notes musicales en Unicode avec des nombres" #: data/io.otsaloma.gaupol.appdata.xml.in:7 msgid "Editor for text-based subtitles" msgstr "Éditeur de sous-titres au format texte" #: data/io.otsaloma.gaupol.appdata.xml.in:9 msgid "" "Gaupol is an editor for text-based subtitle files. It supports multiple " "subtitle file formats and provides means of creating subtitles, editing " "texts and timing subtitles to match video." msgstr "" "Gaupol est un éditeur de sous-titres au format texte. Il supporte de " "nombreux formats de sous-titres et permet de créer, des sous-titres, " "d'éditer du texte, et de synchroniser les sous-titres à une vidéo." #: data/io.otsaloma.gaupol.appdata.xml.in:40 msgid "Main window" msgstr "Fenêtre principale" #: data/io.otsaloma.gaupol.desktop.in:5 msgid "Subtitle Editor" msgstr "Éditeur de sous-titres" #: data/io.otsaloma.gaupol.desktop.in:6 msgid "Edit subtitle files" msgstr "Éditer des fichiers de sous-titres" #. TRANSLATORS: Search terms to find this application. Do NOT translate or #. localize the semicolons! The list MUST also end with a semicolon! #: data/io.otsaloma.gaupol.desktop.in:12 msgid "video;subtitles;captions;" msgstr "video;subtitles;sous-titre;captions;" gaupol-1.11/po/gaupol.pot000066400000000000000000001620131422217132500153560ustar00rootroot00000000000000# 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. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-04-03 04:00+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #: aeidon/enums.py:40 gaupol/enums.py:38 msgid "Subtitle number" msgstr "" #: aeidon/enums.py:43 msgid "Subtitle position" msgstr "" #: aeidon/enums.py:59 msgid "23.976 fps" msgstr "" #: aeidon/enums.py:63 msgid "24.000 fps" msgstr "" #: aeidon/enums.py:67 msgid "25.000 fps" msgstr "" #: aeidon/enums.py:71 msgid "29.970 fps" msgstr "" #: aeidon/enums.py:75 data/ui/menubar.ui:248 msgid "30.000 fps" msgstr "" #: aeidon/enums.py:79 data/ui/menubar.ui:253 msgid "50.000 fps" msgstr "" #: aeidon/enums.py:83 data/ui/menubar.ui:258 msgid "59.940 fps" msgstr "" #: aeidon/enums.py:87 data/ui/menubar.ui:263 msgid "60.000 fps" msgstr "" #: aeidon/enums.py:112 msgid "Mac (classic)" msgstr "" #. TRANSLATORS: Most of the character encoding descriptions are copied from #. gedit, which is translated to very many languages. Check the gedit .po #. files for a reference: . #: aeidon/encodings.py:40 aeidon/encodings.py:43 aeidon/encodings.py:46 msgid "English" msgstr "" #: aeidon/encodings.py:41 aeidon/encodings.py:42 aeidon/encodings.py:69 msgid "Chinese traditional" msgstr "" #: aeidon/encodings.py:44 msgid "German" msgstr "" #: aeidon/encodings.py:45 aeidon/encodings.py:54 aeidon/encodings.py:59 #: aeidon/encodings.py:79 aeidon/encodings.py:105 msgid "Hebrew" msgstr "" #: aeidon/encodings.py:47 aeidon/encodings.py:51 aeidon/encodings.py:56 #: aeidon/encodings.py:73 aeidon/encodings.py:76 aeidon/encodings.py:98 #: aeidon/encodings.py:111 aeidon/encodings.py:122 msgid "Western" msgstr "" #: aeidon/encodings.py:48 aeidon/encodings.py:61 aeidon/encodings.py:80 #: aeidon/encodings.py:103 msgid "Arabic" msgstr "" #: aeidon/encodings.py:49 aeidon/encodings.py:64 aeidon/encodings.py:66 #: aeidon/encodings.py:77 aeidon/encodings.py:104 aeidon/encodings.py:119 msgid "Greek" msgstr "" #: aeidon/encodings.py:50 aeidon/encodings.py:81 aeidon/encodings.py:101 #: aeidon/encodings.py:109 msgid "Baltic" msgstr "" #: aeidon/encodings.py:52 aeidon/encodings.py:74 aeidon/encodings.py:99 #: aeidon/encodings.py:121 msgid "Central European" msgstr "" #: aeidon/encodings.py:53 aeidon/encodings.py:75 aeidon/encodings.py:102 #: aeidon/encodings.py:118 msgid "Cyrillic" msgstr "" #: aeidon/encodings.py:55 aeidon/encodings.py:71 aeidon/encodings.py:78 #: aeidon/encodings.py:106 aeidon/encodings.py:123 msgid "Turkish" msgstr "" #: aeidon/encodings.py:57 msgid "Portuguese" msgstr "" #: aeidon/encodings.py:58 aeidon/encodings.py:120 msgid "Icelandic" msgstr "" #: aeidon/encodings.py:60 msgid "Canadian" msgstr "" #: aeidon/encodings.py:62 aeidon/encodings.py:107 msgid "Nordic" msgstr "" #: aeidon/encodings.py:63 aeidon/encodings.py:114 msgid "Russian" msgstr "" #: aeidon/encodings.py:65 aeidon/encodings.py:108 msgid "Thai" msgstr "" #: aeidon/encodings.py:67 aeidon/encodings.py:83 aeidon/encodings.py:84 #: aeidon/encodings.py:85 aeidon/encodings.py:91 aeidon/encodings.py:92 #: aeidon/encodings.py:93 aeidon/encodings.py:94 aeidon/encodings.py:95 #: aeidon/encodings.py:96 aeidon/encodings.py:125 aeidon/encodings.py:126 #: aeidon/encodings.py:127 msgid "Japanese" msgstr "" #: aeidon/encodings.py:68 aeidon/encodings.py:86 aeidon/encodings.py:97 #: aeidon/encodings.py:113 msgid "Korean" msgstr "" #: aeidon/encodings.py:70 msgid "Urdu" msgstr "" #: aeidon/encodings.py:72 aeidon/encodings.py:116 msgid "Ukrainian" msgstr "" #: aeidon/encodings.py:82 msgid "Vietnamese" msgstr "" #: aeidon/encodings.py:87 aeidon/encodings.py:90 msgid "Chinese simplified" msgstr "" #: aeidon/encodings.py:88 aeidon/encodings.py:89 msgid "Chinese unified" msgstr "" #: aeidon/encodings.py:100 aeidon/encodings.py:112 msgid "South European" msgstr "" #: aeidon/encodings.py:110 msgid "Celtic" msgstr "" #: aeidon/encodings.py:115 msgid "Tajik" msgstr "" #: aeidon/encodings.py:117 msgid "Kazakh" msgstr "" #: aeidon/encodings.py:124 msgid "Cyrillic Asian" msgstr "" #: aeidon/encodings.py:128 aeidon/encodings.py:129 aeidon/encodings.py:130 #: aeidon/encodings.py:131 aeidon/encodings.py:132 aeidon/encodings.py:133 #: aeidon/encodings.py:134 aeidon/encodings.py:135 aeidon/encodings.py:136 msgid "Unicode" msgstr "" #: aeidon/encodings.py:156 #, python-brace-format msgid "{description} ({name})" msgstr "" #: aeidon/encodings.py:232 msgid "Current locale ({})" msgstr "" #: aeidon/locales.py:46 #, python-brace-format msgid "{language} ({country})" msgstr "" #: aeidon/agents/search.py:227 msgid "Replacing" msgstr "" #: aeidon/agents/search.py:256 aeidon/agents/search.py:258 msgid "Replacing all" msgstr "" #: aeidon/agents/position.py:74 msgid "Adjusting durations" msgstr "" #: aeidon/agents/position.py:96 msgid "Converting framerate" msgstr "" #: aeidon/agents/position.py:146 msgid "Setting framerate" msgstr "" #: aeidon/agents/position.py:168 msgid "Shifting positions" msgstr "" #: aeidon/agents/position.py:188 msgid "Transforming positions" msgstr "" #: aeidon/agents/clipboard.py:44 msgid "Cutting texts" msgstr "" #: aeidon/agents/clipboard.py:61 msgid "Pasting texts" msgstr "" #: aeidon/agents/text.py:91 msgid "Breaking lines" msgstr "" #: aeidon/agents/text.py:128 msgid "Capitalizing texts" msgstr "" #: aeidon/agents/text.py:185 msgid "Correcting common errors" msgstr "" #: aeidon/agents/text.py:234 msgid "Removing hearing impaired texts" msgstr "" #: aeidon/agents/text.py:315 msgid "Joining words by spell-check suggestions" msgstr "" #: aeidon/agents/text.py:354 msgid "Splitting words by spell-check suggestions" msgstr "" #: aeidon/agents/set.py:58 aeidon/agents/set.py:80 aeidon/agents/set.py:113 msgid "Editing position" msgstr "" #: aeidon/agents/set.py:129 msgid "Editing text" msgstr "" #: aeidon/agents/edit.py:35 msgid "Clearing texts" msgstr "" #: aeidon/agents/edit.py:61 aeidon/agents/edit.py:83 msgid "Inserting subtitles" msgstr "" #: aeidon/agents/edit.py:103 msgid "Merging subtitles" msgstr "" #: aeidon/agents/edit.py:114 msgid "Removing subtitles" msgstr "" #: aeidon/agents/edit.py:131 msgid "Replacing positions" msgstr "" #: aeidon/agents/edit.py:147 msgid "Replacing texts" msgstr "" #: aeidon/agents/edit.py:171 msgid "Splitting subtitle" msgstr "" #: aeidon/agents/format.py:49 msgid "Adding dialogue dashes" msgstr "" #: aeidon/agents/format.py:68 msgid "Changing case" msgstr "" #: aeidon/agents/format.py:92 msgid "Italicizing" msgstr "" #: aeidon/agents/format.py:108 msgid "Removing dialogue dashes" msgstr "" #: aeidon/agents/format.py:174 msgid "Unitalicizing" msgstr "" #: gaupol/application.py:219 gaupol/agents/open.py:203 msgid "Open" msgstr "" #: gaupol/application.py:223 msgid "Open main files" msgstr "" #: gaupol/application.py:230 msgid "Save" msgstr "" #: gaupol/application.py:233 msgid "Save the current main document" msgstr "" #: gaupol/application.py:238 msgid "Undo" msgstr "" #: gaupol/application.py:242 msgid "Undo the last action" msgstr "" #: gaupol/application.py:249 msgid "Redo" msgstr "" #: gaupol/application.py:252 msgid "Redo the last undone action" msgstr "" #: gaupol/application.py:260 msgid "Insert" msgstr "" #: gaupol/application.py:262 msgid "Insert new subtitles" msgstr "" #: gaupol/application.py:266 #: data/extensions/custom-framerates/preferences-dialog.ui:78 msgid "Remove" msgstr "" #: gaupol/application.py:268 msgid "Remove the selected subtitles" msgstr "" #: gaupol/application.py:273 data/ui/search-dialog.ui:283 msgid "Find" msgstr "" #: gaupol/application.py:275 msgid "Search for and replace text" msgstr "" #: gaupol/application.py:279 data/ui/preferences-dialog.ui:942 msgid "Video" msgstr "" #: gaupol/application.py:281 msgid "Show or hide the video player" msgstr "" #: gaupol/application.py:285 data/ui/preferences-dialog.ui:1173 msgid "Preview" msgstr "" #: gaupol/application.py:287 msgid "Preview from selected position with a video player" msgstr "" #: gaupol/enums.py:37 msgid "No." msgstr "" #: gaupol/enums.py:43 msgid "Start" msgstr "" #: gaupol/enums.py:44 msgid "Start position" msgstr "" #: gaupol/enums.py:49 msgid "End" msgstr "" #: gaupol/enums.py:50 msgid "End position" msgstr "" #. TRANSLATORS: 'Dur.' is short for duration. It is used in the header #. of a column that contains numbers five digits wide. #: gaupol/enums.py:57 msgid "Dur." msgstr "" #: gaupol/enums.py:58 msgid "Duration" msgstr "" #: gaupol/enums.py:63 gaupol/enums.py:64 msgid "Text" msgstr "" #: gaupol/enums.py:69 gaupol/enums.py:70 msgid "Translation" msgstr "" #: gaupol/enums.py:82 msgid "characters" msgstr "" #: gaupol/enums.py:85 msgid "ems" msgstr "" #: gaupol/page.py:60 msgid "Untitled {:d}" msgstr "" #: gaupol/page.py:133 msgid "Close project" msgstr "" #: gaupol/page.py:145 msgid "{} translation" msgstr "" #: gaupol/page.py:302 msgid "Path:" msgstr "" #: gaupol/page.py:303 msgid "Format:" msgstr "" #: gaupol/page.py:304 msgid "Encoding:" msgstr "" #: gaupol/page.py:305 msgid "Newlines:" msgstr "" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:99 msgid "Tasks and Target" msgstr "" #: gaupol/assistants.py:128 msgid "Correct texts in the text column" msgstr "" #: gaupol/assistants.py:129 msgid "Correct texts in the translation column" msgstr "" #: gaupol/assistants.py:138 msgid "Correct texts in selected subtitles" msgstr "" #: gaupol/assistants.py:139 msgid "Correct texts in current project" msgstr "" #: gaupol/assistants.py:140 msgid "Correct texts in all open projects" msgstr "" #: gaupol/assistants.py:363 msgid "Other" msgstr "" #: gaupol/assistants.py:439 msgid "Capitalize texts written in lower case" msgstr "" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:443 msgid "Capitalization Patterns" msgstr "" #: gaupol/assistants.py:445 msgid "Capitalize texts" msgstr "" #: gaupol/assistants.py:468 msgid "Correct common errors made by humans or image recognition software" msgstr "" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:472 msgid "Common Error Patterns" msgstr "" #: gaupol/assistants.py:474 msgid "Correct common errors" msgstr "" #: gaupol/assistants.py:526 msgid "Remove explanatory texts meant for the hearing impaired" msgstr "" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:530 msgid "Hearing Impaired Patterns" msgstr "" #: gaupol/assistants.py:532 msgid "Remove hearing impaired texts" msgstr "" #: gaupol/assistants.py:544 msgid "" "Use spell-check suggestions to fix whitespace detection errors of image " "recognition software" msgstr "" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:548 msgid "Joining and Splitting Words" msgstr "" #: gaupol/assistants.py:550 msgid "Join or Split Words" msgstr "" #: gaupol/assistants.py:599 gaupol/agents/tools.py:45 msgid "Failed to load dictionary for language \"{}\"" msgstr "" #: gaupol/assistants.py:601 gaupol/player.py:263 gaupol/player.py:381 #: gaupol/dialogs/search.py:560 gaupol/dialogs/search.py:568 #: gaupol/dialogs/text_edit.py:49 gaupol/dialogs/encoding.py:56 #: gaupol/agents/open.py:328 gaupol/agents/open.py:337 #: gaupol/agents/open.py:345 gaupol/agents/open.py:354 #: gaupol/agents/tools.py:48 gaupol/agents/save.py:197 #: gaupol/agents/save.py:205 gaupol/agents/preview.py:108 #: gaupol/agents/preview.py:116 gaupol/agents/preview.py:125 #: gaupol/agents/preview.py:133 msgid "_OK" msgstr "" #: gaupol/assistants.py:635 msgid "Break text into lines of defined length" msgstr "" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:639 msgid "Line-Break Patterns" msgstr "" #: gaupol/assistants.py:641 msgid "Break lines" msgstr "" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:679 msgid "Line-Break Options" msgstr "" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:763 msgid "Correcting Texts" msgstr "" #: gaupol/assistants.py:769 msgid "Each task is now being run on each project." msgstr "" #: gaupol/assistants.py:793 #, python-brace-format msgid "{current:d} of {total:d} tasks complete" msgstr "" #: gaupol/assistants.py:801 msgid "Project: {}" msgstr "" #: gaupol/assistants.py:807 msgid "Task: {}" msgstr "" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:832 msgid "Confirm Changes" msgstr "" #: gaupol/assistants.py:892 msgid "Accept" msgstr "" #: gaupol/assistants.py:898 msgid "Original Text" msgstr "" #: gaupol/assistants.py:899 msgid "Corrected Text" msgstr "" #: gaupol/assistants.py:1048 msgid "Correct Texts" msgstr "" #: gaupol/assistants.py:1076 msgid "Correcting texts" msgstr "" #: gaupol/assistants.py:1092 #, python-brace-format msgid "Edited {edits:d} and removed {removals:d} subtitles" msgstr "" #: gaupol/assistants.py:1126 msgid "Confirm {:d} Change" msgid_plural "Confirm {:d} Changes" msgstr[0] "" msgstr[1] "" #: gaupol/renderers/multiline.py:86 msgid "Italic" msgstr "" #: gaupol/player.py:372 msgid "No video streams found" msgstr "" #: gaupol/player.py:379 msgid "Failed to initialize playback" msgstr "" #: gaupol/dialogs/search.py:189 data/ui/menubar.ui:524 msgid "_Help" msgstr "" #: gaupol/dialogs/search.py:471 msgid "Found and replaced {:d} occurence" msgid_plural "Found and replaced {:d} occurences" msgstr[0] "" msgstr[1] "" #: gaupol/dialogs/search.py:488 msgid "\"{}\" not found" msgstr "" #: gaupol/dialogs/search.py:558 msgid "Error in regular expression pattern" msgstr "" #: gaupol/dialogs/search.py:566 msgid "Error in regular expression replacement" msgstr "" #: gaupol/dialogs/text_edit.py:48 gaupol/dialogs/framerate_convert.py:63 #: gaupol/dialogs/insert.py:44 gaupol/dialogs/encoding.py:55 #: gaupol/dialogs/split.py:44 gaupol/dialogs/multi_close.py:54 #: gaupol/dialogs/open.py:63 gaupol/dialogs/position_transform.py:69 #: gaupol/dialogs/position_shift.py:71 gaupol/dialogs/multi_save.py:83 #: gaupol/dialogs/multi_save.py:215 gaupol/dialogs/duration_adjust.py:86 #: gaupol/dialogs/save.py:73 gaupol/dialogs/video.py:41 #: gaupol/agents/open.py:363 gaupol/agents/open.py:375 #: gaupol/agents/open.py:387 gaupol/agents/close.py:71 #: data/extensions/custom-framerates/custom-framerates.py:39 msgid "_Cancel" msgstr "" #: gaupol/dialogs/text_edit.py:53 msgid "Edit Text" msgstr "" #: gaupol/dialogs/framerate_convert.py:64 msgid "Co_nvert" msgstr "" #: gaupol/dialogs/insert.py:45 msgid "_Insert" msgstr "" #: gaupol/dialogs/insert.py:54 msgid "Above selection" msgstr "" #: gaupol/dialogs/insert.py:55 msgid "Below selection" msgstr "" #: gaupol/dialogs/encoding.py:60 data/ui/preferences-dialog.ui:70 msgid "Character Encodings" msgstr "" #: gaupol/dialogs/encoding.py:78 gaupol/dialogs/encoding.py:125 msgid "Description" msgstr "" #: gaupol/dialogs/encoding.py:85 gaupol/dialogs/encoding.py:132 msgid "Encoding" msgstr "" #: gaupol/dialogs/encoding.py:141 msgid "Show in Menu" msgstr "" #: gaupol/dialogs/split.py:45 msgid "_Split" msgstr "" #: gaupol/dialogs/split.py:76 msgid "Splitting project" msgstr "" #: gaupol/dialogs/split.py:97 #, python-brace-format msgid "Split {amount:d} subtitles to project \"{name}\"" msgstr "" #: gaupol/dialogs/spell_check.py:269 msgid "Spell-checking" msgstr "" #: gaupol/dialogs/preferences.py:217 msgid "{} Extension Website" msgstr "" #: gaupol/dialogs/preferences.py:429 msgid "Custom" msgstr "" #: gaupol/dialogs/multi_close.py:38 msgid "Save changes to documents before closing?" msgstr "" #: gaupol/dialogs/multi_close.py:39 gaupol/agents/open.py:384 #: gaupol/agents/close.py:68 msgid "If you don't save, changes will be permanently lost." msgstr "" #: gaupol/dialogs/multi_close.py:53 gaupol/agents/close.py:70 msgid "Close _Without Saving" msgstr "" #: gaupol/dialogs/multi_close.py:55 gaupol/dialogs/multi_save.py:84 #: gaupol/dialogs/save.py:74 gaupol/agents/open.py:388 #: gaupol/agents/close.py:72 data/ui/menubar.ui:34 msgid "_Save" msgstr "" #: gaupol/dialogs/multi_close.py:70 msgid "Select the _main documents you want to save:" msgstr "" #: gaupol/dialogs/multi_close.py:95 msgid "Select the _translation documents you want to save:" msgstr "" #: gaupol/dialogs/open.py:64 gaupol/agents/open.py:364 #: gaupol/agents/open.py:376 msgid "_Open" msgstr "" #: gaupol/dialogs/position_transform.py:70 msgid "_Transform" msgstr "" #: gaupol/dialogs/position_shift.py:72 msgid "_Shift" msgstr "" #: gaupol/dialogs/position_shift.py:150 msgid "frames" msgstr "" #: gaupol/dialogs/position_shift.py:168 data/ui/preferences-dialog.ui:911 msgid "seconds" msgstr "" #: gaupol/dialogs/about.py:36 msgid "About Gaupol" msgstr "" #: gaupol/dialogs/about.py:40 msgid "Subtitle editor" msgstr "" #. TRANSLATORS: This is a special message that shouldn't be translated #. literally. It is used in the about dialog to give credits to the #. translators. Thus, you should translate it to your name and email #. address. You can also include other translators who have contributed #. to this translation; in that case, please write them on separate #. lines seperated by newlines (\n). #: gaupol/dialogs/about.py:51 msgid "translator-credits" msgstr "" #: gaupol/dialogs/about.py:54 msgid "Gaupol Website" msgstr "" #: gaupol/dialogs/append.py:35 msgid "Append File" msgstr "" #: gaupol/dialogs/debug.py:43 msgid "Something went wrong" msgstr "" #: gaupol/dialogs/debug.py:44 msgid "" "You have probably discovered a bug. Please report it by providing the below " "information and a description of what you were doing." msgstr "" #: gaupol/dialogs/debug.py:52 msgid "_Report Bug" msgstr "" #: gaupol/dialogs/debug.py:53 data/ui/menubar.ui:56 msgid "_Quit" msgstr "" #: gaupol/dialogs/debug.py:54 gaupol/dialogs/preview_error.py:45 #: data/ui/menubar.ui:52 data/ui/tab-popup.ui:16 msgid "_Close" msgstr "" #: gaupol/dialogs/multi_save.py:98 gaupol/dialogs/save.py:110 msgid "{} (recommended)" msgstr "" #: gaupol/dialogs/multi_save.py:212 msgid "" "{:d} of the files to be saved already exist. Do you want to replace them?" msgstr "" #: gaupol/dialogs/multi_save.py:213 msgid "" "The files already exist in \"{}\". Replacing them will overwrite their " "contents." msgstr "" #: gaupol/dialogs/multi_save.py:216 data/ui/search-dialog.ui:192 #: data/ui/spell-check-dialog.ui:122 msgid "_Replace" msgstr "" #: gaupol/dialogs/duration_adjust.py:70 msgid "Adjusted duration of {:d} subtitle" msgid_plural "Adjusted durations of {:d} subtitles" msgstr[0] "" msgstr[1] "" #: gaupol/dialogs/duration_adjust.py:87 msgid "_Adjust" msgstr "" #: gaupol/dialogs/preview_error.py:36 msgid "Preview in video player failed" msgstr "" #: gaupol/dialogs/preview_error.py:37 msgid "" "There is probably a problem with either the video file or the video player. " "See the preferences dialog to choose the video player or to customize the " "command." msgstr "" #: gaupol/dialogs/language.py:97 msgid "Set Language" msgstr "" #: gaupol/dialogs/video.py:52 gaupol/dialogs/file.py:59 msgid "All files" msgstr "" #: gaupol/dialogs/video.py:56 msgid "Video files" msgstr "" #: gaupol/dialogs/file.py:63 msgid "All supported files" msgstr "" #: gaupol/dialogs/file.py:77 #, python-brace-format msgid "{format} (*{extension})" msgstr "" #: gaupol/dialogs/file.py:120 msgid "Auto-detected" msgstr "" #: gaupol/dialogs/file.py:122 msgid "Other…" msgstr "" #: gaupol/agents/menu.py:94 gaupol/agents/menu.py:103 gaupol/agents/menu.py:110 msgid "File not found" msgstr "" #: gaupol/agents/open.py:85 #, python-brace-format msgid "Appended {amount:d} subtitles from \"{basename}\"" msgstr "" #: gaupol/agents/open.py:96 msgid "Appending file" msgstr "" #: gaupol/agents/open.py:111 msgid "File \"{}\" is already open" msgstr "" #: gaupol/agents/open.py:214 msgid "Open Translation" msgstr "" #: gaupol/agents/open.py:223 msgid "Select Video" msgstr "" #: gaupol/agents/open.py:224 msgid "_Select" msgstr "" #: gaupol/agents/open.py:325 msgid "Failed to decode file \"{}\" with all attempted codecs" msgstr "" #: gaupol/agents/open.py:326 msgid "Please try to open the file with a different character encoding." msgstr "" #: gaupol/agents/open.py:334 msgid "Failed to recognize format of file \"{}\"" msgstr "" #: gaupol/agents/open.py:335 msgid "" "Please check that the file you are trying to open is a subtitle file of a " "format supported by Gaupol." msgstr "" #: gaupol/agents/open.py:343 msgid "Failed to open file \"{}\"" msgstr "" #: gaupol/agents/open.py:351 msgid "Failed to parse file \"{}\"" msgstr "" #: gaupol/agents/open.py:352 msgid "Please check that the file you are trying to open is a valid {} file." msgstr "" #: gaupol/agents/open.py:360 msgid "Open abnormally large file \"{}\"?" msgstr "" #: gaupol/agents/open.py:361 msgid "" "Size of the file is {:.1f} MB, which is abnormally large for a text-based " "subtitle file. Please, check that you are not trying to open a binary file." msgstr "" #: gaupol/agents/open.py:371 msgid "Open unsorted file \"{}\"?" msgstr "" #: gaupol/agents/open.py:372 msgid "" "The order of {:d} subtitles needs to be changed. If {:d} sounds like a lot, " "the file may be erroneously composed." msgstr "" #: gaupol/agents/open.py:383 msgid "Save changes to translation document \"{}\" before opening a new one?" msgstr "" #: gaupol/agents/open.py:386 msgid "Open _Without Saving" msgstr "" #: gaupol/agents/close.py:66 msgid "Save changes to document \"{}\" before closing?" msgstr "" #: gaupol/agents/edit.py:101 gaupol/agents/edit.py:119 msgid "Stretching end position" msgstr "" #: gaupol/agents/edit.py:208 msgid "Inserted {:d} subtitle to fit clipboard contents" msgid_plural "Inserted {:d} subtitles to fit clipboard contents" msgstr[0] "" msgstr[1] "" #: gaupol/agents/edit.py:334 gaupol/agents/edit.py:352 msgid "Stretching start position" msgstr "" #: gaupol/agents/edit.py:411 msgid "Use Shift+Return for line-break" msgstr "" #: gaupol/agents/save.py:129 msgid "Save As" msgstr "" #: gaupol/agents/save.py:135 msgid "Saved main document as \"{}\"" msgstr "" #: gaupol/agents/save.py:153 msgid "Save Translation As" msgstr "" #: gaupol/agents/save.py:159 msgid "Saved translation document as \"{}\"" msgstr "" #: gaupol/agents/save.py:194 #, python-brace-format msgid "Failed to encode file \"{basename}\" with codec \"{codec}\"" msgstr "" #: gaupol/agents/save.py:195 msgid "Please try to save the file with a different character encoding." msgstr "" #: gaupol/agents/save.py:203 msgid "Failed to save file \"{}\"" msgstr "" #: gaupol/agents/video.py:67 data/ui/menubar.ui:380 msgid "_Play/Pause" msgstr "" #: gaupol/agents/video.py:69 msgid "Play or pause video" msgstr "" #: gaupol/agents/video.py:75 data/ui/menubar.ui:390 msgid "Seek _Previous" msgstr "" #: gaupol/agents/video.py:77 msgid "Seek to the start of the previous subtitle" msgstr "" #: gaupol/agents/video.py:81 data/ui/menubar.ui:394 msgid "Seek _Next" msgstr "" #: gaupol/agents/video.py:83 msgid "Seek to the start of the next subtitle" msgstr "" #: gaupol/agents/video.py:88 data/ui/menubar.ui:400 msgid "Seek _Backward" msgstr "" #: gaupol/agents/video.py:90 msgid "Seek backward" msgstr "" #: gaupol/agents/video.py:94 data/ui/menubar.ui:404 msgid "Seek _Forward" msgstr "" #: gaupol/agents/video.py:96 msgid "Seek forward" msgstr "" #: gaupol/agents/video.py:109 msgid "Volume" msgstr "" #: gaupol/agents/video.py:189 msgid "Load Video" msgstr "" #: gaupol/agents/video.py:189 msgid "_Load" msgstr "" #: gaupol/agents/video.py:361 msgid "Track {:d}" msgstr "" #: gaupol/agents/preview.py:105 msgid "Failed to encode subtitle file to temporary directory \"{}\"" msgstr "" #: gaupol/agents/preview.py:106 msgid "" "Subtitle data could not be encoded to a temporary file for preview with the " "current character encoding. Please first save the subtitle file with a " "different character encoding." msgstr "" #: gaupol/agents/preview.py:114 msgid "Failed to save subtitle file to temporary directory \"{}\"" msgstr "" #: gaupol/agents/preview.py:122 msgid "Video player not found" msgstr "" #: gaupol/agents/preview.py:123 msgid "" "Please install one of the supported video players: mpv (recommended), " "MPlayer or VLC. See the preferences dialog to choose the video player or to " "customize the command." msgstr "" #: gaupol/agents/preview.py:131 msgid "Failed to launch video player" msgstr "" #: gaupol/applicationman.py:105 msgid "gaupol [OPTION...] [FILE...] [+[NUM]]" msgstr "" #: gaupol/applicationman.py:109 msgid "FILE..." msgstr "" #: gaupol/applicationman.py:112 msgid "subtitle files to open" msgstr "" #: gaupol/applicationman.py:122 msgid "ENCODING" msgstr "" #: gaupol/applicationman.py:125 msgid "set the character encoding used to open files" msgstr "" #: gaupol/applicationman.py:132 msgid "list all available character encodings" msgstr "" #: gaupol/applicationman.py:137 gaupol/applicationman.py:154 msgid "FILE" msgstr "" #: gaupol/applicationman.py:140 msgid "open translation file" msgstr "" #: gaupol/applicationman.py:145 msgid "METHOD" msgstr "" #: gaupol/applicationman.py:149 msgid "method used to align translation subtitles: 'number' or 'position'" msgstr "" #: gaupol/applicationman.py:157 msgid "select video file" msgstr "" #: data/extensions/custom-framerates/custom-framerates.py:40 #: data/ui/spell-check-dialog.ui:152 msgid "_Add" msgstr "" #: data/extensions/custom-framerates/custom-framerates.py:171 msgid "{:.3f} fps" msgstr "" #: data/extensions/custom-framerates/add-framerate-dialog.ui:13 msgid "Add Framerate" msgstr "" #: data/extensions/custom-framerates/add-framerate-dialog.ui:44 msgid "_Framerate:" msgstr "" #: data/extensions/custom-framerates/add-framerate-dialog.ui:73 msgid "fps" msgstr "" #: data/extensions/custom-framerates/preferences-dialog.ui:8 msgid "Framerates" msgstr "" #: data/extensions/custom-framerates/preferences-dialog.ui:64 msgid "Add" msgstr "" #: data/ui/columns-popup.ui:6 data/ui/menubar.ui:275 msgid "_No." msgstr "" #: data/ui/columns-popup.ui:10 data/ui/menubar.ui:279 msgid "_Start" msgstr "" #: data/ui/columns-popup.ui:14 data/ui/menubar.ui:283 msgid "_End" msgstr "" #: data/ui/columns-popup.ui:18 data/ui/menubar.ui:287 msgid "_Duration" msgstr "" #: data/ui/columns-popup.ui:22 data/ui/menubar.ui:291 data/ui/menubar.ui:303 msgid "_Text" msgstr "" #: data/ui/columns-popup.ui:26 data/ui/menubar.ui:295 msgid "T_ranslation" msgstr "" #: data/ui/split-dialog.ui:15 msgid "Split Project" msgstr "" #: data/ui/split-dialog.ui:48 msgid "_First subtitle of new project:" msgstr "" #: data/ui/search-dialog.ui:89 msgid "_Search for:" msgstr "" #: data/ui/search-dialog.ui:103 data/ui/spell-check-dialog.ui:193 msgid "Replace _with:" msgstr "" #: data/ui/search-dialog.ui:162 data/ui/menubar.ui:328 msgid "Find _Next" msgstr "" #: data/ui/search-dialog.ui:177 msgid "Find _Previous" msgstr "" #: data/ui/search-dialog.ui:207 msgid "Replace _All" msgstr "" #: data/ui/search-dialog.ui:241 msgid "R_egular expression" msgstr "" #: data/ui/search-dialog.ui:258 msgid "_Ignore case" msgstr "" #: data/ui/search-dialog.ui:304 data/ui/language-dialog.ui:108 msgid "Columns" msgstr "" #: data/ui/search-dialog.ui:324 msgid "Find in _text column" msgstr "" #: data/ui/search-dialog.ui:341 msgid "Find in t_ranslation column" msgstr "" #: data/ui/search-dialog.ui:381 data/ui/framerate-convert-dialog.ui:144 #: data/ui/language-dialog.ui:186 #: data/ui/text-assistant/line-break-options-page.ui:178 #: data/ui/duration-adjust-dialog.ui:388 data/ui/position-shift-dialog.ui:180 #: data/ui/position-transform-dialog.ui:444 msgid "Subtitles" msgstr "" #: data/ui/search-dialog.ui:401 msgid "Find in c_urrent project" msgstr "" #: data/ui/search-dialog.ui:419 msgid "Find in _all open projects" msgstr "" #: data/ui/search-dialog.ui:452 msgid "Target" msgstr "" #: data/ui/framerate-convert-dialog.ui:8 msgid "Convert Framerate" msgstr "" #: data/ui/framerate-convert-dialog.ui:48 msgid "Framerate" msgstr "" #: data/ui/framerate-convert-dialog.ui:71 msgid "_Input:" msgstr "" #: data/ui/framerate-convert-dialog.ui:86 msgid "_Output:" msgstr "" #: data/ui/framerate-convert-dialog.ui:164 msgid "Convert c_urrent project" msgstr "" #: data/ui/framerate-convert-dialog.ui:181 msgid "Convert _all open projects" msgstr "" #: data/ui/spell-check-dialog.ui:8 msgid "Check Spelling" msgstr "" #: data/ui/spell-check-dialog.ui:47 msgid "Join _Back" msgstr "" #: data/ui/spell-check-dialog.ui:62 msgid "Join _Forward" msgstr "" #: data/ui/spell-check-dialog.ui:77 data/ui/menubar.ui:62 msgid "_Edit" msgstr "" #: data/ui/spell-check-dialog.ui:92 msgid "_Ignore" msgstr "" #: data/ui/spell-check-dialog.ui:107 msgid "Ig_nore All" msgstr "" #: data/ui/spell-check-dialog.ui:137 msgid "Rep_lace All" msgstr "" #: data/ui/spell-check-dialog.ui:179 msgid "_Suggestions:" msgstr "" #: data/ui/multi-save-dialog.ui:8 msgid "Save All As" msgstr "" #: data/ui/multi-save-dialog.ui:46 msgid "Save in _folder:" msgstr "" #: data/ui/multi-save-dialog.ui:60 data/ui/save-dialog.ui:25 msgid "For_mat:" msgstr "" #: data/ui/multi-save-dialog.ui:74 data/ui/open-dialog.ui:25 #: data/ui/save-dialog.ui:39 msgid "_Encoding:" msgstr "" #: data/ui/multi-save-dialog.ui:88 data/ui/save-dialog.ui:53 msgid "Ne_wlines:" msgstr "" #: data/ui/multi-save-dialog.ui:103 msgid "Select A Folder" msgstr "" #: data/ui/multi-save-dialog.ui:150 data/ui/save-dialog.ui:102 msgid "F_ramerate:" msgstr "" #: data/ui/menubar.ui:5 msgid "_File" msgstr "" #: data/ui/menubar.ui:8 msgid "_New" msgstr "" #: data/ui/menubar.ui:12 msgid "_Open…" msgstr "" #: data/ui/menubar.ui:16 msgid "Open _Translation…" msgstr "" #: data/ui/menubar.ui:22 msgid "Open _Recent" msgstr "" #: data/ui/menubar.ui:27 msgid "Open R_ecent Translation" msgstr "" #: data/ui/menubar.ui:38 msgid "Save _As…" msgstr "" #: data/ui/menubar.ui:42 msgid "Save Trans_lation" msgstr "" #: data/ui/menubar.ui:46 msgid "Save Translat_ion As…" msgstr "" #: data/ui/menubar.ui:65 msgid "_Undo" msgstr "" #: data/ui/menubar.ui:69 msgid "_Redo" msgstr "" #: data/ui/menubar.ui:75 msgid "_Edit Cell" msgstr "" #: data/ui/menubar.ui:79 msgid "Edit _Next Cell" msgstr "" #: data/ui/menubar.ui:85 msgid "Stretc_h" msgstr "" #: data/ui/menubar.ui:88 msgid "_Start Earlier" msgstr "" #: data/ui/menubar.ui:92 msgid "S_tart Later" msgstr "" #: data/ui/menubar.ui:98 msgid "E_nd Earlier" msgstr "" #: data/ui/menubar.ui:102 msgid "En_d Later" msgstr "" #: data/ui/menubar.ui:108 msgid "Set St_art From Video Position" msgstr "" #: data/ui/menubar.ui:112 msgid "Set En_d From Video Position" msgstr "" #: data/ui/menubar.ui:118 data/ui/view-popup.ui:6 msgid "_Split Subtitle" msgstr "" #: data/ui/menubar.ui:122 data/ui/view-popup.ui:10 msgid "_Merge Subtitles" msgstr "" #: data/ui/menubar.ui:128 data/ui/view-popup.ui:16 msgid "_Insert Subtitles…" msgstr "" #: data/ui/menubar.ui:132 msgid "Inser_t Subtitle At Video Position" msgstr "" #: data/ui/menubar.ui:136 data/ui/view-popup.ui:20 msgid "Rem_ove Subtitles" msgstr "" #: data/ui/menubar.ui:142 msgid "Sele_ction" msgstr "" #: data/ui/menubar.ui:145 msgid "Select _All" msgstr "" #: data/ui/menubar.ui:149 msgid "_Invert Selection" msgstr "" #: data/ui/menubar.ui:155 msgid "Extend To _Beginning" msgstr "" #: data/ui/menubar.ui:159 msgid "Extend To _End" msgstr "" #: data/ui/menubar.ui:165 msgid "_Previous From Video Position" msgstr "" #: data/ui/menubar.ui:169 msgid "_Next From Video Position" msgstr "" #: data/ui/menubar.ui:177 msgid "_Preferences" msgstr "" #: data/ui/menubar.ui:183 msgid "_View" msgstr "" #: data/ui/menubar.ui:186 msgid "Tool_bar" msgstr "" #: data/ui/menubar.ui:190 msgid "_Video Player" msgstr "" #: data/ui/menubar.ui:196 msgid "_Layout" msgstr "" #: data/ui/menubar.ui:199 msgid "_Horizontal" msgstr "" #: data/ui/menubar.ui:204 msgid "_Vertical" msgstr "" #: data/ui/menubar.ui:213 msgid "_Times" msgstr "" #: data/ui/menubar.ui:218 msgid "_Frames" msgstr "" #: data/ui/menubar.ui:225 msgid "F_ramerate" msgstr "" #: data/ui/menubar.ui:228 msgid "2_3.976 fps" msgstr "" #: data/ui/menubar.ui:233 msgid "2_4.000 fps" msgstr "" #: data/ui/menubar.ui:238 msgid "2_5.000 fps" msgstr "" #: data/ui/menubar.ui:243 msgid "2_9.970 fps" msgstr "" #: data/ui/menubar.ui:272 msgid "_Columns" msgstr "" #: data/ui/menubar.ui:306 msgid "Cu_t" msgstr "" #: data/ui/menubar.ui:310 msgid "_Copy" msgstr "" #: data/ui/menubar.ui:314 msgid "_Paste" msgstr "" #: data/ui/menubar.ui:318 msgid "Cl_ear" msgstr "" #: data/ui/menubar.ui:324 msgid "_Find And Replace…" msgstr "" #: data/ui/menubar.ui:332 msgid "Find Pre_vious" msgstr "" #: data/ui/menubar.ui:338 msgid "_Italic" msgstr "" #: data/ui/menubar.ui:342 msgid "_Dialogue" msgstr "" #: data/ui/menubar.ui:348 msgid "Ca_se" msgstr "" #: data/ui/menubar.ui:351 msgid "_Title" msgstr "" #: data/ui/menubar.ui:355 msgid "_Sentence" msgstr "" #: data/ui/menubar.ui:359 msgid "_Upper" msgstr "" #: data/ui/menubar.ui:363 msgid "_Lower" msgstr "" #: data/ui/menubar.ui:371 msgid "Vi_deo" msgstr "" #: data/ui/menubar.ui:374 msgid "_Load Video…" msgstr "" #: data/ui/menubar.ui:384 data/ui/view-popup.ui:26 msgid "Play _Selection" msgstr "" #: data/ui/menubar.ui:410 data/ui/view-popup.ui:30 msgid "S_eek Selection Start" msgstr "" #: data/ui/menubar.ui:414 msgid "See_k Selection End" msgstr "" #: data/ui/menubar.ui:420 msgid "_Audio" msgstr "" #: data/ui/menubar.ui:423 msgid "_Language" msgstr "" #: data/ui/menubar.ui:430 msgid "Volume _Down" msgstr "" #: data/ui/menubar.ui:434 msgid "Volume _Up" msgstr "" #: data/ui/menubar.ui:440 msgid "T_ools" msgstr "" #: data/ui/menubar.ui:443 data/ui/text-assistant/confirmation-page.ui:97 #: data/ui/view-popup.ui:36 msgid "_Preview" msgstr "" #: data/ui/menubar.ui:447 msgid "Select _Video…" msgstr "" #: data/ui/menubar.ui:453 msgid "_Check Spelling" msgstr "" #: data/ui/menubar.ui:457 msgid "Co_nfigure Spell-check…" msgstr "" #: data/ui/menubar.ui:461 msgid "C_orrect Texts…" msgstr "" #: data/ui/menubar.ui:467 msgid "_Shift Positions…" msgstr "" #: data/ui/menubar.ui:471 msgid "_Transform Positions…" msgstr "" #: data/ui/menubar.ui:475 msgid "Adjust _Durations…" msgstr "" #: data/ui/menubar.ui:479 msgid "Convert _Framerate…" msgstr "" #: data/ui/menubar.ui:485 msgid "_Append File…" msgstr "" #: data/ui/menubar.ui:489 msgid "Spli_t Project…" msgstr "" #: data/ui/menubar.ui:495 msgid "_Projects" msgstr "" #: data/ui/menubar.ui:498 msgid "_Save All" msgstr "" #: data/ui/menubar.ui:502 msgid "Save _All As…" msgstr "" #: data/ui/menubar.ui:506 msgid "_Close All" msgstr "" #: data/ui/menubar.ui:512 msgid "_Previous" msgstr "" #: data/ui/menubar.ui:516 msgid "_Next" msgstr "" #: data/ui/menubar.ui:527 msgid "_Documentation" msgstr "" #: data/ui/menubar.ui:531 msgid "_Report A Bug" msgstr "" #: data/ui/menubar.ui:535 msgid "_About" msgstr "" #: data/ui/open-dialog.ui:39 msgid "Align _method:" msgstr "" #: data/ui/preferences-dialog.ui:18 msgid "Preferences" msgstr "" #: data/ui/preferences-dialog.ui:93 msgid "When opening files, try encodings in the following order:" msgstr "" #: data/ui/preferences-dialog.ui:104 msgid "Curr_ent locale encoding" msgstr "" #: data/ui/preferences-dialog.ui:130 msgid "_Fallback encodings:" msgstr "" #: data/ui/preferences-dialog.ui:246 msgid "Aut_o-detection" msgstr "" #: data/ui/preferences-dialog.ui:266 msgid "Encoding specified in the open dialog will always be tried first." msgstr "" #: data/ui/preferences-dialog.ui:296 msgid "File" msgstr "" #: data/ui/preferences-dialog.ui:324 msgid "Font" msgstr "" #: data/ui/preferences-dialog.ui:344 msgid "Use _default theme fixed width font" msgstr "" #: data/ui/preferences-dialog.ui:368 msgid "_Editor font:" msgstr "" #: data/ui/preferences-dialog.ui:425 msgid "Line Lengths" msgstr "" #: data/ui/preferences-dialog.ui:445 msgid "_Show line lengths in list cells" msgstr "" #: data/ui/preferences-dialog.ui:462 msgid "S_how line lengths in editable text fields" msgstr "" #: data/ui/preferences-dialog.ui:486 msgid "_Length unit:" msgstr "" #: data/ui/preferences-dialog.ui:540 msgid "Spell-Check" msgstr "" #: data/ui/preferences-dialog.ui:560 msgid "Chec_k spelling as you type" msgstr "" #: data/ui/preferences-dialog.ui:598 msgid "Editor" msgstr "" #: data/ui/preferences-dialog.ui:626 msgid "Fonts" msgstr "" #: data/ui/preferences-dialog.ui:649 msgid "_Subtitles:" msgstr "" #: data/ui/preferences-dialog.ui:679 msgid "_Time:" msgstr "" #: data/ui/preferences-dialog.ui:729 msgid "Colors" msgstr "" #: data/ui/preferences-dialog.ui:752 msgid "Su_btitles:" msgstr "" #: data/ui/preferences-dialog.ui:777 msgid "_Use a background behind text" msgstr "" #: data/ui/preferences-dialog.ui:797 msgid "Ti_me:" msgstr "" #: data/ui/preferences-dialog.ui:822 msgid "Us_e a background behind text" msgstr "" #: data/ui/preferences-dialog.ui:862 msgid "Seek" msgstr "" #: data/ui/preferences-dialog.ui:883 msgid "_Length:" msgstr "" #: data/ui/preferences-dialog.ui:971 msgid "Video Player" msgstr "" #: data/ui/preferences-dialog.ui:994 msgid "_Application:" msgstr "" #: data/ui/preferences-dialog.ui:1008 msgid "Co_mmand:" msgstr "" #. Translators: Only the title is to be translated, field names not. #: data/ui/preferences-dialog.ui:1033 msgid "" "Fields:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" msgstr "" #: data/ui/preferences-dialog.ui:1048 msgid "Al_ways use UTF-8 character encoding" msgstr "" #: data/ui/preferences-dialog.ui:1089 msgid "Start Position" msgstr "" #: data/ui/preferences-dialog.ui:1111 msgid "_Offset:" msgstr "" #: data/ui/preferences-dialog.ui:1142 msgid "seconds before selection" msgstr "" #: data/ui/preferences-dialog.ui:1281 msgid "Extensions" msgstr "" #: data/ui/language-dialog.ui:8 msgid "Configure Spell-Check" msgstr "" #: data/ui/language-dialog.ui:50 msgid "Language" msgstr "" #: data/ui/language-dialog.ui:128 msgid "Check _text column" msgstr "" #: data/ui/language-dialog.ui:146 msgid "Check t_ranslation column" msgstr "" #: data/ui/language-dialog.ui:206 msgid "Check c_urrent project" msgstr "" #: data/ui/language-dialog.ui:224 msgid "Check _all open projects" msgstr "" #: data/ui/text-assistant/confirmation-page.ui:22 msgid "Acc_ept, discard or edit changes:" msgstr "" #: data/ui/text-assistant/confirmation-page.ui:67 msgid "_Mark All" msgstr "" #: data/ui/text-assistant/confirmation-page.ui:82 msgid "_Unmark All" msgstr "" #: data/ui/text-assistant/confirmation-page.ui:119 msgid "_Remove all blank subtitles" msgstr "" #: data/ui/text-assistant/join-split-page.ui:28 msgid "Spell-Check Dictionary" msgstr "" #: data/ui/text-assistant/join-split-page.ui:49 #: data/ui/text-assistant/line-break-page.ui:81 #: data/ui/text-assistant/hearing-impaired-page.ui:81 #: data/ui/text-assistant/common-error-page.ui:80 #: data/ui/text-assistant/capitalization-page.ui:80 msgid "_Language:" msgstr "" #: data/ui/text-assistant/join-split-page.ui:97 msgid "Corrections" msgstr "" #: data/ui/text-assistant/join-split-page.ui:117 msgid "_Join words not found in spell-check dictionary" msgstr "" #: data/ui/text-assistant/join-split-page.ui:134 msgid "_Split words not found in spell-check dictionary" msgstr "" #: data/ui/text-assistant/line-break-page.ui:22 msgid "S_elect preferred line-break points:" msgstr "" #: data/ui/text-assistant/line-break-page.ui:67 #: data/ui/text-assistant/hearing-impaired-page.ui:67 #: data/ui/text-assistant/common-error-page.ui:66 #: data/ui/text-assistant/capitalization-page.ui:66 msgid "_Script:" msgstr "" #: data/ui/text-assistant/line-break-page.ui:95 #: data/ui/text-assistant/hearing-impaired-page.ui:95 #: data/ui/text-assistant/common-error-page.ui:94 #: data/ui/text-assistant/capitalization-page.ui:94 msgid "Co_untry:" msgstr "" #: data/ui/text-assistant/introduction-page.ui:28 msgid "_Select corrections to perform on texts:" msgstr "" #: data/ui/text-assistant/introduction-page.ui:79 msgid "Colu_mns:" msgstr "" #: data/ui/text-assistant/introduction-page.ui:93 msgid "S_ubtitles:" msgstr "" #: data/ui/text-assistant/line-break-options-page.ui:56 #: data/ui/duration-adjust-dialog.ui:207 msgid "Limits" msgstr "" #: data/ui/text-assistant/line-break-options-page.ui:79 msgid "_Maximum line length:" msgstr "" #: data/ui/text-assistant/line-break-options-page.ui:93 msgid "_Preferred maximum amount of lines:" msgstr "" #: data/ui/text-assistant/line-break-options-page.ui:198 msgid "_Skip subtitles with maximum line length of:" msgstr "" #: data/ui/text-assistant/line-break-options-page.ui:214 msgid "S_kip subtitles with maximum line amount of:" msgstr "" #: data/ui/text-assistant/hearing-impaired-page.ui:22 msgid "S_elect parts to remove:" msgstr "" #: data/ui/text-assistant/common-error-page.ui:22 msgid "S_elect errors to correct:" msgstr "" #: data/ui/text-assistant/common-error-page.ui:108 msgid "Error types:" msgstr "" #: data/ui/text-assistant/common-error-page.ui:158 msgid "_Human errors" msgstr "" #: data/ui/text-assistant/common-error-page.ui:175 msgid "_Image recognition errors" msgstr "" #: data/ui/text-assistant/capitalization-page.ui:22 msgid "S_elect parts to capitalize:" msgstr "" #: data/ui/duration-adjust-dialog.ui:33 msgid "Adjust Durations" msgstr "" #: data/ui/duration-adjust-dialog.ui:73 msgid "Theoretic Duration" msgstr "" #: data/ui/duration-adjust-dialog.ui:101 msgid "_Reading speed:" msgstr "" #: data/ui/duration-adjust-dialog.ui:133 msgid "characters per second" msgstr "" #: data/ui/duration-adjust-dialog.ui:150 msgid "_Lengthen duration to match reading speed" msgstr "" #: data/ui/duration-adjust-dialog.ui:167 msgid "_Shorten duration to match reading speed" msgstr "" #: data/ui/duration-adjust-dialog.ui:227 msgid "_Minimum duration:" msgstr "" #: data/ui/duration-adjust-dialog.ui:243 msgid "Ma_ximum duration:" msgstr "" #: data/ui/duration-adjust-dialog.ui:259 msgid "_Gap between subtitles:" msgstr "" #: data/ui/duration-adjust-dialog.ui:294 msgid "s_econds" msgstr "" #: data/ui/duration-adjust-dialog.ui:324 msgid "seco_nds" msgstr "" #: data/ui/duration-adjust-dialog.ui:354 msgid "secon_ds" msgstr "" #: data/ui/duration-adjust-dialog.ui:408 msgid "Adj_ust selected subtitles" msgstr "" #: data/ui/duration-adjust-dialog.ui:425 msgid "Adjus_t current project" msgstr "" #: data/ui/duration-adjust-dialog.ui:442 msgid "Adjust all _open projects" msgstr "" #: data/ui/tab-popup.ui:6 msgid "Move Tab _Left" msgstr "" #: data/ui/tab-popup.ui:10 msgid "Move Tab _Right" msgstr "" #: data/ui/insert-dialog.ui:15 msgid "Insert Subtitles" msgstr "" #: data/ui/insert-dialog.ui:48 data/ui/position-shift-dialog.ui:82 msgid "_Amount:" msgstr "" #: data/ui/insert-dialog.ui:62 msgid "_Position:" msgstr "" #: data/ui/position-shift-dialog.ui:14 msgid "Shift Positions" msgstr "" #: data/ui/position-shift-dialog.ui:54 msgid "Shift" msgstr "" #: data/ui/position-shift-dialog.ui:135 #: data/ui/position-transform-dialog.ui:208 msgid "_Preview Changes" msgstr "" #: data/ui/position-shift-dialog.ui:200 msgid "Shift s_elected subtitles" msgstr "" #: data/ui/position-shift-dialog.ui:217 msgid "Shift su_btitles from selection to end" msgstr "" #: data/ui/position-shift-dialog.ui:234 msgid "Shift c_urrent project" msgstr "" #: data/ui/position-shift-dialog.ui:251 msgid "Shift all _open projects" msgstr "" #: data/ui/position-transform-dialog.ui:22 msgid "Transform Positions" msgstr "" #: data/ui/position-transform-dialog.ui:62 msgid "First Point" msgstr "" #: data/ui/position-transform-dialog.ui:91 msgid "_Subtitle:" msgstr "" #: data/ui/position-transform-dialog.ui:105 msgid "C_orrection:" msgstr "" #: data/ui/position-transform-dialog.ui:119 #: data/ui/position-transform-dialog.ui:310 msgid "Text:" msgstr "" #: data/ui/position-transform-dialog.ui:253 msgid "Second Point" msgstr "" #: data/ui/position-transform-dialog.ui:282 msgid "Su_btitle:" msgstr "" #: data/ui/position-transform-dialog.ui:296 msgid "Co_rrection:" msgstr "" #: data/ui/position-transform-dialog.ui:399 msgid "Pre_view Changes" msgstr "" #: data/ui/position-transform-dialog.ui:464 msgid "Transform se_lected subtitles" msgstr "" #: data/ui/position-transform-dialog.ui:482 msgid "Transform c_urrent project" msgstr "" #: data/extensions/custom-framerates/custom-framerates.extension.in:7 msgid "Custom Framerates" msgstr "" #: data/extensions/custom-framerates/custom-framerates.extension.in:8 msgid "Allow use of non-standard framerates" msgstr "" #: data/patterns/Latn-en-US.common-error.in:5 msgid "Period after title" msgstr "" #: data/patterns/Latn-en-US.common-error.in:6 msgid "Add period after a shortened title, such as \"Mr\" and \"Dr\"" msgstr "" #: data/patterns/Latn-en.capitalization.in:5 msgid "First person pronoun" msgstr "" #: data/patterns/Latn-en.capitalization.in:6 msgid "Capitalize the first person pronoun \"I\"" msgstr "" #: data/patterns/Latn-en.common-error.in:5 #: data/patterns/Latn-en.common-error.in:14 #: data/patterns/Latn-en.common-error.in:23 msgid "Letter \"I\" in a lower case word" msgstr "" #: data/patterns/Latn-en.common-error.in:6 #: data/patterns/Latn-en.common-error.in:15 #: data/patterns/Latn-en.common-error.in:24 msgid "Replace letter \"I\" with letter \"l\" in a lower case word" msgstr "" #: data/patterns/Latn-en.common-error.in:32 #: data/patterns/Latn-en.common-error.in:41 #: data/patterns/Latn-en.common-error.in:50 #: data/patterns/Latn-en.common-error.in:62 msgid "Letter \"l\" in an upper case word" msgstr "" #: data/patterns/Latn-en.common-error.in:33 #: data/patterns/Latn-en.common-error.in:42 #: data/patterns/Latn-en.common-error.in:51 #: data/patterns/Latn-en.common-error.in:63 msgid "Replace letter \"l\" with letter \"I\" in an upper case word" msgstr "" #: data/patterns/Latn-en.common-error.in:73 #: data/patterns/Latn-en.common-error.in:82 msgid "Zero in an upper case word" msgstr "" #: data/patterns/Latn-en.common-error.in:74 #: data/patterns/Latn-en.common-error.in:83 msgid "Replace zero with letter \"O\" in an upper case word" msgstr "" #: data/patterns/Latn-en.common-error.in:91 #: data/patterns/Latn.common-error.in:108 msgid "Space between number and unit" msgstr "" #: data/patterns/Latn-en.common-error.in:92 #: data/patterns/Latn.common-error.in:109 msgid "Add or remove space between a number and the associated unit" msgstr "" #: data/patterns/Latn-en.common-error.in:100 msgid "Spaces around an apostrophe" msgstr "" #: data/patterns/Latn-en.common-error.in:101 msgid "Remove spaces around an apostrophe" msgstr "" #: data/patterns/Latn-en.common-error.in:109 #: data/patterns/Latn-en.common-error.in:118 msgid "Okay" msgstr "" #: data/patterns/Latn-en.common-error.in:110 #: data/patterns/Latn-en.common-error.in:119 msgid "Spell two-letter forms of \"okay\" in all upper case" msgstr "" #: data/patterns/Latn-en.hearing-impaired.in:5 msgid "Uppercase speaker before a colon" msgstr "" #: data/patterns/Latn-en.hearing-impaired.in:6 msgid "" "Replace the uppercase name of the speaker before a colon with a dialogue dash" msgstr "" #: data/patterns/Latn-en.line-break.in:5 msgid "Title" msgstr "" #: data/patterns/Latn-en.line-break.in:6 msgid "Do not break after a title, e.g. \" Dr.\"" msgstr "" #: data/patterns/Latn-en.line-break.in:13 msgid "Article" msgstr "" #: data/patterns/Latn-en.line-break.in:14 msgid "Do not break after an article" msgstr "" #: data/patterns/Latn-en.line-break.in:21 msgid "Preposition" msgstr "" #: data/patterns/Latn-en.line-break.in:22 msgid "Do not break after a preposition" msgstr "" #: data/patterns/Latn-en.line-break.in:30 msgid "Possessive determiner" msgstr "" #: data/patterns/Latn-en.line-break.in:31 msgid "Do not break after a possessive determiner, e.g. \"my\"" msgstr "" #: data/patterns/Latn-fi.common-error.in:5 #: data/patterns/Latn.common-error.in:182 msgid "Space after punctuation marks" msgstr "" #: data/patterns/Latn-fi.common-error.in:6 #: data/patterns/Latn.common-error.in:183 msgid "Add space after various punctuation marks" msgstr "" #: data/patterns/Latn-fr.common-error.in:5 #: data/patterns/Latn-fr.common-error.in:14 #: data/patterns/Latn-fr.common-error.in:23 #: data/patterns/Latn-fr.common-error.in:32 msgid "Spaces around guillemets" msgstr "" #: data/patterns/Latn-fr.common-error.in:6 #: data/patterns/Latn-fr.common-error.in:15 #: data/patterns/Latn-fr.common-error.in:24 #: data/patterns/Latn-fr.common-error.in:33 msgid "Add spaces around guillemets" msgstr "" #: data/patterns/Latn-fr.common-error.in:41 #: data/patterns/Latn-fr.common-error.in:52 #: data/patterns/Latn.common-error.in:171 msgid "Space before punctuation marks" msgstr "" #: data/patterns/Latn-fr.common-error.in:42 #: data/patterns/Latn-fr.common-error.in:53 msgid "Add or remove space before various punctuation marks" msgstr "" #: data/patterns/Latn.capitalization.in:5 msgid "Sentence" msgstr "" #: data/patterns/Latn.capitalization.in:6 msgid "Capitalize the first word of a sentence" msgstr "" #: data/patterns/Latn.capitalization.in:12 msgid "Ellipsis" msgstr "" #: data/patterns/Latn.capitalization.in:13 msgid "Capitalize after an ellipsis" msgstr "" #: data/patterns/Latn.common-error.in:8 data/patterns/Latn.common-error.in:17 #: data/patterns/Latn.common-error.in:26 data/patterns/Latn.common-error.in:35 #: data/patterns/Latn.common-error.in:44 data/patterns/Latn.common-error.in:53 #: data/patterns/Latn.common-error.in:62 msgid "Ligatures" msgstr "" #: data/patterns/Latn.common-error.in:9 data/patterns/Latn.common-error.in:18 #: data/patterns/Latn.common-error.in:27 data/patterns/Latn.common-error.in:36 #: data/patterns/Latn.common-error.in:45 data/patterns/Latn.common-error.in:54 #: data/patterns/Latn.common-error.in:63 msgid "Unpack ligatures to individual characters" msgstr "" #: data/patterns/Latn.common-error.in:71 data/patterns/Latn.common-error.in:80 msgid "Spelling of a.m. and p.m." msgstr "" #: data/patterns/Latn.common-error.in:72 data/patterns/Latn.common-error.in:81 msgid "" "Change the various spellings of 12-hour periods to \"a.m.\" and \"p.m.\"" msgstr "" #: data/patterns/Latn.common-error.in:89 data/patterns/Latn.common-error.in:98 msgid "Letter \"O\" in a number" msgstr "" #: data/patterns/Latn.common-error.in:90 data/patterns/Latn.common-error.in:99 msgid "Replace letter \"O\" with a zero in a number" msgstr "" #: data/patterns/Latn.common-error.in:117 msgid "Double apostrophe" msgstr "" #: data/patterns/Latn.common-error.in:118 msgid "Replace a double apostrophe with a quotation mark" msgstr "" #: data/patterns/Latn.common-error.in:126 #: data/patterns/Latn.common-error.in:135 #: data/patterns/Latn.common-error.in:144 #: data/patterns/Latn.common-error.in:153 msgid "Spaces around brackets" msgstr "" #: data/patterns/Latn.common-error.in:127 #: data/patterns/Latn.common-error.in:136 #: data/patterns/Latn.common-error.in:145 #: data/patterns/Latn.common-error.in:154 msgid "Add or remove spaces around parantheses and square brackets" msgstr "" #: data/patterns/Latn.common-error.in:162 msgid "Space after a dialogue dash" msgstr "" #: data/patterns/Latn.common-error.in:163 msgid "Add space after a dialogue dash" msgstr "" #: data/patterns/Latn.common-error.in:172 msgid "Remove space before various punctuation marks" msgstr "" #: data/patterns/Latn.common-error.in:192 msgid "Space after an ellipsis" msgstr "" #: data/patterns/Latn.common-error.in:193 msgid "Add space after an ellipsis" msgstr "" #: data/patterns/Latn.common-error.in:201 msgid "Space after a starting ellipsis" msgstr "" #: data/patterns/Latn.common-error.in:202 msgid "Remove space after an ellipsis that starts a line" msgstr "" #: data/patterns/Latn.common-error.in:210 #: data/patterns/Latn.common-error.in:221 #: data/patterns/Latn.common-error.in:232 #: data/patterns/Latn.common-error.in:242 msgid "Spaces around a quotation mark" msgstr "" #: data/patterns/Latn.common-error.in:211 #: data/patterns/Latn.common-error.in:222 #: data/patterns/Latn.common-error.in:233 #: data/patterns/Latn.common-error.in:243 msgid "Remove space after a starting- and before an ending quotation mark" msgstr "" #: data/patterns/Latn.common-error.in:252 #: data/patterns/Latn.common-error.in:261 msgid "Spaces around musical notes" msgstr "" #: data/patterns/Latn.common-error.in:253 #: data/patterns/Latn.common-error.in:262 msgid "Add spaces between musical note characters and lyrics" msgstr "" #: data/patterns/Latn.common-error.in:270 #: data/patterns/Latn.common-error.in:279 msgid "Multiple question- and exclamation marks" msgstr "" #: data/patterns/Latn.common-error.in:271 #: data/patterns/Latn.common-error.in:280 msgid "" "Replace multiple consequtive question- and exclamation marks with only one" msgstr "" #: data/patterns/Latn.common-error.in:288 #: data/patterns/Latn.common-error.in:298 msgid "Periods around a punctuation mark" msgstr "" #: data/patterns/Latn.common-error.in:289 #: data/patterns/Latn.common-error.in:299 msgid "Remove period before or after various punctuation marks" msgstr "" #: data/patterns/Latn.common-error.in:308 msgid "Terminating double-dashes" msgstr "" #: data/patterns/Latn.common-error.in:309 msgid "Replace a single clause-terminating dash with two dashes" msgstr "" #: data/patterns/Latn.hearing-impaired.in:5 msgid "Sound in brackets" msgstr "" #: data/patterns/Latn.hearing-impaired.in:6 msgid "Remove description of a sound between square brackets" msgstr "" #: data/patterns/Latn.hearing-impaired.in:12 msgid "Sound in parantheses" msgstr "" #: data/patterns/Latn.hearing-impaired.in:13 msgid "Remove description of a sound between parantheses" msgstr "" #: data/patterns/Latn.hearing-impaired.in:19 msgid "Song lyrics between number signs" msgstr "" #: data/patterns/Latn.hearing-impaired.in:20 msgid "Remove song lyrics starting with or between number signs" msgstr "" #: data/patterns/Latn.hearing-impaired.in:27 msgid "One-line song lyrics between number signs" msgstr "" #: data/patterns/Latn.hearing-impaired.in:28 msgid "Remove one-line song lyrics starting with or between number signs" msgstr "" #: data/patterns/Latn.hearing-impaired.in:35 msgid "Speaker before a colon" msgstr "" #: data/patterns/Latn.hearing-impaired.in:36 msgid "Replace the name of the speaker before a colon with a dialogue dash" msgstr "" #: data/patterns/Latn.line-break.in:5 data/patterns/Latn.line-break.in:13 msgid "Dialogue" msgstr "" #: data/patterns/Latn.line-break.in:6 data/patterns/Latn.line-break.in:14 msgid "Break according to dialogue separated by dashes" msgstr "" #: data/patterns/Latn.line-break.in:21 data/patterns/Latn.line-break.in:30 msgid "Clause" msgstr "" #: data/patterns/Latn.line-break.in:22 data/patterns/Latn.line-break.in:31 msgid "Break according to clauses terminated by a punctuation mark" msgstr "" #: data/patterns/Latn.line-break.in:38 msgid "Number and unit" msgstr "" #: data/patterns/Latn.line-break.in:39 msgid "Do not break between a number and associated unit" msgstr "" #: data/patterns/Zyyy.common-error.in:5 data/patterns/Zyyy.common-error.in:14 msgid "Leading and trailing spaces" msgstr "" #: data/patterns/Zyyy.common-error.in:6 data/patterns/Zyyy.common-error.in:15 msgid "Remove spaces from the beginning and end of lines" msgstr "" #: data/patterns/Zyyy.common-error.in:23 msgid "Multiple consecutive spaces" msgstr "" #: data/patterns/Zyyy.common-error.in:24 msgid "Replace multiple consecutive spaces with only one" msgstr "" #: data/patterns/Zyyy.common-error.in:32 data/patterns/Zyyy.common-error.in:45 #: data/patterns/Zyyy.common-error.in:55 data/patterns/Zyyy.common-error.in:65 msgid "Space between digits" msgstr "" #: data/patterns/Zyyy.common-error.in:33 data/patterns/Zyyy.common-error.in:46 #: data/patterns/Zyyy.common-error.in:56 data/patterns/Zyyy.common-error.in:66 msgid "Remove space between digits of a number" msgstr "" #: data/patterns/Zyyy.common-error.in:79 msgid "Musical notes" msgstr "" #: data/patterns/Zyyy.common-error.in:80 msgid "Replace Unicode musical note characters with number signs" msgstr "" #: data/io.otsaloma.gaupol.appdata.xml.in:7 msgid "Editor for text-based subtitles" msgstr "" #: data/io.otsaloma.gaupol.appdata.xml.in:9 msgid "" "Gaupol is an editor for text-based subtitle files. It supports multiple " "subtitle file formats and provides means of creating subtitles, editing " "texts and timing subtitles to match video." msgstr "" #: data/io.otsaloma.gaupol.appdata.xml.in:40 msgid "Main window" msgstr "" #: data/io.otsaloma.gaupol.desktop.in:5 msgid "Subtitle Editor" msgstr "" #: data/io.otsaloma.gaupol.desktop.in:6 msgid "Edit subtitle files" msgstr "" #. TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! #: data/io.otsaloma.gaupol.desktop.in:12 msgid "video;subtitles;captions;" msgstr "" gaupol-1.11/po/gl.po000066400000000000000000002143151422217132500143100ustar00rootroot00000000000000# 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. # # Translators: # Osmo Salomaa , 2016 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-04-03 04:00+0300\n" "PO-Revision-Date: 2016-07-07 00:55+0000\n" "Last-Translator: Osmo Salomaa , 2016\n" "Language-Team: Galician (https://www.transifex.com/otsaloma/teams/64879/gl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: gl\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: aeidon/enums.py:40 gaupol/enums.py:38 msgid "Subtitle number" msgstr "Número de subtítulo" #: aeidon/enums.py:43 msgid "Subtitle position" msgstr "Posición do subtítulo" #: aeidon/enums.py:59 msgid "23.976 fps" msgstr "23,976 fps" #: aeidon/enums.py:63 msgid "24.000 fps" msgstr "24,000 fps" #: aeidon/enums.py:67 msgid "25.000 fps" msgstr "25,000 fps" #: aeidon/enums.py:71 msgid "29.970 fps" msgstr "29,970 fps" #: aeidon/enums.py:75 data/ui/menubar.ui:248 msgid "30.000 fps" msgstr "" #: aeidon/enums.py:79 data/ui/menubar.ui:253 msgid "50.000 fps" msgstr "" #: aeidon/enums.py:83 data/ui/menubar.ui:258 msgid "59.940 fps" msgstr "" #: aeidon/enums.py:87 data/ui/menubar.ui:263 msgid "60.000 fps" msgstr "" #: aeidon/enums.py:112 msgid "Mac (classic)" msgstr "Mac (clásico)" #. TRANSLATORS: Most of the character encoding descriptions are copied from #. gedit, which is translated to very many languages. Check the gedit .po #. files for a reference: #. . #: aeidon/encodings.py:40 aeidon/encodings.py:43 aeidon/encodings.py:46 msgid "English" msgstr "Inglés" #: aeidon/encodings.py:41 aeidon/encodings.py:42 aeidon/encodings.py:69 msgid "Chinese traditional" msgstr "Chinés tradicional" #: aeidon/encodings.py:44 msgid "German" msgstr "" #: aeidon/encodings.py:45 aeidon/encodings.py:54 aeidon/encodings.py:59 #: aeidon/encodings.py:79 aeidon/encodings.py:105 msgid "Hebrew" msgstr "Hebreo" #: aeidon/encodings.py:47 aeidon/encodings.py:51 aeidon/encodings.py:56 #: aeidon/encodings.py:73 aeidon/encodings.py:76 aeidon/encodings.py:98 #: aeidon/encodings.py:111 aeidon/encodings.py:122 msgid "Western" msgstr "Occidental" #: aeidon/encodings.py:48 aeidon/encodings.py:61 aeidon/encodings.py:80 #: aeidon/encodings.py:103 msgid "Arabic" msgstr "Árabe" #: aeidon/encodings.py:49 aeidon/encodings.py:64 aeidon/encodings.py:66 #: aeidon/encodings.py:77 aeidon/encodings.py:104 aeidon/encodings.py:119 msgid "Greek" msgstr "Grego" #: aeidon/encodings.py:50 aeidon/encodings.py:81 aeidon/encodings.py:101 #: aeidon/encodings.py:109 msgid "Baltic" msgstr "Báltico" #: aeidon/encodings.py:52 aeidon/encodings.py:74 aeidon/encodings.py:99 #: aeidon/encodings.py:121 msgid "Central European" msgstr "Centroeuropeo" #: aeidon/encodings.py:53 aeidon/encodings.py:75 aeidon/encodings.py:102 #: aeidon/encodings.py:118 msgid "Cyrillic" msgstr "Cirílico" #: aeidon/encodings.py:55 aeidon/encodings.py:71 aeidon/encodings.py:78 #: aeidon/encodings.py:106 aeidon/encodings.py:123 msgid "Turkish" msgstr "Turco" #: aeidon/encodings.py:57 msgid "Portuguese" msgstr "Portugués" #: aeidon/encodings.py:58 aeidon/encodings.py:120 msgid "Icelandic" msgstr "Islandés" #: aeidon/encodings.py:60 msgid "Canadian" msgstr "Canadense" #: aeidon/encodings.py:62 aeidon/encodings.py:107 msgid "Nordic" msgstr "Nórdico" #: aeidon/encodings.py:63 aeidon/encodings.py:114 msgid "Russian" msgstr "Ruso" #: aeidon/encodings.py:65 aeidon/encodings.py:108 msgid "Thai" msgstr "Tailandés" #: aeidon/encodings.py:67 aeidon/encodings.py:83 aeidon/encodings.py:84 #: aeidon/encodings.py:85 aeidon/encodings.py:91 aeidon/encodings.py:92 #: aeidon/encodings.py:93 aeidon/encodings.py:94 aeidon/encodings.py:95 #: aeidon/encodings.py:96 aeidon/encodings.py:125 aeidon/encodings.py:126 #: aeidon/encodings.py:127 msgid "Japanese" msgstr "Xaponés" #: aeidon/encodings.py:68 aeidon/encodings.py:86 aeidon/encodings.py:97 #: aeidon/encodings.py:113 msgid "Korean" msgstr "Coreano" #: aeidon/encodings.py:70 msgid "Urdu" msgstr "Urdu" #: aeidon/encodings.py:72 aeidon/encodings.py:116 msgid "Ukrainian" msgstr "Ucraíno" #: aeidon/encodings.py:82 msgid "Vietnamese" msgstr "Vietnamita" #: aeidon/encodings.py:87 aeidon/encodings.py:90 msgid "Chinese simplified" msgstr "Chinés simplificado" #: aeidon/encodings.py:88 aeidon/encodings.py:89 msgid "Chinese unified" msgstr "Chinés unificado" #: aeidon/encodings.py:100 aeidon/encodings.py:112 msgid "South European" msgstr "Sureuropeo" #: aeidon/encodings.py:110 msgid "Celtic" msgstr "Celta" #: aeidon/encodings.py:115 msgid "Tajik" msgstr "" #: aeidon/encodings.py:117 msgid "Kazakh" msgstr "" #: aeidon/encodings.py:124 msgid "Cyrillic Asian" msgstr "Cirílico asiático" #: aeidon/encodings.py:128 aeidon/encodings.py:129 aeidon/encodings.py:130 #: aeidon/encodings.py:131 aeidon/encodings.py:132 aeidon/encodings.py:133 #: aeidon/encodings.py:134 aeidon/encodings.py:135 aeidon/encodings.py:136 msgid "Unicode" msgstr "Unicode" #: aeidon/encodings.py:156 #, python-brace-format msgid "{description} ({name})" msgstr "{description} ({name})" #: aeidon/encodings.py:232 msgid "Current locale ({})" msgstr "Configuración rexional actual ({})" #: aeidon/locales.py:46 #, python-brace-format msgid "{language} ({country})" msgstr "{language} ({country})" #: aeidon/agents/search.py:227 msgid "Replacing" msgstr "Substituír" #: aeidon/agents/search.py:256 aeidon/agents/search.py:258 msgid "Replacing all" msgstr "Substituír todo" #: aeidon/agents/position.py:74 msgid "Adjusting durations" msgstr "Axustar as duracións" #: aeidon/agents/position.py:96 msgid "Converting framerate" msgstr "Converter a taxa de fotogramas" #: aeidon/agents/position.py:146 msgid "Setting framerate" msgstr "Definir a taxa de fotogramas" #: aeidon/agents/position.py:168 msgid "Shifting positions" msgstr "Desprazar as posicións" #: aeidon/agents/position.py:188 msgid "Transforming positions" msgstr "Transformar as posicións" #: aeidon/agents/clipboard.py:44 msgid "Cutting texts" msgstr "Cortar textos" #: aeidon/agents/clipboard.py:61 msgid "Pasting texts" msgstr "Pegar textos" #: aeidon/agents/text.py:91 msgid "Breaking lines" msgstr "Quebrar liñas" #: aeidon/agents/text.py:128 msgid "Capitalizing texts" msgstr "" #: aeidon/agents/text.py:185 msgid "Correcting common errors" msgstr "Corrixir erros comúns" #: aeidon/agents/text.py:234 msgid "Removing hearing impaired texts" msgstr "Retirar textos para xordos" #: aeidon/agents/text.py:315 msgid "Joining words by spell-check suggestions" msgstr "" #: aeidon/agents/text.py:354 msgid "Splitting words by spell-check suggestions" msgstr "" #: aeidon/agents/set.py:58 aeidon/agents/set.py:80 aeidon/agents/set.py:113 msgid "Editing position" msgstr "Editar a posición" #: aeidon/agents/set.py:129 msgid "Editing text" msgstr "Editar texto" #: aeidon/agents/edit.py:35 msgid "Clearing texts" msgstr "Limpar textos" #: aeidon/agents/edit.py:61 aeidon/agents/edit.py:83 msgid "Inserting subtitles" msgstr "Inserir subtítulos" #: aeidon/agents/edit.py:103 msgid "Merging subtitles" msgstr "Combinar subt" #: aeidon/agents/edit.py:114 msgid "Removing subtitles" msgstr "Retirar subtítulos" #: aeidon/agents/edit.py:131 msgid "Replacing positions" msgstr "Substituír posicións" #: aeidon/agents/edit.py:147 msgid "Replacing texts" msgstr "Substituír textos" #: aeidon/agents/edit.py:171 msgid "Splitting subtitle" msgstr "Dividir subtítulos" #: aeidon/agents/format.py:49 msgid "Adding dialogue dashes" msgstr "Engadir trazos de diálogo" #: aeidon/agents/format.py:68 msgid "Changing case" msgstr "Cambiar maiúsculas/minúsculas" #: aeidon/agents/format.py:92 msgid "Italicizing" msgstr "Pór en cursiva" #: aeidon/agents/format.py:108 msgid "Removing dialogue dashes" msgstr "Retirar trazos de diálogo" #: aeidon/agents/format.py:174 msgid "Unitalicizing" msgstr "Retirar a cursiva" #: gaupol/application.py:219 gaupol/agents/open.py:203 msgid "Open" msgstr "Abrir" #: gaupol/application.py:223 msgid "Open main files" msgstr "Abrir ficheiros principais" #: gaupol/application.py:230 msgid "Save" msgstr "" #: gaupol/application.py:233 msgid "Save the current main document" msgstr "Gardar o documento principal actual" #: gaupol/application.py:238 msgid "Undo" msgstr "" #: gaupol/application.py:242 msgid "Undo the last action" msgstr "Desfacer a última acción" #: gaupol/application.py:249 msgid "Redo" msgstr "" #: gaupol/application.py:252 msgid "Redo the last undone action" msgstr "Refacer a última acción desfeita" #: gaupol/application.py:260 msgid "Insert" msgstr "Inserir" #: gaupol/application.py:262 msgid "Insert new subtitles" msgstr "Inserir novos subtítulos" #: gaupol/application.py:266 #: data/extensions/custom-framerates/preferences-dialog.ui:78 msgid "Remove" msgstr "Retirar" #: gaupol/application.py:268 msgid "Remove the selected subtitles" msgstr "Retirar os subtítulos seleccionados" #: gaupol/application.py:273 data/ui/search-dialog.ui:283 msgid "Find" msgstr "Buscar" #: gaupol/application.py:275 msgid "Search for and replace text" msgstr "Buscar e substituír texto" #: gaupol/application.py:279 data/ui/preferences-dialog.ui:942 msgid "Video" msgstr "Vídeo" #: gaupol/application.py:281 msgid "Show or hide the video player" msgstr "Mostrar ou ocultar o reprodutor de vídeo" #: gaupol/application.py:285 data/ui/preferences-dialog.ui:1173 msgid "Preview" msgstr "" #: gaupol/application.py:287 msgid "Preview from selected position with a video player" msgstr "" #: gaupol/enums.py:37 msgid "No." msgstr "Nº" #: gaupol/enums.py:43 msgid "Start" msgstr "Inicio" #: gaupol/enums.py:44 msgid "Start position" msgstr "Posición inicial" #: gaupol/enums.py:49 msgid "End" msgstr "Fin" #: gaupol/enums.py:50 msgid "End position" msgstr "Posición final" #. TRANSLATORS: 'Dur.' is short for duration. It is used in the header #. of a column that contains numbers five digits wide. #: gaupol/enums.py:57 msgid "Dur." msgstr "Dur." #: gaupol/enums.py:58 msgid "Duration" msgstr "Duración" #: gaupol/enums.py:63 gaupol/enums.py:64 msgid "Text" msgstr "" #: gaupol/enums.py:69 gaupol/enums.py:70 msgid "Translation" msgstr "" #: gaupol/enums.py:82 msgid "characters" msgstr "caracteres" #: gaupol/enums.py:85 msgid "ems" msgstr "ems" #: gaupol/page.py:60 msgid "Untitled {:d}" msgstr "Sen nome {:d}" #: gaupol/page.py:133 msgid "Close project" msgstr "Pechar o proxecto" #: gaupol/page.py:145 msgid "{} translation" msgstr "tradución de {}" #: gaupol/page.py:302 msgid "Path:" msgstr "Ruta:" #: gaupol/page.py:303 msgid "Format:" msgstr "Formato:" #: gaupol/page.py:304 msgid "Encoding:" msgstr "Codificación:" #: gaupol/page.py:305 msgid "Newlines:" msgstr "Novas liñas:" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:99 msgid "Tasks and Target" msgstr "" #: gaupol/assistants.py:128 msgid "Correct texts in the text column" msgstr "" #: gaupol/assistants.py:129 msgid "Correct texts in the translation column" msgstr "" #: gaupol/assistants.py:138 msgid "Correct texts in selected subtitles" msgstr "Corrixir textos nos subtítulos seleccionados" #: gaupol/assistants.py:139 msgid "Correct texts in current project" msgstr "Corrixir textos no proxecto actual" #: gaupol/assistants.py:140 msgid "Correct texts in all open projects" msgstr "Corrixir textos en todos os proxectos abertos" #: gaupol/assistants.py:363 msgid "Other" msgstr "Outro" #: gaupol/assistants.py:439 msgid "Capitalize texts written in lower case" msgstr "" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:443 msgid "Capitalization Patterns" msgstr "" #: gaupol/assistants.py:445 msgid "Capitalize texts" msgstr "" #: gaupol/assistants.py:468 msgid "Correct common errors made by humans or image recognition software" msgstr "" "Corrixir erros comúns realizados por humanos ou software de recoñecemento de" " imaxes" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:472 msgid "Common Error Patterns" msgstr "Patróns de erros comúns" #: gaupol/assistants.py:474 msgid "Correct common errors" msgstr "Corrixir erros comúns" #: gaupol/assistants.py:526 msgid "Remove explanatory texts meant for the hearing impaired" msgstr "Retirar os textos explicativos para xordos" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:530 msgid "Hearing Impaired Patterns" msgstr "" #: gaupol/assistants.py:532 msgid "Remove hearing impaired texts" msgstr "Retirar os textos para xordos" #: gaupol/assistants.py:544 msgid "" "Use spell-check suggestions to fix whitespace detection errors of image " "recognition software" msgstr "" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:548 msgid "Joining and Splitting Words" msgstr "" #: gaupol/assistants.py:550 msgid "Join or Split Words" msgstr "" #: gaupol/assistants.py:599 gaupol/agents/tools.py:45 msgid "Failed to load dictionary for language \"{}\"" msgstr "Produciuse un erro ao cargar o dicionario para o idioma «{}»" #: gaupol/assistants.py:601 gaupol/player.py:263 gaupol/player.py:381 #: gaupol/dialogs/search.py:560 gaupol/dialogs/search.py:568 #: gaupol/dialogs/text_edit.py:49 gaupol/dialogs/encoding.py:56 #: gaupol/agents/open.py:328 gaupol/agents/open.py:337 #: gaupol/agents/open.py:345 gaupol/agents/open.py:354 #: gaupol/agents/tools.py:48 gaupol/agents/save.py:197 #: gaupol/agents/save.py:205 gaupol/agents/preview.py:108 #: gaupol/agents/preview.py:116 gaupol/agents/preview.py:125 #: gaupol/agents/preview.py:133 msgid "_OK" msgstr "" #: gaupol/assistants.py:635 msgid "Break text into lines of defined length" msgstr "Quebrar o texto en liñas de lonxitude definida" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:639 msgid "Line-Break Patterns" msgstr "Patróns de quebra de liñas" #: gaupol/assistants.py:641 msgid "Break lines" msgstr "Quebrar liñas" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:679 msgid "Line-Break Options" msgstr "Opcións de quebra de liñas" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:763 msgid "Correcting Texts" msgstr "Corrección de textos" #: gaupol/assistants.py:769 msgid "Each task is now being run on each project." msgstr "Cada tarefa execútase agora en cada proxecto." #: gaupol/assistants.py:793 #, python-brace-format msgid "{current:d} of {total:d} tasks complete" msgstr "{current:d} de {total:d} tarefas completadas" #: gaupol/assistants.py:801 msgid "Project: {}" msgstr "Proxecto: {}" #: gaupol/assistants.py:807 msgid "Task: {}" msgstr "Tarefa: {}" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:832 msgid "Confirm Changes" msgstr "Confirmar os cambios" #: gaupol/assistants.py:892 msgid "Accept" msgstr "Aceptar" #: gaupol/assistants.py:898 msgid "Original Text" msgstr "Texto orixinal" #: gaupol/assistants.py:899 msgid "Corrected Text" msgstr "Texto corrixido" #: gaupol/assistants.py:1048 msgid "Correct Texts" msgstr "Textos corrixidos" #: gaupol/assistants.py:1076 msgid "Correcting texts" msgstr "Corrixindo textos" #: gaupol/assistants.py:1092 #, python-brace-format msgid "Edited {edits:d} and removed {removals:d} subtitles" msgstr "Editáronse {edits:d} e retiráronse {removals:d} subtítulos" #: gaupol/assistants.py:1126 msgid "Confirm {:d} Change" msgid_plural "Confirm {:d} Changes" msgstr[0] "" msgstr[1] "" #: gaupol/renderers/multiline.py:86 msgid "Italic" msgstr "" #: gaupol/player.py:372 msgid "No video streams found" msgstr "" #: gaupol/player.py:379 msgid "Failed to initialize playback" msgstr "" #: gaupol/dialogs/search.py:189 data/ui/menubar.ui:524 msgid "_Help" msgstr "A_xuda" #: gaupol/dialogs/search.py:471 msgid "Found and replaced {:d} occurence" msgid_plural "Found and replaced {:d} occurences" msgstr[0] "" msgstr[1] "" #: gaupol/dialogs/search.py:488 msgid "\"{}\" not found" msgstr "Non se atopou «{}»" #: gaupol/dialogs/search.py:558 msgid "Error in regular expression pattern" msgstr "Erro no patrón de expresión regular" #: gaupol/dialogs/search.py:566 msgid "Error in regular expression replacement" msgstr "Erro na substitución de expresión regular" #: gaupol/dialogs/text_edit.py:48 gaupol/dialogs/framerate_convert.py:63 #: gaupol/dialogs/insert.py:44 gaupol/dialogs/encoding.py:55 #: gaupol/dialogs/split.py:44 gaupol/dialogs/multi_close.py:54 #: gaupol/dialogs/open.py:63 gaupol/dialogs/position_transform.py:69 #: gaupol/dialogs/position_shift.py:71 gaupol/dialogs/multi_save.py:83 #: gaupol/dialogs/multi_save.py:215 gaupol/dialogs/duration_adjust.py:86 #: gaupol/dialogs/save.py:73 gaupol/dialogs/video.py:41 #: gaupol/agents/open.py:363 gaupol/agents/open.py:375 #: gaupol/agents/open.py:387 gaupol/agents/close.py:71 #: data/extensions/custom-framerates/custom-framerates.py:39 msgid "_Cancel" msgstr "" #: gaupol/dialogs/text_edit.py:53 msgid "Edit Text" msgstr "Editar texto" #: gaupol/dialogs/framerate_convert.py:64 msgid "Co_nvert" msgstr "Co_nverter" #: gaupol/dialogs/insert.py:45 msgid "_Insert" msgstr "_Inserir" #: gaupol/dialogs/insert.py:54 msgid "Above selection" msgstr "Selección superior" #: gaupol/dialogs/insert.py:55 msgid "Below selection" msgstr "Selección inferior" #: gaupol/dialogs/encoding.py:60 data/ui/preferences-dialog.ui:70 msgid "Character Encodings" msgstr "Codificacións de caracteres" #: gaupol/dialogs/encoding.py:78 gaupol/dialogs/encoding.py:125 msgid "Description" msgstr "Descrición" #: gaupol/dialogs/encoding.py:85 gaupol/dialogs/encoding.py:132 msgid "Encoding" msgstr "Codificación" #: gaupol/dialogs/encoding.py:141 msgid "Show in Menu" msgstr "Mostrar no menú" #: gaupol/dialogs/split.py:45 msgid "_Split" msgstr "_Dividir" #: gaupol/dialogs/split.py:76 msgid "Splitting project" msgstr "Dividir o proxecto" #: gaupol/dialogs/split.py:97 #, python-brace-format msgid "Split {amount:d} subtitles to project \"{name}\"" msgstr "Dividir apartando {amount:d} subtítulos ao proxecto «{name}»" #: gaupol/dialogs/spell_check.py:269 msgid "Spell-checking" msgstr "Corrección ortográfica" #: gaupol/dialogs/preferences.py:217 msgid "{} Extension Website" msgstr "Sitio web do complemento {}" #: gaupol/dialogs/preferences.py:429 msgid "Custom" msgstr "Personalizado" #: gaupol/dialogs/multi_close.py:38 msgid "Save changes to documents before closing?" msgstr "Gardar os cambios nos documentos antes de pechar?" #: gaupol/dialogs/multi_close.py:39 gaupol/agents/open.py:384 #: gaupol/agents/close.py:68 msgid "If you don't save, changes will be permanently lost." msgstr "Se non os garda, os seus cambios perderanse permanentemente." #: gaupol/dialogs/multi_close.py:53 gaupol/agents/close.py:70 msgid "Close _Without Saving" msgstr "Pechar _sen gardar" #: gaupol/dialogs/multi_close.py:55 gaupol/dialogs/multi_save.py:84 #: gaupol/dialogs/save.py:74 gaupol/agents/open.py:388 #: gaupol/agents/close.py:72 data/ui/menubar.ui:34 msgid "_Save" msgstr "_Gardar" #: gaupol/dialogs/multi_close.py:70 msgid "Select the _main documents you want to save:" msgstr "Seleccione os docu_mentos principais que quere gardar:" #: gaupol/dialogs/multi_close.py:95 msgid "Select the _translation documents you want to save:" msgstr "Seleccione os documentos de _tradución que desexa gardar:" #: gaupol/dialogs/open.py:64 gaupol/agents/open.py:364 #: gaupol/agents/open.py:376 msgid "_Open" msgstr "" #: gaupol/dialogs/position_transform.py:70 msgid "_Transform" msgstr "_Transformar" #: gaupol/dialogs/position_shift.py:72 msgid "_Shift" msgstr "De_sprazar" #: gaupol/dialogs/position_shift.py:150 msgid "frames" msgstr "fotogramas" #: gaupol/dialogs/position_shift.py:168 data/ui/preferences-dialog.ui:911 msgid "seconds" msgstr "segundos" #: gaupol/dialogs/about.py:36 msgid "About Gaupol" msgstr "Sobre Gaupol" #: gaupol/dialogs/about.py:40 msgid "Subtitle editor" msgstr "Editor de subtítulos" #. TRANSLATORS: This is a special message that shouldn't be translated #. literally. It is used in the about dialog to give credits to the #. translators. Thus, you should translate it to your name and email #. address. You can also include other translators who have contributed #. to this translation; in that case, please write them on separate #. lines seperated by newlines (\n). #: gaupol/dialogs/about.py:51 msgid "translator-credits" msgstr "" "Leandro Regueiro , 2012, 2013.\n" "\n" "Proxecto Trasno - Adaptación de software libre á lingua galega.\n" "Se desexas colaborar connosco podes atopar máis información en http://www.trasno.net" #: gaupol/dialogs/about.py:54 msgid "Gaupol Website" msgstr "Sitio web de Gaupol" #: gaupol/dialogs/append.py:35 msgid "Append File" msgstr "Agregar ficheiro" #: gaupol/dialogs/debug.py:43 msgid "Something went wrong" msgstr "Algo foi mal" #: gaupol/dialogs/debug.py:44 msgid "" "You have probably discovered a bug. Please report it by providing the below " "information and a description of what you were doing." msgstr "" #: gaupol/dialogs/debug.py:52 msgid "_Report Bug" msgstr "" #: gaupol/dialogs/debug.py:53 data/ui/menubar.ui:56 msgid "_Quit" msgstr "_Saír" #: gaupol/dialogs/debug.py:54 gaupol/dialogs/preview_error.py:45 #: data/ui/menubar.ui:52 data/ui/tab-popup.ui:16 msgid "_Close" msgstr "Pe_char" #: gaupol/dialogs/multi_save.py:98 gaupol/dialogs/save.py:110 msgid "{} (recommended)" msgstr "" #: gaupol/dialogs/multi_save.py:212 msgid "" "{:d} of the files to be saved already exist. Do you want to replace them?" msgstr "{:d} dos ficheiros a gardar xa existen. Quere substituílos?" #: gaupol/dialogs/multi_save.py:213 msgid "" "The files already exist in \"{}\". Replacing them will overwrite their " "contents." msgstr "" "Os ficheiros xa existen en «{}». Ao substituílos sobrescribirase o seu " "contido." #: gaupol/dialogs/multi_save.py:216 data/ui/search-dialog.ui:192 #: data/ui/spell-check-dialog.ui:122 msgid "_Replace" msgstr "Substituí_r" #: gaupol/dialogs/duration_adjust.py:70 msgid "Adjusted duration of {:d} subtitle" msgid_plural "Adjusted durations of {:d} subtitles" msgstr[0] "" msgstr[1] "" #: gaupol/dialogs/duration_adjust.py:87 msgid "_Adjust" msgstr "_Axustar" #: gaupol/dialogs/preview_error.py:36 msgid "Preview in video player failed" msgstr "" #: gaupol/dialogs/preview_error.py:37 msgid "" "There is probably a problem with either the video file or the video player. " "See the preferences dialog to choose the video player or to customize the " "command." msgstr "" #: gaupol/dialogs/language.py:97 msgid "Set Language" msgstr "Definir o idioma" #: gaupol/dialogs/video.py:52 gaupol/dialogs/file.py:59 msgid "All files" msgstr "Todos os ficheiros" #: gaupol/dialogs/video.py:56 msgid "Video files" msgstr "Ficheiros de vídeo" #: gaupol/dialogs/file.py:63 msgid "All supported files" msgstr "Todos os ficheiros compatíbeis" #: gaupol/dialogs/file.py:77 #, python-brace-format msgid "{format} (*{extension})" msgstr "{format} (*{extension})" #: gaupol/dialogs/file.py:120 msgid "Auto-detected" msgstr "Detección automática" #: gaupol/dialogs/file.py:122 msgid "Other…" msgstr "Outro…" #: gaupol/agents/menu.py:94 gaupol/agents/menu.py:103 #: gaupol/agents/menu.py:110 msgid "File not found" msgstr "" #: gaupol/agents/open.py:85 #, python-brace-format msgid "Appended {amount:d} subtitles from \"{basename}\"" msgstr "Agregáronse {amount:d} subtítulos desde «{basename}»" #: gaupol/agents/open.py:96 msgid "Appending file" msgstr "Agregando ficheiro" #: gaupol/agents/open.py:111 msgid "File \"{}\" is already open" msgstr "O ficheiro «{}» xa está aberto" #: gaupol/agents/open.py:214 msgid "Open Translation" msgstr "Abrir tradución" #: gaupol/agents/open.py:223 msgid "Select Video" msgstr "Seleccionar vídeo" #: gaupol/agents/open.py:224 msgid "_Select" msgstr "_Seleccionar" #: gaupol/agents/open.py:325 msgid "Failed to decode file \"{}\" with all attempted codecs" msgstr "" "Produciuse un erro ao descodificar o ficheiro «{}» con todos os códecs " "probados" #: gaupol/agents/open.py:326 msgid "Please try to open the file with a different character encoding." msgstr "Intente abrir o ficheiro cunha codificación de caracteres diferente." #: gaupol/agents/open.py:334 msgid "Failed to recognize format of file \"{}\"" msgstr "Produciuse un erro ao recoñecer o formato do ficheiro «{}»" #: gaupol/agents/open.py:335 msgid "" "Please check that the file you are trying to open is a subtitle file of a " "format supported by Gaupol." msgstr "" "Comprobe que o ficheiro que está intentando abrir é un ficheiro de " "subtítulos cun formato admitido por Gaupol." #: gaupol/agents/open.py:343 msgid "Failed to open file \"{}\"" msgstr "Produciuse un erro ao abrir o ficheiro «{}»" #: gaupol/agents/open.py:351 msgid "Failed to parse file \"{}\"" msgstr "Produciuse un erro ao analizar o ficheiro «{}»" #: gaupol/agents/open.py:352 msgid "Please check that the file you are trying to open is a valid {} file." msgstr "" "Comprobe que o ficheiro que está intentando abrir é un ficheiro {} válido." #: gaupol/agents/open.py:360 msgid "Open abnormally large file \"{}\"?" msgstr "Desexa abrir o ficheiro anormalmente grande «{}»?" #: gaupol/agents/open.py:361 msgid "" "Size of the file is {:.1f} MB, which is abnormally large for a text-based " "subtitle file. Please, check that you are not trying to open a binary file." msgstr "" "O tamaño do ficheiro é de {:.1f} MB, o cal é anormalmente grande para un " "ficheiro de texto con subtítulos. Comprobe que non está intentando abrir un " "ficheiro binario." #: gaupol/agents/open.py:371 msgid "Open unsorted file \"{}\"?" msgstr "Quere abrir o ficheiro non ordenado «{}»?" #: gaupol/agents/open.py:372 msgid "" "The order of {:d} subtitles needs to be changed. If {:d} sounds like a lot, " "the file may be erroneously composed." msgstr "" "Hai que cambiar a orde de {:d} subtítulos. Se {:d} lle parecen demasiados " "pode que o ficheiro estea mal composto." #: gaupol/agents/open.py:383 msgid "Save changes to translation document \"{}\" before opening a new one?" msgstr "" "Quere gardar os cambios do documento de tradución «{}» antes de abrir un " "novo?" #: gaupol/agents/open.py:386 msgid "Open _Without Saving" msgstr "Abrir _sen gardar" #: gaupol/agents/close.py:66 msgid "Save changes to document \"{}\" before closing?" msgstr "" #: gaupol/agents/edit.py:101 gaupol/agents/edit.py:119 msgid "Stretching end position" msgstr "" #: gaupol/agents/edit.py:208 msgid "Inserted {:d} subtitle to fit clipboard contents" msgid_plural "Inserted {:d} subtitles to fit clipboard contents" msgstr[0] "" msgstr[1] "" #: gaupol/agents/edit.py:334 gaupol/agents/edit.py:352 msgid "Stretching start position" msgstr "" #: gaupol/agents/edit.py:411 msgid "Use Shift+Return for line-break" msgstr "Use Maiús+Intro para quebrar as liñas" #: gaupol/agents/save.py:129 msgid "Save As" msgstr "Gardar como" #: gaupol/agents/save.py:135 msgid "Saved main document as \"{}\"" msgstr "Gardouse o documento principal como «{}»" #: gaupol/agents/save.py:153 msgid "Save Translation As" msgstr "Gardar a tradución como" #: gaupol/agents/save.py:159 msgid "Saved translation document as \"{}\"" msgstr "Gardouse o documento de tradución como «{}»" #: gaupol/agents/save.py:194 #, python-brace-format msgid "Failed to encode file \"{basename}\" with codec \"{codec}\"" msgstr "" "Produciuse un erro ao codificar o ficheiro \"{basename}\" co códec " "\"{codec}\"" #: gaupol/agents/save.py:195 msgid "Please try to save the file with a different character encoding." msgstr "Intente gardar o ficheiro cunha codificación de caracteres diferente." #: gaupol/agents/save.py:203 msgid "Failed to save file \"{}\"" msgstr "Produciuse un erro ao gardar o ficheiro «{}»" #: gaupol/agents/video.py:67 data/ui/menubar.ui:380 msgid "_Play/Pause" msgstr "Re_producir/Pór en pausa" #: gaupol/agents/video.py:69 msgid "Play or pause video" msgstr "Reproducir ou pór en pausa o vídeo" #: gaupol/agents/video.py:75 data/ui/menubar.ui:390 msgid "Seek _Previous" msgstr "Saltar ao an_terior" #: gaupol/agents/video.py:77 msgid "Seek to the start of the previous subtitle" msgstr "Saltar ao inicio do anterior subtítulo" #: gaupol/agents/video.py:81 data/ui/menubar.ui:394 msgid "Seek _Next" msgstr "Saltar ao segui_nte" #: gaupol/agents/video.py:83 msgid "Seek to the start of the next subtitle" msgstr "Saltar ao inicio do seguinte subtítulo" #: gaupol/agents/video.py:88 data/ui/menubar.ui:400 msgid "Seek _Backward" msgstr "Saltar cara _atrás" #: gaupol/agents/video.py:90 msgid "Seek backward" msgstr "Saltar cara atrás" #: gaupol/agents/video.py:94 data/ui/menubar.ui:404 msgid "Seek _Forward" msgstr "Saltar cara a_diante" #: gaupol/agents/video.py:96 msgid "Seek forward" msgstr "Saltar cara adiante" #: gaupol/agents/video.py:109 msgid "Volume" msgstr "Volume" #: gaupol/agents/video.py:189 msgid "Load Video" msgstr "Cargar vídeo" #: gaupol/agents/video.py:189 msgid "_Load" msgstr "_Cargar" #: gaupol/agents/video.py:361 msgid "Track {:d}" msgstr "" #: gaupol/agents/preview.py:105 msgid "Failed to encode subtitle file to temporary directory \"{}\"" msgstr "" "Produciuse un erro ao codificar o ficheiro de subtítulos no directorio " "temporal «{}»" #: gaupol/agents/preview.py:106 msgid "" "Subtitle data could not be encoded to a temporary file for preview with the " "current character encoding. Please first save the subtitle file with a " "different character encoding." msgstr "" #: gaupol/agents/preview.py:114 msgid "Failed to save subtitle file to temporary directory \"{}\"" msgstr "" "Produciuse un erro ao gardar o ficheiros de subtítulos no directorio " "temporal «{}»" #: gaupol/agents/preview.py:122 msgid "Video player not found" msgstr "" #: gaupol/agents/preview.py:123 msgid "" "Please install one of the supported video players: mpv (recommended), " "MPlayer or VLC. See the preferences dialog to choose the video player or to " "customize the command." msgstr "" #: gaupol/agents/preview.py:131 msgid "Failed to launch video player" msgstr "Produciuse un erro ao iniciar o reprodutor de vídeo" #: gaupol/applicationman.py:105 msgid "gaupol [OPTION...] [FILE...] [+[NUM]]" msgstr "gaupol [OPCIÓN...] [FICHEIRO...] [+[NÚM]]" #: gaupol/applicationman.py:109 msgid "FILE..." msgstr "" #: gaupol/applicationman.py:112 msgid "subtitle files to open" msgstr "" #: gaupol/applicationman.py:122 msgid "ENCODING" msgstr "CODIFICACIÓN" #: gaupol/applicationman.py:125 msgid "set the character encoding used to open files" msgstr "definir a codificación de caracteres para abrir ficheiros" #: gaupol/applicationman.py:132 msgid "list all available character encodings" msgstr "listar todas as codificacións de caracteres dispoñíbeis" #: gaupol/applicationman.py:137 gaupol/applicationman.py:154 msgid "FILE" msgstr "FICHEIRO" #: gaupol/applicationman.py:140 msgid "open translation file" msgstr "abrir ficheiro de tradución" #: gaupol/applicationman.py:145 msgid "METHOD" msgstr "MÉTODO" #: gaupol/applicationman.py:149 msgid "method used to align translation subtitles: 'number' or 'position'" msgstr "" "método empregado para aliñar os subtítulos de tradución: 'number' ou " "'position'" #: gaupol/applicationman.py:157 msgid "select video file" msgstr "seleccionar ficheiro de vídeo" #: data/extensions/custom-framerates/custom-framerates.py:40 #: data/ui/spell-check-dialog.ui:152 msgid "_Add" msgstr "Eng_adir" #: data/extensions/custom-framerates/custom-framerates.py:171 msgid "{:.3f} fps" msgstr "{:.3f} fps" #: data/extensions/custom-framerates/add-framerate-dialog.ui:13 msgid "Add Framerate" msgstr "Engadir taxa de fotogramas" #: data/extensions/custom-framerates/add-framerate-dialog.ui:44 msgid "_Framerate:" msgstr "Taxa de _fotogramas:" #: data/extensions/custom-framerates/add-framerate-dialog.ui:73 msgid "fps" msgstr "fps" #: data/extensions/custom-framerates/preferences-dialog.ui:8 msgid "Framerates" msgstr "" #: data/extensions/custom-framerates/preferences-dialog.ui:64 msgid "Add" msgstr "" #: data/ui/columns-popup.ui:6 data/ui/menubar.ui:275 msgid "_No." msgstr "_Nº" #: data/ui/columns-popup.ui:10 data/ui/menubar.ui:279 msgid "_Start" msgstr "_Inicio" #: data/ui/columns-popup.ui:14 data/ui/menubar.ui:283 msgid "_End" msgstr "_Fin" #: data/ui/columns-popup.ui:18 data/ui/menubar.ui:287 msgid "_Duration" msgstr "_Duración" #: data/ui/columns-popup.ui:22 data/ui/menubar.ui:291 data/ui/menubar.ui:303 msgid "_Text" msgstr "_Texto" #: data/ui/columns-popup.ui:26 data/ui/menubar.ui:295 msgid "T_ranslation" msgstr "" #: data/ui/split-dialog.ui:15 msgid "Split Project" msgstr "Dividir proxecto" #: data/ui/split-dialog.ui:48 msgid "_First subtitle of new project:" msgstr "_Primeiro subtítulo do novo proxecto:" #: data/ui/search-dialog.ui:89 msgid "_Search for:" msgstr "Bu_scar:" #: data/ui/search-dialog.ui:103 data/ui/spell-check-dialog.ui:193 msgid "Replace _with:" msgstr "Substituír _por:" #: data/ui/search-dialog.ui:162 data/ui/menubar.ui:328 msgid "Find _Next" msgstr "Buscar _seguinte" #: data/ui/search-dialog.ui:177 msgid "Find _Previous" msgstr "Buscar _anterior" #: data/ui/search-dialog.ui:207 msgid "Replace _All" msgstr "Substituír _todo" #: data/ui/search-dialog.ui:241 msgid "R_egular expression" msgstr "_Expresión regular" #: data/ui/search-dialog.ui:258 msgid "_Ignore case" msgstr "_Ignorar maiúsculas e minúsculas" #: data/ui/search-dialog.ui:304 data/ui/language-dialog.ui:108 msgid "Columns" msgstr "Columnas" #: data/ui/search-dialog.ui:324 msgid "Find in _text column" msgstr "" #: data/ui/search-dialog.ui:341 msgid "Find in t_ranslation column" msgstr "" #: data/ui/search-dialog.ui:381 data/ui/framerate-convert-dialog.ui:144 #: data/ui/language-dialog.ui:186 #: data/ui/text-assistant/line-break-options-page.ui:178 #: data/ui/duration-adjust-dialog.ui:388 data/ui/position-shift-dialog.ui:180 #: data/ui/position-transform-dialog.ui:444 msgid "Subtitles" msgstr "Subtítulos" #: data/ui/search-dialog.ui:401 msgid "Find in c_urrent project" msgstr "Buscar no _proxecto actual" #: data/ui/search-dialog.ui:419 msgid "Find in _all open projects" msgstr "Buscar en _todos os proxectos abertos" #: data/ui/search-dialog.ui:452 msgid "Target" msgstr "Obxectivo" #: data/ui/framerate-convert-dialog.ui:8 msgid "Convert Framerate" msgstr "Converter a taxa de fotogramas" #: data/ui/framerate-convert-dialog.ui:48 msgid "Framerate" msgstr "Taxa de fotogramas" #: data/ui/framerate-convert-dialog.ui:71 msgid "_Input:" msgstr "_Entrada:" #: data/ui/framerate-convert-dialog.ui:86 msgid "_Output:" msgstr "_Saída:" #: data/ui/framerate-convert-dialog.ui:164 msgid "Convert c_urrent project" msgstr "Con_verter o proxecto actual" #: data/ui/framerate-convert-dialog.ui:181 msgid "Convert _all open projects" msgstr "Conv_erter todos os proxectos abertos" #: data/ui/spell-check-dialog.ui:8 msgid "Check Spelling" msgstr "Corrección ortográfica" #: data/ui/spell-check-dialog.ui:47 msgid "Join _Back" msgstr "" #: data/ui/spell-check-dialog.ui:62 msgid "Join _Forward" msgstr "" #: data/ui/spell-check-dialog.ui:77 data/ui/menubar.ui:62 msgid "_Edit" msgstr "_Editar" #: data/ui/spell-check-dialog.ui:92 msgid "_Ignore" msgstr "_Ignorar" #: data/ui/spell-check-dialog.ui:107 msgid "Ig_nore All" msgstr "Ig_norar todo" #: data/ui/spell-check-dialog.ui:137 msgid "Rep_lace All" msgstr "_Substituír todo" #: data/ui/spell-check-dialog.ui:179 msgid "_Suggestions:" msgstr "_Suxestións:" #: data/ui/multi-save-dialog.ui:8 msgid "Save All As" msgstr "Gardar todo como" #: data/ui/multi-save-dialog.ui:46 msgid "Save in _folder:" msgstr "Gardar no carta_fol:" #: data/ui/multi-save-dialog.ui:60 data/ui/save-dialog.ui:25 msgid "For_mat:" msgstr "For_mato:" #: data/ui/multi-save-dialog.ui:74 data/ui/open-dialog.ui:25 #: data/ui/save-dialog.ui:39 msgid "_Encoding:" msgstr "_Codificación:" #: data/ui/multi-save-dialog.ui:88 data/ui/save-dialog.ui:53 msgid "Ne_wlines:" msgstr "No_vas liñas:" #: data/ui/multi-save-dialog.ui:103 msgid "Select A Folder" msgstr "Seleccionar un cartafol" #: data/ui/multi-save-dialog.ui:150 data/ui/save-dialog.ui:102 msgid "F_ramerate:" msgstr "" #: data/ui/menubar.ui:5 msgid "_File" msgstr "_Ficheiro" #: data/ui/menubar.ui:8 msgid "_New" msgstr "_Novo" #: data/ui/menubar.ui:12 msgid "_Open…" msgstr "_Abrir…" #: data/ui/menubar.ui:16 msgid "Open _Translation…" msgstr "Abrir _tradución…" #: data/ui/menubar.ui:22 msgid "Open _Recent" msgstr "Abrir _recentes" #: data/ui/menubar.ui:27 msgid "Open R_ecent Translation" msgstr "Abrir tradución r_ecente" #: data/ui/menubar.ui:38 msgid "Save _As…" msgstr "Gardar _como…" #: data/ui/menubar.ui:42 msgid "Save Trans_lation" msgstr "Gardar tra_dución" #: data/ui/menubar.ui:46 msgid "Save Translat_ion As…" msgstr "Gardar a traduc_ión como…" #: data/ui/menubar.ui:65 msgid "_Undo" msgstr "_Desfacer" #: data/ui/menubar.ui:69 msgid "_Redo" msgstr "_Refacer" #: data/ui/menubar.ui:75 msgid "_Edit Cell" msgstr "_Editar a cela" #: data/ui/menubar.ui:79 msgid "Edit _Next Cell" msgstr "Editar a segui_nte cela" #: data/ui/menubar.ui:85 msgid "Stretc_h" msgstr "" #: data/ui/menubar.ui:88 msgid "_Start Earlier" msgstr "_Iniciar máis cedo" #: data/ui/menubar.ui:92 msgid "S_tart Later" msgstr "I_niciar máis tarde" #: data/ui/menubar.ui:98 msgid "E_nd Earlier" msgstr "Re_matar máis cedo" #: data/ui/menubar.ui:102 msgid "En_d Later" msgstr "_Rematar máis tarde" #: data/ui/menubar.ui:108 msgid "Set St_art From Video Position" msgstr "" #: data/ui/menubar.ui:112 msgid "Set En_d From Video Position" msgstr "" #: data/ui/menubar.ui:118 data/ui/view-popup.ui:6 msgid "_Split Subtitle" msgstr "_Dividir subtítulo" #: data/ui/menubar.ui:122 data/ui/view-popup.ui:10 msgid "_Merge Subtitles" msgstr "Co_mbinar os subtítulos" #: data/ui/menubar.ui:128 data/ui/view-popup.ui:16 msgid "_Insert Subtitles…" msgstr "_Inserir subtítulos…" #: data/ui/menubar.ui:132 msgid "Inser_t Subtitle At Video Position" msgstr "Inserir sub_título na posición do vídeo" #: data/ui/menubar.ui:136 data/ui/view-popup.ui:20 msgid "Rem_ove Subtitles" msgstr "Ret_irar subtítulos" #: data/ui/menubar.ui:142 msgid "Sele_ction" msgstr "Selec_ción" #: data/ui/menubar.ui:145 msgid "Select _All" msgstr "Seleccionar _todo" #: data/ui/menubar.ui:149 msgid "_Invert Selection" msgstr "_Inverter a selección" #: data/ui/menubar.ui:155 msgid "Extend To _Beginning" msgstr "Estender ata o _comezo" #: data/ui/menubar.ui:159 msgid "Extend To _End" msgstr "Estender ata o _final" #: data/ui/menubar.ui:165 msgid "_Previous From Video Position" msgstr "" #: data/ui/menubar.ui:169 msgid "_Next From Video Position" msgstr "" #: data/ui/menubar.ui:177 msgid "_Preferences" msgstr "_Preferencias" #: data/ui/menubar.ui:183 msgid "_View" msgstr "_Ver" #: data/ui/menubar.ui:186 msgid "Tool_bar" msgstr "" #: data/ui/menubar.ui:190 msgid "_Video Player" msgstr "Reprodutor de _vídeo" #: data/ui/menubar.ui:196 msgid "_Layout" msgstr "_Disposición" #: data/ui/menubar.ui:199 msgid "_Horizontal" msgstr "_Horizontal" #: data/ui/menubar.ui:204 msgid "_Vertical" msgstr "_Vertical" #: data/ui/menubar.ui:213 msgid "_Times" msgstr "_Tempos" #: data/ui/menubar.ui:218 msgid "_Frames" msgstr "_Fotogramas" #: data/ui/menubar.ui:225 msgid "F_ramerate" msgstr "Taxa de fotog_ramas" #: data/ui/menubar.ui:228 msgid "2_3.976 fps" msgstr "2_3,976 fps" #: data/ui/menubar.ui:233 msgid "2_4.000 fps" msgstr "2_4,000 fps" #: data/ui/menubar.ui:238 msgid "2_5.000 fps" msgstr "2_5,000 fps" #: data/ui/menubar.ui:243 msgid "2_9.970 fps" msgstr "2_9,970 fps" #: data/ui/menubar.ui:272 msgid "_Columns" msgstr "_Columnas" #: data/ui/menubar.ui:306 msgid "Cu_t" msgstr "Cor_tar" #: data/ui/menubar.ui:310 msgid "_Copy" msgstr "_Copiar" #: data/ui/menubar.ui:314 msgid "_Paste" msgstr "_Pegar" #: data/ui/menubar.ui:318 msgid "Cl_ear" msgstr "_Limpar" #: data/ui/menubar.ui:324 msgid "_Find And Replace…" msgstr "_Buscar e substituír…" #: data/ui/menubar.ui:332 msgid "Find Pre_vious" msgstr "Buscar an_terior" #: data/ui/menubar.ui:338 msgid "_Italic" msgstr "_Cursiva" #: data/ui/menubar.ui:342 msgid "_Dialogue" msgstr "_Diálogo" #: data/ui/menubar.ui:348 msgid "Ca_se" msgstr "" #: data/ui/menubar.ui:351 msgid "_Title" msgstr "" #: data/ui/menubar.ui:355 msgid "_Sentence" msgstr "" #: data/ui/menubar.ui:359 msgid "_Upper" msgstr "_Maiúsculas" #: data/ui/menubar.ui:363 msgid "_Lower" msgstr "_Minúsculas" #: data/ui/menubar.ui:371 msgid "Vi_deo" msgstr "Ví_deo" #: data/ui/menubar.ui:374 msgid "_Load Video…" msgstr "_Cargar vídeo…" #: data/ui/menubar.ui:384 data/ui/view-popup.ui:26 msgid "Play _Selection" msgstr "Reproducir a _selección" #: data/ui/menubar.ui:410 data/ui/view-popup.ui:30 msgid "S_eek Selection Start" msgstr "Sa_ltar o comezo da selección" #: data/ui/menubar.ui:414 msgid "See_k Selection End" msgstr "Sal_tar ao fin da selección" #: data/ui/menubar.ui:420 msgid "_Audio" msgstr "_Son" #: data/ui/menubar.ui:423 msgid "_Language" msgstr "_Idioma" #: data/ui/menubar.ui:430 msgid "Volume _Down" msgstr "_Baixar o volume" #: data/ui/menubar.ui:434 msgid "Volume _Up" msgstr "_Subir o volume" #: data/ui/menubar.ui:440 msgid "T_ools" msgstr "_Ferramentas" #: data/ui/menubar.ui:443 data/ui/text-assistant/confirmation-page.ui:97 #: data/ui/view-popup.ui:36 msgid "_Preview" msgstr "" #: data/ui/menubar.ui:447 msgid "Select _Video…" msgstr "Seleccionar _vídeo…" #: data/ui/menubar.ui:453 msgid "_Check Spelling" msgstr "_Corrección ortográfica" #: data/ui/menubar.ui:457 msgid "Co_nfigure Spell-check…" msgstr "Co_nfigurar a corrección ortográfica…" #: data/ui/menubar.ui:461 msgid "C_orrect Texts…" msgstr "C_orrixir os textos…" #: data/ui/menubar.ui:467 msgid "_Shift Positions…" msgstr "De_sprazar as posicións…" #: data/ui/menubar.ui:471 msgid "_Transform Positions…" msgstr "_Transformar as posicións…" #: data/ui/menubar.ui:475 msgid "Adjust _Durations…" msgstr "Axustar as _duracións…" #: data/ui/menubar.ui:479 msgid "Convert _Framerate…" msgstr "Converter a taxa de _fotogramas…" #: data/ui/menubar.ui:485 msgid "_Append File…" msgstr "_Agregar ficheiro…" #: data/ui/menubar.ui:489 msgid "Spli_t Project…" msgstr "_Dividir proxecto…" #: data/ui/menubar.ui:495 msgid "_Projects" msgstr "_Proxectos" #: data/ui/menubar.ui:498 msgid "_Save All" msgstr "_Gardar todos" #: data/ui/menubar.ui:502 msgid "Save _All As…" msgstr "Gardar _todo como…" #: data/ui/menubar.ui:506 msgid "_Close All" msgstr "_Pechar todo" #: data/ui/menubar.ui:512 msgid "_Previous" msgstr "_Anterior" #: data/ui/menubar.ui:516 msgid "_Next" msgstr "Segui_nte" #: data/ui/menubar.ui:527 msgid "_Documentation" msgstr "" #: data/ui/menubar.ui:531 msgid "_Report A Bug" msgstr "Info_rmar dun fallo" #: data/ui/menubar.ui:535 msgid "_About" msgstr "_Sobre" #: data/ui/open-dialog.ui:39 msgid "Align _method:" msgstr "_Método de aliñamento:" #: data/ui/preferences-dialog.ui:18 msgid "Preferences" msgstr "Preferencias" #: data/ui/preferences-dialog.ui:93 msgid "When opening files, try encodings in the following order:" msgstr "Ao abrir os ficheiros, probar as codificacións na seguinte orde:" #: data/ui/preferences-dialog.ui:104 msgid "Curr_ent locale encoding" msgstr "Codificación da configuración r_exional actual" #: data/ui/preferences-dialog.ui:130 msgid "_Fallback encodings:" msgstr "Codi_ficacións de reserva:" #: data/ui/preferences-dialog.ui:246 msgid "Aut_o-detection" msgstr "Detección automática" #: data/ui/preferences-dialog.ui:266 msgid "Encoding specified in the open dialog will always be tried first." msgstr "" "Sempre se probará primeira a codificación especificada no diálogo de " "apertura." #: data/ui/preferences-dialog.ui:296 msgid "File" msgstr "Ficheiro" #: data/ui/preferences-dialog.ui:324 msgid "Font" msgstr "Tipo de letra" #: data/ui/preferences-dialog.ui:344 msgid "Use _default theme fixed width font" msgstr "" #: data/ui/preferences-dialog.ui:368 msgid "_Editor font:" msgstr "Tipo de letra do _editor:" #: data/ui/preferences-dialog.ui:425 msgid "Line Lengths" msgstr "Lonxitudes de liña" #: data/ui/preferences-dialog.ui:445 msgid "_Show line lengths in list cells" msgstr "" #: data/ui/preferences-dialog.ui:462 msgid "S_how line lengths in editable text fields" msgstr "M_ostrar as lonxitudes de liña nos campos de textos editábeis" #: data/ui/preferences-dialog.ui:486 msgid "_Length unit:" msgstr "Unidade de _lonxitude:" #: data/ui/preferences-dialog.ui:540 msgid "Spell-Check" msgstr "Corrección ortográfica" #: data/ui/preferences-dialog.ui:560 msgid "Chec_k spelling as you type" msgstr "_Corrixir a ortografía mentres se escribe" #: data/ui/preferences-dialog.ui:598 msgid "Editor" msgstr "Editor" #: data/ui/preferences-dialog.ui:626 msgid "Fonts" msgstr "" #: data/ui/preferences-dialog.ui:649 msgid "_Subtitles:" msgstr "" #: data/ui/preferences-dialog.ui:679 msgid "_Time:" msgstr "" #: data/ui/preferences-dialog.ui:729 msgid "Colors" msgstr "" #: data/ui/preferences-dialog.ui:752 msgid "Su_btitles:" msgstr "" #: data/ui/preferences-dialog.ui:777 msgid "_Use a background behind text" msgstr "_Usar un fondo detrás do texto" #: data/ui/preferences-dialog.ui:797 msgid "Ti_me:" msgstr "" #: data/ui/preferences-dialog.ui:822 msgid "Us_e a background behind text" msgstr "Usar un fondo d_etrás do texto" #: data/ui/preferences-dialog.ui:862 msgid "Seek" msgstr "" #: data/ui/preferences-dialog.ui:883 msgid "_Length:" msgstr "" #: data/ui/preferences-dialog.ui:971 msgid "Video Player" msgstr "Reprodutor de vídeo" #: data/ui/preferences-dialog.ui:994 msgid "_Application:" msgstr "_Aplicativo:" #: data/ui/preferences-dialog.ui:1008 msgid "Co_mmand:" msgstr "_Orde:" #. Translators: Only the title is to be translated, field names not. #: data/ui/preferences-dialog.ui:1033 msgid "" "Fields:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" msgstr "" #: data/ui/preferences-dialog.ui:1048 msgid "Al_ways use UTF-8 character encoding" msgstr "Usar _sempre a codificación de caracteres UTF-8" #: data/ui/preferences-dialog.ui:1089 msgid "Start Position" msgstr "Posición inicial" #: data/ui/preferences-dialog.ui:1111 msgid "_Offset:" msgstr "_Desprazamento:" #: data/ui/preferences-dialog.ui:1142 msgid "seconds before selection" msgstr "segundos antes da selección" #: data/ui/preferences-dialog.ui:1281 msgid "Extensions" msgstr "Complementos" #: data/ui/language-dialog.ui:8 msgid "Configure Spell-Check" msgstr "Configurar a corrección ortográfica" #: data/ui/language-dialog.ui:50 msgid "Language" msgstr "Idioma" #: data/ui/language-dialog.ui:128 msgid "Check _text column" msgstr "" #: data/ui/language-dialog.ui:146 msgid "Check t_ranslation column" msgstr "" #: data/ui/language-dialog.ui:206 msgid "Check c_urrent project" msgstr "Corrixir no _proxecto actual" #: data/ui/language-dialog.ui:224 msgid "Check _all open projects" msgstr "_Corrixir en todos os proxectos abertos" #: data/ui/text-assistant/confirmation-page.ui:22 msgid "Acc_ept, discard or edit changes:" msgstr "Ac_eptar, desbotar ou editar os cambios:" #: data/ui/text-assistant/confirmation-page.ui:67 msgid "_Mark All" msgstr "_Marcar todo" #: data/ui/text-assistant/confirmation-page.ui:82 msgid "_Unmark All" msgstr "_Desmarcar todo" #: data/ui/text-assistant/confirmation-page.ui:119 msgid "_Remove all blank subtitles" msgstr "_Retirar todos os subtítulos en branco" #: data/ui/text-assistant/join-split-page.ui:28 msgid "Spell-Check Dictionary" msgstr "Dicionario do corrector ortográfico" #: data/ui/text-assistant/join-split-page.ui:49 #: data/ui/text-assistant/line-break-page.ui:81 #: data/ui/text-assistant/hearing-impaired-page.ui:81 #: data/ui/text-assistant/common-error-page.ui:80 #: data/ui/text-assistant/capitalization-page.ui:80 msgid "_Language:" msgstr "_Idioma:" #: data/ui/text-assistant/join-split-page.ui:97 msgid "Corrections" msgstr "Correccións" #: data/ui/text-assistant/join-split-page.ui:117 msgid "_Join words not found in spell-check dictionary" msgstr "" "_Unir as palabras que non se atopan no dicionario do corrector ortográfico" #: data/ui/text-assistant/join-split-page.ui:134 msgid "_Split words not found in spell-check dictionary" msgstr "" "_Dividir as palabras que non se atopan no dicionario do corrector " "ortográfico" #: data/ui/text-assistant/line-break-page.ui:22 msgid "S_elect preferred line-break points:" msgstr "S_eleccione os puntos de quebra de liñas preferidos:" #: data/ui/text-assistant/line-break-page.ui:67 #: data/ui/text-assistant/hearing-impaired-page.ui:67 #: data/ui/text-assistant/common-error-page.ui:66 #: data/ui/text-assistant/capitalization-page.ui:66 msgid "_Script:" msgstr "" #: data/ui/text-assistant/line-break-page.ui:95 #: data/ui/text-assistant/hearing-impaired-page.ui:95 #: data/ui/text-assistant/common-error-page.ui:94 #: data/ui/text-assistant/capitalization-page.ui:94 msgid "Co_untry:" msgstr "P_aís:" #: data/ui/text-assistant/introduction-page.ui:28 msgid "_Select corrections to perform on texts:" msgstr "_Seleccionar as correccións a realizar nos textos:" #: data/ui/text-assistant/introduction-page.ui:79 msgid "Colu_mns:" msgstr "Colu_mnas:" #: data/ui/text-assistant/introduction-page.ui:93 msgid "S_ubtitles:" msgstr "S_ubtítulos:" #: data/ui/text-assistant/line-break-options-page.ui:56 #: data/ui/duration-adjust-dialog.ui:207 msgid "Limits" msgstr "Límites" #: data/ui/text-assistant/line-break-options-page.ui:79 msgid "_Maximum line length:" msgstr "Lonxitude _máxima de liña:" #: data/ui/text-assistant/line-break-options-page.ui:93 msgid "_Preferred maximum amount of lines:" msgstr "Cantidade de liñas máxima _preferida:" #: data/ui/text-assistant/line-break-options-page.ui:198 msgid "_Skip subtitles with maximum line length of:" msgstr "_Saltar os subtítulos cunha lonxitude de liña máxima de:" #: data/ui/text-assistant/line-break-options-page.ui:214 msgid "S_kip subtitles with maximum line amount of:" msgstr "S_altar os subtítulos cunha cantidade de liñas máxima de:" #: data/ui/text-assistant/hearing-impaired-page.ui:22 msgid "S_elect parts to remove:" msgstr "S_eleccionar as partes a retirar:" #: data/ui/text-assistant/common-error-page.ui:22 msgid "S_elect errors to correct:" msgstr "S_eleccionar erros para corrixir:" #: data/ui/text-assistant/common-error-page.ui:108 msgid "Error types:" msgstr "Tipos de erro:" #: data/ui/text-assistant/common-error-page.ui:158 msgid "_Human errors" msgstr "Erros _humanos" #: data/ui/text-assistant/common-error-page.ui:175 msgid "_Image recognition errors" msgstr "Erros de recoñecemento de _imaxe" #: data/ui/text-assistant/capitalization-page.ui:22 msgid "S_elect parts to capitalize:" msgstr "" #: data/ui/duration-adjust-dialog.ui:33 msgid "Adjust Durations" msgstr "Axustar as duracións" #: data/ui/duration-adjust-dialog.ui:73 msgid "Theoretic Duration" msgstr "Duración teórica" #: data/ui/duration-adjust-dialog.ui:101 msgid "_Reading speed:" msgstr "_Velocidade de lectura:" #: data/ui/duration-adjust-dialog.ui:133 msgid "characters per second" msgstr "caracteres por segundo" #: data/ui/duration-adjust-dialog.ui:150 msgid "_Lengthen duration to match reading speed" msgstr "Pro_longar a duración para igualar a velocidade de lectura" #: data/ui/duration-adjust-dialog.ui:167 msgid "_Shorten duration to match reading speed" msgstr "_Acurtar a duración para igualar a velocidade de lectura" #: data/ui/duration-adjust-dialog.ui:227 msgid "_Minimum duration:" msgstr "Duración _mínima:" #: data/ui/duration-adjust-dialog.ui:243 msgid "Ma_ximum duration:" msgstr "Duración _máxima:" #: data/ui/duration-adjust-dialog.ui:259 msgid "_Gap between subtitles:" msgstr "_Intervalo entre subtítulos:" #: data/ui/duration-adjust-dialog.ui:294 msgid "s_econds" msgstr "s_egundos" #: data/ui/duration-adjust-dialog.ui:324 msgid "seco_nds" msgstr "segu_ndos" #: data/ui/duration-adjust-dialog.ui:354 msgid "secon_ds" msgstr "segun_dos" #: data/ui/duration-adjust-dialog.ui:408 msgid "Adj_ust selected subtitles" msgstr "Ax_ustar os subtítulos seleccionados" #: data/ui/duration-adjust-dialog.ui:425 msgid "Adjus_t current project" msgstr "Axus_tar o proxecto actual" #: data/ui/duration-adjust-dialog.ui:442 msgid "Adjust all _open projects" msgstr "Axustar t_odos os proxectos abertos" #: data/ui/tab-popup.ui:6 msgid "Move Tab _Left" msgstr "Mover a lapela á _esquerda" #: data/ui/tab-popup.ui:10 msgid "Move Tab _Right" msgstr "Mover a lapela á _dereita" #: data/ui/insert-dialog.ui:15 msgid "Insert Subtitles" msgstr "Inserir subtítulos" #: data/ui/insert-dialog.ui:48 data/ui/position-shift-dialog.ui:82 msgid "_Amount:" msgstr "_Cantidade:" #: data/ui/insert-dialog.ui:62 msgid "_Position:" msgstr "_Posición:" #: data/ui/position-shift-dialog.ui:14 msgid "Shift Positions" msgstr "Desprazar as posicións" #: data/ui/position-shift-dialog.ui:54 msgid "Shift" msgstr "Desprazar" #: data/ui/position-shift-dialog.ui:135 #: data/ui/position-transform-dialog.ui:208 msgid "_Preview Changes" msgstr "" #: data/ui/position-shift-dialog.ui:200 msgid "Shift s_elected subtitles" msgstr "D_esprazar os subtítulos seleccionados" #: data/ui/position-shift-dialog.ui:217 msgid "Shift su_btitles from selection to end" msgstr "" #: data/ui/position-shift-dialog.ui:234 msgid "Shift c_urrent project" msgstr "_Desprazar o proxecto actual" #: data/ui/position-shift-dialog.ui:251 msgid "Shift all _open projects" msgstr "" #: data/ui/position-transform-dialog.ui:22 msgid "Transform Positions" msgstr "Transformar as posicións" #: data/ui/position-transform-dialog.ui:62 msgid "First Point" msgstr "" #: data/ui/position-transform-dialog.ui:91 msgid "_Subtitle:" msgstr "_Subtítulo:" #: data/ui/position-transform-dialog.ui:105 msgid "C_orrection:" msgstr "C_orrección:" #: data/ui/position-transform-dialog.ui:119 #: data/ui/position-transform-dialog.ui:310 msgid "Text:" msgstr "Texto:" #: data/ui/position-transform-dialog.ui:253 msgid "Second Point" msgstr "" #: data/ui/position-transform-dialog.ui:282 msgid "Su_btitle:" msgstr "Su_btítulo:" #: data/ui/position-transform-dialog.ui:296 msgid "Co_rrection:" msgstr "Co_rrección:" #: data/ui/position-transform-dialog.ui:399 msgid "Pre_view Changes" msgstr "" #: data/ui/position-transform-dialog.ui:464 msgid "Transform se_lected subtitles" msgstr "Transformar os subtítulos se_leccionados" #: data/ui/position-transform-dialog.ui:482 msgid "Transform c_urrent project" msgstr "Transformar o proxecto act_ual" #: data/extensions/custom-framerates/custom-framerates.extension.in:7 msgid "Custom Framerates" msgstr "Taxa de fotogramas personalizada" #: data/extensions/custom-framerates/custom-framerates.extension.in:8 msgid "Allow use of non-standard framerates" msgstr "Permitir o emprego de taxas de fotogramas non estándar" #: data/patterns/Latn-en-US.common-error.in:5 msgid "Period after title" msgstr "Punto despois do título" #: data/patterns/Latn-en-US.common-error.in:6 msgid "Add period after a shortened title, such as \"Mr\" and \"Dr\"" msgstr "Engadir un punto despois dun título abreviado, como «Sr» ou «Dr»" #: data/patterns/Latn-en.capitalization.in:5 msgid "First person pronoun" msgstr "Pronome de primeira persoa" #: data/patterns/Latn-en.capitalization.in:6 msgid "Capitalize the first person pronoun \"I\"" msgstr "" #: data/patterns/Latn-en.common-error.in:5 #: data/patterns/Latn-en.common-error.in:14 #: data/patterns/Latn-en.common-error.in:23 msgid "Letter \"I\" in a lower case word" msgstr "Letra «I» nunha palabra en minúsculas" #: data/patterns/Latn-en.common-error.in:6 #: data/patterns/Latn-en.common-error.in:15 #: data/patterns/Latn-en.common-error.in:24 msgid "Replace letter \"I\" with letter \"l\" in a lower case word" msgstr "Subtituír a letra «I» pola letra «l» nunha palabra en minúsculas" #: data/patterns/Latn-en.common-error.in:32 #: data/patterns/Latn-en.common-error.in:41 #: data/patterns/Latn-en.common-error.in:50 #: data/patterns/Latn-en.common-error.in:62 msgid "Letter \"l\" in an upper case word" msgstr "Letra «l» nunha palabra en maiúsculas" #: data/patterns/Latn-en.common-error.in:33 #: data/patterns/Latn-en.common-error.in:42 #: data/patterns/Latn-en.common-error.in:51 #: data/patterns/Latn-en.common-error.in:63 msgid "Replace letter \"l\" with letter \"I\" in an upper case word" msgstr "Subtituír a letra «l» pola letra «I» nunha palabra en maiúsculas" #: data/patterns/Latn-en.common-error.in:73 #: data/patterns/Latn-en.common-error.in:82 msgid "Zero in an upper case word" msgstr "Cero nunha palabra en maiúsculas" #: data/patterns/Latn-en.common-error.in:74 #: data/patterns/Latn-en.common-error.in:83 msgid "Replace zero with letter \"O\" in an upper case word" msgstr "Subtituír o cero pola letra «O» nunha palabra en maiúsculas" #: data/patterns/Latn-en.common-error.in:91 #: data/patterns/Latn.common-error.in:108 msgid "Space between number and unit" msgstr "Espazo entre número e unidade" #: data/patterns/Latn-en.common-error.in:92 #: data/patterns/Latn.common-error.in:109 msgid "Add or remove space between a number and the associated unit" msgstr "Engadir ou eliminar espazo entre un número e a unidade asociada" #: data/patterns/Latn-en.common-error.in:100 msgid "Spaces around an apostrophe" msgstr "Espazos arredor dun apóstrofo" #: data/patterns/Latn-en.common-error.in:101 msgid "Remove spaces around an apostrophe" msgstr "Eliminar os espazos arredor dun apóstrofo" #: data/patterns/Latn-en.common-error.in:109 #: data/patterns/Latn-en.common-error.in:118 msgid "Okay" msgstr "Okay" #: data/patterns/Latn-en.common-error.in:110 #: data/patterns/Latn-en.common-error.in:119 msgid "Spell two-letter forms of \"okay\" in all upper case" msgstr "" #: data/patterns/Latn-en.hearing-impaired.in:5 msgid "Uppercase speaker before a colon" msgstr "Falante en maiúsculas antes de dous puntos" #: data/patterns/Latn-en.hearing-impaired.in:6 msgid "" "Replace the uppercase name of the speaker before a colon with a dialogue " "dash" msgstr "" "Substituír o nome do falante en maiúsculas antes dos dous puntos cun trazo " "de diálogo" #: data/patterns/Latn-en.line-break.in:5 msgid "Title" msgstr "Título" #: data/patterns/Latn-en.line-break.in:6 msgid "Do not break after a title, e.g. \" Dr.\"" msgstr "" #: data/patterns/Latn-en.line-break.in:13 msgid "Article" msgstr "Artigo" #: data/patterns/Latn-en.line-break.in:14 msgid "Do not break after an article" msgstr "Non quebrar despois dun artigo" #: data/patterns/Latn-en.line-break.in:21 msgid "Preposition" msgstr "Preposición" #: data/patterns/Latn-en.line-break.in:22 msgid "Do not break after a preposition" msgstr "Non quebrar despois dunha preposición" #: data/patterns/Latn-en.line-break.in:30 msgid "Possessive determiner" msgstr "Determinante posesivo" #: data/patterns/Latn-en.line-break.in:31 msgid "Do not break after a possessive determiner, e.g. \"my\"" msgstr "Non quebrar despois dun determinante posesivo, p.ex. \"meu\"" #: data/patterns/Latn-fi.common-error.in:5 #: data/patterns/Latn.common-error.in:182 msgid "Space after punctuation marks" msgstr "Espazo despois de signos de puntuación" #: data/patterns/Latn-fi.common-error.in:6 #: data/patterns/Latn.common-error.in:183 msgid "Add space after various punctuation marks" msgstr "Engadir un espazo despois de diferentes signos de puntuación" #: data/patterns/Latn-fr.common-error.in:5 #: data/patterns/Latn-fr.common-error.in:14 #: data/patterns/Latn-fr.common-error.in:23 #: data/patterns/Latn-fr.common-error.in:32 msgid "Spaces around guillemets" msgstr "Espazos arredor de aspas" #: data/patterns/Latn-fr.common-error.in:6 #: data/patterns/Latn-fr.common-error.in:15 #: data/patterns/Latn-fr.common-error.in:24 #: data/patterns/Latn-fr.common-error.in:33 msgid "Add spaces around guillemets" msgstr "Engadir espazos arredor de aspas" #: data/patterns/Latn-fr.common-error.in:41 #: data/patterns/Latn-fr.common-error.in:52 #: data/patterns/Latn.common-error.in:171 msgid "Space before punctuation marks" msgstr "Espazo antes dos signos de puntuación" #: data/patterns/Latn-fr.common-error.in:42 #: data/patterns/Latn-fr.common-error.in:53 msgid "Add or remove space before various punctuation marks" msgstr "Engadir ou eliminar espazo antes de diferentes signos de puntuación" #: data/patterns/Latn.capitalization.in:5 msgid "Sentence" msgstr "Frase" #: data/patterns/Latn.capitalization.in:6 msgid "Capitalize the first word of a sentence" msgstr "Pór en maiúsculas a primeira palabra dunha frase" #: data/patterns/Latn.capitalization.in:12 msgid "Ellipsis" msgstr "Puntos suspensivos" #: data/patterns/Latn.capitalization.in:13 msgid "Capitalize after an ellipsis" msgstr "Pór en maiúsculas despois de puntos suspensivos" #: data/patterns/Latn.common-error.in:8 data/patterns/Latn.common-error.in:17 #: data/patterns/Latn.common-error.in:26 data/patterns/Latn.common-error.in:35 #: data/patterns/Latn.common-error.in:44 data/patterns/Latn.common-error.in:53 #: data/patterns/Latn.common-error.in:62 msgid "Ligatures" msgstr "" #: data/patterns/Latn.common-error.in:9 data/patterns/Latn.common-error.in:18 #: data/patterns/Latn.common-error.in:27 data/patterns/Latn.common-error.in:36 #: data/patterns/Latn.common-error.in:45 data/patterns/Latn.common-error.in:54 #: data/patterns/Latn.common-error.in:63 msgid "Unpack ligatures to individual characters" msgstr "" #: data/patterns/Latn.common-error.in:71 data/patterns/Latn.common-error.in:80 msgid "Spelling of a.m. and p.m." msgstr "Formas de escribir a.m. e p.m." #: data/patterns/Latn.common-error.in:72 data/patterns/Latn.common-error.in:81 msgid "Change the various spellings of 12-hour periods to \"a.m.\" and \"p.m.\"" msgstr "" "Cambiar as diferentes formas de escribir dos períodos de 12 horas a «a.m.» e" " «p.m.»" #: data/patterns/Latn.common-error.in:89 data/patterns/Latn.common-error.in:98 msgid "Letter \"O\" in a number" msgstr "Letra «O» nun número" #: data/patterns/Latn.common-error.in:90 data/patterns/Latn.common-error.in:99 msgid "Replace letter \"O\" with a zero in a number" msgstr "Substituír a letra «O» cun cero nos números" #: data/patterns/Latn.common-error.in:117 msgid "Double apostrophe" msgstr "Dobre apóstrofo" #: data/patterns/Latn.common-error.in:118 msgid "Replace a double apostrophe with a quotation mark" msgstr "Substituír os dobres apóstrofos con comiñas" #: data/patterns/Latn.common-error.in:126 #: data/patterns/Latn.common-error.in:135 #: data/patterns/Latn.common-error.in:144 #: data/patterns/Latn.common-error.in:153 msgid "Spaces around brackets" msgstr "Espazos arredor de parénteses" #: data/patterns/Latn.common-error.in:127 #: data/patterns/Latn.common-error.in:136 #: data/patterns/Latn.common-error.in:145 #: data/patterns/Latn.common-error.in:154 msgid "Add or remove spaces around parantheses and square brackets" msgstr "Engadir ou eliminar espazos arredor de parénteses e corchetes" #: data/patterns/Latn.common-error.in:162 msgid "Space after a dialogue dash" msgstr "Espazo despois dun trazo de diálogo" #: data/patterns/Latn.common-error.in:163 msgid "Add space after a dialogue dash" msgstr "Engadir espazo despois dun trazo de diálogo" #: data/patterns/Latn.common-error.in:172 msgid "Remove space before various punctuation marks" msgstr "Eliminar espazo antes de diferentes signos de puntuación" #: data/patterns/Latn.common-error.in:192 msgid "Space after an ellipsis" msgstr "Espazo despois de puntos suspensivos" #: data/patterns/Latn.common-error.in:193 msgid "Add space after an ellipsis" msgstr "Engadir espazo despois dos puntos suspensivos" #: data/patterns/Latn.common-error.in:201 msgid "Space after a starting ellipsis" msgstr "Espazo despois de puntos suspensivos iniciais" #: data/patterns/Latn.common-error.in:202 msgid "Remove space after an ellipsis that starts a line" msgstr "" "Eliminar o espazo despois duns puntos suspensivos ao comezo dunha liña" #: data/patterns/Latn.common-error.in:210 #: data/patterns/Latn.common-error.in:221 #: data/patterns/Latn.common-error.in:232 #: data/patterns/Latn.common-error.in:242 msgid "Spaces around a quotation mark" msgstr "Espazos arredor de comiñas" #: data/patterns/Latn.common-error.in:211 #: data/patterns/Latn.common-error.in:222 #: data/patterns/Latn.common-error.in:233 #: data/patterns/Latn.common-error.in:243 msgid "Remove space after a starting- and before an ending quotation mark" msgstr "" "Eliminar espazo despois dunhas comiñas iniciais e antes dunhas comiñas " "finais" #: data/patterns/Latn.common-error.in:252 #: data/patterns/Latn.common-error.in:261 msgid "Spaces around musical notes" msgstr "" #: data/patterns/Latn.common-error.in:253 #: data/patterns/Latn.common-error.in:262 msgid "Add spaces between musical note characters and lyrics" msgstr "" #: data/patterns/Latn.common-error.in:270 #: data/patterns/Latn.common-error.in:279 msgid "Multiple question- and exclamation marks" msgstr "Múltiples signos de interrogación e exclamación" #: data/patterns/Latn.common-error.in:271 #: data/patterns/Latn.common-error.in:280 msgid "" "Replace multiple consequtive question- and exclamation marks with only one" msgstr "" "Substituír os signos de interrogación (ou exclamación) múltiples " "consecutivos por só un " #: data/patterns/Latn.common-error.in:288 #: data/patterns/Latn.common-error.in:298 msgid "Periods around a punctuation mark" msgstr "Puntos arredor de signos de puntuación" #: data/patterns/Latn.common-error.in:289 #: data/patterns/Latn.common-error.in:299 msgid "Remove period before or after various punctuation marks" msgstr "Retirar os puntos antes ou despois de diferentes signos de puntuación" #: data/patterns/Latn.common-error.in:308 msgid "Terminating double-dashes" msgstr "" #: data/patterns/Latn.common-error.in:309 msgid "Replace a single clause-terminating dash with two dashes" msgstr "" #: data/patterns/Latn.hearing-impaired.in:5 msgid "Sound in brackets" msgstr "Son entre corchetes" #: data/patterns/Latn.hearing-impaired.in:6 msgid "Remove description of a sound between square brackets" msgstr "Retirar a descrición dun son entre corchetes" #: data/patterns/Latn.hearing-impaired.in:12 msgid "Sound in parantheses" msgstr "Son entre parénteses" #: data/patterns/Latn.hearing-impaired.in:13 msgid "Remove description of a sound between parantheses" msgstr "Retirar a descrición dun son entre parénteses" #: data/patterns/Latn.hearing-impaired.in:19 msgid "Song lyrics between number signs" msgstr "Letra de canción entre signos de número" #: data/patterns/Latn.hearing-impaired.in:20 msgid "Remove song lyrics starting with or between number signs" msgstr "" "Retirar a letra de cancións que comece con, ou estea entre signos de número" #: data/patterns/Latn.hearing-impaired.in:27 msgid "One-line song lyrics between number signs" msgstr "" #: data/patterns/Latn.hearing-impaired.in:28 msgid "Remove one-line song lyrics starting with or between number signs" msgstr "" #: data/patterns/Latn.hearing-impaired.in:35 msgid "Speaker before a colon" msgstr "Falante antes de dous puntos" #: data/patterns/Latn.hearing-impaired.in:36 msgid "Replace the name of the speaker before a colon with a dialogue dash" msgstr "" "Substituír o nome do falante antes dos dous puntos cun trazo de diálogo" #: data/patterns/Latn.line-break.in:5 data/patterns/Latn.line-break.in:13 msgid "Dialogue" msgstr "Diálogo" #: data/patterns/Latn.line-break.in:6 data/patterns/Latn.line-break.in:14 msgid "Break according to dialogue separated by dashes" msgstr "Quebrar de acordo ao diálogo separado mediante trazos" #: data/patterns/Latn.line-break.in:21 data/patterns/Latn.line-break.in:30 msgid "Clause" msgstr "" #: data/patterns/Latn.line-break.in:22 data/patterns/Latn.line-break.in:31 msgid "Break according to clauses terminated by a punctuation mark" msgstr "" #: data/patterns/Latn.line-break.in:38 msgid "Number and unit" msgstr "Número e unidade" #: data/patterns/Latn.line-break.in:39 msgid "Do not break between a number and associated unit" msgstr "Non quebrar entre un número e a unidade asociada" #: data/patterns/Zyyy.common-error.in:5 data/patterns/Zyyy.common-error.in:14 msgid "Leading and trailing spaces" msgstr "Espazos iniciais e finais" #: data/patterns/Zyyy.common-error.in:6 data/patterns/Zyyy.common-error.in:15 msgid "Remove spaces from the beginning and end of lines" msgstr "Retirar os espazos do comezo e do final das liñas" #: data/patterns/Zyyy.common-error.in:23 msgid "Multiple consecutive spaces" msgstr "Varios espazos consecutivos" #: data/patterns/Zyyy.common-error.in:24 msgid "Replace multiple consecutive spaces with only one" msgstr "Substituír múltiples espazos consecutivos por só un" #: data/patterns/Zyyy.common-error.in:32 data/patterns/Zyyy.common-error.in:45 #: data/patterns/Zyyy.common-error.in:55 data/patterns/Zyyy.common-error.in:65 msgid "Space between digits" msgstr "Espazo entre díxitos" #: data/patterns/Zyyy.common-error.in:33 data/patterns/Zyyy.common-error.in:46 #: data/patterns/Zyyy.common-error.in:56 data/patterns/Zyyy.common-error.in:66 msgid "Remove space between digits of a number" msgstr "Eliminar o espazo entre os díxitos dun número" #: data/patterns/Zyyy.common-error.in:79 msgid "Musical notes" msgstr "Notas musicais" #: data/patterns/Zyyy.common-error.in:80 msgid "Replace Unicode musical note characters with number signs" msgstr "" #: data/io.otsaloma.gaupol.appdata.xml.in:7 msgid "Editor for text-based subtitles" msgstr "" #: data/io.otsaloma.gaupol.appdata.xml.in:9 msgid "" "Gaupol is an editor for text-based subtitle files. It supports multiple " "subtitle file formats and provides means of creating subtitles, editing " "texts and timing subtitles to match video." msgstr "" #: data/io.otsaloma.gaupol.appdata.xml.in:40 msgid "Main window" msgstr "" #: data/io.otsaloma.gaupol.desktop.in:5 msgid "Subtitle Editor" msgstr "Editor de subtítulos" #: data/io.otsaloma.gaupol.desktop.in:6 msgid "Edit subtitle files" msgstr "Editar ficheiros de subtítulos" #. TRANSLATORS: Search terms to find this application. Do NOT translate or #. localize the semicolons! The list MUST also end with a semicolon! #: data/io.otsaloma.gaupol.desktop.in:12 msgid "video;subtitles;captions;" msgstr "" gaupol-1.11/po/he.po000066400000000000000000002210051422217132500142740ustar00rootroot00000000000000# 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. # # Translators: # Osmo Salomaa , 2016 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-04-03 04:00+0300\n" "PO-Revision-Date: 2016-07-07 00:55+0000\n" "Last-Translator: Osmo Salomaa , 2016\n" "Language-Team: Hebrew (https://www.transifex.com/otsaloma/teams/64879/he/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: he\n" "Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;\n" #: aeidon/enums.py:40 gaupol/enums.py:38 msgid "Subtitle number" msgstr "מספר הכתובית" #: aeidon/enums.py:43 msgid "Subtitle position" msgstr "מיקום הכתובית" #: aeidon/enums.py:59 msgid "23.976 fps" msgstr "" #: aeidon/enums.py:63 msgid "24.000 fps" msgstr "" #: aeidon/enums.py:67 msgid "25.000 fps" msgstr "" #: aeidon/enums.py:71 msgid "29.970 fps" msgstr "" #: aeidon/enums.py:75 data/ui/menubar.ui:248 msgid "30.000 fps" msgstr "" #: aeidon/enums.py:79 data/ui/menubar.ui:253 msgid "50.000 fps" msgstr "" #: aeidon/enums.py:83 data/ui/menubar.ui:258 msgid "59.940 fps" msgstr "" #: aeidon/enums.py:87 data/ui/menubar.ui:263 msgid "60.000 fps" msgstr "" #: aeidon/enums.py:112 msgid "Mac (classic)" msgstr "מק (קלאסי)" #. TRANSLATORS: Most of the character encoding descriptions are copied from #. gedit, which is translated to very many languages. Check the gedit .po #. files for a reference: #. . #: aeidon/encodings.py:40 aeidon/encodings.py:43 aeidon/encodings.py:46 msgid "English" msgstr "אנגלית" #: aeidon/encodings.py:41 aeidon/encodings.py:42 aeidon/encodings.py:69 msgid "Chinese traditional" msgstr "סינית מסורתית" #: aeidon/encodings.py:44 msgid "German" msgstr "" #: aeidon/encodings.py:45 aeidon/encodings.py:54 aeidon/encodings.py:59 #: aeidon/encodings.py:79 aeidon/encodings.py:105 msgid "Hebrew" msgstr "עברית" #: aeidon/encodings.py:47 aeidon/encodings.py:51 aeidon/encodings.py:56 #: aeidon/encodings.py:73 aeidon/encodings.py:76 aeidon/encodings.py:98 #: aeidon/encodings.py:111 aeidon/encodings.py:122 msgid "Western" msgstr "מערבי" #: aeidon/encodings.py:48 aeidon/encodings.py:61 aeidon/encodings.py:80 #: aeidon/encodings.py:103 msgid "Arabic" msgstr "ערבית" #: aeidon/encodings.py:49 aeidon/encodings.py:64 aeidon/encodings.py:66 #: aeidon/encodings.py:77 aeidon/encodings.py:104 aeidon/encodings.py:119 msgid "Greek" msgstr "יוונית" #: aeidon/encodings.py:50 aeidon/encodings.py:81 aeidon/encodings.py:101 #: aeidon/encodings.py:109 msgid "Baltic" msgstr "בלטית" #: aeidon/encodings.py:52 aeidon/encodings.py:74 aeidon/encodings.py:99 #: aeidon/encodings.py:121 msgid "Central European" msgstr "מרכז אירופאי" #: aeidon/encodings.py:53 aeidon/encodings.py:75 aeidon/encodings.py:102 #: aeidon/encodings.py:118 msgid "Cyrillic" msgstr "קירילי" #: aeidon/encodings.py:55 aeidon/encodings.py:71 aeidon/encodings.py:78 #: aeidon/encodings.py:106 aeidon/encodings.py:123 msgid "Turkish" msgstr "טורקית" #: aeidon/encodings.py:57 msgid "Portuguese" msgstr "פורטוגזית" #: aeidon/encodings.py:58 aeidon/encodings.py:120 msgid "Icelandic" msgstr "איסלנדית" #: aeidon/encodings.py:60 msgid "Canadian" msgstr "קנדי" #: aeidon/encodings.py:62 aeidon/encodings.py:107 msgid "Nordic" msgstr "נורדי" #: aeidon/encodings.py:63 aeidon/encodings.py:114 msgid "Russian" msgstr "רוסית" #: aeidon/encodings.py:65 aeidon/encodings.py:108 msgid "Thai" msgstr "תאילנדית" #: aeidon/encodings.py:67 aeidon/encodings.py:83 aeidon/encodings.py:84 #: aeidon/encodings.py:85 aeidon/encodings.py:91 aeidon/encodings.py:92 #: aeidon/encodings.py:93 aeidon/encodings.py:94 aeidon/encodings.py:95 #: aeidon/encodings.py:96 aeidon/encodings.py:125 aeidon/encodings.py:126 #: aeidon/encodings.py:127 msgid "Japanese" msgstr "יפנית" #: aeidon/encodings.py:68 aeidon/encodings.py:86 aeidon/encodings.py:97 #: aeidon/encodings.py:113 msgid "Korean" msgstr "קוריאנית" #: aeidon/encodings.py:70 msgid "Urdu" msgstr "אורדו" #: aeidon/encodings.py:72 aeidon/encodings.py:116 msgid "Ukrainian" msgstr "אוקראינית" #: aeidon/encodings.py:82 msgid "Vietnamese" msgstr "וייטנאמית" #: aeidon/encodings.py:87 aeidon/encodings.py:90 msgid "Chinese simplified" msgstr "סינית מופשטת" #: aeidon/encodings.py:88 aeidon/encodings.py:89 msgid "Chinese unified" msgstr "סינית אחידה" #: aeidon/encodings.py:100 aeidon/encodings.py:112 msgid "South European" msgstr "דרום אירופאי" #: aeidon/encodings.py:110 msgid "Celtic" msgstr "סלטיק" #: aeidon/encodings.py:115 msgid "Tajik" msgstr "" #: aeidon/encodings.py:117 msgid "Kazakh" msgstr "" #: aeidon/encodings.py:124 msgid "Cyrillic Asian" msgstr "קירילי אסיתי" #: aeidon/encodings.py:128 aeidon/encodings.py:129 aeidon/encodings.py:130 #: aeidon/encodings.py:131 aeidon/encodings.py:132 aeidon/encodings.py:133 #: aeidon/encodings.py:134 aeidon/encodings.py:135 aeidon/encodings.py:136 msgid "Unicode" msgstr "יוניקוד" #: aeidon/encodings.py:156 #, python-brace-format msgid "{description} ({name})" msgstr "{description} ({name})" #: aeidon/encodings.py:232 msgid "Current locale ({})" msgstr "סוג כתב נוכחי ({})" #: aeidon/locales.py:46 #, python-brace-format msgid "{language} ({country})" msgstr "{language} ({country})" #: aeidon/agents/search.py:227 msgid "Replacing" msgstr "מתבצעת החלפה" #: aeidon/agents/search.py:256 aeidon/agents/search.py:258 msgid "Replacing all" msgstr "הכול מוחלף" #: aeidon/agents/position.py:74 msgid "Adjusting durations" msgstr "פרקי הזמן מתואמים" #: aeidon/agents/position.py:96 msgid "Converting framerate" msgstr "קצב השקופיות מומר" #: aeidon/agents/position.py:146 msgid "Setting framerate" msgstr "הגדרת קצב השקופיות" #: aeidon/agents/position.py:168 msgid "Shifting positions" msgstr "הזזת המקומות" #: aeidon/agents/position.py:188 msgid "Transforming positions" msgstr "החלפת המקומות" #: aeidon/agents/clipboard.py:44 msgid "Cutting texts" msgstr "הטקסטים נגזרים" #: aeidon/agents/clipboard.py:61 msgid "Pasting texts" msgstr "הטקסטים מודבקים" #: aeidon/agents/text.py:91 msgid "Breaking lines" msgstr "השורות נשברות" #: aeidon/agents/text.py:128 msgid "Capitalizing texts" msgstr "הרשיות בטקסטים מתואמות" #: aeidon/agents/text.py:185 msgid "Correcting common errors" msgstr "שגיאות נפוצות מתוקנות" #: aeidon/agents/text.py:234 msgid "Removing hearing impaired texts" msgstr "מוסרים טקסטים המותאמים ללקויי שמיעה" #: aeidon/agents/text.py:315 msgid "Joining words by spell-check suggestions" msgstr "צירוף מילים לפי הצעות בדיקות איות" #: aeidon/agents/text.py:354 msgid "Splitting words by spell-check suggestions" msgstr "פיצול מילים לפי הצעות בדיקת איות" #: aeidon/agents/set.py:58 aeidon/agents/set.py:80 aeidon/agents/set.py:113 msgid "Editing position" msgstr "המיקום נערך" #: aeidon/agents/set.py:129 msgid "Editing text" msgstr "הטקסט נערך" #: aeidon/agents/edit.py:35 msgid "Clearing texts" msgstr "הטקסטים נמחקים" #: aeidon/agents/edit.py:61 aeidon/agents/edit.py:83 msgid "Inserting subtitles" msgstr "הכתוביות נוספות" #: aeidon/agents/edit.py:103 msgid "Merging subtitles" msgstr "הכתוביות מתמזגות" #: aeidon/agents/edit.py:114 msgid "Removing subtitles" msgstr "הכתוביות מוסרות" #: aeidon/agents/edit.py:131 msgid "Replacing positions" msgstr "המיקומים מוחלפים" #: aeidon/agents/edit.py:147 msgid "Replacing texts" msgstr "הטקסטים מוחלפים" #: aeidon/agents/edit.py:171 msgid "Splitting subtitle" msgstr "הכתובית מפוצלת" #: aeidon/agents/format.py:49 msgid "Adding dialogue dashes" msgstr "מקפי הדו־שיח נוספים" #: aeidon/agents/format.py:68 msgid "Changing case" msgstr "שינוי בין קטנות לרשיות" #: aeidon/agents/format.py:92 msgid "Italicizing" msgstr "ההטיה מוחלת" #: aeidon/agents/format.py:108 msgid "Removing dialogue dashes" msgstr "מקפי הדו־שיח מוסרים" #: aeidon/agents/format.py:174 msgid "Unitalicizing" msgstr "ההטיה מבוטלת" #: gaupol/application.py:219 gaupol/agents/open.py:203 msgid "Open" msgstr "פתיחה" #: gaupol/application.py:223 msgid "Open main files" msgstr "פתיחת הקבצים הראשיים" #: gaupol/application.py:230 msgid "Save" msgstr "" #: gaupol/application.py:233 msgid "Save the current main document" msgstr "שמירת המסמך הראשי הנוכחי" #: gaupol/application.py:238 msgid "Undo" msgstr "" #: gaupol/application.py:242 msgid "Undo the last action" msgstr "ביטול הפעולה האחרונה" #: gaupol/application.py:249 msgid "Redo" msgstr "" #: gaupol/application.py:252 msgid "Redo the last undone action" msgstr "ביצוע מחדש של הפעולה האחרונה שבוטלה" #: gaupol/application.py:260 msgid "Insert" msgstr "הוספה" #: gaupol/application.py:262 msgid "Insert new subtitles" msgstr "הוספת כתוביות חדשות" #: gaupol/application.py:266 #: data/extensions/custom-framerates/preferences-dialog.ui:78 msgid "Remove" msgstr "הסרה" #: gaupol/application.py:268 msgid "Remove the selected subtitles" msgstr "הסרת הכתוביות הנבחרות" #: gaupol/application.py:273 data/ui/search-dialog.ui:283 msgid "Find" msgstr "חיפוש" #: gaupol/application.py:275 msgid "Search for and replace text" msgstr "חיפוש והחלפה של טקסט" #: gaupol/application.py:279 data/ui/preferences-dialog.ui:942 msgid "Video" msgstr "וידאו" #: gaupol/application.py:281 msgid "Show or hide the video player" msgstr "" #: gaupol/application.py:285 data/ui/preferences-dialog.ui:1173 msgid "Preview" msgstr "תצוגה מקדימה" #: gaupol/application.py:287 msgid "Preview from selected position with a video player" msgstr "הצגה מקדימה מהמיקום הנבחר באמצעות נגן וידאו" #: gaupol/enums.py:37 msgid "No." msgstr "מס׳" #: gaupol/enums.py:43 msgid "Start" msgstr "התחלה" #: gaupol/enums.py:44 msgid "Start position" msgstr "מיקום ההתחלה" #: gaupol/enums.py:49 msgid "End" msgstr "סוף" #: gaupol/enums.py:50 msgid "End position" msgstr "מיקום הסוף" #. TRANSLATORS: 'Dur.' is short for duration. It is used in the header #. of a column that contains numbers five digits wide. #: gaupol/enums.py:57 msgid "Dur." msgstr "משך" #: gaupol/enums.py:58 msgid "Duration" msgstr "משך" #: gaupol/enums.py:63 gaupol/enums.py:64 msgid "Text" msgstr "" #: gaupol/enums.py:69 gaupol/enums.py:70 msgid "Translation" msgstr "" #: gaupol/enums.py:82 msgid "characters" msgstr "תווים" #: gaupol/enums.py:85 msgid "ems" msgstr "ems" #: gaupol/page.py:60 msgid "Untitled {:d}" msgstr "ללא שם {:d}" #: gaupol/page.py:133 msgid "Close project" msgstr "סגירת המיזם" #: gaupol/page.py:145 msgid "{} translation" msgstr "תרגום {}" #: gaupol/page.py:302 msgid "Path:" msgstr "נתיב:" #: gaupol/page.py:303 msgid "Format:" msgstr "מבנה:" #: gaupol/page.py:304 msgid "Encoding:" msgstr "" #: gaupol/page.py:305 msgid "Newlines:" msgstr "שורות חדשות:" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:99 msgid "Tasks and Target" msgstr "" #: gaupol/assistants.py:128 msgid "Correct texts in the text column" msgstr "" #: gaupol/assistants.py:129 msgid "Correct texts in the translation column" msgstr "" #: gaupol/assistants.py:138 msgid "Correct texts in selected subtitles" msgstr "" #: gaupol/assistants.py:139 msgid "Correct texts in current project" msgstr "" #: gaupol/assistants.py:140 msgid "Correct texts in all open projects" msgstr "" #: gaupol/assistants.py:363 msgid "Other" msgstr "אחר" #: gaupol/assistants.py:439 msgid "Capitalize texts written in lower case" msgstr "הפיכת טקסטים שנכתבו באותיות קטנות לאותיות רשיות" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:443 msgid "Capitalization Patterns" msgstr "" #: gaupol/assistants.py:445 msgid "Capitalize texts" msgstr "הגדלת אותיות בטקסט (המרה לרשיות)" #: gaupol/assistants.py:468 msgid "Correct common errors made by humans or image recognition software" msgstr "תיקון שגיאות נפוצות שבוצעו על ידי בני אדם או תוכנות לזיהוי תמונה" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:472 msgid "Common Error Patterns" msgstr "" #: gaupol/assistants.py:474 msgid "Correct common errors" msgstr "תיקון שגיאות נפוצות" #: gaupol/assistants.py:526 msgid "Remove explanatory texts meant for the hearing impaired" msgstr "הסרת טקסט הסברה המיועד ללקויי שמיעה" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:530 msgid "Hearing Impaired Patterns" msgstr "" #: gaupol/assistants.py:532 msgid "Remove hearing impaired texts" msgstr "הסרת טקסטים המותאמים ללקויי שמיעה" #: gaupol/assistants.py:544 msgid "" "Use spell-check suggestions to fix whitespace detection errors of image " "recognition software" msgstr "" "יש להשתמש בהצעות מבודק האיות כדי לתקן שגיאות בזיהוי רווחים שנעשות על ידי " "תוכנות לזיהוי תמונה" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:548 msgid "Joining and Splitting Words" msgstr "" #: gaupol/assistants.py:550 msgid "Join or Split Words" msgstr "צירוף או פיצול מילים" #: gaupol/assistants.py:599 gaupol/agents/tools.py:45 msgid "Failed to load dictionary for language \"{}\"" msgstr "ארע כשל בטעינת המילון עבור השפה״{}״" #: gaupol/assistants.py:601 gaupol/player.py:263 gaupol/player.py:381 #: gaupol/dialogs/search.py:560 gaupol/dialogs/search.py:568 #: gaupol/dialogs/text_edit.py:49 gaupol/dialogs/encoding.py:56 #: gaupol/agents/open.py:328 gaupol/agents/open.py:337 #: gaupol/agents/open.py:345 gaupol/agents/open.py:354 #: gaupol/agents/tools.py:48 gaupol/agents/save.py:197 #: gaupol/agents/save.py:205 gaupol/agents/preview.py:108 #: gaupol/agents/preview.py:116 gaupol/agents/preview.py:125 #: gaupol/agents/preview.py:133 msgid "_OK" msgstr "" #: gaupol/assistants.py:635 msgid "Break text into lines of defined length" msgstr "שבירת טקסט לשורות באורך המוגדר" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:639 msgid "Line-Break Patterns" msgstr "" #: gaupol/assistants.py:641 msgid "Break lines" msgstr "שבירת שורות" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:679 msgid "Line-Break Options" msgstr "" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:763 msgid "Correcting Texts" msgstr "טקסטים לתיקון" #: gaupol/assistants.py:769 msgid "Each task is now being run on each project." msgstr "כל משימה מתבצעת כעת על כל מיזם." #: gaupol/assistants.py:793 #, python-brace-format msgid "{current:d} of {total:d} tasks complete" msgstr "{current:d} מתוך {total:d} משימות הושלמו" #: gaupol/assistants.py:801 msgid "Project: {}" msgstr "מיזם: {}" #: gaupol/assistants.py:807 msgid "Task: {}" msgstr "משימה: {}" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:832 msgid "Confirm Changes" msgstr "קבלת השינויים" #: gaupol/assistants.py:892 msgid "Accept" msgstr "קבלה" #: gaupol/assistants.py:898 msgid "Original Text" msgstr "הטקסט המקורי" #: gaupol/assistants.py:899 msgid "Corrected Text" msgstr "הטקסט המתוקן" #: gaupol/assistants.py:1048 msgid "Correct Texts" msgstr "תיקון הטקסטים" #: gaupol/assistants.py:1076 msgid "Correcting texts" msgstr "הטקסטים מתוקנים" #: gaupol/assistants.py:1092 #, python-brace-format msgid "Edited {edits:d} and removed {removals:d} subtitles" msgstr "נערכו {edits:d} והוסרו {removals:d} כתוביות" #: gaupol/assistants.py:1126 msgid "Confirm {:d} Change" msgid_plural "Confirm {:d} Changes" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" #: gaupol/renderers/multiline.py:86 msgid "Italic" msgstr "" #: gaupol/player.py:372 msgid "No video streams found" msgstr "" #: gaupol/player.py:379 msgid "Failed to initialize playback" msgstr "" #: gaupol/dialogs/search.py:189 data/ui/menubar.ui:524 msgid "_Help" msgstr "ע_זרה" #: gaupol/dialogs/search.py:471 msgid "Found and replaced {:d} occurence" msgid_plural "Found and replaced {:d} occurences" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" #: gaupol/dialogs/search.py:488 msgid "\"{}\" not found" msgstr "״{}״ לא נמצא" #: gaupol/dialogs/search.py:558 msgid "Error in regular expression pattern" msgstr "שגיאה בתבנית הביטוי הרגולרי" #: gaupol/dialogs/search.py:566 msgid "Error in regular expression replacement" msgstr "שגיאה בהחלפת הביטוי הרגולרי" #: gaupol/dialogs/text_edit.py:48 gaupol/dialogs/framerate_convert.py:63 #: gaupol/dialogs/insert.py:44 gaupol/dialogs/encoding.py:55 #: gaupol/dialogs/split.py:44 gaupol/dialogs/multi_close.py:54 #: gaupol/dialogs/open.py:63 gaupol/dialogs/position_transform.py:69 #: gaupol/dialogs/position_shift.py:71 gaupol/dialogs/multi_save.py:83 #: gaupol/dialogs/multi_save.py:215 gaupol/dialogs/duration_adjust.py:86 #: gaupol/dialogs/save.py:73 gaupol/dialogs/video.py:41 #: gaupol/agents/open.py:363 gaupol/agents/open.py:375 #: gaupol/agents/open.py:387 gaupol/agents/close.py:71 #: data/extensions/custom-framerates/custom-framerates.py:39 msgid "_Cancel" msgstr "" #: gaupol/dialogs/text_edit.py:53 msgid "Edit Text" msgstr "עריכת טקסט" #: gaupol/dialogs/framerate_convert.py:64 msgid "Co_nvert" msgstr "ה_מרה" #: gaupol/dialogs/insert.py:45 msgid "_Insert" msgstr "הו_ספה" #: gaupol/dialogs/insert.py:54 msgid "Above selection" msgstr "מעל לבחירה" #: gaupol/dialogs/insert.py:55 msgid "Below selection" msgstr "מתחת לבחירה" #: gaupol/dialogs/encoding.py:60 data/ui/preferences-dialog.ui:70 msgid "Character Encodings" msgstr "קידוד תווים" #: gaupol/dialogs/encoding.py:78 gaupol/dialogs/encoding.py:125 msgid "Description" msgstr "תיאור" #: gaupol/dialogs/encoding.py:85 gaupol/dialogs/encoding.py:132 msgid "Encoding" msgstr "קידוד" #: gaupol/dialogs/encoding.py:141 msgid "Show in Menu" msgstr "הצגה בתפריט" #: gaupol/dialogs/split.py:45 msgid "_Split" msgstr "_פיצול" #: gaupol/dialogs/split.py:76 msgid "Splitting project" msgstr "פיצול מיזם" #: gaupol/dialogs/split.py:97 #, python-brace-format msgid "Split {amount:d} subtitles to project \"{name}\"" msgstr "פיצול {amount:d} כתוביות למיזם {name}" #: gaupol/dialogs/spell_check.py:269 msgid "Spell-checking" msgstr "בדיקת איות" #: gaupol/dialogs/preferences.py:217 msgid "{} Extension Website" msgstr "אתר ההרחבות {}" #: gaupol/dialogs/preferences.py:429 msgid "Custom" msgstr "התאמה אישית" #: gaupol/dialogs/multi_close.py:38 msgid "Save changes to documents before closing?" msgstr "האם לשמור את השינויים למסמכים בטרם הסגירה?" #: gaupol/dialogs/multi_close.py:39 gaupol/agents/open.py:384 #: gaupol/agents/close.py:68 msgid "If you don't save, changes will be permanently lost." msgstr "אם השינויים לא ישמרו, הם יאבדו לעד." #: gaupol/dialogs/multi_close.py:53 gaupol/agents/close.py:70 msgid "Close _Without Saving" msgstr "סגירה _ללא שמירה" #: gaupol/dialogs/multi_close.py:55 gaupol/dialogs/multi_save.py:84 #: gaupol/dialogs/save.py:74 gaupol/agents/open.py:388 #: gaupol/agents/close.py:72 data/ui/menubar.ui:34 msgid "_Save" msgstr "_שמירה" #: gaupol/dialogs/multi_close.py:70 msgid "Select the _main documents you want to save:" msgstr "נא לבחור את המסמכים ה_ראשיים שברצונך לשמור:" #: gaupol/dialogs/multi_close.py:95 msgid "Select the _translation documents you want to save:" msgstr "נא לבחור את מסמכים ה_תרגום שברצונך לשמור:" #: gaupol/dialogs/open.py:64 gaupol/agents/open.py:364 #: gaupol/agents/open.py:376 msgid "_Open" msgstr "" #: gaupol/dialogs/position_transform.py:70 msgid "_Transform" msgstr "ה_חלפה" #: gaupol/dialogs/position_shift.py:72 msgid "_Shift" msgstr "ה_זזה" #: gaupol/dialogs/position_shift.py:150 msgid "frames" msgstr "שקופיות" #: gaupol/dialogs/position_shift.py:168 data/ui/preferences-dialog.ui:911 msgid "seconds" msgstr "שניות" #: gaupol/dialogs/about.py:36 msgid "About Gaupol" msgstr "על אודות Gaupol" #: gaupol/dialogs/about.py:40 msgid "Subtitle editor" msgstr "עורך הכתוביות" #. TRANSLATORS: This is a special message that shouldn't be translated #. literally. It is used in the about dialog to give credits to the #. translators. Thus, you should translate it to your name and email #. address. You can also include other translators who have contributed #. to this translation; in that case, please write them on separate #. lines seperated by newlines (\n). #: gaupol/dialogs/about.py:51 msgid "translator-credits" msgstr "ירון שהרבני " #: gaupol/dialogs/about.py:54 msgid "Gaupol Website" msgstr "האתר של Gaupol" #: gaupol/dialogs/append.py:35 msgid "Append File" msgstr "הוספת קובץ" #: gaupol/dialogs/debug.py:43 msgid "Something went wrong" msgstr "" #: gaupol/dialogs/debug.py:44 msgid "" "You have probably discovered a bug. Please report it by providing the below " "information and a description of what you were doing." msgstr "" #: gaupol/dialogs/debug.py:52 msgid "_Report Bug" msgstr "" #: gaupol/dialogs/debug.py:53 data/ui/menubar.ui:56 msgid "_Quit" msgstr "י_ציאה" #: gaupol/dialogs/debug.py:54 gaupol/dialogs/preview_error.py:45 #: data/ui/menubar.ui:52 data/ui/tab-popup.ui:16 msgid "_Close" msgstr "_סגירה" #: gaupol/dialogs/multi_save.py:98 gaupol/dialogs/save.py:110 msgid "{} (recommended)" msgstr "" #: gaupol/dialogs/multi_save.py:212 msgid "" "{:d} of the files to be saved already exist. Do you want to replace them?" msgstr "{:d} מתוך הקבצים לשמירה כבר קיימים. האם ברצונך להחליף אותם?" #: gaupol/dialogs/multi_save.py:213 msgid "" "The files already exist in \"{}\". Replacing them will overwrite their " "contents." msgstr "הקבצים כבר קיימים תחת ״{}״. החלפתם תשכתב על תוכנם." #: gaupol/dialogs/multi_save.py:216 data/ui/search-dialog.ui:192 #: data/ui/spell-check-dialog.ui:122 msgid "_Replace" msgstr "ה_חלפה" #: gaupol/dialogs/duration_adjust.py:70 msgid "Adjusted duration of {:d} subtitle" msgid_plural "Adjusted durations of {:d} subtitles" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" #: gaupol/dialogs/duration_adjust.py:87 msgid "_Adjust" msgstr "ה_תאמה" #: gaupol/dialogs/preview_error.py:36 msgid "Preview in video player failed" msgstr "התצוגה המקדימה בנגן הווידאו נכשלה" #: gaupol/dialogs/preview_error.py:37 msgid "" "There is probably a problem with either the video file or the video player. " "See the preferences dialog to choose the video player or to customize the " "command." msgstr "" #: gaupol/dialogs/language.py:97 msgid "Set Language" msgstr "הגדרת שפה" #: gaupol/dialogs/video.py:52 gaupol/dialogs/file.py:59 msgid "All files" msgstr "כל הקבצים" #: gaupol/dialogs/video.py:56 msgid "Video files" msgstr "קובצי וידאו" #: gaupol/dialogs/file.py:63 msgid "All supported files" msgstr "כל הקבצים הנתמכים" #: gaupol/dialogs/file.py:77 #, python-brace-format msgid "{format} (*{extension})" msgstr "" #: gaupol/dialogs/file.py:120 msgid "Auto-detected" msgstr "זיהוי אוטומטי" #: gaupol/dialogs/file.py:122 msgid "Other…" msgstr "אחר…" #: gaupol/agents/menu.py:94 gaupol/agents/menu.py:103 #: gaupol/agents/menu.py:110 msgid "File not found" msgstr "" #: gaupol/agents/open.py:85 #, python-brace-format msgid "Appended {amount:d} subtitles from \"{basename}\"" msgstr "האם להוסיף {amount:d} כתוביות מ־״{basename}״" #: gaupol/agents/open.py:96 msgid "Appending file" msgstr "הקובץ מתווסף" #: gaupol/agents/open.py:111 msgid "File \"{}\" is already open" msgstr "הקובץ ״{}״ כבר פתוח" #: gaupol/agents/open.py:214 msgid "Open Translation" msgstr "פתיחת תרגום" #: gaupol/agents/open.py:223 msgid "Select Video" msgstr "בחירת וידאו" #: gaupol/agents/open.py:224 msgid "_Select" msgstr "_בחירה" #: gaupol/agents/open.py:325 msgid "Failed to decode file \"{}\" with all attempted codecs" msgstr "ארע כשל בפענוח הקובץ ״{}״ עם כל המקודדים שנוסו" #: gaupol/agents/open.py:326 msgid "Please try to open the file with a different character encoding." msgstr "נא לנסות לפתוח את הקובץ עם קידוד תווים שונה." #: gaupol/agents/open.py:334 msgid "Failed to recognize format of file \"{}\"" msgstr "ארע כשל בזיהוי מבנה הקובץ ״{}״" #: gaupol/agents/open.py:335 msgid "" "Please check that the file you are trying to open is a subtitle file of a " "format supported by Gaupol." msgstr "נא לבדוק שהקובץ המועמד לפתיחה הוא מסוג קובץ הנתמך על ידי Gaupol." #: gaupol/agents/open.py:343 msgid "Failed to open file \"{}\"" msgstr "ארע כשל בפתיחת הקובץ ״{}״" #: gaupol/agents/open.py:351 msgid "Failed to parse file \"{}\"" msgstr "ארע כשל בפענוח הקובץ ״{}״" #: gaupol/agents/open.py:352 msgid "Please check that the file you are trying to open is a valid {} file." msgstr "" #: gaupol/agents/open.py:360 msgid "Open abnormally large file \"{}\"?" msgstr "האם לפתוח את הקובץ הגדול באופן חריג ״{}״?" #: gaupol/agents/open.py:361 msgid "" "Size of the file is {:.1f} MB, which is abnormally large for a text-based " "subtitle file. Please, check that you are not trying to open a binary file." msgstr "" "גודל הקובץ הוא {:.1f} מ״ב, שזהו גודל גדול באופן חריג עבור קובץ כתוביות מבוסס" " טקסט. נא לבדוק שזהו אינו קובץ בינרי." #: gaupol/agents/open.py:371 msgid "Open unsorted file \"{}\"?" msgstr "האם לפתוח את הקובץ הבלתי ממוין ״{}״?" #: gaupol/agents/open.py:372 msgid "" "The order of {:d} subtitles needs to be changed. If {:d} sounds like a lot, " "the file may be erroneously composed." msgstr "" "יש לשנות את סדרן של {:d} כתוביות. אם {:d} נשמע כמו הרבה, יתכן שהקובץ הורכב " "בצורה לא נכונה." #: gaupol/agents/open.py:383 msgid "Save changes to translation document \"{}\" before opening a new one?" msgstr "האם לשמור את השינויים למסמך התרגום ״{}״ לפני פתיחת מסמך חדש?" #: gaupol/agents/open.py:386 msgid "Open _Without Saving" msgstr "פתיחה _ללא שמירה" #: gaupol/agents/close.py:66 msgid "Save changes to document \"{}\" before closing?" msgstr "" #: gaupol/agents/edit.py:101 gaupol/agents/edit.py:119 msgid "Stretching end position" msgstr "" #: gaupol/agents/edit.py:208 msgid "Inserted {:d} subtitle to fit clipboard contents" msgid_plural "Inserted {:d} subtitles to fit clipboard contents" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" #: gaupol/agents/edit.py:334 gaupol/agents/edit.py:352 msgid "Stretching start position" msgstr "" #: gaupol/agents/edit.py:411 msgid "Use Shift+Return for line-break" msgstr "שימוש ב־Shift+אנטר כדי לשבור שורות" #: gaupol/agents/save.py:129 msgid "Save As" msgstr "שמירה בשם" #: gaupol/agents/save.py:135 msgid "Saved main document as \"{}\"" msgstr "המסמך הראשי נשמר בשם ״{}״" #: gaupol/agents/save.py:153 msgid "Save Translation As" msgstr "שמירת התרגום בשם" #: gaupol/agents/save.py:159 msgid "Saved translation document as \"{}\"" msgstr "מסמך התרגום נשמר בשם ״{}״" #: gaupol/agents/save.py:194 #, python-brace-format msgid "Failed to encode file \"{basename}\" with codec \"{codec}\"" msgstr "ארע כשל בקידוד הקובץ ״{basename}״ באמצעות המפענח ״{codec}״" #: gaupol/agents/save.py:195 msgid "Please try to save the file with a different character encoding." msgstr "נא לנסות לשמור את הקובץ בקידוד תווים שונה." #: gaupol/agents/save.py:203 msgid "Failed to save file \"{}\"" msgstr "ארע כשל בשמירת הקובץ ״{}״" #: gaupol/agents/video.py:67 data/ui/menubar.ui:380 msgid "_Play/Pause" msgstr "" #: gaupol/agents/video.py:69 msgid "Play or pause video" msgstr "" #: gaupol/agents/video.py:75 data/ui/menubar.ui:390 msgid "Seek _Previous" msgstr "" #: gaupol/agents/video.py:77 msgid "Seek to the start of the previous subtitle" msgstr "" #: gaupol/agents/video.py:81 data/ui/menubar.ui:394 msgid "Seek _Next" msgstr "" #: gaupol/agents/video.py:83 msgid "Seek to the start of the next subtitle" msgstr "" #: gaupol/agents/video.py:88 data/ui/menubar.ui:400 msgid "Seek _Backward" msgstr "" #: gaupol/agents/video.py:90 msgid "Seek backward" msgstr "" #: gaupol/agents/video.py:94 data/ui/menubar.ui:404 msgid "Seek _Forward" msgstr "" #: gaupol/agents/video.py:96 msgid "Seek forward" msgstr "" #: gaupol/agents/video.py:109 msgid "Volume" msgstr "" #: gaupol/agents/video.py:189 msgid "Load Video" msgstr "" #: gaupol/agents/video.py:189 msgid "_Load" msgstr "" #: gaupol/agents/video.py:361 msgid "Track {:d}" msgstr "" #: gaupol/agents/preview.py:105 msgid "Failed to encode subtitle file to temporary directory \"{}\"" msgstr "ארע כשל בקידוד קובץ הכתוביות אל התיקייה הזמנית ״{}״" #: gaupol/agents/preview.py:106 msgid "" "Subtitle data could not be encoded to a temporary file for preview with the " "current character encoding. Please first save the subtitle file with a " "different character encoding." msgstr "" "לא ניתן לקודד את נתוני הכתוביות לקובץ זמני לתצוגה מקדימה עם קידוד התווים " "הנבחר. נא לשנות תחילה את קובץ הכתוביות לקידוד תווים שונה." #: gaupol/agents/preview.py:114 msgid "Failed to save subtitle file to temporary directory \"{}\"" msgstr "ארע כשל בשמירת קובץ הכתוביות לתיקייה הזמנית ״{}״" #: gaupol/agents/preview.py:122 msgid "Video player not found" msgstr "" #: gaupol/agents/preview.py:123 msgid "" "Please install one of the supported video players: mpv (recommended), " "MPlayer or VLC. See the preferences dialog to choose the video player or to " "customize the command." msgstr "" #: gaupol/agents/preview.py:131 msgid "Failed to launch video player" msgstr "ארע כשל בהפעלת נגן הווידאו" #: gaupol/applicationman.py:105 msgid "gaupol [OPTION...] [FILE...] [+[NUM]]" msgstr "gaupol [OPTION...] [FILE...] [+[NUM]]" #: gaupol/applicationman.py:109 msgid "FILE..." msgstr "" #: gaupol/applicationman.py:112 msgid "subtitle files to open" msgstr "" #: gaupol/applicationman.py:122 msgid "ENCODING" msgstr "ENCODING" #: gaupol/applicationman.py:125 msgid "set the character encoding used to open files" msgstr "set the character encoding used to open files" #: gaupol/applicationman.py:132 msgid "list all available character encodings" msgstr "list all available character encodings" #: gaupol/applicationman.py:137 gaupol/applicationman.py:154 msgid "FILE" msgstr "FILE" #: gaupol/applicationman.py:140 msgid "open translation file" msgstr "open translation file" #: gaupol/applicationman.py:145 msgid "METHOD" msgstr "METHOD" #: gaupol/applicationman.py:149 msgid "method used to align translation subtitles: 'number' or 'position'" msgstr "method used to align translation subtitles: 'number' or 'position'" #: gaupol/applicationman.py:157 msgid "select video file" msgstr "select video file" #: data/extensions/custom-framerates/custom-framerates.py:40 #: data/ui/spell-check-dialog.ui:152 msgid "_Add" msgstr "הו_ספה" #: data/extensions/custom-framerates/custom-framerates.py:171 msgid "{:.3f} fps" msgstr "" #: data/extensions/custom-framerates/add-framerate-dialog.ui:13 msgid "Add Framerate" msgstr "" #: data/extensions/custom-framerates/add-framerate-dialog.ui:44 msgid "_Framerate:" msgstr "" #: data/extensions/custom-framerates/add-framerate-dialog.ui:73 msgid "fps" msgstr "" #: data/extensions/custom-framerates/preferences-dialog.ui:8 msgid "Framerates" msgstr "" #: data/extensions/custom-framerates/preferences-dialog.ui:64 msgid "Add" msgstr "" #: data/ui/columns-popup.ui:6 data/ui/menubar.ui:275 msgid "_No." msgstr "_מס׳" #: data/ui/columns-popup.ui:10 data/ui/menubar.ui:279 msgid "_Start" msgstr "ה_תחלה" #: data/ui/columns-popup.ui:14 data/ui/menubar.ui:283 msgid "_End" msgstr "_סוף" #: data/ui/columns-popup.ui:18 data/ui/menubar.ui:287 msgid "_Duration" msgstr "_פרק הזמן" #: data/ui/columns-popup.ui:22 data/ui/menubar.ui:291 data/ui/menubar.ui:303 msgid "_Text" msgstr "_טקסט" #: data/ui/columns-popup.ui:26 data/ui/menubar.ui:295 msgid "T_ranslation" msgstr "" #: data/ui/split-dialog.ui:15 msgid "Split Project" msgstr "פיצול מיזם" #: data/ui/split-dialog.ui:48 msgid "_First subtitle of new project:" msgstr "הכתובית ה_ראשונה של המיזם החדש:" #: data/ui/search-dialog.ui:89 msgid "_Search for:" msgstr "חיפוש _אחר:" #: data/ui/search-dialog.ui:103 data/ui/spell-check-dialog.ui:193 msgid "Replace _with:" msgstr "החלפה _ב־:" #: data/ui/search-dialog.ui:162 data/ui/menubar.ui:328 msgid "Find _Next" msgstr "חיפוש ה_בא" #: data/ui/search-dialog.ui:177 msgid "Find _Previous" msgstr "חיפוש ה_קודם" #: data/ui/search-dialog.ui:207 msgid "Replace _All" msgstr "החלפת ה_כול" #: data/ui/search-dialog.ui:241 msgid "R_egular expression" msgstr "ביטוי ר_גולרי" #: data/ui/search-dialog.ui:258 msgid "_Ignore case" msgstr "ה_תעלמות מהבדלי רשיות" #: data/ui/search-dialog.ui:304 data/ui/language-dialog.ui:108 msgid "Columns" msgstr "עמודות" #: data/ui/search-dialog.ui:324 msgid "Find in _text column" msgstr "" #: data/ui/search-dialog.ui:341 msgid "Find in t_ranslation column" msgstr "" #: data/ui/search-dialog.ui:381 data/ui/framerate-convert-dialog.ui:144 #: data/ui/language-dialog.ui:186 #: data/ui/text-assistant/line-break-options-page.ui:178 #: data/ui/duration-adjust-dialog.ui:388 data/ui/position-shift-dialog.ui:180 #: data/ui/position-transform-dialog.ui:444 msgid "Subtitles" msgstr "כתוביות" #: data/ui/search-dialog.ui:401 msgid "Find in c_urrent project" msgstr "חיפוש במיזם ה_נוכחי" #: data/ui/search-dialog.ui:419 msgid "Find in _all open projects" msgstr "חיפוש ב_כול המיזמים הפתוחים" #: data/ui/search-dialog.ui:452 msgid "Target" msgstr "יעד" #: data/ui/framerate-convert-dialog.ui:8 msgid "Convert Framerate" msgstr "קצב השקופיות להמרה" #: data/ui/framerate-convert-dialog.ui:48 msgid "Framerate" msgstr "קצב שקופיות" #: data/ui/framerate-convert-dialog.ui:71 msgid "_Input:" msgstr "_קלט:" #: data/ui/framerate-convert-dialog.ui:86 msgid "_Output:" msgstr "_פלט:" #: data/ui/framerate-convert-dialog.ui:164 msgid "Convert c_urrent project" msgstr "המרת המיזם ה_נוכחי" #: data/ui/framerate-convert-dialog.ui:181 msgid "Convert _all open projects" msgstr "המרת _כל המיזמים הפתוחים" #: data/ui/spell-check-dialog.ui:8 msgid "Check Spelling" msgstr "בדיקת איות" #: data/ui/spell-check-dialog.ui:47 msgid "Join _Back" msgstr "_צירוף בחזרה" #: data/ui/spell-check-dialog.ui:62 msgid "Join _Forward" msgstr "צירוף _קדימה" #: data/ui/spell-check-dialog.ui:77 data/ui/menubar.ui:62 msgid "_Edit" msgstr "_עריכה" #: data/ui/spell-check-dialog.ui:92 msgid "_Ignore" msgstr "הת_עלמות" #: data/ui/spell-check-dialog.ui:107 msgid "Ig_nore All" msgstr "ה_תעלמות מהכול" #: data/ui/spell-check-dialog.ui:137 msgid "Rep_lace All" msgstr "הח_לפת הכול" #: data/ui/spell-check-dialog.ui:179 msgid "_Suggestions:" msgstr "ה_צעות:" #: data/ui/multi-save-dialog.ui:8 msgid "Save All As" msgstr "שמירת הכול בשם" #: data/ui/multi-save-dialog.ui:46 msgid "Save in _folder:" msgstr "שמירה ב_תיקייה:" #: data/ui/multi-save-dialog.ui:60 data/ui/save-dialog.ui:25 msgid "For_mat:" msgstr "מ_בנה:" #: data/ui/multi-save-dialog.ui:74 data/ui/open-dialog.ui:25 #: data/ui/save-dialog.ui:39 msgid "_Encoding:" msgstr "" #: data/ui/multi-save-dialog.ui:88 data/ui/save-dialog.ui:53 msgid "Ne_wlines:" msgstr "שורות _חדשות:" #: data/ui/multi-save-dialog.ui:103 msgid "Select A Folder" msgstr "בחירת תיקייה" #: data/ui/multi-save-dialog.ui:150 data/ui/save-dialog.ui:102 msgid "F_ramerate:" msgstr "" #: data/ui/menubar.ui:5 msgid "_File" msgstr "_קובץ" #: data/ui/menubar.ui:8 msgid "_New" msgstr "_חדש" #: data/ui/menubar.ui:12 msgid "_Open…" msgstr "_פתיחה…" #: data/ui/menubar.ui:16 msgid "Open _Translation…" msgstr "פתיחת _תרגום…" #: data/ui/menubar.ui:22 msgid "Open _Recent" msgstr "שנפתחו ל_אחרונה" #: data/ui/menubar.ui:27 msgid "Open R_ecent Translation" msgstr "פתיחת תר_גומים שנפתחו לאחרונה" #: data/ui/menubar.ui:38 msgid "Save _As…" msgstr "שמירה _בשם…" #: data/ui/menubar.ui:42 msgid "Save Trans_lation" msgstr "שמירת הת_רגום" #: data/ui/menubar.ui:46 msgid "Save Translat_ion As…" msgstr "שמירת ה_תרגום בשם…" #: data/ui/menubar.ui:65 msgid "_Undo" msgstr "_ביטול" #: data/ui/menubar.ui:69 msgid "_Redo" msgstr "בי_צוע מחדש" #: data/ui/menubar.ui:75 msgid "_Edit Cell" msgstr "עריכת _תא" #: data/ui/menubar.ui:79 msgid "Edit _Next Cell" msgstr "עריכת התא ה_בא" #: data/ui/menubar.ui:85 msgid "Stretc_h" msgstr "" #: data/ui/menubar.ui:88 msgid "_Start Earlier" msgstr "" #: data/ui/menubar.ui:92 msgid "S_tart Later" msgstr "" #: data/ui/menubar.ui:98 msgid "E_nd Earlier" msgstr "" #: data/ui/menubar.ui:102 msgid "En_d Later" msgstr "" #: data/ui/menubar.ui:108 msgid "Set St_art From Video Position" msgstr "" #: data/ui/menubar.ui:112 msgid "Set En_d From Video Position" msgstr "" #: data/ui/menubar.ui:118 data/ui/view-popup.ui:6 msgid "_Split Subtitle" msgstr "_פיצול כתובית" #: data/ui/menubar.ui:122 data/ui/view-popup.ui:10 msgid "_Merge Subtitles" msgstr "_מיזוג כתוביות" #: data/ui/menubar.ui:128 data/ui/view-popup.ui:16 msgid "_Insert Subtitles…" msgstr "הו_ספת כתוביות…" #: data/ui/menubar.ui:132 msgid "Inser_t Subtitle At Video Position" msgstr "" #: data/ui/menubar.ui:136 data/ui/view-popup.ui:20 msgid "Rem_ove Subtitles" msgstr "ה_סרת כתוביות" #: data/ui/menubar.ui:142 msgid "Sele_ction" msgstr "_בחירה" #: data/ui/menubar.ui:145 msgid "Select _All" msgstr "בחירת ה_כול" #: data/ui/menubar.ui:149 msgid "_Invert Selection" msgstr "ה_פיכת הבחירה" #: data/ui/menubar.ui:155 msgid "Extend To _Beginning" msgstr "הרחבה לה_תחלה" #: data/ui/menubar.ui:159 msgid "Extend To _End" msgstr "הרחבה ל_סוף" #: data/ui/menubar.ui:165 msgid "_Previous From Video Position" msgstr "" #: data/ui/menubar.ui:169 msgid "_Next From Video Position" msgstr "" #: data/ui/menubar.ui:177 msgid "_Preferences" msgstr "הע_דפות" #: data/ui/menubar.ui:183 msgid "_View" msgstr "_תצוגה" #: data/ui/menubar.ui:186 msgid "Tool_bar" msgstr "" #: data/ui/menubar.ui:190 msgid "_Video Player" msgstr "" #: data/ui/menubar.ui:196 msgid "_Layout" msgstr "" #: data/ui/menubar.ui:199 msgid "_Horizontal" msgstr "" #: data/ui/menubar.ui:204 msgid "_Vertical" msgstr "" #: data/ui/menubar.ui:213 msgid "_Times" msgstr "_זמנים" #: data/ui/menubar.ui:218 msgid "_Frames" msgstr "_שקופיות" #: data/ui/menubar.ui:225 msgid "F_ramerate" msgstr "_קצב שקופיות" #: data/ui/menubar.ui:228 msgid "2_3.976 fps" msgstr "" #: data/ui/menubar.ui:233 msgid "2_4.000 fps" msgstr "" #: data/ui/menubar.ui:238 msgid "2_5.000 fps" msgstr "" #: data/ui/menubar.ui:243 msgid "2_9.970 fps" msgstr "" #: data/ui/menubar.ui:272 msgid "_Columns" msgstr "_עמודות" #: data/ui/menubar.ui:306 msgid "Cu_t" msgstr "_גזירה" #: data/ui/menubar.ui:310 msgid "_Copy" msgstr "ה_עתקה" #: data/ui/menubar.ui:314 msgid "_Paste" msgstr "ה_דבקה" #: data/ui/menubar.ui:318 msgid "Cl_ear" msgstr "_ניקוי" #: data/ui/menubar.ui:324 msgid "_Find And Replace…" msgstr "_חיפוש והחלפה…" #: data/ui/menubar.ui:332 msgid "Find Pre_vious" msgstr "חיפוש ה_קודם" #: data/ui/menubar.ui:338 msgid "_Italic" msgstr "_נטוי" #: data/ui/menubar.ui:342 msgid "_Dialogue" msgstr "_דו־שיח" #: data/ui/menubar.ui:348 msgid "Ca_se" msgstr "_רשיות/קטנות" #: data/ui/menubar.ui:351 msgid "_Title" msgstr "_כותרת" #: data/ui/menubar.ui:355 msgid "_Sentence" msgstr "_משפט" #: data/ui/menubar.ui:359 msgid "_Upper" msgstr "_רשיות" #: data/ui/menubar.ui:363 msgid "_Lower" msgstr "_קטנות" #: data/ui/menubar.ui:371 msgid "Vi_deo" msgstr "" #: data/ui/menubar.ui:374 msgid "_Load Video…" msgstr "" #: data/ui/menubar.ui:384 data/ui/view-popup.ui:26 msgid "Play _Selection" msgstr "" #: data/ui/menubar.ui:410 data/ui/view-popup.ui:30 msgid "S_eek Selection Start" msgstr "" #: data/ui/menubar.ui:414 msgid "See_k Selection End" msgstr "" #: data/ui/menubar.ui:420 msgid "_Audio" msgstr "" #: data/ui/menubar.ui:423 msgid "_Language" msgstr "" #: data/ui/menubar.ui:430 msgid "Volume _Down" msgstr "" #: data/ui/menubar.ui:434 msgid "Volume _Up" msgstr "" #: data/ui/menubar.ui:440 msgid "T_ools" msgstr "_כלים" #: data/ui/menubar.ui:443 data/ui/text-assistant/confirmation-page.ui:97 #: data/ui/view-popup.ui:36 msgid "_Preview" msgstr "ת_צוגה מקדימה" #: data/ui/menubar.ui:447 msgid "Select _Video…" msgstr "בחירת _וידאו…" #: data/ui/menubar.ui:453 msgid "_Check Spelling" msgstr "_בדיקת איות" #: data/ui/menubar.ui:457 msgid "Co_nfigure Spell-check…" msgstr "ה_גדרת בדיקת איות…" #: data/ui/menubar.ui:461 msgid "C_orrect Texts…" msgstr "_תיקון הטקסטים…" #: data/ui/menubar.ui:467 msgid "_Shift Positions…" msgstr "ה_זחת מקומות…" #: data/ui/menubar.ui:471 msgid "_Transform Positions…" msgstr "הח_לפת מקומות…" #: data/ui/menubar.ui:475 msgid "Adjust _Durations…" msgstr "התאמת _פרקי הזמן…" #: data/ui/menubar.ui:479 msgid "Convert _Framerate…" msgstr "המרת ק_צב שקופיות…" #: data/ui/menubar.ui:485 msgid "_Append File…" msgstr "הו_ספת קובץ…" #: data/ui/menubar.ui:489 msgid "Spli_t Project…" msgstr "_פיצול המיזם…" #: data/ui/menubar.ui:495 msgid "_Projects" msgstr "_מיזמים" #: data/ui/menubar.ui:498 msgid "_Save All" msgstr "_שמירת הכול" #: data/ui/menubar.ui:502 msgid "Save _All As…" msgstr "שמירת ה_כול בשם…" #: data/ui/menubar.ui:506 msgid "_Close All" msgstr "ס_גירת הכול" #: data/ui/menubar.ui:512 msgid "_Previous" msgstr "ה_קודמת" #: data/ui/menubar.ui:516 msgid "_Next" msgstr "ה_באה" #: data/ui/menubar.ui:527 msgid "_Documentation" msgstr "" #: data/ui/menubar.ui:531 msgid "_Report A Bug" msgstr "דיווח על _באג" #: data/ui/menubar.ui:535 msgid "_About" msgstr "על _אודות" #: data/ui/open-dialog.ui:39 msgid "Align _method:" msgstr "שיטת ה_יישור:" #: data/ui/preferences-dialog.ui:18 msgid "Preferences" msgstr "העדפות" #: data/ui/preferences-dialog.ui:93 msgid "When opening files, try encodings in the following order:" msgstr "בעת פתיחת קבצים, יש לנסות את הקידודים בסדר הבא:" #: data/ui/preferences-dialog.ui:104 msgid "Curr_ent locale encoding" msgstr "קידוד _שפת המקום הנוכחית" #: data/ui/preferences-dialog.ui:130 msgid "_Fallback encodings:" msgstr "קידוד ע_תודה:" #: data/ui/preferences-dialog.ui:246 msgid "Aut_o-detection" msgstr "_זיהוי אוטומטי" #: data/ui/preferences-dialog.ui:266 msgid "Encoding specified in the open dialog will always be tried first." msgstr "תמיד יעשה ניסיון להשתמש בקידוד שצוין בדו־שיח לפתיחת קבצים." #: data/ui/preferences-dialog.ui:296 msgid "File" msgstr "קובץ" #: data/ui/preferences-dialog.ui:324 msgid "Font" msgstr "גופן" #: data/ui/preferences-dialog.ui:344 msgid "Use _default theme fixed width font" msgstr "" #: data/ui/preferences-dialog.ui:368 msgid "_Editor font:" msgstr "גופן ה_עורך:" #: data/ui/preferences-dialog.ui:425 msgid "Line Lengths" msgstr "אורך שורות" #: data/ui/preferences-dialog.ui:445 msgid "_Show line lengths in list cells" msgstr "הצגת אורך השורות בתאים ב_רשימה" #: data/ui/preferences-dialog.ui:462 msgid "S_how line lengths in editable text fields" msgstr "הצגת _אורך השורות בשדות הטקסט הניתנים לעריכה" #: data/ui/preferences-dialog.ui:486 msgid "_Length unit:" msgstr "יחידת ה_אורך:" #: data/ui/preferences-dialog.ui:540 msgid "Spell-Check" msgstr "בדיקת איות" #: data/ui/preferences-dialog.ui:560 msgid "Chec_k spelling as you type" msgstr "_בדיקת האיות בעת ההקלדה" #: data/ui/preferences-dialog.ui:598 msgid "Editor" msgstr "עורך" #: data/ui/preferences-dialog.ui:626 msgid "Fonts" msgstr "" #: data/ui/preferences-dialog.ui:649 msgid "_Subtitles:" msgstr "" #: data/ui/preferences-dialog.ui:679 msgid "_Time:" msgstr "" #: data/ui/preferences-dialog.ui:729 msgid "Colors" msgstr "" #: data/ui/preferences-dialog.ui:752 msgid "Su_btitles:" msgstr "" #: data/ui/preferences-dialog.ui:777 msgid "_Use a background behind text" msgstr "" #: data/ui/preferences-dialog.ui:797 msgid "Ti_me:" msgstr "" #: data/ui/preferences-dialog.ui:822 msgid "Us_e a background behind text" msgstr "" #: data/ui/preferences-dialog.ui:862 msgid "Seek" msgstr "" #: data/ui/preferences-dialog.ui:883 msgid "_Length:" msgstr "" #: data/ui/preferences-dialog.ui:971 msgid "Video Player" msgstr "נגן וידאו" #: data/ui/preferences-dialog.ui:994 msgid "_Application:" msgstr "_יישום:" #: data/ui/preferences-dialog.ui:1008 msgid "Co_mmand:" msgstr "_פקודה:" #. Translators: Only the title is to be translated, field names not. #: data/ui/preferences-dialog.ui:1033 msgid "" "Fields:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" msgstr "" #: data/ui/preferences-dialog.ui:1048 msgid "Al_ways use UTF-8 character encoding" msgstr "יש _תמיד להשתמש בקידוד התווים UTF-8" #: data/ui/preferences-dialog.ui:1089 msgid "Start Position" msgstr "נקודת ההתחלה" #: data/ui/preferences-dialog.ui:1111 msgid "_Offset:" msgstr "הי_סט:" #: data/ui/preferences-dialog.ui:1142 msgid "seconds before selection" msgstr "שניות בטרם הבחירה" #: data/ui/preferences-dialog.ui:1281 msgid "Extensions" msgstr "הרחבות" #: data/ui/language-dialog.ui:8 msgid "Configure Spell-Check" msgstr "הגדרת בדיקת איות" #: data/ui/language-dialog.ui:50 msgid "Language" msgstr "שפה" #: data/ui/language-dialog.ui:128 msgid "Check _text column" msgstr "" #: data/ui/language-dialog.ui:146 msgid "Check t_ranslation column" msgstr "" #: data/ui/language-dialog.ui:206 msgid "Check c_urrent project" msgstr "בדיקת ה_מיזם הנוכחי" #: data/ui/language-dialog.ui:224 msgid "Check _all open projects" msgstr "בדיקת _כל המיזמים הפתוחים" #: data/ui/text-assistant/confirmation-page.ui:22 msgid "Acc_ept, discard or edit changes:" msgstr "_קבלה, דחייה או עריכת השינויים:" #: data/ui/text-assistant/confirmation-page.ui:67 msgid "_Mark All" msgstr "_סימון הכול" #: data/ui/text-assistant/confirmation-page.ui:82 msgid "_Unmark All" msgstr "בי_טול הסימון" #: data/ui/text-assistant/confirmation-page.ui:119 msgid "_Remove all blank subtitles" msgstr "ה_סרת כל הכתוביות הריקות" #: data/ui/text-assistant/join-split-page.ui:28 msgid "Spell-Check Dictionary" msgstr "מילון בדיקת איות" #: data/ui/text-assistant/join-split-page.ui:49 #: data/ui/text-assistant/line-break-page.ui:81 #: data/ui/text-assistant/hearing-impaired-page.ui:81 #: data/ui/text-assistant/common-error-page.ui:80 #: data/ui/text-assistant/capitalization-page.ui:80 msgid "_Language:" msgstr "_שפה:" #: data/ui/text-assistant/join-split-page.ui:97 msgid "Corrections" msgstr "תיקונים" #: data/ui/text-assistant/join-split-page.ui:117 msgid "_Join words not found in spell-check dictionary" msgstr "_צירוף מילים שאינן נמצאות במילון האיות" #: data/ui/text-assistant/join-split-page.ui:134 msgid "_Split words not found in spell-check dictionary" msgstr "_פיצול מילים שאינן נמצאות במילון האיות" #: data/ui/text-assistant/line-break-page.ui:22 msgid "S_elect preferred line-break points:" msgstr "ב_חירת נקודות שבירת השורות המועדפות:" #: data/ui/text-assistant/line-break-page.ui:67 #: data/ui/text-assistant/hearing-impaired-page.ui:67 #: data/ui/text-assistant/common-error-page.ui:66 #: data/ui/text-assistant/capitalization-page.ui:66 msgid "_Script:" msgstr "_תסריט:" #: data/ui/text-assistant/line-break-page.ui:95 #: data/ui/text-assistant/hearing-impaired-page.ui:95 #: data/ui/text-assistant/common-error-page.ui:94 #: data/ui/text-assistant/capitalization-page.ui:94 msgid "Co_untry:" msgstr "" #: data/ui/text-assistant/introduction-page.ui:28 msgid "_Select corrections to perform on texts:" msgstr "בחירת תיקונים להחלה על הטק_סטים:" #: data/ui/text-assistant/introduction-page.ui:79 msgid "Colu_mns:" msgstr "" #: data/ui/text-assistant/introduction-page.ui:93 msgid "S_ubtitles:" msgstr "" #: data/ui/text-assistant/line-break-options-page.ui:56 #: data/ui/duration-adjust-dialog.ui:207 msgid "Limits" msgstr "מגבלות" #: data/ui/text-assistant/line-break-options-page.ui:79 msgid "_Maximum line length:" msgstr "אורך ה_שורה המרבי:" #: data/ui/text-assistant/line-break-options-page.ui:93 msgid "_Preferred maximum amount of lines:" msgstr "_כמות השורות המרבית המועדפת היא:" #: data/ui/text-assistant/line-break-options-page.ui:198 msgid "_Skip subtitles with maximum line length of:" msgstr "_דילוג על כתוביות שאורך השורה המרבי שלהן הוא:" #: data/ui/text-assistant/line-break-options-page.ui:214 msgid "S_kip subtitles with maximum line amount of:" msgstr "_דילוג על כתוביות שכמות שורותיהן המרבי הוא:" #: data/ui/text-assistant/hearing-impaired-page.ui:22 msgid "S_elect parts to remove:" msgstr "בחירת ה_חלקים להסרה:" #: data/ui/text-assistant/common-error-page.ui:22 msgid "S_elect errors to correct:" msgstr "_בחירת שגיאות לתיקון:" #: data/ui/text-assistant/common-error-page.ui:108 msgid "Error types:" msgstr "סוג השגיאות:" #: data/ui/text-assistant/common-error-page.ui:158 msgid "_Human errors" msgstr "שגיאות _אנושיות" #: data/ui/text-assistant/common-error-page.ui:175 msgid "_Image recognition errors" msgstr "שגיאות ב_זיהוי תמונה" #: data/ui/text-assistant/capitalization-page.ui:22 msgid "S_elect parts to capitalize:" msgstr "בחירת חלקים להפיכת האותיות שלהם לרשיות:" #: data/ui/duration-adjust-dialog.ui:33 msgid "Adjust Durations" msgstr "התאמת פרקי הזמן" #: data/ui/duration-adjust-dialog.ui:73 msgid "Theoretic Duration" msgstr "פרק זמן תאורטי" #: data/ui/duration-adjust-dialog.ui:101 msgid "_Reading speed:" msgstr "מהירות הקרי_אה:" #: data/ui/duration-adjust-dialog.ui:133 msgid "characters per second" msgstr "תווים לשנייה" #: data/ui/duration-adjust-dialog.ui:150 msgid "_Lengthen duration to match reading speed" msgstr "הארכת פרק הזמן כדי להתאים למהירות ה_קריאה" #: data/ui/duration-adjust-dialog.ui:167 msgid "_Shorten duration to match reading speed" msgstr "קי_צור פרק הזמן כדי להתאים למהירות הקריאה" #: data/ui/duration-adjust-dialog.ui:227 msgid "_Minimum duration:" msgstr "פרק הזמן המ_זערי:" #: data/ui/duration-adjust-dialog.ui:243 msgid "Ma_ximum duration:" msgstr "פרק הזמן המ_רבי:" #: data/ui/duration-adjust-dialog.ui:259 msgid "_Gap between subtitles:" msgstr "מרוו_ח בין הכתוביות:" #: data/ui/duration-adjust-dialog.ui:294 msgid "s_econds" msgstr "_שניות" #: data/ui/duration-adjust-dialog.ui:324 msgid "seco_nds" msgstr "ש_ניות" #: data/ui/duration-adjust-dialog.ui:354 msgid "secon_ds" msgstr "שניו_ת" #: data/ui/duration-adjust-dialog.ui:408 msgid "Adj_ust selected subtitles" msgstr "הת_אמת הכתוביות הנבחרות" #: data/ui/duration-adjust-dialog.ui:425 msgid "Adjus_t current project" msgstr "התא_מת המיזם הנוכחי" #: data/ui/duration-adjust-dialog.ui:442 msgid "Adjust all _open projects" msgstr "התאמת כל המיזמים ה_פתוחים" #: data/ui/tab-popup.ui:6 msgid "Move Tab _Left" msgstr "העברת הלשונית _שמאלה" #: data/ui/tab-popup.ui:10 msgid "Move Tab _Right" msgstr "העברת הלשונית _ימינה" #: data/ui/insert-dialog.ui:15 msgid "Insert Subtitles" msgstr "הוספת כתוביות" #: data/ui/insert-dialog.ui:48 data/ui/position-shift-dialog.ui:82 msgid "_Amount:" msgstr "_כמות:" #: data/ui/insert-dialog.ui:62 msgid "_Position:" msgstr "_מיקום:" #: data/ui/position-shift-dialog.ui:14 msgid "Shift Positions" msgstr "הזזת מקומות" #: data/ui/position-shift-dialog.ui:54 msgid "Shift" msgstr "הזזה" #: data/ui/position-shift-dialog.ui:135 #: data/ui/position-transform-dialog.ui:208 msgid "_Preview Changes" msgstr "הצגה מקדימה של ה_שינויים" #: data/ui/position-shift-dialog.ui:200 msgid "Shift s_elected subtitles" msgstr "ה_זזת הכתוביות הנבחרות" #: data/ui/position-shift-dialog.ui:217 msgid "Shift su_btitles from selection to end" msgstr "" #: data/ui/position-shift-dialog.ui:234 msgid "Shift c_urrent project" msgstr "הזזת ה_מיזם הנוכחי" #: data/ui/position-shift-dialog.ui:251 msgid "Shift all _open projects" msgstr "" #: data/ui/position-transform-dialog.ui:22 msgid "Transform Positions" msgstr "החלפת המקומות" #: data/ui/position-transform-dialog.ui:62 msgid "First Point" msgstr "הנקודה הראשונה" #: data/ui/position-transform-dialog.ui:91 msgid "_Subtitle:" msgstr "_כתובית:" #: data/ui/position-transform-dialog.ui:105 msgid "C_orrection:" msgstr "_תיקון:" #: data/ui/position-transform-dialog.ui:119 #: data/ui/position-transform-dialog.ui:310 msgid "Text:" msgstr "טקסט:" #: data/ui/position-transform-dialog.ui:253 msgid "Second Point" msgstr "הנקודה השנייה" #: data/ui/position-transform-dialog.ui:282 msgid "Su_btitle:" msgstr "_כתובית:" #: data/ui/position-transform-dialog.ui:296 msgid "Co_rrection:" msgstr "תי_קון:" #: data/ui/position-transform-dialog.ui:399 msgid "Pre_view Changes" msgstr "הצגה _מקדימה של השינויים" #: data/ui/position-transform-dialog.ui:464 msgid "Transform se_lected subtitles" msgstr "החלפה בין הכתו_ביות הנבחרות" #: data/ui/position-transform-dialog.ui:482 msgid "Transform c_urrent project" msgstr "החלפה במיזם ה_נוכחי" #: data/extensions/custom-framerates/custom-framerates.extension.in:7 msgid "Custom Framerates" msgstr "" #: data/extensions/custom-framerates/custom-framerates.extension.in:8 msgid "Allow use of non-standard framerates" msgstr "" #: data/patterns/Latn-en-US.common-error.in:5 msgid "Period after title" msgstr "נקודה לאחר הכותרת" #: data/patterns/Latn-en-US.common-error.in:6 msgid "Add period after a shortened title, such as \"Mr\" and \"Dr\"" msgstr "הוספת נקודות לאחר תארים מקוצרים, כגון ״Mr״ ו־״Dr״ (לא תקף בעברית)" #: data/patterns/Latn-en.capitalization.in:5 msgid "First person pronoun" msgstr "ראשית כינוי עצמית" #: data/patterns/Latn-en.capitalization.in:6 msgid "Capitalize the first person pronoun \"I\"" msgstr "הגדלת ראשית הכינוי העצמי ״I״ (לא תקף בעברית)" #: data/patterns/Latn-en.common-error.in:5 #: data/patterns/Latn-en.common-error.in:14 #: data/patterns/Latn-en.common-error.in:23 msgid "Letter \"I\" in a lower case word" msgstr "האות ״I״ במילה באותיות קטנות" #: data/patterns/Latn-en.common-error.in:6 #: data/patterns/Latn-en.common-error.in:15 #: data/patterns/Latn-en.common-error.in:24 msgid "Replace letter \"I\" with letter \"l\" in a lower case word" msgstr "החלפת האות ״I״ באות ״l״ במילים באותיות קטנות" #: data/patterns/Latn-en.common-error.in:32 #: data/patterns/Latn-en.common-error.in:41 #: data/patterns/Latn-en.common-error.in:50 #: data/patterns/Latn-en.common-error.in:62 msgid "Letter \"l\" in an upper case word" msgstr "האות ״I״ במילה באותיות רשיות" #: data/patterns/Latn-en.common-error.in:33 #: data/patterns/Latn-en.common-error.in:42 #: data/patterns/Latn-en.common-error.in:51 #: data/patterns/Latn-en.common-error.in:63 msgid "Replace letter \"l\" with letter \"I\" in an upper case word" msgstr "החלפת האות ״l״ באות ״I״ במילים באותיות רשיות" #: data/patterns/Latn-en.common-error.in:73 #: data/patterns/Latn-en.common-error.in:82 msgid "Zero in an upper case word" msgstr "אפס במילה באותיות רשיות" #: data/patterns/Latn-en.common-error.in:74 #: data/patterns/Latn-en.common-error.in:83 msgid "Replace zero with letter \"O\" in an upper case word" msgstr "החלפת אפס באות ״O״ במילה הכתובה ברשיות" #: data/patterns/Latn-en.common-error.in:91 #: data/patterns/Latn.common-error.in:108 msgid "Space between number and unit" msgstr "רווחים בין מספר ליחידה" #: data/patterns/Latn-en.common-error.in:92 #: data/patterns/Latn.common-error.in:109 msgid "Add or remove space between a number and the associated unit" msgstr "הוספה או הסרה של רווח בין המספר והיחידה המשויכת אליו" #: data/patterns/Latn-en.common-error.in:100 msgid "Spaces around an apostrophe" msgstr "רווחים מסביב לאפוסטרוף" #: data/patterns/Latn-en.common-error.in:101 msgid "Remove spaces around an apostrophe" msgstr "הסרת רווחים מסביב לאפוסטרוף" #: data/patterns/Latn-en.common-error.in:109 #: data/patterns/Latn-en.common-error.in:118 msgid "Okay" msgstr "אוקיי" #: data/patterns/Latn-en.common-error.in:110 #: data/patterns/Latn-en.common-error.in:119 msgid "Spell two-letter forms of \"okay\" in all upper case" msgstr "" #: data/patterns/Latn-en.hearing-impaired.in:5 msgid "Uppercase speaker before a colon" msgstr "הגדלת שם הדובר לרשיות לפני נקודתיים" #: data/patterns/Latn-en.hearing-impaired.in:6 msgid "" "Replace the uppercase name of the speaker before a colon with a dialogue " "dash" msgstr "החלפת השם באותיות רשיות של הדובר לפני הנקודתיים במקף דו־שיח" #: data/patterns/Latn-en.line-break.in:5 msgid "Title" msgstr "" #: data/patterns/Latn-en.line-break.in:6 msgid "Do not break after a title, e.g. \" Dr.\"" msgstr "" #: data/patterns/Latn-en.line-break.in:13 msgid "Article" msgstr "" #: data/patterns/Latn-en.line-break.in:14 msgid "Do not break after an article" msgstr "" #: data/patterns/Latn-en.line-break.in:21 msgid "Preposition" msgstr "" #: data/patterns/Latn-en.line-break.in:22 msgid "Do not break after a preposition" msgstr "" #: data/patterns/Latn-en.line-break.in:30 msgid "Possessive determiner" msgstr "" #: data/patterns/Latn-en.line-break.in:31 msgid "Do not break after a possessive determiner, e.g. \"my\"" msgstr "" #: data/patterns/Latn-fi.common-error.in:5 #: data/patterns/Latn.common-error.in:182 msgid "Space after punctuation marks" msgstr "רווחים לאחר סימני פיסוק" #: data/patterns/Latn-fi.common-error.in:6 #: data/patterns/Latn.common-error.in:183 msgid "Add space after various punctuation marks" msgstr "הוספת רווח לאחר סימני פיסוק שונים" #: data/patterns/Latn-fr.common-error.in:5 #: data/patterns/Latn-fr.common-error.in:14 #: data/patterns/Latn-fr.common-error.in:23 #: data/patterns/Latn-fr.common-error.in:32 msgid "Spaces around guillemets" msgstr "" #: data/patterns/Latn-fr.common-error.in:6 #: data/patterns/Latn-fr.common-error.in:15 #: data/patterns/Latn-fr.common-error.in:24 #: data/patterns/Latn-fr.common-error.in:33 msgid "Add spaces around guillemets" msgstr "" #: data/patterns/Latn-fr.common-error.in:41 #: data/patterns/Latn-fr.common-error.in:52 #: data/patterns/Latn.common-error.in:171 msgid "Space before punctuation marks" msgstr "רווחים לפני סימני פיסוק" #: data/patterns/Latn-fr.common-error.in:42 #: data/patterns/Latn-fr.common-error.in:53 msgid "Add or remove space before various punctuation marks" msgstr "" #: data/patterns/Latn.capitalization.in:5 msgid "Sentence" msgstr "משפט" #: data/patterns/Latn.capitalization.in:6 msgid "Capitalize the first word of a sentence" msgstr "הפיכת המילה הראשונה במשפט לרישית (הגדלת האות הראשונה)" #: data/patterns/Latn.capitalization.in:12 msgid "Ellipsis" msgstr "" #: data/patterns/Latn.capitalization.in:13 msgid "Capitalize after an ellipsis" msgstr "" #: data/patterns/Latn.common-error.in:8 data/patterns/Latn.common-error.in:17 #: data/patterns/Latn.common-error.in:26 data/patterns/Latn.common-error.in:35 #: data/patterns/Latn.common-error.in:44 data/patterns/Latn.common-error.in:53 #: data/patterns/Latn.common-error.in:62 msgid "Ligatures" msgstr "" #: data/patterns/Latn.common-error.in:9 data/patterns/Latn.common-error.in:18 #: data/patterns/Latn.common-error.in:27 data/patterns/Latn.common-error.in:36 #: data/patterns/Latn.common-error.in:45 data/patterns/Latn.common-error.in:54 #: data/patterns/Latn.common-error.in:63 msgid "Unpack ligatures to individual characters" msgstr "" #: data/patterns/Latn.common-error.in:71 data/patterns/Latn.common-error.in:80 msgid "Spelling of a.m. and p.m." msgstr "איות של a.m.‎ ו־p.m.‎" #: data/patterns/Latn.common-error.in:72 data/patterns/Latn.common-error.in:81 msgid "Change the various spellings of 12-hour periods to \"a.m.\" and \"p.m.\"" msgstr "שינוי צורות האיות השונות של פרקי 12 השעות ל־״a.m.‎״ ו־״p.m.‎״" #: data/patterns/Latn.common-error.in:89 data/patterns/Latn.common-error.in:98 msgid "Letter \"O\" in a number" msgstr "האות ״O״ במספר" #: data/patterns/Latn.common-error.in:90 data/patterns/Latn.common-error.in:99 msgid "Replace letter \"O\" with a zero in a number" msgstr "החלפת האות ״O״ באפס במספר" #: data/patterns/Latn.common-error.in:117 msgid "Double apostrophe" msgstr "אפוסטרוף כפול" #: data/patterns/Latn.common-error.in:118 msgid "Replace a double apostrophe with a quotation mark" msgstr "החלפת אפוסטרוף כפול בסימן ציטוט" #: data/patterns/Latn.common-error.in:126 #: data/patterns/Latn.common-error.in:135 #: data/patterns/Latn.common-error.in:144 #: data/patterns/Latn.common-error.in:153 msgid "Spaces around brackets" msgstr "רווחים מסביב לסוגריים מרובעים" #: data/patterns/Latn.common-error.in:127 #: data/patterns/Latn.common-error.in:136 #: data/patterns/Latn.common-error.in:145 #: data/patterns/Latn.common-error.in:154 msgid "Add or remove spaces around parantheses and square brackets" msgstr "הוספה או הסרה של רווחים מסביב לסוגריים וסוגריים מרובעים" #: data/patterns/Latn.common-error.in:162 msgid "Space after a dialogue dash" msgstr "רווח לאחר קו הפרדה לציון דו־שיח" #: data/patterns/Latn.common-error.in:163 msgid "Add space after a dialogue dash" msgstr "הוספת רווח לאחר מקף דו־שיח" #: data/patterns/Latn.common-error.in:172 msgid "Remove space before various punctuation marks" msgstr "הסרת רווח לפני סימני פיסוק שונים" #: data/patterns/Latn.common-error.in:192 msgid "Space after an ellipsis" msgstr "רווח לאחר שלוש נקודות ההשמטה" #: data/patterns/Latn.common-error.in:193 msgid "Add space after an ellipsis" msgstr "הוספת רווח לאחר שלוש נקודות ההשמטה" #: data/patterns/Latn.common-error.in:201 msgid "Space after a starting ellipsis" msgstr "רווח לאחר קו הפרדה לציון דו־שיח בתחילתו" #: data/patterns/Latn.common-error.in:202 msgid "Remove space after an ellipsis that starts a line" msgstr "הסרת רווח לאחר שלוש נקודות להשמטה המתחילות שורה" #: data/patterns/Latn.common-error.in:210 #: data/patterns/Latn.common-error.in:221 #: data/patterns/Latn.common-error.in:232 #: data/patterns/Latn.common-error.in:242 msgid "Spaces around a quotation mark" msgstr "רווחים מסביב לסימני מרכאות" #: data/patterns/Latn.common-error.in:211 #: data/patterns/Latn.common-error.in:222 #: data/patterns/Latn.common-error.in:233 #: data/patterns/Latn.common-error.in:243 msgid "Remove space after a starting- and before an ending quotation mark" msgstr "הסרת רווח לאחר סימן קריאה סוגר ולפני פותח" #: data/patterns/Latn.common-error.in:252 #: data/patterns/Latn.common-error.in:261 msgid "Spaces around musical notes" msgstr "" #: data/patterns/Latn.common-error.in:253 #: data/patterns/Latn.common-error.in:262 msgid "Add spaces between musical note characters and lyrics" msgstr "" #: data/patterns/Latn.common-error.in:270 #: data/patterns/Latn.common-error.in:279 msgid "Multiple question- and exclamation marks" msgstr "מספר סימני שאלה וקריאה" #: data/patterns/Latn.common-error.in:271 #: data/patterns/Latn.common-error.in:280 msgid "" "Replace multiple consequtive question- and exclamation marks with only one" msgstr "החלפת מספר סימני שאלה וסימני קריאה ברצף בסימנים יחידים" #: data/patterns/Latn.common-error.in:288 #: data/patterns/Latn.common-error.in:298 msgid "Periods around a punctuation mark" msgstr "נקודות מסביב לסימני פיסוק" #: data/patterns/Latn.common-error.in:289 #: data/patterns/Latn.common-error.in:299 msgid "Remove period before or after various punctuation marks" msgstr "הסרת נקודה לפני או אחרי סימני פיסוק שונים" #: data/patterns/Latn.common-error.in:308 msgid "Terminating double-dashes" msgstr "מקפים כפולים לסגירה" #: data/patterns/Latn.common-error.in:309 msgid "Replace a single clause-terminating dash with two dashes" msgstr "החלפת מקף סוף סעיף בשני מקפים" #: data/patterns/Latn.hearing-impaired.in:5 msgid "Sound in brackets" msgstr "צליל בסוגריים מרובעים" #: data/patterns/Latn.hearing-impaired.in:6 msgid "Remove description of a sound between square brackets" msgstr "הסרת תיאורי צליל בסוגריים מרובעים" #: data/patterns/Latn.hearing-impaired.in:12 msgid "Sound in parantheses" msgstr "צליל בסוגריים" #: data/patterns/Latn.hearing-impaired.in:13 msgid "Remove description of a sound between parantheses" msgstr "הסרת תיאורי צליל בסוגריים" #: data/patterns/Latn.hearing-impaired.in:19 msgid "Song lyrics between number signs" msgstr "מילות שירים בין סולמיות" #: data/patterns/Latn.hearing-impaired.in:20 msgid "Remove song lyrics starting with or between number signs" msgstr "הסרת מילות שירים המתחילים עם או בין סולמיות" #: data/patterns/Latn.hearing-impaired.in:27 msgid "One-line song lyrics between number signs" msgstr "מילות שירים בנות שורה אחת בין סולמיות" #: data/patterns/Latn.hearing-impaired.in:28 msgid "Remove one-line song lyrics starting with or between number signs" msgstr "הסרת מילות שירים בנות שורה אחת עם או בין סולמיות" #: data/patterns/Latn.hearing-impaired.in:35 msgid "Speaker before a colon" msgstr "הדובר לפי הנקודתיים" #: data/patterns/Latn.hearing-impaired.in:36 msgid "Replace the name of the speaker before a colon with a dialogue dash" msgstr "החלפת שם הדובר שלפני הנקודתיים במקף דו־שיח" #: data/patterns/Latn.line-break.in:5 data/patterns/Latn.line-break.in:13 msgid "Dialogue" msgstr "דו־שיח" #: data/patterns/Latn.line-break.in:6 data/patterns/Latn.line-break.in:14 msgid "Break according to dialogue separated by dashes" msgstr "שבירה בהתאם לדו־שיח המופרד במקפים" #: data/patterns/Latn.line-break.in:21 data/patterns/Latn.line-break.in:30 msgid "Clause" msgstr "סעיף" #: data/patterns/Latn.line-break.in:22 data/patterns/Latn.line-break.in:31 msgid "Break according to clauses terminated by a punctuation mark" msgstr "שבירה בהתאם לסעיפים שנסגרים על ידי סימני פיסוק" #: data/patterns/Latn.line-break.in:38 msgid "Number and unit" msgstr "" #: data/patterns/Latn.line-break.in:39 msgid "Do not break between a number and associated unit" msgstr "" #: data/patterns/Zyyy.common-error.in:5 data/patterns/Zyyy.common-error.in:14 msgid "Leading and trailing spaces" msgstr "רווחים מובילים ועוקבים" #: data/patterns/Zyyy.common-error.in:6 data/patterns/Zyyy.common-error.in:15 msgid "Remove spaces from the beginning and end of lines" msgstr "הסרת רווחים מתחילת ומסוף השורות" #: data/patterns/Zyyy.common-error.in:23 msgid "Multiple consecutive spaces" msgstr "מספר רווחים עוקבים" #: data/patterns/Zyyy.common-error.in:24 msgid "Replace multiple consecutive spaces with only one" msgstr "החלפת מספר רווחים עוקבים באחד" #: data/patterns/Zyyy.common-error.in:32 data/patterns/Zyyy.common-error.in:45 #: data/patterns/Zyyy.common-error.in:55 data/patterns/Zyyy.common-error.in:65 msgid "Space between digits" msgstr "רווח בין ספרות" #: data/patterns/Zyyy.common-error.in:33 data/patterns/Zyyy.common-error.in:46 #: data/patterns/Zyyy.common-error.in:56 data/patterns/Zyyy.common-error.in:66 msgid "Remove space between digits of a number" msgstr "הסרת רווחים בין ספרות של מספר" #: data/patterns/Zyyy.common-error.in:79 msgid "Musical notes" msgstr "" #: data/patterns/Zyyy.common-error.in:80 msgid "Replace Unicode musical note characters with number signs" msgstr "" #: data/io.otsaloma.gaupol.appdata.xml.in:7 msgid "Editor for text-based subtitles" msgstr "" #: data/io.otsaloma.gaupol.appdata.xml.in:9 msgid "" "Gaupol is an editor for text-based subtitle files. It supports multiple " "subtitle file formats and provides means of creating subtitles, editing " "texts and timing subtitles to match video." msgstr "" #: data/io.otsaloma.gaupol.appdata.xml.in:40 msgid "Main window" msgstr "" #: data/io.otsaloma.gaupol.desktop.in:5 msgid "Subtitle Editor" msgstr "עורך הכתוביות" #: data/io.otsaloma.gaupol.desktop.in:6 msgid "Edit subtitle files" msgstr "עריכת קובצי הכתוביות" #. TRANSLATORS: Search terms to find this application. Do NOT translate or #. localize the semicolons! The list MUST also end with a semicolon! #: data/io.otsaloma.gaupol.desktop.in:12 msgid "video;subtitles;captions;" msgstr "" gaupol-1.11/po/hu.po000066400000000000000000002207531422217132500143250ustar00rootroot00000000000000# 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. # # Translators: # Osmo Salomaa , 2016 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-04-03 04:00+0300\n" "PO-Revision-Date: 2016-07-07 00:55+0000\n" "Last-Translator: Osmo Salomaa , 2016\n" "Language-Team: Hungarian (https://www.transifex.com/otsaloma/teams/64879/hu/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: hu\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: aeidon/enums.py:40 gaupol/enums.py:38 msgid "Subtitle number" msgstr "Feliratsorszám" #: aeidon/enums.py:43 msgid "Subtitle position" msgstr "Feliratpozíció" #: aeidon/enums.py:59 msgid "23.976 fps" msgstr "23.976 fps" #: aeidon/enums.py:63 msgid "24.000 fps" msgstr "24.000 fps" #: aeidon/enums.py:67 msgid "25.000 fps" msgstr "25.000 fps" #: aeidon/enums.py:71 msgid "29.970 fps" msgstr "29.970 fps" #: aeidon/enums.py:75 data/ui/menubar.ui:248 msgid "30.000 fps" msgstr "" #: aeidon/enums.py:79 data/ui/menubar.ui:253 msgid "50.000 fps" msgstr "" #: aeidon/enums.py:83 data/ui/menubar.ui:258 msgid "59.940 fps" msgstr "" #: aeidon/enums.py:87 data/ui/menubar.ui:263 msgid "60.000 fps" msgstr "" #: aeidon/enums.py:112 msgid "Mac (classic)" msgstr "Mac (klasszikus)" #. TRANSLATORS: Most of the character encoding descriptions are copied from #. gedit, which is translated to very many languages. Check the gedit .po #. files for a reference: #. . #: aeidon/encodings.py:40 aeidon/encodings.py:43 aeidon/encodings.py:46 msgid "English" msgstr "Angol" #: aeidon/encodings.py:41 aeidon/encodings.py:42 aeidon/encodings.py:69 msgid "Chinese traditional" msgstr "Hagyományos kínai" #: aeidon/encodings.py:44 msgid "German" msgstr "" #: aeidon/encodings.py:45 aeidon/encodings.py:54 aeidon/encodings.py:59 #: aeidon/encodings.py:79 aeidon/encodings.py:105 msgid "Hebrew" msgstr "Héber" #: aeidon/encodings.py:47 aeidon/encodings.py:51 aeidon/encodings.py:56 #: aeidon/encodings.py:73 aeidon/encodings.py:76 aeidon/encodings.py:98 #: aeidon/encodings.py:111 aeidon/encodings.py:122 msgid "Western" msgstr "Nyugati" #: aeidon/encodings.py:48 aeidon/encodings.py:61 aeidon/encodings.py:80 #: aeidon/encodings.py:103 msgid "Arabic" msgstr "Arab" #: aeidon/encodings.py:49 aeidon/encodings.py:64 aeidon/encodings.py:66 #: aeidon/encodings.py:77 aeidon/encodings.py:104 aeidon/encodings.py:119 msgid "Greek" msgstr "Görög" #: aeidon/encodings.py:50 aeidon/encodings.py:81 aeidon/encodings.py:101 #: aeidon/encodings.py:109 msgid "Baltic" msgstr "Balti" #: aeidon/encodings.py:52 aeidon/encodings.py:74 aeidon/encodings.py:99 #: aeidon/encodings.py:121 msgid "Central European" msgstr "Közép-Európai" #: aeidon/encodings.py:53 aeidon/encodings.py:75 aeidon/encodings.py:102 #: aeidon/encodings.py:118 msgid "Cyrillic" msgstr "Cirill" #: aeidon/encodings.py:55 aeidon/encodings.py:71 aeidon/encodings.py:78 #: aeidon/encodings.py:106 aeidon/encodings.py:123 msgid "Turkish" msgstr "Török" #: aeidon/encodings.py:57 msgid "Portuguese" msgstr "Portugál" #: aeidon/encodings.py:58 aeidon/encodings.py:120 msgid "Icelandic" msgstr "Izlandi" #: aeidon/encodings.py:60 msgid "Canadian" msgstr "Kanadai" #: aeidon/encodings.py:62 aeidon/encodings.py:107 msgid "Nordic" msgstr "Északi" #: aeidon/encodings.py:63 aeidon/encodings.py:114 msgid "Russian" msgstr "Cirill/Orosz" #: aeidon/encodings.py:65 aeidon/encodings.py:108 msgid "Thai" msgstr "Thai" #: aeidon/encodings.py:67 aeidon/encodings.py:83 aeidon/encodings.py:84 #: aeidon/encodings.py:85 aeidon/encodings.py:91 aeidon/encodings.py:92 #: aeidon/encodings.py:93 aeidon/encodings.py:94 aeidon/encodings.py:95 #: aeidon/encodings.py:96 aeidon/encodings.py:125 aeidon/encodings.py:126 #: aeidon/encodings.py:127 msgid "Japanese" msgstr "Japán" #: aeidon/encodings.py:68 aeidon/encodings.py:86 aeidon/encodings.py:97 #: aeidon/encodings.py:113 msgid "Korean" msgstr "Koreai" #: aeidon/encodings.py:70 msgid "Urdu" msgstr "Urdu" #: aeidon/encodings.py:72 aeidon/encodings.py:116 msgid "Ukrainian" msgstr "Cirill/Ukrán" #: aeidon/encodings.py:82 msgid "Vietnamese" msgstr "Vietnámi" #: aeidon/encodings.py:87 aeidon/encodings.py:90 msgid "Chinese simplified" msgstr "Egyszerűsített kínai" #: aeidon/encodings.py:88 aeidon/encodings.py:89 msgid "Chinese unified" msgstr "Egységes kínai" #: aeidon/encodings.py:100 aeidon/encodings.py:112 msgid "South European" msgstr "Dél-Európai" #: aeidon/encodings.py:110 msgid "Celtic" msgstr "Kelta" #: aeidon/encodings.py:115 msgid "Tajik" msgstr "" #: aeidon/encodings.py:117 msgid "Kazakh" msgstr "" #: aeidon/encodings.py:124 msgid "Cyrillic Asian" msgstr "Ázsiai cirill" #: aeidon/encodings.py:128 aeidon/encodings.py:129 aeidon/encodings.py:130 #: aeidon/encodings.py:131 aeidon/encodings.py:132 aeidon/encodings.py:133 #: aeidon/encodings.py:134 aeidon/encodings.py:135 aeidon/encodings.py:136 msgid "Unicode" msgstr "Unicode" #: aeidon/encodings.py:156 #, python-brace-format msgid "{description} ({name})" msgstr "{description} ({name})" #: aeidon/encodings.py:232 msgid "Current locale ({})" msgstr "Területi beállítás ({})" #: aeidon/locales.py:46 #, python-brace-format msgid "{language} ({country})" msgstr "{language} ({country})" #: aeidon/agents/search.py:227 msgid "Replacing" msgstr "Csere" #: aeidon/agents/search.py:256 aeidon/agents/search.py:258 msgid "Replacing all" msgstr "Összes cseréje" #: aeidon/agents/position.py:74 msgid "Adjusting durations" msgstr "Időtartam igazítása" #: aeidon/agents/position.py:96 msgid "Converting framerate" msgstr "Képfrissítés konvertálása" #: aeidon/agents/position.py:146 msgid "Setting framerate" msgstr "Képfrissítés beállítása" #: aeidon/agents/position.py:168 msgid "Shifting positions" msgstr "Időpozíciók eltolása" #: aeidon/agents/position.py:188 msgid "Transforming positions" msgstr "Időpozíciók átalakítása" #: aeidon/agents/clipboard.py:44 msgid "Cutting texts" msgstr "Szöveg kivágása" #: aeidon/agents/clipboard.py:61 msgid "Pasting texts" msgstr "Szöveg beillesztése" #: aeidon/agents/text.py:91 msgid "Breaking lines" msgstr "Sortördelés" #: aeidon/agents/text.py:128 msgid "Capitalizing texts" msgstr "Szöveg nagybetűssé alakítása" #: aeidon/agents/text.py:185 msgid "Correcting common errors" msgstr "Általános hibák javítása" #: aeidon/agents/text.py:234 msgid "Removing hearing impaired texts" msgstr "Halláskárosultak szövegeinek eltávolítása" #: aeidon/agents/text.py:315 msgid "Joining words by spell-check suggestions" msgstr "Szavak egyesítése a helyesírás-ellenőrző javaslata alapján" #: aeidon/agents/text.py:354 msgid "Splitting words by spell-check suggestions" msgstr "Szavak elválasztása a helyesírás-ellenőrző javaslata alapján" #: aeidon/agents/set.py:58 aeidon/agents/set.py:80 aeidon/agents/set.py:113 msgid "Editing position" msgstr "Pozíció szerkesztése" #: aeidon/agents/set.py:129 msgid "Editing text" msgstr "Szöveg szerkesztése" #: aeidon/agents/edit.py:35 msgid "Clearing texts" msgstr "Szöveg törlése" #: aeidon/agents/edit.py:61 aeidon/agents/edit.py:83 msgid "Inserting subtitles" msgstr "Feliratsor beszúrása" #: aeidon/agents/edit.py:103 msgid "Merging subtitles" msgstr "Feliratsorok egyesítése" #: aeidon/agents/edit.py:114 msgid "Removing subtitles" msgstr "Feliratsor(ok) eltávolítása" #: aeidon/agents/edit.py:131 msgid "Replacing positions" msgstr "Pozíció cseréje" #: aeidon/agents/edit.py:147 msgid "Replacing texts" msgstr "Szöveg cseréje" #: aeidon/agents/edit.py:171 msgid "Splitting subtitle" msgstr "Felirat felosztása" #: aeidon/agents/format.py:49 msgid "Adding dialogue dashes" msgstr "Párbeszéd kötőjel hozzáadása" #: aeidon/agents/format.py:68 msgid "Changing case" msgstr "Kis- és nagybetűk cseréje" #: aeidon/agents/format.py:92 msgid "Italicizing" msgstr "Döntött írásmód be" #: aeidon/agents/format.py:108 msgid "Removing dialogue dashes" msgstr "Párbeszéd kötőjel eltávolítása" #: aeidon/agents/format.py:174 msgid "Unitalicizing" msgstr "Döntött írásmód ki" #: gaupol/application.py:219 gaupol/agents/open.py:203 msgid "Open" msgstr "Megnyitás" #: gaupol/application.py:223 msgid "Open main files" msgstr "Alap fájl megnyitása" #: gaupol/application.py:230 msgid "Save" msgstr "" #: gaupol/application.py:233 msgid "Save the current main document" msgstr "Az aktuális dokumentum mentése" #: gaupol/application.py:238 msgid "Undo" msgstr "" #: gaupol/application.py:242 msgid "Undo the last action" msgstr "Utolsó művelet visszavonása" #: gaupol/application.py:249 msgid "Redo" msgstr "" #: gaupol/application.py:252 msgid "Redo the last undone action" msgstr "Visszavont művelet ismételt végrehajtása" #: gaupol/application.py:260 msgid "Insert" msgstr "Beszúrás" #: gaupol/application.py:262 msgid "Insert new subtitles" msgstr "Új feliratsor beszúrása" #: gaupol/application.py:266 #: data/extensions/custom-framerates/preferences-dialog.ui:78 msgid "Remove" msgstr "Eltávolítás" #: gaupol/application.py:268 msgid "Remove the selected subtitles" msgstr "Kijelölt feliratsorok eltávolítása" #: gaupol/application.py:273 data/ui/search-dialog.ui:283 msgid "Find" msgstr "Keresés" #: gaupol/application.py:275 msgid "Search for and replace text" msgstr "Keresés és csere a szövegben" #: gaupol/application.py:279 data/ui/preferences-dialog.ui:942 msgid "Video" msgstr "Videó" #: gaupol/application.py:281 msgid "Show or hide the video player" msgstr "Videólejátszó megjelenítése vagy elrejtése" #: gaupol/application.py:285 data/ui/preferences-dialog.ui:1173 msgid "Preview" msgstr "Előnézet" #: gaupol/application.py:287 msgid "Preview from selected position with a video player" msgstr "A kiválasztott pozíció előnézete videólejátszóval" #: gaupol/enums.py:37 msgid "No." msgstr "Sorszám" #: gaupol/enums.py:43 msgid "Start" msgstr "Kezdet" #: gaupol/enums.py:44 msgid "Start position" msgstr "Kezdőpozíció" #: gaupol/enums.py:49 msgid "End" msgstr "Vég" #: gaupol/enums.py:50 msgid "End position" msgstr "Végpozíció" #. TRANSLATORS: 'Dur.' is short for duration. It is used in the header #. of a column that contains numbers five digits wide. #: gaupol/enums.py:57 msgid "Dur." msgstr "Hossz" #: gaupol/enums.py:58 msgid "Duration" msgstr "Időtartam" #: gaupol/enums.py:63 gaupol/enums.py:64 msgid "Text" msgstr "Szöveg" #: gaupol/enums.py:69 gaupol/enums.py:70 msgid "Translation" msgstr "Fordítás" #: gaupol/enums.py:82 msgid "characters" msgstr "karakter" #: gaupol/enums.py:85 msgid "ems" msgstr "ems" #: gaupol/page.py:60 msgid "Untitled {:d}" msgstr "Névtelen {:d}" #: gaupol/page.py:133 msgid "Close project" msgstr "Projekt bezárása" #: gaupol/page.py:145 msgid "{} translation" msgstr "{} fordítás" #: gaupol/page.py:302 msgid "Path:" msgstr "Útvonal:" #: gaupol/page.py:303 msgid "Format:" msgstr "Formátum:" #: gaupol/page.py:304 msgid "Encoding:" msgstr "Kódolás:" #: gaupol/page.py:305 msgid "Newlines:" msgstr "Új s_or:" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:99 msgid "Tasks and Target" msgstr "Feladatok és célok" #: gaupol/assistants.py:128 msgid "Correct texts in the text column" msgstr "Javítás az alap szöveg oszlopban" #: gaupol/assistants.py:129 msgid "Correct texts in the translation column" msgstr "Javítás a fordítási szöveg oszlopban" #: gaupol/assistants.py:138 msgid "Correct texts in selected subtitles" msgstr "Javítás a kijelölt feliratokban" #: gaupol/assistants.py:139 msgid "Correct texts in current project" msgstr "Javítás az aktuális projektben" #: gaupol/assistants.py:140 msgid "Correct texts in all open projects" msgstr "Javítás az összes nyitott projektben" #: gaupol/assistants.py:363 msgid "Other" msgstr "Egyéb" #: gaupol/assistants.py:439 msgid "Capitalize texts written in lower case" msgstr "Kisbetűs szöveg nagybetűssé alakítása" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:443 msgid "Capitalization Patterns" msgstr "Szövegátalakítás sablonjai" #: gaupol/assistants.py:445 msgid "Capitalize texts" msgstr "Szöveg nagybetűssé alakítása" #: gaupol/assistants.py:468 msgid "Correct common errors made by humans or image recognition software" msgstr "Emberi és szövegfelismerési (OCR) általános hibák javítása" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:472 msgid "Common Error Patterns" msgstr "Általános hibák sablonjai" #: gaupol/assistants.py:474 msgid "Correct common errors" msgstr "Általános hibák javítása" #: gaupol/assistants.py:526 msgid "Remove explanatory texts meant for the hearing impaired" msgstr "Halláskárosultak magyarázó szövegeinek eltávolítása" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:530 msgid "Hearing Impaired Patterns" msgstr "Halláskárosultak sablonjai" #: gaupol/assistants.py:532 msgid "Remove hearing impaired texts" msgstr "Halláskárosultak szövegeinek eltávolítása" #: gaupol/assistants.py:544 msgid "" "Use spell-check suggestions to fix whitespace detection errors of image " "recognition software" msgstr "" "Helyesírás-ellenőrző javaslatainak használata a szövegfelismerő szoftver " "(OCR) által észlelt szóközhibák javítására" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:548 msgid "Joining and Splitting Words" msgstr "Szavak egyesítése és szétválasztása" #: gaupol/assistants.py:550 msgid "Join or Split Words" msgstr "Szavak egyesítése vagy szétválasztása" #: gaupol/assistants.py:599 gaupol/agents/tools.py:45 msgid "Failed to load dictionary for language \"{}\"" msgstr "A megadott nyelvhez \"{}\" tartozó szótár beolvasása sikertelen" #: gaupol/assistants.py:601 gaupol/player.py:263 gaupol/player.py:381 #: gaupol/dialogs/search.py:560 gaupol/dialogs/search.py:568 #: gaupol/dialogs/text_edit.py:49 gaupol/dialogs/encoding.py:56 #: gaupol/agents/open.py:328 gaupol/agents/open.py:337 #: gaupol/agents/open.py:345 gaupol/agents/open.py:354 #: gaupol/agents/tools.py:48 gaupol/agents/save.py:197 #: gaupol/agents/save.py:205 gaupol/agents/preview.py:108 #: gaupol/agents/preview.py:116 gaupol/agents/preview.py:125 #: gaupol/agents/preview.py:133 msgid "_OK" msgstr "_OK" #: gaupol/assistants.py:635 msgid "Break text into lines of defined length" msgstr "Szöveg tördelése a megadott sorhosszra" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:639 msgid "Line-Break Patterns" msgstr "Sortördelés sablonjai" #: gaupol/assistants.py:641 msgid "Break lines" msgstr "Sortördelés" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:679 msgid "Line-Break Options" msgstr "Sortördelés beállítása" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:763 msgid "Correcting Texts" msgstr "Szöveg javítása" #: gaupol/assistants.py:769 msgid "Each task is now being run on each project." msgstr "Kiválasztott feladat(ok) futatása az összes projekten." #: gaupol/assistants.py:793 #, python-brace-format msgid "{current:d} of {total:d} tasks complete" msgstr "{current:d} a(z) {total:d} feladatból kész" #: gaupol/assistants.py:801 msgid "Project: {}" msgstr "Projekt: {}" #: gaupol/assistants.py:807 msgid "Task: {}" msgstr "Feladat: {}" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:832 msgid "Confirm Changes" msgstr "Változások elfogadása" #: gaupol/assistants.py:892 msgid "Accept" msgstr "Elfogad" #: gaupol/assistants.py:898 msgid "Original Text" msgstr "Eredeti szöveg" #: gaupol/assistants.py:899 msgid "Corrected Text" msgstr "Javított szöveg" #: gaupol/assistants.py:1048 msgid "Correct Texts" msgstr "Szövegek javítása" #: gaupol/assistants.py:1076 msgid "Correcting texts" msgstr "Szövegek javítása" #: gaupol/assistants.py:1092 #, python-brace-format msgid "Edited {edits:d} and removed {removals:d} subtitles" msgstr "Szerkesztett {edits:d} és eltávolított {removals:d} feliratsorok" #: gaupol/assistants.py:1126 msgid "Confirm {:d} Change" msgid_plural "Confirm {:d} Changes" msgstr[0] "" msgstr[1] "" #: gaupol/renderers/multiline.py:86 msgid "Italic" msgstr "" #: gaupol/player.py:372 msgid "No video streams found" msgstr "" #: gaupol/player.py:379 msgid "Failed to initialize playback" msgstr "" #: gaupol/dialogs/search.py:189 data/ui/menubar.ui:524 msgid "_Help" msgstr "Sú_gó" #: gaupol/dialogs/search.py:471 msgid "Found and replaced {:d} occurence" msgid_plural "Found and replaced {:d} occurences" msgstr[0] "" msgstr[1] "" #: gaupol/dialogs/search.py:488 msgid "\"{}\" not found" msgstr "\"{}\" nem található" #: gaupol/dialogs/search.py:558 msgid "Error in regular expression pattern" msgstr "Hiba az általános kifejezések sablonjában" #: gaupol/dialogs/search.py:566 msgid "Error in regular expression replacement" msgstr "Hiba az általános kifejezés cseréjében" #: gaupol/dialogs/text_edit.py:48 gaupol/dialogs/framerate_convert.py:63 #: gaupol/dialogs/insert.py:44 gaupol/dialogs/encoding.py:55 #: gaupol/dialogs/split.py:44 gaupol/dialogs/multi_close.py:54 #: gaupol/dialogs/open.py:63 gaupol/dialogs/position_transform.py:69 #: gaupol/dialogs/position_shift.py:71 gaupol/dialogs/multi_save.py:83 #: gaupol/dialogs/multi_save.py:215 gaupol/dialogs/duration_adjust.py:86 #: gaupol/dialogs/save.py:73 gaupol/dialogs/video.py:41 #: gaupol/agents/open.py:363 gaupol/agents/open.py:375 #: gaupol/agents/open.py:387 gaupol/agents/close.py:71 #: data/extensions/custom-framerates/custom-framerates.py:39 msgid "_Cancel" msgstr "_Mégse" #: gaupol/dialogs/text_edit.py:53 msgid "Edit Text" msgstr "Szöveg szerkesztése" #: gaupol/dialogs/framerate_convert.py:64 msgid "Co_nvert" msgstr "_Konvertálás" #: gaupol/dialogs/insert.py:45 msgid "_Insert" msgstr "_Beszúrás" #: gaupol/dialogs/insert.py:54 msgid "Above selection" msgstr "Kijelölés felett" #: gaupol/dialogs/insert.py:55 msgid "Below selection" msgstr "Kijelölés alatt" #: gaupol/dialogs/encoding.py:60 data/ui/preferences-dialog.ui:70 msgid "Character Encodings" msgstr "Karakterkódolás" #: gaupol/dialogs/encoding.py:78 gaupol/dialogs/encoding.py:125 msgid "Description" msgstr "Leírás" #: gaupol/dialogs/encoding.py:85 gaupol/dialogs/encoding.py:132 msgid "Encoding" msgstr "Kódolás" #: gaupol/dialogs/encoding.py:141 msgid "Show in Menu" msgstr "Megjelenít a menüben" #: gaupol/dialogs/split.py:45 msgid "_Split" msgstr "Felo_sztás" #: gaupol/dialogs/split.py:76 msgid "Splitting project" msgstr "Projekt felosztása" #: gaupol/dialogs/split.py:97 #, python-brace-format msgid "Split {amount:d} subtitles to project \"{name}\"" msgstr "{amount:d} felirat felosztása a \"{name}\" projektbe" #: gaupol/dialogs/spell_check.py:269 msgid "Spell-checking" msgstr "Helyesírás-ellenőrzés" #: gaupol/dialogs/preferences.py:217 msgid "{} Extension Website" msgstr "{} Bővítmények honlapja" #: gaupol/dialogs/preferences.py:429 msgid "Custom" msgstr "Egyéni" #: gaupol/dialogs/multi_close.py:38 msgid "Save changes to documents before closing?" msgstr "Menti a változtatásokat bezárás előtt?" #: gaupol/dialogs/multi_close.py:39 gaupol/agents/open.py:384 #: gaupol/agents/close.py:68 msgid "If you don't save, changes will be permanently lost." msgstr "Ha nem menti, akkor a változtatások véglegesen el fognak veszni." #: gaupol/dialogs/multi_close.py:53 gaupol/agents/close.py:70 msgid "Close _Without Saving" msgstr "Bezárás _mentés nélkül" #: gaupol/dialogs/multi_close.py:55 gaupol/dialogs/multi_save.py:84 #: gaupol/dialogs/save.py:74 gaupol/agents/open.py:388 #: gaupol/agents/close.py:72 data/ui/menubar.ui:34 msgid "_Save" msgstr "_Mentés" #: gaupol/dialogs/multi_close.py:70 msgid "Select the _main documents you want to save:" msgstr "_Válassza ki az alap dokumentumot, ha menteni szeretné:" #: gaupol/dialogs/multi_close.py:95 msgid "Select the _translation documents you want to save:" msgstr "Válassza ki a fordí_tási dokumentumot, ha menteni szeretné:" #: gaupol/dialogs/open.py:64 gaupol/agents/open.py:364 #: gaupol/agents/open.py:376 msgid "_Open" msgstr "_Megnyitás" #: gaupol/dialogs/position_transform.py:70 msgid "_Transform" msgstr "Á_talakítás" #: gaupol/dialogs/position_shift.py:72 msgid "_Shift" msgstr "Eltolá_s" #: gaupol/dialogs/position_shift.py:150 msgid "frames" msgstr "képkocka" #: gaupol/dialogs/position_shift.py:168 data/ui/preferences-dialog.ui:911 msgid "seconds" msgstr "másodperc" #: gaupol/dialogs/about.py:36 msgid "About Gaupol" msgstr "Gaupol névjegye" #: gaupol/dialogs/about.py:40 msgid "Subtitle editor" msgstr "Feliratszerkesztő" #. TRANSLATORS: This is a special message that shouldn't be translated #. literally. It is used in the about dialog to give credits to the #. translators. Thus, you should translate it to your name and email #. address. You can also include other translators who have contributed #. to this translation; in that case, please write them on separate #. lines seperated by newlines (\n). #: gaupol/dialogs/about.py:51 msgid "translator-credits" msgstr "Andrássy László , 2009-2015" #: gaupol/dialogs/about.py:54 msgid "Gaupol Website" msgstr "A Gaupol honlapja" #: gaupol/dialogs/append.py:35 msgid "Append File" msgstr "Fájl hozzáfűzése" #: gaupol/dialogs/debug.py:43 msgid "Something went wrong" msgstr "Valami gond van" #: gaupol/dialogs/debug.py:44 msgid "" "You have probably discovered a bug. Please report it by providing the below " "information and a description of what you were doing." msgstr "" #: gaupol/dialogs/debug.py:52 msgid "_Report Bug" msgstr "" #: gaupol/dialogs/debug.py:53 data/ui/menubar.ui:56 msgid "_Quit" msgstr "_Kilépés" #: gaupol/dialogs/debug.py:54 gaupol/dialogs/preview_error.py:45 #: data/ui/menubar.ui:52 data/ui/tab-popup.ui:16 msgid "_Close" msgstr "Be_zárás" #: gaupol/dialogs/multi_save.py:98 gaupol/dialogs/save.py:110 msgid "{} (recommended)" msgstr "" #: gaupol/dialogs/multi_save.py:212 msgid "" "{:d} of the files to be saved already exist. Do you want to replace them?" msgstr "{:d} a fájlok közül már létezik! Le szeretné őket cserélni?" #: gaupol/dialogs/multi_save.py:213 msgid "" "The files already exist in \"{}\". Replacing them will overwrite their " "contents." msgstr "A(z) \"{}\" fájl már létezik. Lecserélésével a tartalma felül lesz írva." #: gaupol/dialogs/multi_save.py:216 data/ui/search-dialog.ui:192 #: data/ui/spell-check-dialog.ui:122 msgid "_Replace" msgstr "Cse_re" #: gaupol/dialogs/duration_adjust.py:70 msgid "Adjusted duration of {:d} subtitle" msgid_plural "Adjusted durations of {:d} subtitles" msgstr[0] "" msgstr[1] "" #: gaupol/dialogs/duration_adjust.py:87 msgid "_Adjust" msgstr "_Igazítás" #: gaupol/dialogs/preview_error.py:36 msgid "Preview in video player failed" msgstr "Az előnézet a videólejátszóval nem sikerült" #: gaupol/dialogs/preview_error.py:37 msgid "" "There is probably a problem with either the video file or the video player. " "See the preferences dialog to choose the video player or to customize the " "command." msgstr "" #: gaupol/dialogs/language.py:97 msgid "Set Language" msgstr "Nyelv beállítása" #: gaupol/dialogs/video.py:52 gaupol/dialogs/file.py:59 msgid "All files" msgstr "Összes fájl" #: gaupol/dialogs/video.py:56 msgid "Video files" msgstr "Videófájlok" #: gaupol/dialogs/file.py:63 msgid "All supported files" msgstr "Összes támogatott fájl" #: gaupol/dialogs/file.py:77 #, python-brace-format msgid "{format} (*{extension})" msgstr "{format} (*{extension})" #: gaupol/dialogs/file.py:120 msgid "Auto-detected" msgstr "Automatikus felismerés" #: gaupol/dialogs/file.py:122 msgid "Other…" msgstr "Egyéb…" #: gaupol/agents/menu.py:94 gaupol/agents/menu.py:103 #: gaupol/agents/menu.py:110 msgid "File not found" msgstr "" #: gaupol/agents/open.py:85 #, python-brace-format msgid "Appended {amount:d} subtitles from \"{basename}\"" msgstr "{amount:d} feliratsor hozzáfűzve innen: \"{basename}\"" #: gaupol/agents/open.py:96 msgid "Appending file" msgstr "Fájl hozzáfűzése" #: gaupol/agents/open.py:111 msgid "File \"{}\" is already open" msgstr "A fájl \"{}\" már megnyitva" #: gaupol/agents/open.py:214 msgid "Open Translation" msgstr "Fordítás megnyitása" #: gaupol/agents/open.py:223 msgid "Select Video" msgstr "Videó kiválasztása" #: gaupol/agents/open.py:224 msgid "_Select" msgstr "_Kiválasztás" #: gaupol/agents/open.py:325 msgid "Failed to decode file \"{}\" with all attempted codecs" msgstr "A(z) \"{}\" fájl dekódolása az összes támogatott kodekkel sikertelen." #: gaupol/agents/open.py:326 msgid "Please try to open the file with a different character encoding." msgstr "Próbálja megnyitni a fájlt más karakterkódolással." #: gaupol/agents/open.py:334 msgid "Failed to recognize format of file \"{}\"" msgstr "A(z) \"{}\" fájl formátuma ismeretlen" #: gaupol/agents/open.py:335 msgid "" "Please check that the file you are trying to open is a subtitle file of a " "format supported by Gaupol." msgstr "Ellenőrizze, hogy a fájl a Gaupol által támogatott felirat fájl-e." #: gaupol/agents/open.py:343 msgid "Failed to open file \"{}\"" msgstr "A fájl \"{}\" megnyitása sikertelen." #: gaupol/agents/open.py:351 msgid "Failed to parse file \"{}\"" msgstr "A fájl \"{}\" elemzése sikertelen." #: gaupol/agents/open.py:352 msgid "Please check that the file you are trying to open is a valid {} file." msgstr "Ellenőrizze, hogy a megnyitni kívánt {}, érvényes fájl-e." #: gaupol/agents/open.py:360 msgid "Open abnormally large file \"{}\"?" msgstr "Megnyitja ezt az abnormálisan nagy fájlt: \"{}\"?" #: gaupol/agents/open.py:361 msgid "" "Size of the file is {:.1f} MB, which is abnormally large for a text-based " "subtitle file. Please, check that you are not trying to open a binary file." msgstr "" "A fájl mérete {:.1f} MB. Ez túl nagy méretű ahhoz, hogy szöveg-alapú felirat" " fájl legyen! Ellenőrizze, hogy nem bináris fájlt szeretne-e megnyitni!" #: gaupol/agents/open.py:371 msgid "Open unsorted file \"{}\"?" msgstr "Megnyitja ezt a rendezetlen fájlt: \"{}\"?" #: gaupol/agents/open.py:372 msgid "" "The order of {:d} subtitles needs to be changed. If {:d} sounds like a lot, " "the file may be erroneously composed." msgstr "" "A(z) {:d} fordítás sorrendjét meg kell változtatni. Ha {:d} soknak tűnik, " "akkor lehet, hogy a fájl hibásan lett összeállítva." #: gaupol/agents/open.py:383 msgid "Save changes to translation document \"{}\" before opening a new one?" msgstr "" "Menti a(z) \"{}\" fordítási dokumentum változásait mielőtt megnyit egy újat?" #: gaupol/agents/open.py:386 msgid "Open _Without Saving" msgstr "Megnyitás _mentés nélkül" #: gaupol/agents/close.py:66 msgid "Save changes to document \"{}\" before closing?" msgstr "" #: gaupol/agents/edit.py:101 gaupol/agents/edit.py:119 msgid "Stretching end position" msgstr "Végpozíció nyújtása" #: gaupol/agents/edit.py:208 msgid "Inserted {:d} subtitle to fit clipboard contents" msgid_plural "Inserted {:d} subtitles to fit clipboard contents" msgstr[0] "" msgstr[1] "" #: gaupol/agents/edit.py:334 gaupol/agents/edit.py:352 msgid "Stretching start position" msgstr "Kezdőpozíció nyújtása" #: gaupol/agents/edit.py:411 msgid "Use Shift+Return for line-break" msgstr "Shift+Enter - Sortörés" #: gaupol/agents/save.py:129 msgid "Save As" msgstr "Mentés másként" #: gaupol/agents/save.py:135 msgid "Saved main document as \"{}\"" msgstr "A dokumentum mentve \"{}\" néven" #: gaupol/agents/save.py:153 msgid "Save Translation As" msgstr "Fordítás mentése más néven" #: gaupol/agents/save.py:159 msgid "Saved translation document as \"{}\"" msgstr "A fordítási dokumentum mentve \"{}\" néven" #: gaupol/agents/save.py:194 #, python-brace-format msgid "Failed to encode file \"{basename}\" with codec \"{codec}\"" msgstr "A(z) \"{basename}\" fájl átkódolása a(z) \"{codec}\" kodekkel nem sikerült" #: gaupol/agents/save.py:195 msgid "Please try to save the file with a different character encoding." msgstr "Próbálja más karakterkódolással menteni a fájlt!" #: gaupol/agents/save.py:203 msgid "Failed to save file \"{}\"" msgstr "A(z) \"{}\" fájl mentése sikertelen" #: gaupol/agents/video.py:67 data/ui/menubar.ui:380 msgid "_Play/Pause" msgstr "_Lejátszás/Megállítás" #: gaupol/agents/video.py:69 msgid "Play or pause video" msgstr "Videó lejátszása vagy megállítása" #: gaupol/agents/video.py:75 data/ui/menubar.ui:390 msgid "Seek _Previous" msgstr "_Ugrás az előzőre" #: gaupol/agents/video.py:77 msgid "Seek to the start of the previous subtitle" msgstr "Ugrás az előző feliratsorra" #: gaupol/agents/video.py:81 data/ui/menubar.ui:394 msgid "Seek _Next" msgstr "_Ugrás a következőre" #: gaupol/agents/video.py:83 msgid "Seek to the start of the next subtitle" msgstr "Ugrás a következő feliratsorra" #: gaupol/agents/video.py:88 data/ui/menubar.ui:400 msgid "Seek _Backward" msgstr "Lé_ptetés hátra" #: gaupol/agents/video.py:90 msgid "Seek backward" msgstr "Léptetés hátra" #: gaupol/agents/video.py:94 data/ui/menubar.ui:404 msgid "Seek _Forward" msgstr "Léptetés elő_re" #: gaupol/agents/video.py:96 msgid "Seek forward" msgstr "Léptetés előre" #: gaupol/agents/video.py:109 msgid "Volume" msgstr "Hangerő" #: gaupol/agents/video.py:189 msgid "Load Video" msgstr "Videó betöltése" #: gaupol/agents/video.py:189 msgid "_Load" msgstr "_Betöltés" #: gaupol/agents/video.py:361 msgid "Track {:d}" msgstr "" #: gaupol/agents/preview.py:105 msgid "Failed to encode subtitle file to temporary directory \"{}\"" msgstr "A(z) \"{}\" felirat fájl átkódolása az átmeneti mappába nem sikerült" #: gaupol/agents/preview.py:106 msgid "" "Subtitle data could not be encoded to a temporary file for preview with the " "current character encoding. Please first save the subtitle file with a " "different character encoding." msgstr "" "A felirat átkódolása az előnézethez nem sikerült az aktuális " "karakterkódolással. Először mentse ki a felirat fájlt más karakter " "kódolással!" #: gaupol/agents/preview.py:114 msgid "Failed to save subtitle file to temporary directory \"{}\"" msgstr "A(z) \"{}\" felirat fájl mentése az átmeneti mappába nem sikerült" #: gaupol/agents/preview.py:122 msgid "Video player not found" msgstr "" #: gaupol/agents/preview.py:123 msgid "" "Please install one of the supported video players: mpv (recommended), " "MPlayer or VLC. See the preferences dialog to choose the video player or to " "customize the command." msgstr "" #: gaupol/agents/preview.py:131 msgid "Failed to launch video player" msgstr "A videólejátszó elindítása sikertelen" #: gaupol/applicationman.py:105 msgid "gaupol [OPTION...] [FILE...] [+[NUM]]" msgstr "gaupol [OPCIÓK...] [FÁJL...] [+[SZÁM]]" #: gaupol/applicationman.py:109 msgid "FILE..." msgstr "" #: gaupol/applicationman.py:112 msgid "subtitle files to open" msgstr "" #: gaupol/applicationman.py:122 msgid "ENCODING" msgstr "KÓDOLÁS" #: gaupol/applicationman.py:125 msgid "set the character encoding used to open files" msgstr "Karakterkódolás beállítása a fájlok megnyitásához" #: gaupol/applicationman.py:132 msgid "list all available character encodings" msgstr "összes elérhető karakterkódolás megjelenítése" #: gaupol/applicationman.py:137 gaupol/applicationman.py:154 msgid "FILE" msgstr "FÁJL" #: gaupol/applicationman.py:140 msgid "open translation file" msgstr "fordítási fájl megnyitása" #: gaupol/applicationman.py:145 msgid "METHOD" msgstr "MÓDSZER" #: gaupol/applicationman.py:149 msgid "method used to align translation subtitles: 'number' or 'position'" msgstr "Igazítás módszere a fordítási szövegben: \"Szám\" vagy \"Pozíció\"" #: gaupol/applicationman.py:157 msgid "select video file" msgstr "Videófájl kiválasztása" #: data/extensions/custom-framerates/custom-framerates.py:40 #: data/ui/spell-check-dialog.ui:152 msgid "_Add" msgstr "_Hozzáadás" #: data/extensions/custom-framerates/custom-framerates.py:171 msgid "{:.3f} fps" msgstr "{:.3f} fps" #: data/extensions/custom-framerates/add-framerate-dialog.ui:13 msgid "Add Framerate" msgstr "Képfrissítés megadása" #: data/extensions/custom-framerates/add-framerate-dialog.ui:44 msgid "_Framerate:" msgstr "_Képfrissítés:" #: data/extensions/custom-framerates/add-framerate-dialog.ui:73 msgid "fps" msgstr "fps" #: data/extensions/custom-framerates/preferences-dialog.ui:8 msgid "Framerates" msgstr "Képfrissítés" #: data/extensions/custom-framerates/preferences-dialog.ui:64 msgid "Add" msgstr "Hozzáadás" #: data/ui/columns-popup.ui:6 data/ui/menubar.ui:275 msgid "_No." msgstr "_Sorszám" #: data/ui/columns-popup.ui:10 data/ui/menubar.ui:279 msgid "_Start" msgstr "Ke_zdet" #: data/ui/columns-popup.ui:14 data/ui/menubar.ui:283 msgid "_End" msgstr "_Vég" #: data/ui/columns-popup.ui:18 data/ui/menubar.ui:287 msgid "_Duration" msgstr "I_dőtartam" #: data/ui/columns-popup.ui:22 data/ui/menubar.ui:291 data/ui/menubar.ui:303 msgid "_Text" msgstr "Szö_veg" #: data/ui/columns-popup.ui:26 data/ui/menubar.ui:295 msgid "T_ranslation" msgstr "Fo_rdítás" #: data/ui/split-dialog.ui:15 msgid "Split Project" msgstr "Projekt felosztása" #: data/ui/split-dialog.ui:48 msgid "_First subtitle of new project:" msgstr "Az új projekt első _feliratsora:" #: data/ui/search-dialog.ui:89 msgid "_Search for:" msgstr "Kere_sés:" #: data/ui/search-dialog.ui:103 data/ui/spell-check-dialog.ui:193 msgid "Replace _with:" msgstr "Cse_re erre:" #: data/ui/search-dialog.ui:162 data/ui/menubar.ui:328 msgid "Find _Next" msgstr "Kö_vetkező találat" #: data/ui/search-dialog.ui:177 msgid "Find _Previous" msgstr "Elő_ző találat" #: data/ui/search-dialog.ui:207 msgid "Replace _All" msgstr "Összes _cseréje" #: data/ui/search-dialog.ui:241 msgid "R_egular expression" msgstr "Általános kif_ejezés" #: data/ui/search-dialog.ui:258 msgid "_Ignore case" msgstr "K_is- és nagybetű nem számít" #: data/ui/search-dialog.ui:304 data/ui/language-dialog.ui:108 msgid "Columns" msgstr "Oszlopok" #: data/ui/search-dialog.ui:324 msgid "Find in _text column" msgstr "Kere_sés az alap szöveg oszlopban" #: data/ui/search-dialog.ui:341 msgid "Find in t_ranslation column" msgstr "Keresés a _fordítási szöveg oszlopban" #: data/ui/search-dialog.ui:381 data/ui/framerate-convert-dialog.ui:144 #: data/ui/language-dialog.ui:186 #: data/ui/text-assistant/line-break-options-page.ui:178 #: data/ui/duration-adjust-dialog.ui:388 data/ui/position-shift-dialog.ui:180 #: data/ui/position-transform-dialog.ui:444 msgid "Subtitles" msgstr "Feliratok" #: data/ui/search-dialog.ui:401 msgid "Find in c_urrent project" msgstr "Keresés az _aktuális projektben" #: data/ui/search-dialog.ui:419 msgid "Find in _all open projects" msgstr "Ke_resés az összes nyitott projektben" #: data/ui/search-dialog.ui:452 msgid "Target" msgstr "Cél" #: data/ui/framerate-convert-dialog.ui:8 msgid "Convert Framerate" msgstr "Képfrissítés konvertálása" #: data/ui/framerate-convert-dialog.ui:48 msgid "Framerate" msgstr "Képfrissítés" #: data/ui/framerate-convert-dialog.ui:71 msgid "_Input:" msgstr "_Bemenet:" #: data/ui/framerate-convert-dialog.ui:86 msgid "_Output:" msgstr "_Kimenet:" #: data/ui/framerate-convert-dialog.ui:164 msgid "Convert c_urrent project" msgstr "Aktuális pro_jekt konvertálása" #: data/ui/framerate-convert-dialog.ui:181 msgid "Convert _all open projects" msgstr "Összes nyitott projekt konvertálás_a" #: data/ui/spell-check-dialog.ui:8 msgid "Check Spelling" msgstr "Helyesírás-ellenőrzés" #: data/ui/spell-check-dialog.ui:47 msgid "Join _Back" msgstr "Mö_gé (illesztés)" #: data/ui/spell-check-dialog.ui:62 msgid "Join _Forward" msgstr "E_lé (illesztés)" #: data/ui/spell-check-dialog.ui:77 data/ui/menubar.ui:62 msgid "_Edit" msgstr "_Szerkesztés" #: data/ui/spell-check-dialog.ui:92 msgid "_Ignore" msgstr "_Mellőzés" #: data/ui/spell-check-dialog.ui:107 msgid "Ig_nore All" msgstr "Mi_nden visszavonása" #: data/ui/spell-check-dialog.ui:137 msgid "Rep_lace All" msgstr "Összes cseré_je" #: data/ui/spell-check-dialog.ui:179 msgid "_Suggestions:" msgstr "Java_slat:" #: data/ui/multi-save-dialog.ui:8 msgid "Save All As" msgstr "Ö_sszes mentése másként" #: data/ui/multi-save-dialog.ui:46 msgid "Save in _folder:" msgstr "Mentés _mappába:" #: data/ui/multi-save-dialog.ui:60 data/ui/save-dialog.ui:25 msgid "For_mat:" msgstr "_Formátum:" #: data/ui/multi-save-dialog.ui:74 data/ui/open-dialog.ui:25 #: data/ui/save-dialog.ui:39 msgid "_Encoding:" msgstr "_Kódolás:" #: data/ui/multi-save-dialog.ui:88 data/ui/save-dialog.ui:53 msgid "Ne_wlines:" msgstr "Új s_or:" #: data/ui/multi-save-dialog.ui:103 msgid "Select A Folder" msgstr "Mappa kiválasztása" #: data/ui/multi-save-dialog.ui:150 data/ui/save-dialog.ui:102 msgid "F_ramerate:" msgstr "Képf_rissítés:" #: data/ui/menubar.ui:5 msgid "_File" msgstr "_Fájl" #: data/ui/menubar.ui:8 msgid "_New" msgstr "Ú_j" #: data/ui/menubar.ui:12 msgid "_Open…" msgstr "Me_gnyitás…" #: data/ui/menubar.ui:16 msgid "Open _Translation…" msgstr "Fordí_tási fájl megnyitása…" #: data/ui/menubar.ui:22 msgid "Open _Recent" msgstr "Legutó_bbi fájl megnyitása" #: data/ui/menubar.ui:27 msgid "Open R_ecent Translation" msgstr "Leg_utóbbi fordítási fájl megnyitása" #: data/ui/menubar.ui:38 msgid "Save _As…" msgstr "Me_ntés másként…" #: data/ui/menubar.ui:42 msgid "Save Trans_lation" msgstr "_Fordítás mentése" #: data/ui/menubar.ui:46 msgid "Save Translat_ion As…" msgstr "For_dítás mentése másként…" #: data/ui/menubar.ui:65 msgid "_Undo" msgstr "_Visszavonás" #: data/ui/menubar.ui:69 msgid "_Redo" msgstr "Új_ra" #: data/ui/menubar.ui:75 msgid "_Edit Cell" msgstr "M_ező szerkesztése" #: data/ui/menubar.ui:79 msgid "Edit _Next Cell" msgstr "Következő me_ző szerkesztése" #: data/ui/menubar.ui:85 msgid "Stretc_h" msgstr "" #: data/ui/menubar.ui:88 msgid "_Start Earlier" msgstr "Ke_zdet előbbre" #: data/ui/menubar.ui:92 msgid "S_tart Later" msgstr "Kez_det későbbre" #: data/ui/menubar.ui:98 msgid "E_nd Earlier" msgstr "Vé_g előbbre" #: data/ui/menubar.ui:102 msgid "En_d Later" msgstr "_Vég későbbre" #: data/ui/menubar.ui:108 msgid "Set St_art From Video Position" msgstr "" #: data/ui/menubar.ui:112 msgid "Set En_d From Video Position" msgstr "Vég-időpont beállítása a videó pozíciójából" #: data/ui/menubar.ui:118 data/ui/view-popup.ui:6 msgid "_Split Subtitle" msgstr "Felirats_or felosztása" #: data/ui/menubar.ui:122 data/ui/view-popup.ui:10 msgid "_Merge Subtitles" msgstr "Fel_iratsorok egyesítése" #: data/ui/menubar.ui:128 data/ui/view-popup.ui:16 msgid "_Insert Subtitles…" msgstr "Fel_iratsor beszúrása…" #: data/ui/menubar.ui:132 msgid "Inser_t Subtitle At Video Position" msgstr "Felira_tsor beszúrása a videópozícióhoz" #: data/ui/menubar.ui:136 data/ui/view-popup.ui:20 msgid "Rem_ove Subtitles" msgstr "_Feliratsor(ok) eltávolítása" #: data/ui/menubar.ui:142 msgid "Sele_ction" msgstr "Ki_jelölés" #: data/ui/menubar.ui:145 msgid "Select _All" msgstr "Összes ki_jelölése" #: data/ui/menubar.ui:149 msgid "_Invert Selection" msgstr "K_ijelölés invertálása" #: data/ui/menubar.ui:155 msgid "Extend To _Beginning" msgstr "Ki_bővítés az első feliratsorig" #: data/ui/menubar.ui:159 msgid "Extend To _End" msgstr "Kibő_vítés az utolsó feliratsorig" #: data/ui/menubar.ui:165 msgid "_Previous From Video Position" msgstr "" #: data/ui/menubar.ui:169 msgid "_Next From Video Position" msgstr "" #: data/ui/menubar.ui:177 msgid "_Preferences" msgstr "_Beállítások" #: data/ui/menubar.ui:183 msgid "_View" msgstr "_Nézet" #: data/ui/menubar.ui:186 msgid "Tool_bar" msgstr "_Eszköztár" #: data/ui/menubar.ui:190 msgid "_Video Player" msgstr "_Videólejátszó" #: data/ui/menubar.ui:196 msgid "_Layout" msgstr "_Elrendezés" #: data/ui/menubar.ui:199 msgid "_Horizontal" msgstr "_Vízszintes" #: data/ui/menubar.ui:204 msgid "_Vertical" msgstr "_Függőleges" #: data/ui/menubar.ui:213 msgid "_Times" msgstr "_Idő" #: data/ui/menubar.ui:218 msgid "_Frames" msgstr "Ké_pkocka" #: data/ui/menubar.ui:225 msgid "F_ramerate" msgstr "Képf_rissítés" #: data/ui/menubar.ui:228 msgid "2_3.976 fps" msgstr "2_3.976 fps" #: data/ui/menubar.ui:233 msgid "2_4.000 fps" msgstr "2_4.000 fps" #: data/ui/menubar.ui:238 msgid "2_5.000 fps" msgstr "2_5.000 fps" #: data/ui/menubar.ui:243 msgid "2_9.970 fps" msgstr "2_9.970 fps" #: data/ui/menubar.ui:272 msgid "_Columns" msgstr "_Oszlopok" #: data/ui/menubar.ui:306 msgid "Cu_t" msgstr "_Kivágás" #: data/ui/menubar.ui:310 msgid "_Copy" msgstr "_Másolás" #: data/ui/menubar.ui:314 msgid "_Paste" msgstr "Bei_llesztés" #: data/ui/menubar.ui:318 msgid "Cl_ear" msgstr "_Törlés" #: data/ui/menubar.ui:324 msgid "_Find And Replace…" msgstr "Keresés és _csere…" #: data/ui/menubar.ui:332 msgid "Find Pre_vious" msgstr "Elő_ző találat" #: data/ui/menubar.ui:338 msgid "_Italic" msgstr "_Dőlt betű" #: data/ui/menubar.ui:342 msgid "_Dialogue" msgstr "_Párbeszéd" #: data/ui/menubar.ui:348 msgid "Ca_se" msgstr "Ki_s- és nagybetű" #: data/ui/menubar.ui:351 msgid "_Title" msgstr "_Cím" #: data/ui/menubar.ui:355 msgid "_Sentence" msgstr "M_ondat" #: data/ui/menubar.ui:359 msgid "_Upper" msgstr "_Nagybetűs" #: data/ui/menubar.ui:363 msgid "_Lower" msgstr "_Kisbetűs" #: data/ui/menubar.ui:371 msgid "Vi_deo" msgstr "Vi_deó" #: data/ui/menubar.ui:374 msgid "_Load Video…" msgstr "_Videó betöltése…" #: data/ui/menubar.ui:384 data/ui/view-popup.ui:26 msgid "Play _Selection" msgstr "Kijelö_lt lejátszása" #: data/ui/menubar.ui:410 data/ui/view-popup.ui:30 msgid "S_eek Selection Start" msgstr "Ugrás a ki_jelölés elejére" #: data/ui/menubar.ui:414 msgid "See_k Selection End" msgstr "Ugrás a _kijelölés végére" #: data/ui/menubar.ui:420 msgid "_Audio" msgstr "_Audió" #: data/ui/menubar.ui:423 msgid "_Language" msgstr "_Nyelv" #: data/ui/menubar.ui:430 msgid "Volume _Down" msgstr "Hangerő _Le" #: data/ui/menubar.ui:434 msgid "Volume _Up" msgstr "Hangerő _Fel" #: data/ui/menubar.ui:440 msgid "T_ools" msgstr "_Eszközök" #: data/ui/menubar.ui:443 data/ui/text-assistant/confirmation-page.ui:97 #: data/ui/view-popup.ui:36 msgid "_Preview" msgstr "_Előnézet" #: data/ui/menubar.ui:447 msgid "Select _Video…" msgstr "_Videó kiválasztása…" #: data/ui/menubar.ui:453 msgid "_Check Spelling" msgstr "Hel_yesírás-ellenőrzés" #: data/ui/menubar.ui:457 msgid "Co_nfigure Spell-check…" msgstr "Helyesírás-elle_nőrző beállítása…" #: data/ui/menubar.ui:461 msgid "C_orrect Texts…" msgstr "Szöveg _javítása…" #: data/ui/menubar.ui:467 msgid "_Shift Positions…" msgstr "Időpozíciók eltolá_sa…" #: data/ui/menubar.ui:471 msgid "_Transform Positions…" msgstr "Idő_pozíciók átalakítása…" #: data/ui/menubar.ui:475 msgid "Adjust _Durations…" msgstr "I_dőtartam beállítása…" #: data/ui/menubar.ui:479 msgid "Convert _Framerate…" msgstr "Kép_frissítés módosítása…" #: data/ui/menubar.ui:485 msgid "_Append File…" msgstr "Fáj_l hozzáfűzése…" #: data/ui/menubar.ui:489 msgid "Spli_t Project…" msgstr "Projek_t felosztása…" #: data/ui/menubar.ui:495 msgid "_Projects" msgstr "_Projektek" #: data/ui/menubar.ui:498 msgid "_Save All" msgstr "Ö_sszes mentése" #: data/ui/menubar.ui:502 msgid "Save _All As…" msgstr "Összes me_ntése másként…" #: data/ui/menubar.ui:506 msgid "_Close All" msgstr "Öss_zes bezárása" #: data/ui/menubar.ui:512 msgid "_Previous" msgstr "_Előző" #: data/ui/menubar.ui:516 msgid "_Next" msgstr "_Következő" #: data/ui/menubar.ui:527 msgid "_Documentation" msgstr "" #: data/ui/menubar.ui:531 msgid "_Report A Bug" msgstr "Hi_bajelentés" #: data/ui/menubar.ui:535 msgid "_About" msgstr "Névjeg_y" #: data/ui/open-dialog.ui:39 msgid "Align _method:" msgstr "Igazítás _módszere:" #: data/ui/preferences-dialog.ui:18 msgid "Preferences" msgstr "Tulajdonságok" #: data/ui/preferences-dialog.ui:93 msgid "When opening files, try encodings in the following order:" msgstr "Fájl megnyitásakor a karakterkódolást próbája az alábbi sorrendben:" #: data/ui/preferences-dialog.ui:104 msgid "Curr_ent locale encoding" msgstr "Aktuális h_elyi kódolás" #: data/ui/preferences-dialog.ui:130 msgid "_Fallback encodings:" msgstr "Elé_rhető kódolások:" #: data/ui/preferences-dialog.ui:246 msgid "Aut_o-detection" msgstr "Aut_omatikus felismerés" #: data/ui/preferences-dialog.ui:266 msgid "Encoding specified in the open dialog will always be tried first." msgstr "Mindig a párbeszédablakban megadott kódolásokat próbálja először." #: data/ui/preferences-dialog.ui:296 msgid "File" msgstr "Fájl" #: data/ui/preferences-dialog.ui:324 msgid "Font" msgstr "Betűtípus" #: data/ui/preferences-dialog.ui:344 msgid "Use _default theme fixed width font" msgstr "" #: data/ui/preferences-dialog.ui:368 msgid "_Editor font:" msgstr "_Szerkesztő betűtípusa:" #: data/ui/preferences-dialog.ui:425 msgid "Line Lengths" msgstr "Sorhossz" #: data/ui/preferences-dialog.ui:445 msgid "_Show line lengths in list cells" msgstr "_Sorhossz megjelenítése a mezőkben" #: data/ui/preferences-dialog.ui:462 msgid "S_how line lengths in editable text fields" msgstr "Sor_hossz megjelenítése a szerkeszthető szövegmezőkben" #: data/ui/preferences-dialog.ui:486 msgid "_Length unit:" msgstr "_Hosszegység:" #: data/ui/preferences-dialog.ui:540 msgid "Spell-Check" msgstr "Helyesírás-ellenőrzés" #: data/ui/preferences-dialog.ui:560 msgid "Chec_k spelling as you type" msgstr "He_lyesírás-ellenőrzés beíráskor" #: data/ui/preferences-dialog.ui:598 msgid "Editor" msgstr "Szerkesztő" #: data/ui/preferences-dialog.ui:626 msgid "Fonts" msgstr "Betűtípusok" #: data/ui/preferences-dialog.ui:649 msgid "_Subtitles:" msgstr "Feli_rat:" #: data/ui/preferences-dialog.ui:679 msgid "_Time:" msgstr "_Idő:" #: data/ui/preferences-dialog.ui:729 msgid "Colors" msgstr "Színek" #: data/ui/preferences-dialog.ui:752 msgid "Su_btitles:" msgstr "_Feliratok:" #: data/ui/preferences-dialog.ui:777 msgid "_Use a background behind text" msgstr "_Háttér használata a szöveg mögött" #: data/ui/preferences-dialog.ui:797 msgid "Ti_me:" msgstr "I_dő:" #: data/ui/preferences-dialog.ui:822 msgid "Us_e a background behind text" msgstr "_Háttér használata a szöveg mögött" #: data/ui/preferences-dialog.ui:862 msgid "Seek" msgstr "" #: data/ui/preferences-dialog.ui:883 msgid "_Length:" msgstr "" #: data/ui/preferences-dialog.ui:971 msgid "Video Player" msgstr "Videólejátszó" #: data/ui/preferences-dialog.ui:994 msgid "_Application:" msgstr "_Alkalmazás:" #: data/ui/preferences-dialog.ui:1008 msgid "Co_mmand:" msgstr "Para_ncs:" #. Translators: Only the title is to be translated, field names not. #: data/ui/preferences-dialog.ui:1033 msgid "" "Fields:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" msgstr "" #: data/ui/preferences-dialog.ui:1048 msgid "Al_ways use UTF-8 character encoding" msgstr "Mi_ndig UTF-8 karakterkódolást használjon" #: data/ui/preferences-dialog.ui:1089 msgid "Start Position" msgstr "Kezdőpozíció" #: data/ui/preferences-dialog.ui:1111 msgid "_Offset:" msgstr "_Offset:" #: data/ui/preferences-dialog.ui:1142 msgid "seconds before selection" msgstr "másodperc a kijelölés előtt" #: data/ui/preferences-dialog.ui:1281 msgid "Extensions" msgstr "Bővítmények" #: data/ui/language-dialog.ui:8 msgid "Configure Spell-Check" msgstr "Helyesírás-ellenőrző beállítása" #: data/ui/language-dialog.ui:50 msgid "Language" msgstr "Nyelv" #: data/ui/language-dialog.ui:128 msgid "Check _text column" msgstr "Az ala_p szöveg oszlop ellenőrzése" #: data/ui/language-dialog.ui:146 msgid "Check t_ranslation column" msgstr "A fordítási s_zöveg oszlop ellenőrzése" #: data/ui/language-dialog.ui:206 msgid "Check c_urrent project" msgstr "Aktuális _projekt ellenőrzése" #: data/ui/language-dialog.ui:224 msgid "Check _all open projects" msgstr "Összes _nyitott projekt ellenőrzése" #: data/ui/text-assistant/confirmation-page.ui:22 msgid "Acc_ept, discard or edit changes:" msgstr "A módosítások _elfogadása, visszavonása, vagy szerkesztése:" #: data/ui/text-assistant/confirmation-page.ui:67 msgid "_Mark All" msgstr "_Összes kijelölése" #: data/ui/text-assistant/confirmation-page.ui:82 msgid "_Unmark All" msgstr "Az ö_sszes kijelölés törlése" #: data/ui/text-assistant/confirmation-page.ui:119 msgid "_Remove all blank subtitles" msgstr "Az összes ü_res feliratsor törlése" #: data/ui/text-assistant/join-split-page.ui:28 msgid "Spell-Check Dictionary" msgstr "Helyesírás-ellenőrző szótár" #: data/ui/text-assistant/join-split-page.ui:49 #: data/ui/text-assistant/line-break-page.ui:81 #: data/ui/text-assistant/hearing-impaired-page.ui:81 #: data/ui/text-assistant/common-error-page.ui:80 #: data/ui/text-assistant/capitalization-page.ui:80 msgid "_Language:" msgstr "_Nyelv:" #: data/ui/text-assistant/join-split-page.ui:97 msgid "Corrections" msgstr "Korrekciók" #: data/ui/text-assistant/join-split-page.ui:117 msgid "_Join words not found in spell-check dictionary" msgstr "" "_Szavak összevonása, melyek nem találhatók a helyesírás-ellenőrző szótárban" #: data/ui/text-assistant/join-split-page.ui:134 msgid "_Split words not found in spell-check dictionary" msgstr "" "S_zavak elválasztása, melyek nem találhatók a helyesírás-ellenőrző szótárban" #: data/ui/text-assistant/line-break-page.ui:22 msgid "S_elect preferred line-break points:" msgstr "Pre_ferált sortördelési pont kiválasztása:" #: data/ui/text-assistant/line-break-page.ui:67 #: data/ui/text-assistant/hearing-impaired-page.ui:67 #: data/ui/text-assistant/common-error-page.ui:66 #: data/ui/text-assistant/capitalization-page.ui:66 msgid "_Script:" msgstr "_Szkript:" #: data/ui/text-assistant/line-break-page.ui:95 #: data/ui/text-assistant/hearing-impaired-page.ui:95 #: data/ui/text-assistant/common-error-page.ui:94 #: data/ui/text-assistant/capitalization-page.ui:94 msgid "Co_untry:" msgstr "_Ország:" #: data/ui/text-assistant/introduction-page.ui:28 msgid "_Select corrections to perform on texts:" msgstr "Ja_vítási feladatok kijelölése és végrehajtása a szövegen:" #: data/ui/text-assistant/introduction-page.ui:79 msgid "Colu_mns:" msgstr "Oszlo_pok:" #: data/ui/text-assistant/introduction-page.ui:93 msgid "S_ubtitles:" msgstr "Fe_liratok:" #: data/ui/text-assistant/line-break-options-page.ui:56 #: data/ui/duration-adjust-dialog.ui:207 msgid "Limits" msgstr "Korlátozások" #: data/ui/text-assistant/line-break-options-page.ui:79 msgid "_Maximum line length:" msgstr "_Maximális sorhossz:" #: data/ui/text-assistant/line-break-options-page.ui:93 msgid "_Preferred maximum amount of lines:" msgstr "Sorok _preferált maximális száma:" #: data/ui/text-assistant/line-break-options-page.ui:198 msgid "_Skip subtitles with maximum line length of:" msgstr "Feli_ratsor átlépése ha a sorhossz nagyobb, mint:" #: data/ui/text-assistant/line-break-options-page.ui:214 msgid "S_kip subtitles with maximum line amount of:" msgstr "Feliratsor átlépése ha a soro_k száma több, mint:" #: data/ui/text-assistant/hearing-impaired-page.ui:22 msgid "S_elect parts to remove:" msgstr "Kij_elölt részeket törölni:" #: data/ui/text-assistant/common-error-page.ui:22 msgid "S_elect errors to correct:" msgstr "H_ibák kijelölése javításra:" #: data/ui/text-assistant/common-error-page.ui:108 msgid "Error types:" msgstr "Hiba típus:" #: data/ui/text-assistant/common-error-page.ui:158 msgid "_Human errors" msgstr "_Emberi hibák" #: data/ui/text-assistant/common-error-page.ui:175 msgid "_Image recognition errors" msgstr "_Szövegfelismerési (OCR) hibák" #: data/ui/text-assistant/capitalization-page.ui:22 msgid "S_elect parts to capitalize:" msgstr "A kijelölt rész_ek nagybetűssé alakítása:" #: data/ui/duration-adjust-dialog.ui:33 msgid "Adjust Durations" msgstr "Időtartam igazítása" #: data/ui/duration-adjust-dialog.ui:73 msgid "Theoretic Duration" msgstr "Elméleti időtartam" #: data/ui/duration-adjust-dialog.ui:101 msgid "_Reading speed:" msgstr "_Olvasási sebesség:" #: data/ui/duration-adjust-dialog.ui:133 msgid "characters per second" msgstr "karakter másodpercenként" #: data/ui/duration-adjust-dialog.ui:150 msgid "_Lengthen duration to match reading speed" msgstr "Az időtartam növe_lése, hogy megegyezzen az olvasási sebességgel" #: data/ui/duration-adjust-dialog.ui:167 msgid "_Shorten duration to match reading speed" msgstr "Az időtartam c_sökkentése, hogy megegyezzen az olvasási sebességgel" #: data/ui/duration-adjust-dialog.ui:227 msgid "_Minimum duration:" msgstr "_Minimum időtartam:" #: data/ui/duration-adjust-dialog.ui:243 msgid "Ma_ximum duration:" msgstr "Ma_ximum időtartam:" #: data/ui/duration-adjust-dialog.ui:259 msgid "_Gap between subtitles:" msgstr "S_zünet a feliratsorok között:" #: data/ui/duration-adjust-dialog.ui:294 msgid "s_econds" msgstr "másodp_erc" #: data/ui/duration-adjust-dialog.ui:324 msgid "seco_nds" msgstr "_másodperc" #: data/ui/duration-adjust-dialog.ui:354 msgid "secon_ds" msgstr "máso_dperc" #: data/ui/duration-adjust-dialog.ui:408 msgid "Adj_ust selected subtitles" msgstr "Ki_jelölt felirat igazítása" #: data/ui/duration-adjust-dialog.ui:425 msgid "Adjus_t current project" msgstr "Ak_tuális projekt igazítása" #: data/ui/duration-adjust-dialog.ui:442 msgid "Adjust all _open projects" msgstr "Összes nyitott p_rojekt igazítása" #: data/ui/tab-popup.ui:6 msgid "Move Tab _Left" msgstr "_Lap mozgatása balra" #: data/ui/tab-popup.ui:10 msgid "Move Tab _Right" msgstr "Lap mozgatása jobb_ra" #: data/ui/insert-dialog.ui:15 msgid "Insert Subtitles" msgstr "Feliratsor beszúrása" #: data/ui/insert-dialog.ui:48 data/ui/position-shift-dialog.ui:82 msgid "_Amount:" msgstr "_Mennyiség:" #: data/ui/insert-dialog.ui:62 msgid "_Position:" msgstr "_Pozíció:" #: data/ui/position-shift-dialog.ui:14 msgid "Shift Positions" msgstr "Időpozíciók eltolása" #: data/ui/position-shift-dialog.ui:54 msgid "Shift" msgstr "Eltolás" #: data/ui/position-shift-dialog.ui:135 #: data/ui/position-transform-dialog.ui:208 msgid "_Preview Changes" msgstr "Mó_dosítások előnézete" #: data/ui/position-shift-dialog.ui:200 msgid "Shift s_elected subtitles" msgstr "Kijelölt feli_rat eltolása" #: data/ui/position-shift-dialog.ui:217 msgid "Shift su_btitles from selection to end" msgstr "Feliratsorok el_tolása a kijelöléstől a végéig" #: data/ui/position-shift-dialog.ui:234 msgid "Shift c_urrent project" msgstr "Akt_uális projekt eltolása" #: data/ui/position-shift-dialog.ui:251 msgid "Shift all _open projects" msgstr "" #: data/ui/position-transform-dialog.ui:22 msgid "Transform Positions" msgstr "Pozíciók átalakítása" #: data/ui/position-transform-dialog.ui:62 msgid "First Point" msgstr "Első pont" #: data/ui/position-transform-dialog.ui:91 msgid "_Subtitle:" msgstr "Feli_rat:" #: data/ui/position-transform-dialog.ui:105 msgid "C_orrection:" msgstr "K_orrekció:" #: data/ui/position-transform-dialog.ui:119 #: data/ui/position-transform-dialog.ui:310 msgid "Text:" msgstr "Szöveg:" #: data/ui/position-transform-dialog.ui:253 msgid "Second Point" msgstr "Második pont" #: data/ui/position-transform-dialog.ui:282 msgid "Su_btitle:" msgstr "_Felirat:" #: data/ui/position-transform-dialog.ui:296 msgid "Co_rrection:" msgstr "Ko_rrekciók:" #: data/ui/position-transform-dialog.ui:399 msgid "Pre_view Changes" msgstr "Mó_dosítások előnézete" #: data/ui/position-transform-dialog.ui:464 msgid "Transform se_lected subtitles" msgstr "Kije_lölt felirat átalakítása" #: data/ui/position-transform-dialog.ui:482 msgid "Transform c_urrent project" msgstr "Akt_uális projekt átalakítása" #: data/extensions/custom-framerates/custom-framerates.extension.in:7 msgid "Custom Framerates" msgstr "Egyéni képfrissítés" #: data/extensions/custom-framerates/custom-framerates.extension.in:8 msgid "Allow use of non-standard framerates" msgstr "Nem szokványos képfrissítés használatának engedélyezése" #: data/patterns/Latn-en-US.common-error.in:5 msgid "Period after title" msgstr "Pont az előtag után" #: data/patterns/Latn-en-US.common-error.in:6 msgid "Add period after a shortened title, such as \"Mr\" and \"Dr\"" msgstr "Pont hozzáadása olyan rövidített előtagok után, mint pl. a \"Mr\" és \"Dr\"" #: data/patterns/Latn-en.capitalization.in:5 msgid "First person pronoun" msgstr "Egyes szám első személy" #: data/patterns/Latn-en.capitalization.in:6 msgid "Capitalize the first person pronoun \"I\"" msgstr "Az \"I\" (én) névmás cseréje nagy betűre (Angol)" #: data/patterns/Latn-en.common-error.in:5 #: data/patterns/Latn-en.common-error.in:14 #: data/patterns/Latn-en.common-error.in:23 msgid "Letter \"I\" in a lower case word" msgstr "Az \"I\" betű egy kisbetűs szóban (Angol)" #: data/patterns/Latn-en.common-error.in:6 #: data/patterns/Latn-en.common-error.in:15 #: data/patterns/Latn-en.common-error.in:24 msgid "Replace letter \"I\" with letter \"l\" in a lower case word" msgstr "Az \"I\" betű cseréje \"l\" betűre kisbetűs szavakban (Angol)" #: data/patterns/Latn-en.common-error.in:32 #: data/patterns/Latn-en.common-error.in:41 #: data/patterns/Latn-en.common-error.in:50 #: data/patterns/Latn-en.common-error.in:62 msgid "Letter \"l\" in an upper case word" msgstr "Az \"l\" betű egy nagybetűs szóban (Angol)" #: data/patterns/Latn-en.common-error.in:33 #: data/patterns/Latn-en.common-error.in:42 #: data/patterns/Latn-en.common-error.in:51 #: data/patterns/Latn-en.common-error.in:63 msgid "Replace letter \"l\" with letter \"I\" in an upper case word" msgstr "Az \"l\" betű cseréje \"I\" betűre nagybetűs szavakban (Angol)" #: data/patterns/Latn-en.common-error.in:73 #: data/patterns/Latn-en.common-error.in:82 msgid "Zero in an upper case word" msgstr "Nulla (0) egy nagybetűs szóban" #: data/patterns/Latn-en.common-error.in:74 #: data/patterns/Latn-en.common-error.in:83 msgid "Replace zero with letter \"O\" in an upper case word" msgstr "Nulla (0) cseréje \"O\" betűre a nagybetűs szavakban" #: data/patterns/Latn-en.common-error.in:91 #: data/patterns/Latn.common-error.in:108 msgid "Space between number and unit" msgstr "Szóközök a számok és a mértékegységek között" #: data/patterns/Latn-en.common-error.in:92 #: data/patterns/Latn.common-error.in:109 msgid "Add or remove space between a number and the associated unit" msgstr "" "A számok és a társított mértékegységek közötti szóköz hozzáadása vagy " "eltávolítása" #: data/patterns/Latn-en.common-error.in:100 msgid "Spaces around an apostrophe" msgstr "Szóközök az idézőjelek mellett" #: data/patterns/Latn-en.common-error.in:101 msgid "Remove spaces around an apostrophe" msgstr "Szóközök eltávolítása az idézőjelek mellől" #: data/patterns/Latn-en.common-error.in:109 #: data/patterns/Latn-en.common-error.in:118 msgid "Okay" msgstr "Okay" #: data/patterns/Latn-en.common-error.in:110 #: data/patterns/Latn-en.common-error.in:119 msgid "Spell two-letter forms of \"okay\" in all upper case" msgstr "Az \"okay\" kétbetűs formája mindig nagybetűvel" #: data/patterns/Latn-en.hearing-impaired.in:5 msgid "Uppercase speaker before a colon" msgstr "A \"Beszélő\" kettőspont előtti nagybetűs neve" #: data/patterns/Latn-en.hearing-impaired.in:6 msgid "" "Replace the uppercase name of the speaker before a colon with a dialogue " "dash" msgstr "A \"Beszélő\" kettőspont előtti nagybetűs nevének cseréje gondolatjelre" #: data/patterns/Latn-en.line-break.in:5 msgid "Title" msgstr "Előtag" #: data/patterns/Latn-en.line-break.in:6 msgid "Do not break after a title, e.g. \" Dr.\"" msgstr "Ne legyen törés az olyan előtagok után, mint a \"Dr.\"" #: data/patterns/Latn-en.line-break.in:13 msgid "Article" msgstr "Névelő" #: data/patterns/Latn-en.line-break.in:14 msgid "Do not break after an article" msgstr "Ne legyen törés névelő után" #: data/patterns/Latn-en.line-break.in:21 msgid "Preposition" msgstr "_Elöljáró:" #: data/patterns/Latn-en.line-break.in:22 msgid "Do not break after a preposition" msgstr "Ne legyen törés elöljáró után" #: data/patterns/Latn-en.line-break.in:30 msgid "Possessive determiner" msgstr "Birtokos névmás" #: data/patterns/Latn-en.line-break.in:31 msgid "Do not break after a possessive determiner, e.g. \"my\"" msgstr "Ne legyen törés az olyan birtokos névmások után, mint a \"my\"" #: data/patterns/Latn-fi.common-error.in:5 #: data/patterns/Latn.common-error.in:182 msgid "Space after punctuation marks" msgstr "Szóköz az írásjelek után" #: data/patterns/Latn-fi.common-error.in:6 #: data/patterns/Latn.common-error.in:183 msgid "Add space after various punctuation marks" msgstr "Szóköz hozzáadása a különböző írásjelek után" #: data/patterns/Latn-fr.common-error.in:5 #: data/patterns/Latn-fr.common-error.in:14 #: data/patterns/Latn-fr.common-error.in:23 #: data/patterns/Latn-fr.common-error.in:32 msgid "Spaces around guillemets" msgstr "Szóközök az idézőjelek mellett" #: data/patterns/Latn-fr.common-error.in:6 #: data/patterns/Latn-fr.common-error.in:15 #: data/patterns/Latn-fr.common-error.in:24 #: data/patterns/Latn-fr.common-error.in:33 msgid "Add spaces around guillemets" msgstr "Szóközök hozzáadása az idézőjelek mellé" #: data/patterns/Latn-fr.common-error.in:41 #: data/patterns/Latn-fr.common-error.in:52 #: data/patterns/Latn.common-error.in:171 msgid "Space before punctuation marks" msgstr "Szóköz az írásjelek előtt" #: data/patterns/Latn-fr.common-error.in:42 #: data/patterns/Latn-fr.common-error.in:53 msgid "Add or remove space before various punctuation marks" msgstr "A különböző írásjelek előtti szóközök hozzáadása vagy eltávolítása" #: data/patterns/Latn.capitalization.in:5 msgid "Sentence" msgstr "Mondat" #: data/patterns/Latn.capitalization.in:6 msgid "Capitalize the first word of a sentence" msgstr "A mondat nagybetűvel kezdődjön" #: data/patterns/Latn.capitalization.in:12 msgid "Ellipsis" msgstr "Pontozás" #: data/patterns/Latn.capitalization.in:13 msgid "Capitalize after an ellipsis" msgstr "Nagybetű a pontozás (...) után" #: data/patterns/Latn.common-error.in:8 data/patterns/Latn.common-error.in:17 #: data/patterns/Latn.common-error.in:26 data/patterns/Latn.common-error.in:35 #: data/patterns/Latn.common-error.in:44 data/patterns/Latn.common-error.in:53 #: data/patterns/Latn.common-error.in:62 msgid "Ligatures" msgstr "" #: data/patterns/Latn.common-error.in:9 data/patterns/Latn.common-error.in:18 #: data/patterns/Latn.common-error.in:27 data/patterns/Latn.common-error.in:36 #: data/patterns/Latn.common-error.in:45 data/patterns/Latn.common-error.in:54 #: data/patterns/Latn.common-error.in:63 msgid "Unpack ligatures to individual characters" msgstr "" #: data/patterns/Latn.common-error.in:71 data/patterns/Latn.common-error.in:80 msgid "Spelling of a.m. and p.m." msgstr "\"a.m.\" és \"p.m.\" helyesírása" #: data/patterns/Latn.common-error.in:72 data/patterns/Latn.common-error.in:81 msgid "Change the various spellings of 12-hour periods to \"a.m.\" and \"p.m.\"" msgstr "A 12 órás időformátumok átalakítása \"a.m\" és \"p.m.\" formátumúra" #: data/patterns/Latn.common-error.in:89 data/patterns/Latn.common-error.in:98 msgid "Letter \"O\" in a number" msgstr "\"O\" betű a számokban" #: data/patterns/Latn.common-error.in:90 data/patterns/Latn.common-error.in:99 msgid "Replace letter \"O\" with a zero in a number" msgstr "\"O\" betű cseréje 0-ra a számokban" #: data/patterns/Latn.common-error.in:117 msgid "Double apostrophe" msgstr "Dupla idézőjel" #: data/patterns/Latn.common-error.in:118 msgid "Replace a double apostrophe with a quotation mark" msgstr "Két szimpla idézőjel cseréje dupla idézőjelre" #: data/patterns/Latn.common-error.in:126 #: data/patterns/Latn.common-error.in:135 #: data/patterns/Latn.common-error.in:144 #: data/patterns/Latn.common-error.in:153 msgid "Spaces around brackets" msgstr "Szóközök a zárójelek mellett" #: data/patterns/Latn.common-error.in:127 #: data/patterns/Latn.common-error.in:136 #: data/patterns/Latn.common-error.in:145 #: data/patterns/Latn.common-error.in:154 msgid "Add or remove spaces around parantheses and square brackets" msgstr "" "A zárójelek és a szögletes zárójelek melletti szóközök hozzáadása vagy " "eltávolítása" #: data/patterns/Latn.common-error.in:162 msgid "Space after a dialogue dash" msgstr "Szóköz a párbeszéd kötőjel után" #: data/patterns/Latn.common-error.in:163 msgid "Add space after a dialogue dash" msgstr "Szóköz hozzáadása a párbeszéd kötőjel után" #: data/patterns/Latn.common-error.in:172 msgid "Remove space before various punctuation marks" msgstr "Szóközök eltávolítása a különböző írásjelek elől" #: data/patterns/Latn.common-error.in:192 msgid "Space after an ellipsis" msgstr "Szóköz a pontozás (...) után" #: data/patterns/Latn.common-error.in:193 msgid "Add space after an ellipsis" msgstr "Szóköz hozzáadása pontozás (...) után" #: data/patterns/Latn.common-error.in:201 msgid "Space after a starting ellipsis" msgstr "Szóköz a pontozás indítása után" #: data/patterns/Latn.common-error.in:202 msgid "Remove space after an ellipsis that starts a line" msgstr "Sort elindító pontozás (...) utáni szóköz eltávolítása" #: data/patterns/Latn.common-error.in:210 #: data/patterns/Latn.common-error.in:221 #: data/patterns/Latn.common-error.in:232 #: data/patterns/Latn.common-error.in:242 msgid "Spaces around a quotation mark" msgstr "Szóközök az idézőjelek mellett" #: data/patterns/Latn.common-error.in:211 #: data/patterns/Latn.common-error.in:222 #: data/patterns/Latn.common-error.in:233 #: data/patterns/Latn.common-error.in:243 msgid "Remove space after a starting- and before an ending quotation mark" msgstr "Kezdő idézőjel utáni és záró idézőjel előtti szóközök eltávolítása" #: data/patterns/Latn.common-error.in:252 #: data/patterns/Latn.common-error.in:261 msgid "Spaces around musical notes" msgstr "Szóközök a hangjegyek mellett" #: data/patterns/Latn.common-error.in:253 #: data/patterns/Latn.common-error.in:262 msgid "Add spaces between musical note characters and lyrics" msgstr "Szóköz hozzáadása a hangjegyek és a dalszövegek közé" #: data/patterns/Latn.common-error.in:270 #: data/patterns/Latn.common-error.in:279 msgid "Multiple question- and exclamation marks" msgstr "Többszörös kérdőjelek és felkiáltójelek" #: data/patterns/Latn.common-error.in:271 #: data/patterns/Latn.common-error.in:280 msgid "" "Replace multiple consequtive question- and exclamation marks with only one" msgstr "Többszörös kérdőjelek és felkiáltójelek cseréje egyre" #: data/patterns/Latn.common-error.in:288 #: data/patterns/Latn.common-error.in:298 msgid "Periods around a punctuation mark" msgstr "Pont az írásjelek mellett" #: data/patterns/Latn.common-error.in:289 #: data/patterns/Latn.common-error.in:299 msgid "Remove period before or after various punctuation marks" msgstr "Pont eltávolítása a különböző írásjelek mellől" #: data/patterns/Latn.common-error.in:308 msgid "Terminating double-dashes" msgstr "Befejező dupla kötőjel" #: data/patterns/Latn.common-error.in:309 msgid "Replace a single clause-terminating dash with two dashes" msgstr "Lecseréli a lezáró kötőjelet két kötőjelre" #: data/patterns/Latn.hearing-impaired.in:5 msgid "Sound in brackets" msgstr "Hangok zárójelben" #: data/patterns/Latn.hearing-impaired.in:6 msgid "Remove description of a sound between square brackets" msgstr "Szögletes zárójelek közötti hang-leírások eltávolítása" #: data/patterns/Latn.hearing-impaired.in:12 msgid "Sound in parantheses" msgstr "Hangok kapcsos zárójelben" #: data/patterns/Latn.hearing-impaired.in:13 msgid "Remove description of a sound between parantheses" msgstr "Zárójelek közötti hang-leírások eltávolítása" #: data/patterns/Latn.hearing-impaired.in:19 msgid "Song lyrics between number signs" msgstr "Dalszöveg kettős-keresztek között" #: data/patterns/Latn.hearing-impaired.in:20 msgid "Remove song lyrics starting with or between number signs" msgstr "" "Olyan dalszövegek eltávolítása, melyek kettős-kereszttel kezdődnek, vagy " "azok között vannak" #: data/patterns/Latn.hearing-impaired.in:27 msgid "One-line song lyrics between number signs" msgstr "Egysoros dalszövegek kettős-keresztek között" #: data/patterns/Latn.hearing-impaired.in:28 msgid "Remove one-line song lyrics starting with or between number signs" msgstr "" "Olyan egysoros dalszövegek eltávolítása, melyek kettős-kereszttel kezdődnek," " vagy azok között vannak" #: data/patterns/Latn.hearing-impaired.in:35 msgid "Speaker before a colon" msgstr "\"Beszélő\" neve a kettőspont előtt" #: data/patterns/Latn.hearing-impaired.in:36 msgid "Replace the name of the speaker before a colon with a dialogue dash" msgstr "A \"Beszélő\" nevének cseréje gondolatjelre a kettőspont előtt" #: data/patterns/Latn.line-break.in:5 data/patterns/Latn.line-break.in:13 msgid "Dialogue" msgstr "Párbeszéd" #: data/patterns/Latn.line-break.in:6 data/patterns/Latn.line-break.in:14 msgid "Break according to dialogue separated by dashes" msgstr "Kötőjellel elválasztott párbeszédek tördelése" #: data/patterns/Latn.line-break.in:21 data/patterns/Latn.line-break.in:30 msgid "Clause" msgstr "Feltétel" #: data/patterns/Latn.line-break.in:22 data/patterns/Latn.line-break.in:31 msgid "Break according to clauses terminated by a punctuation mark" msgstr "Tördelés a mondatban szereplő írásjelek alapján" #: data/patterns/Latn.line-break.in:38 msgid "Number and unit" msgstr "Számok és mértékegységek" #: data/patterns/Latn.line-break.in:39 msgid "Do not break between a number and associated unit" msgstr "Ne legyen törés a számok és a mértékegységek között" #: data/patterns/Zyyy.common-error.in:5 data/patterns/Zyyy.common-error.in:14 msgid "Leading and trailing spaces" msgstr "Vezető és záró szóközök" #: data/patterns/Zyyy.common-error.in:6 data/patterns/Zyyy.common-error.in:15 msgid "Remove spaces from the beginning and end of lines" msgstr "Sorok vezető és záró szóközeinek eltávolítása" #: data/patterns/Zyyy.common-error.in:23 msgid "Multiple consecutive spaces" msgstr "Több egymást követő szóköz" #: data/patterns/Zyyy.common-error.in:24 msgid "Replace multiple consecutive spaces with only one" msgstr "Több egymást követő szóköz cseréje egyre" #: data/patterns/Zyyy.common-error.in:32 data/patterns/Zyyy.common-error.in:45 #: data/patterns/Zyyy.common-error.in:55 data/patterns/Zyyy.common-error.in:65 msgid "Space between digits" msgstr "Szóköz a számjegyek között" #: data/patterns/Zyyy.common-error.in:33 data/patterns/Zyyy.common-error.in:46 #: data/patterns/Zyyy.common-error.in:56 data/patterns/Zyyy.common-error.in:66 msgid "Remove space between digits of a number" msgstr "Számjegyek közötti szóközök eltávolítása" #: data/patterns/Zyyy.common-error.in:79 msgid "Musical notes" msgstr "Hangjegyek" #: data/patterns/Zyyy.common-error.in:80 msgid "Replace Unicode musical note characters with number signs" msgstr "Hangjegyek Unicode-os karaktereinek cseréje kettős-keresztekre" #: data/io.otsaloma.gaupol.appdata.xml.in:7 msgid "Editor for text-based subtitles" msgstr "" #: data/io.otsaloma.gaupol.appdata.xml.in:9 msgid "" "Gaupol is an editor for text-based subtitle files. It supports multiple " "subtitle file formats and provides means of creating subtitles, editing " "texts and timing subtitles to match video." msgstr "" #: data/io.otsaloma.gaupol.appdata.xml.in:40 msgid "Main window" msgstr "" #: data/io.otsaloma.gaupol.desktop.in:5 msgid "Subtitle Editor" msgstr "Feliratszerkesztő" #: data/io.otsaloma.gaupol.desktop.in:6 msgid "Edit subtitle files" msgstr "Felirat fájl szerkesztése" #. TRANSLATORS: Search terms to find this application. Do NOT translate or #. localize the semicolons! The list MUST also end with a semicolon! #: data/io.otsaloma.gaupol.desktop.in:12 msgid "video;subtitles;captions;" msgstr "video;subtitles;captions;" gaupol-1.11/po/ie.po000066400000000000000000002131241422217132500143000ustar00rootroot00000000000000# 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. # # Translators: # Osmo Salomaa , 2020 # Caarmi, 2021 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-04-03 04:00+0300\n" "PO-Revision-Date: 2016-07-07 00:55+0000\n" "Last-Translator: Caarmi, 2021\n" "Language-Team: Interlingue (https://www.transifex.com/otsaloma/teams/64879/ie/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ie\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: aeidon/enums.py:40 gaupol/enums.py:38 msgid "Subtitle number" msgstr "Nró de subtitul" #: aeidon/enums.py:43 msgid "Subtitle position" msgstr "Position de subtitul" #: aeidon/enums.py:59 msgid "23.976 fps" msgstr "23.976 fps" #: aeidon/enums.py:63 msgid "24.000 fps" msgstr "24.000 fps" #: aeidon/enums.py:67 msgid "25.000 fps" msgstr "25.000 fps" #: aeidon/enums.py:71 msgid "29.970 fps" msgstr "29.970 fps" #: aeidon/enums.py:75 data/ui/menubar.ui:248 msgid "30.000 fps" msgstr "30,000 fps" #: aeidon/enums.py:79 data/ui/menubar.ui:253 msgid "50.000 fps" msgstr "50,000 fps" #: aeidon/enums.py:83 data/ui/menubar.ui:258 msgid "59.940 fps" msgstr "59,940 fps" #: aeidon/enums.py:87 data/ui/menubar.ui:263 msgid "60.000 fps" msgstr "60,000 fps" #: aeidon/enums.py:112 msgid "Mac (classic)" msgstr "Mac (classic)" #. TRANSLATORS: Most of the character encoding descriptions are copied from #. gedit, which is translated to very many languages. Check the gedit .po #. files for a reference: #. . #: aeidon/encodings.py:40 aeidon/encodings.py:43 aeidon/encodings.py:46 msgid "English" msgstr "Anglesi" #: aeidon/encodings.py:41 aeidon/encodings.py:42 aeidon/encodings.py:69 msgid "Chinese traditional" msgstr "Chinesi traditional" #: aeidon/encodings.py:44 msgid "German" msgstr "German" #: aeidon/encodings.py:45 aeidon/encodings.py:54 aeidon/encodings.py:59 #: aeidon/encodings.py:79 aeidon/encodings.py:105 msgid "Hebrew" msgstr "Hebreic" #: aeidon/encodings.py:47 aeidon/encodings.py:51 aeidon/encodings.py:56 #: aeidon/encodings.py:73 aeidon/encodings.py:76 aeidon/encodings.py:98 #: aeidon/encodings.py:111 aeidon/encodings.py:122 msgid "Western" msgstr "Occidental" #: aeidon/encodings.py:48 aeidon/encodings.py:61 aeidon/encodings.py:80 #: aeidon/encodings.py:103 msgid "Arabic" msgstr "Arabic" #: aeidon/encodings.py:49 aeidon/encodings.py:64 aeidon/encodings.py:66 #: aeidon/encodings.py:77 aeidon/encodings.py:104 aeidon/encodings.py:119 msgid "Greek" msgstr "Grec" #: aeidon/encodings.py:50 aeidon/encodings.py:81 aeidon/encodings.py:101 #: aeidon/encodings.py:109 msgid "Baltic" msgstr "Baltic" #: aeidon/encodings.py:52 aeidon/encodings.py:74 aeidon/encodings.py:99 #: aeidon/encodings.py:121 msgid "Central European" msgstr "Central Europan" #: aeidon/encodings.py:53 aeidon/encodings.py:75 aeidon/encodings.py:102 #: aeidon/encodings.py:118 msgid "Cyrillic" msgstr "Cirilic" #: aeidon/encodings.py:55 aeidon/encodings.py:71 aeidon/encodings.py:78 #: aeidon/encodings.py:106 aeidon/encodings.py:123 msgid "Turkish" msgstr "Turcian" #: aeidon/encodings.py:57 msgid "Portuguese" msgstr "Portugues" #: aeidon/encodings.py:58 aeidon/encodings.py:120 msgid "Icelandic" msgstr "Islandesi" #: aeidon/encodings.py:60 msgid "Canadian" msgstr "Canadian" #: aeidon/encodings.py:62 aeidon/encodings.py:107 msgid "Nordic" msgstr "Nord-Europan" #: aeidon/encodings.py:63 aeidon/encodings.py:114 msgid "Russian" msgstr "Russ" #: aeidon/encodings.py:65 aeidon/encodings.py:108 msgid "Thai" msgstr "Thai" #: aeidon/encodings.py:67 aeidon/encodings.py:83 aeidon/encodings.py:84 #: aeidon/encodings.py:85 aeidon/encodings.py:91 aeidon/encodings.py:92 #: aeidon/encodings.py:93 aeidon/encodings.py:94 aeidon/encodings.py:95 #: aeidon/encodings.py:96 aeidon/encodings.py:125 aeidon/encodings.py:126 #: aeidon/encodings.py:127 msgid "Japanese" msgstr "Japanesi" #: aeidon/encodings.py:68 aeidon/encodings.py:86 aeidon/encodings.py:97 #: aeidon/encodings.py:113 msgid "Korean" msgstr "Korean" #: aeidon/encodings.py:70 msgid "Urdu" msgstr "Urdu" #: aeidon/encodings.py:72 aeidon/encodings.py:116 msgid "Ukrainian" msgstr "Ucrainan" #: aeidon/encodings.py:82 msgid "Vietnamese" msgstr "Vietnamesi" #: aeidon/encodings.py:87 aeidon/encodings.py:90 msgid "Chinese simplified" msgstr "Chinesi simplificat" #: aeidon/encodings.py:88 aeidon/encodings.py:89 msgid "Chinese unified" msgstr "Chinesi unificat" #: aeidon/encodings.py:100 aeidon/encodings.py:112 msgid "South European" msgstr "Sud-Europan" #: aeidon/encodings.py:110 msgid "Celtic" msgstr "Celtic" #: aeidon/encodings.py:115 msgid "Tajik" msgstr "Tajik" #: aeidon/encodings.py:117 msgid "Kazakh" msgstr "Kazakh" #: aeidon/encodings.py:124 msgid "Cyrillic Asian" msgstr "Cirilic del Asia" #: aeidon/encodings.py:128 aeidon/encodings.py:129 aeidon/encodings.py:130 #: aeidon/encodings.py:131 aeidon/encodings.py:132 aeidon/encodings.py:133 #: aeidon/encodings.py:134 aeidon/encodings.py:135 aeidon/encodings.py:136 msgid "Unicode" msgstr "Unicode" #: aeidon/encodings.py:156 #, python-brace-format msgid "{description} ({name})" msgstr "{description} ({name})" #: aeidon/encodings.py:232 msgid "Current locale ({})" msgstr "Locale actual ({})" #: aeidon/locales.py:46 #, python-brace-format msgid "{language} ({country})" msgstr "{language} ({country})" #: aeidon/agents/search.py:227 msgid "Replacing" msgstr "" #: aeidon/agents/search.py:256 aeidon/agents/search.py:258 msgid "Replacing all" msgstr "" #: aeidon/agents/position.py:74 msgid "Adjusting durations" msgstr "" #: aeidon/agents/position.py:96 msgid "Converting framerate" msgstr "Conversion de rapidore" #: aeidon/agents/position.py:146 msgid "Setting framerate" msgstr "" #: aeidon/agents/position.py:168 msgid "Shifting positions" msgstr "Motion de positiones" #: aeidon/agents/position.py:188 msgid "Transforming positions" msgstr "Transformation de positiones" #: aeidon/agents/clipboard.py:44 msgid "Cutting texts" msgstr "Excision de textu" #: aeidon/agents/clipboard.py:61 msgid "Pasting texts" msgstr "Collation de textus" #: aeidon/agents/text.py:91 msgid "Breaking lines" msgstr "Ruption de lineas" #: aeidon/agents/text.py:128 msgid "Capitalizing texts" msgstr "Majusculisation" #: aeidon/agents/text.py:185 msgid "Correcting common errors" msgstr "Corection de comun errores" #: aeidon/agents/text.py:234 msgid "Removing hearing impaired texts" msgstr "" #: aeidon/agents/text.py:315 msgid "Joining words by spell-check suggestions" msgstr "" #: aeidon/agents/text.py:354 msgid "Splitting words by spell-check suggestions" msgstr "" #: aeidon/agents/set.py:58 aeidon/agents/set.py:80 aeidon/agents/set.py:113 msgid "Editing position" msgstr "" #: aeidon/agents/set.py:129 msgid "Editing text" msgstr "" #: aeidon/agents/edit.py:35 msgid "Clearing texts" msgstr "" #: aeidon/agents/edit.py:61 aeidon/agents/edit.py:83 msgid "Inserting subtitles" msgstr "" #: aeidon/agents/edit.py:103 msgid "Merging subtitles" msgstr "" #: aeidon/agents/edit.py:114 msgid "Removing subtitles" msgstr "Remotion de subtitules" #: aeidon/agents/edit.py:131 msgid "Replacing positions" msgstr "" #: aeidon/agents/edit.py:147 msgid "Replacing texts" msgstr "" #: aeidon/agents/edit.py:171 msgid "Splitting subtitle" msgstr "Separation de un subtitul" #: aeidon/agents/format.py:49 msgid "Adding dialogue dashes" msgstr "" #: aeidon/agents/format.py:68 msgid "Changing case" msgstr "Conversion de min/MAJ" #: aeidon/agents/format.py:92 msgid "Italicizing" msgstr "Italicisation" #: aeidon/agents/format.py:108 msgid "Removing dialogue dashes" msgstr "" #: aeidon/agents/format.py:174 msgid "Unitalicizing" msgstr "Deitalicisation" #: gaupol/application.py:219 gaupol/agents/open.py:203 msgid "Open" msgstr "Aperter" #: gaupol/application.py:223 msgid "Open main files" msgstr "Apertion de subtitules" #: gaupol/application.py:230 msgid "Save" msgstr "Salvar" #: gaupol/application.py:233 msgid "Save the current main document" msgstr "Gardar li actual document" #: gaupol/application.py:238 msgid "Undo" msgstr "Defar" #: gaupol/application.py:242 msgid "Undo the last action" msgstr "Defar li ultim action" #: gaupol/application.py:249 msgid "Redo" msgstr "Refar" #: gaupol/application.py:252 msgid "Redo the last undone action" msgstr "Refar li ultim action defat" #: gaupol/application.py:260 msgid "Insert" msgstr "Inserter" #: gaupol/application.py:262 msgid "Insert new subtitles" msgstr "Inserter nov subtitules" #: gaupol/application.py:266 #: data/extensions/custom-framerates/preferences-dialog.ui:78 msgid "Remove" msgstr "Remover" #: gaupol/application.py:268 msgid "Remove the selected subtitles" msgstr "Remover li selectet subtitules" #: gaupol/application.py:273 data/ui/search-dialog.ui:283 msgid "Find" msgstr "Trovar" #: gaupol/application.py:275 msgid "Search for and replace text" msgstr "Serchar e vicear textu" #: gaupol/application.py:279 data/ui/preferences-dialog.ui:942 msgid "Video" msgstr "Video" #: gaupol/application.py:281 msgid "Show or hide the video player" msgstr "Monstrar o celar li reproductor de video" #: gaupol/application.py:285 data/ui/preferences-dialog.ui:1173 msgid "Preview" msgstr "Previder" #: gaupol/application.py:287 msgid "Preview from selected position with a video player" msgstr "Previder del actual position per un reproductor de video" #: gaupol/enums.py:37 msgid "No." msgstr "Nró" #: gaupol/enums.py:43 msgid "Start" msgstr "Comense" #: gaupol/enums.py:44 msgid "Start position" msgstr "Inicial position" #: gaupol/enums.py:49 msgid "End" msgstr "Fin" #: gaupol/enums.py:50 msgid "End position" msgstr "Final position" #. TRANSLATORS: 'Dur.' is short for duration. It is used in the header #. of a column that contains numbers five digits wide. #: gaupol/enums.py:57 msgid "Dur." msgstr "Dur." #: gaupol/enums.py:58 msgid "Duration" msgstr "Duration" #: gaupol/enums.py:63 gaupol/enums.py:64 msgid "Text" msgstr "Textu" #: gaupol/enums.py:69 gaupol/enums.py:70 msgid "Translation" msgstr "Traduction" #: gaupol/enums.py:82 msgid "characters" msgstr "caracteres" #: gaupol/enums.py:85 msgid "ems" msgstr "ems" #: gaupol/page.py:60 msgid "Untitled {:d}" msgstr "Sin nómine {:d}" #: gaupol/page.py:133 msgid "Close project" msgstr "Clúder li project" #: gaupol/page.py:145 msgid "{} translation" msgstr "Traduction de {}" #: gaupol/page.py:302 msgid "Path:" msgstr "Rute:" #: gaupol/page.py:303 msgid "Format:" msgstr "Formate:" #: gaupol/page.py:304 msgid "Encoding:" msgstr "Codification:" #: gaupol/page.py:305 msgid "Newlines:" msgstr "Fines de linea:" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:99 msgid "Tasks and Target" msgstr "Taches e campe" #: gaupol/assistants.py:128 msgid "Correct texts in the text column" msgstr "Corecter li original textu" #: gaupol/assistants.py:129 msgid "Correct texts in the translation column" msgstr "Corecter li traduction" #: gaupol/assistants.py:138 msgid "Correct texts in selected subtitles" msgstr "Corecter textu in li selectet subtitules" #: gaupol/assistants.py:139 msgid "Correct texts in current project" msgstr "Corecter li textu del actual projecte" #: gaupol/assistants.py:140 msgid "Correct texts in all open projects" msgstr "Corecter li textu de omni apertet projectes" #: gaupol/assistants.py:363 msgid "Other" msgstr "Altri" #: gaupol/assistants.py:439 msgid "Capitalize texts written in lower case" msgstr "Adjunter majuscules a un textu in minuscules" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:443 msgid "Capitalization Patterns" msgstr "Majusculisation" #: gaupol/assistants.py:445 msgid "Capitalize texts" msgstr "Majusculisar li textu" #: gaupol/assistants.py:468 msgid "Correct common errors made by humans or image recognition software" msgstr "Correcter comun errores de homes e programmas de OCR" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:472 msgid "Common Error Patterns" msgstr "Comun errores" #: gaupol/assistants.py:474 msgid "Correct common errors" msgstr "Corecter comun errores" #: gaupol/assistants.py:526 msgid "Remove explanatory texts meant for the hearing impaired" msgstr "Remover textus explicativ por lis malaudient" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:530 msgid "Hearing Impaired Patterns" msgstr "Por li malaudient" #: gaupol/assistants.py:532 msgid "Remove hearing impaired texts" msgstr "Remover comentas por lis malaudient" #: gaupol/assistants.py:544 msgid "" "Use spell-check suggestions to fix whitespace detection errors of image " "recognition software" msgstr "" "Usar control de ortografie por corecter fals spacies pos li automatic " "reconossement" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:548 msgid "Joining and Splitting Words" msgstr "Juncter e separar paroles" #: gaupol/assistants.py:550 msgid "Join or Split Words" msgstr "Unir o separar paroles" #: gaupol/assistants.py:599 gaupol/agents/tools.py:45 msgid "Failed to load dictionary for language \"{}\"" msgstr "Ne posset cargar li dictionarium por lingue «{}»" #: gaupol/assistants.py:601 gaupol/player.py:263 gaupol/player.py:381 #: gaupol/dialogs/search.py:560 gaupol/dialogs/search.py:568 #: gaupol/dialogs/text_edit.py:49 gaupol/dialogs/encoding.py:56 #: gaupol/agents/open.py:328 gaupol/agents/open.py:337 #: gaupol/agents/open.py:345 gaupol/agents/open.py:354 #: gaupol/agents/tools.py:48 gaupol/agents/save.py:197 #: gaupol/agents/save.py:205 gaupol/agents/preview.py:108 #: gaupol/agents/preview.py:116 gaupol/agents/preview.py:125 #: gaupol/agents/preview.py:133 msgid "_OK" msgstr "_OK" #: gaupol/assistants.py:635 msgid "Break text into lines of defined length" msgstr "Rupter li lines secun un definit longore" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:639 msgid "Line-Break Patterns" msgstr "Ruption de lineas" #: gaupol/assistants.py:641 msgid "Break lines" msgstr "Rupter lineas" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:679 msgid "Line-Break Options" msgstr "Parametres del ruption" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:763 msgid "Correcting Texts" msgstr "Corection" #: gaupol/assistants.py:769 msgid "Each task is now being run on each project." msgstr "" #: gaupol/assistants.py:793 #, python-brace-format msgid "{current:d} of {total:d} tasks complete" msgstr "{current:d} ex {total:d} taches es complet" #: gaupol/assistants.py:801 msgid "Project: {}" msgstr "Projecte: {}" #: gaupol/assistants.py:807 msgid "Task: {}" msgstr "Tache: {}" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:832 msgid "Confirm Changes" msgstr "Confirmation" #: gaupol/assistants.py:892 msgid "Accept" msgstr "Acceptar" #: gaupol/assistants.py:898 msgid "Original Text" msgstr "Original textu" #: gaupol/assistants.py:899 msgid "Corrected Text" msgstr "Corectet textu" #: gaupol/assistants.py:1048 msgid "Correct Texts" msgstr "Corecter textus" #: gaupol/assistants.py:1076 msgid "Correcting texts" msgstr "Corection de textus" #: gaupol/assistants.py:1092 #, python-brace-format msgid "Edited {edits:d} and removed {removals:d} subtitles" msgstr "Redactet {edits:d} e removet {removals:d} subtitules" #: gaupol/assistants.py:1126 msgid "Confirm {:d} Change" msgid_plural "Confirm {:d} Changes" msgstr[0] "Confirmar {:d} modification" msgstr[1] "Confirmar {:d} modificationes" #: gaupol/renderers/multiline.py:86 msgid "Italic" msgstr "Italic" #: gaupol/player.py:372 msgid "No video streams found" msgstr "Null video-fluvies trovat" #: gaupol/player.py:379 msgid "Failed to initialize playback" msgstr "Ne successat inicialisar reproduction" #: gaupol/dialogs/search.py:189 data/ui/menubar.ui:524 msgid "_Help" msgstr "Au_xilie" #: gaupol/dialogs/search.py:471 msgid "Found and replaced {:d} occurence" msgid_plural "Found and replaced {:d} occurences" msgstr[0] "Trovat e substituet {:d} occurrentie" msgstr[1] "Trovat e substituet {:d} occurrenties" #: gaupol/dialogs/search.py:488 msgid "\"{}\" not found" msgstr "«{}» ne esset trovat" #: gaupol/dialogs/search.py:558 msgid "Error in regular expression pattern" msgstr "Errore de expression regulari in li mustre" #: gaupol/dialogs/search.py:566 msgid "Error in regular expression replacement" msgstr "Errore de expression regulari in li substitution" #: gaupol/dialogs/text_edit.py:48 gaupol/dialogs/framerate_convert.py:63 #: gaupol/dialogs/insert.py:44 gaupol/dialogs/encoding.py:55 #: gaupol/dialogs/split.py:44 gaupol/dialogs/multi_close.py:54 #: gaupol/dialogs/open.py:63 gaupol/dialogs/position_transform.py:69 #: gaupol/dialogs/position_shift.py:71 gaupol/dialogs/multi_save.py:83 #: gaupol/dialogs/multi_save.py:215 gaupol/dialogs/duration_adjust.py:86 #: gaupol/dialogs/save.py:73 gaupol/dialogs/video.py:41 #: gaupol/agents/open.py:363 gaupol/agents/open.py:375 #: gaupol/agents/open.py:387 gaupol/agents/close.py:71 #: data/extensions/custom-framerates/custom-framerates.py:39 msgid "_Cancel" msgstr "_Anullar" #: gaupol/dialogs/text_edit.py:53 msgid "Edit Text" msgstr "" #: gaupol/dialogs/framerate_convert.py:64 msgid "Co_nvert" msgstr "Co_nverter" #: gaupol/dialogs/insert.py:45 msgid "_Insert" msgstr "_Inserter" #: gaupol/dialogs/insert.py:54 msgid "Above selection" msgstr "Ad-supra" #: gaupol/dialogs/insert.py:55 msgid "Below selection" msgstr "Ad-infra" #: gaupol/dialogs/encoding.py:60 data/ui/preferences-dialog.ui:70 msgid "Character Encodings" msgstr "Codificationes de caracteres" #: gaupol/dialogs/encoding.py:78 gaupol/dialogs/encoding.py:125 msgid "Description" msgstr "Descrition" #: gaupol/dialogs/encoding.py:85 gaupol/dialogs/encoding.py:132 msgid "Encoding" msgstr "Codification" #: gaupol/dialogs/encoding.py:141 msgid "Show in Menu" msgstr "Monstrar in li menú" #: gaupol/dialogs/split.py:45 msgid "_Split" msgstr "_Separar" #: gaupol/dialogs/split.py:76 msgid "Splitting project" msgstr "Separation del projecte" #: gaupol/dialogs/split.py:97 #, python-brace-format msgid "Split {amount:d} subtitles to project \"{name}\"" msgstr "Separation de {amount:d} subtitules al projecte «{name}»" #: gaupol/dialogs/spell_check.py:269 msgid "Spell-checking" msgstr "Control de ortografie" #: gaupol/dialogs/preferences.py:217 msgid "{} Extension Website" msgstr "Website del extension {}" #: gaupol/dialogs/preferences.py:429 msgid "Custom" msgstr "Personal" #: gaupol/dialogs/multi_close.py:38 msgid "Save changes to documents before closing?" msgstr "Gardar li modificationes del documentes ante que cluder?" #: gaupol/dialogs/multi_close.py:39 gaupol/agents/open.py:384 #: gaupol/agents/close.py:68 msgid "If you don't save, changes will be permanently lost." msgstr "" "Si vu ne garda it, omni modificationes va esser perdit irrevocabilmen." #: gaupol/dialogs/multi_close.py:53 gaupol/agents/close.py:70 msgid "Close _Without Saving" msgstr "Clúder si_n salvation" #: gaupol/dialogs/multi_close.py:55 gaupol/dialogs/multi_save.py:84 #: gaupol/dialogs/save.py:74 gaupol/agents/open.py:388 #: gaupol/agents/close.py:72 data/ui/menubar.ui:34 msgid "_Save" msgstr "_Salvar" #: gaupol/dialogs/multi_close.py:70 msgid "Select the _main documents you want to save:" msgstr "S_electe li documentes quel vu vole gardar:" #: gaupol/dialogs/multi_close.py:95 msgid "Select the _translation documents you want to save:" msgstr "Selecte li _traductiones quel vu vole gardar:" #: gaupol/dialogs/open.py:64 gaupol/agents/open.py:364 #: gaupol/agents/open.py:376 msgid "_Open" msgstr "_Aperter" #: gaupol/dialogs/position_transform.py:70 msgid "_Transform" msgstr "_Transformar" #: gaupol/dialogs/position_shift.py:72 msgid "_Shift" msgstr "Mo_ver" #: gaupol/dialogs/position_shift.py:150 msgid "frames" msgstr "cadres" #: gaupol/dialogs/position_shift.py:168 data/ui/preferences-dialog.ui:911 msgid "seconds" msgstr "secondes" #: gaupol/dialogs/about.py:36 msgid "About Gaupol" msgstr "Pri Gaupol" #: gaupol/dialogs/about.py:40 msgid "Subtitle editor" msgstr "Redactor de subtitules" #. TRANSLATORS: This is a special message that shouldn't be translated #. literally. It is used in the about dialog to give credits to the #. translators. Thus, you should translate it to your name and email #. address. You can also include other translators who have contributed #. to this translation; in that case, please write them on separate #. lines seperated by newlines (\n). #: gaupol/dialogs/about.py:51 msgid "translator-credits" msgstr "OIS , 2016-20" #: gaupol/dialogs/about.py:54 msgid "Gaupol Website" msgstr "Website de Gaupol" #: gaupol/dialogs/append.py:35 msgid "Append File" msgstr "Apender un file" #: gaupol/dialogs/debug.py:43 msgid "Something went wrong" msgstr "Un errore evenit" #: gaupol/dialogs/debug.py:44 msgid "" "You have probably discovered a bug. Please report it by providing the below " "information and a description of what you were doing." msgstr "" #: gaupol/dialogs/debug.py:52 msgid "_Report Bug" msgstr "_Raportar un defecte" #: gaupol/dialogs/debug.py:53 data/ui/menubar.ui:56 msgid "_Quit" msgstr "Sa_lir" #: gaupol/dialogs/debug.py:54 gaupol/dialogs/preview_error.py:45 #: data/ui/menubar.ui:52 data/ui/tab-popup.ui:16 msgid "_Close" msgstr "_Clúder" #: gaupol/dialogs/multi_save.py:98 gaupol/dialogs/save.py:110 msgid "{} (recommended)" msgstr "{} (recomandat)" #: gaupol/dialogs/multi_save.py:212 msgid "" "{:d} of the files to be saved already exist. Do you want to replace them?" msgstr "{:d} gardat files ja existe. Esque vu vole substituer les?" #: gaupol/dialogs/multi_save.py:213 msgid "" "The files already exist in \"{}\". Replacing them will overwrite their " "contents." msgstr "Li files ja existe in «{}». Lor contenete va esser superscrit." #: gaupol/dialogs/multi_save.py:216 data/ui/search-dialog.ui:192 #: data/ui/spell-check-dialog.ui:122 msgid "_Replace" msgstr "_Substituer" #: gaupol/dialogs/duration_adjust.py:70 msgid "Adjusted duration of {:d} subtitle" msgid_plural "Adjusted durations of {:d} subtitles" msgstr[0] "Adjustat li duration de {:d} subtitul" msgstr[1] "Adjustat li duration de {:d} subtitules" #: gaupol/dialogs/duration_adjust.py:87 msgid "_Adjust" msgstr "_Adjustar" #: gaupol/dialogs/preview_error.py:36 msgid "Preview in video player failed" msgstr "Prevision li reproductor de video ne successat" #: gaupol/dialogs/preview_error.py:37 msgid "" "There is probably a problem with either the video file or the video player. " "See the preferences dialog to choose the video player or to customize the " "command." msgstr "" #: gaupol/dialogs/language.py:97 msgid "Set Language" msgstr "Assignar li lingue" #: gaupol/dialogs/video.py:52 gaupol/dialogs/file.py:59 msgid "All files" msgstr "Omni files" #: gaupol/dialogs/video.py:56 msgid "Video files" msgstr "Video-files" #: gaupol/dialogs/file.py:63 msgid "All supported files" msgstr "Omni files subtenet" #: gaupol/dialogs/file.py:77 #, python-brace-format msgid "{format} (*{extension})" msgstr "{format} (*{extension})" #: gaupol/dialogs/file.py:120 msgid "Auto-detected" msgstr "Auto-detectet" #: gaupol/dialogs/file.py:122 msgid "Other…" msgstr "Altri..." #: gaupol/agents/menu.py:94 gaupol/agents/menu.py:103 #: gaupol/agents/menu.py:110 msgid "File not found" msgstr "File ne es trovat" #: gaupol/agents/open.py:85 #, python-brace-format msgid "Appended {amount:d} subtitles from \"{basename}\"" msgstr "Adjuntet {amount:d} subtitules ex li «{basename}»" #: gaupol/agents/open.py:96 msgid "Appending file" msgstr "Appension de un file" #: gaupol/agents/open.py:111 msgid "File \"{}\" is already open" msgstr "Li file «{}» es jam apertet" #: gaupol/agents/open.py:214 msgid "Open Translation" msgstr "Aperter un traduction" #: gaupol/agents/open.py:223 msgid "Select Video" msgstr "Selecter un video" #: gaupol/agents/open.py:224 msgid "_Select" msgstr "_Selecter" #: gaupol/agents/open.py:325 msgid "Failed to decode file \"{}\" with all attempted codecs" msgstr "Ne successat decodificar li file «{}» per omni usat codificatores." #: gaupol/agents/open.py:326 msgid "Please try to open the file with a different character encoding." msgstr "Ples provar aperter li file con un altri codification de caracteres." #: gaupol/agents/open.py:334 msgid "Failed to recognize format of file \"{}\"" msgstr "Ne successat reconosser li formate del file «{}»" #: gaupol/agents/open.py:335 msgid "" "Please check that the file you are trying to open is a subtitle file of a " "format supported by Gaupol." msgstr "" "Ples assecurar que vu aperte un file quel formate es suportat per Gaupol." #: gaupol/agents/open.py:343 msgid "Failed to open file \"{}\"" msgstr "Ne posset aperter li file «{}»" #: gaupol/agents/open.py:351 msgid "Failed to parse file \"{}\"" msgstr "Ne successat analisar li file «{}»" #: gaupol/agents/open.py:352 msgid "Please check that the file you are trying to open is a valid {} file." msgstr "Assecura que vu aperte un valid file {}." #: gaupol/agents/open.py:360 msgid "Open abnormally large file \"{}\"?" msgstr "Aperter un abnormalmen grand file «{}»?" #: gaupol/agents/open.py:361 msgid "" "Size of the file is {:.1f} MB, which is abnormally large for a text-based " "subtitle file. Please, check that you are not trying to open a binary file." msgstr "" "Li grandore del file es {:.1f} Mo, que es tro mult por un file de textual " "subtitules. Assecura que vos ne aperte un binari file." #: gaupol/agents/open.py:371 msgid "Open unsorted file \"{}\"?" msgstr "Aperter li ínordinat file «{}»?" #: gaupol/agents/open.py:372 msgid "" "The order of {:d} subtitles needs to be changed. If {:d} sounds like a lot, " "the file may be erroneously composed." msgstr "" "Li órdine de {:d} subtitules deve esser changeat. Si {:d} es tro mult, li " "file posse esser composit íncorrectmen." #: gaupol/agents/open.py:383 msgid "Save changes to translation document \"{}\" before opening a new one?" msgstr "Gardar li modificationes del traduction «{}» ante que aperter un nov?" #: gaupol/agents/open.py:386 msgid "Open _Without Saving" msgstr "Surtir s_in salvation" #: gaupol/agents/close.py:66 msgid "Save changes to document \"{}\" before closing?" msgstr "Gardar li modificationes del document «{}» ante que cluder?" #: gaupol/agents/edit.py:101 gaupol/agents/edit.py:119 msgid "Stretching end position" msgstr "Extension del fin" #: gaupol/agents/edit.py:208 msgid "Inserted {:d} subtitle to fit clipboard contents" msgid_plural "Inserted {:d} subtitles to fit clipboard contents" msgstr[0] "" "Insertet {:d} additional subtitul por metter li contene del Paperiere" msgstr[1] "" "Insertet {:d} additional subtitules por metter li contene del Paperiere" #: gaupol/agents/edit.py:334 gaupol/agents/edit.py:352 msgid "Stretching start position" msgstr "Extension del inicie" #: gaupol/agents/edit.py:411 msgid "Use Shift+Return for line-break" msgstr "Usa Shift+Return por rupter lineas" #: gaupol/agents/save.py:129 msgid "Save As" msgstr "Salvar quam" #: gaupol/agents/save.py:135 msgid "Saved main document as \"{}\"" msgstr "Li document sta gardat quam «{}»" #: gaupol/agents/save.py:153 msgid "Save Translation As" msgstr "Salvar li traduction quam" #: gaupol/agents/save.py:159 msgid "Saved translation document as \"{}\"" msgstr "Li traduction sta gardat quam «{}»" #: gaupol/agents/save.py:194 #, python-brace-format msgid "Failed to encode file \"{basename}\" with codec \"{codec}\"" msgstr "Ne successat codificar li file «{basename}» per li codec «{codec}»" #: gaupol/agents/save.py:195 msgid "Please try to save the file with a different character encoding." msgstr "Ples garda li file in un altri codification." #: gaupol/agents/save.py:203 msgid "Failed to save file \"{}\"" msgstr "Ne posset salvar li file «{}»" #: gaupol/agents/video.py:67 data/ui/menubar.ui:380 msgid "_Play/Pause" msgstr "Re_producter/pausar" #: gaupol/agents/video.py:69 msgid "Play or pause video" msgstr "Reproducter o pausar li video" #: gaupol/agents/video.py:75 data/ui/menubar.ui:390 msgid "Seek _Previous" msgstr "Ear al _precedent" #: gaupol/agents/video.py:77 msgid "Seek to the start of the previous subtitle" msgstr "Ear al inicie del precedent subtitul" #: gaupol/agents/video.py:81 data/ui/menubar.ui:394 msgid "Seek _Next" msgstr "Ear al _sequent" #: gaupol/agents/video.py:83 msgid "Seek to the start of the next subtitle" msgstr "Ear al inicie del sequent subtitul" #: gaupol/agents/video.py:88 data/ui/menubar.ui:400 msgid "Seek _Backward" msgstr "Saltar _retro" #: gaupol/agents/video.py:90 msgid "Seek backward" msgstr "Saltar retro" #: gaupol/agents/video.py:94 data/ui/menubar.ui:404 msgid "Seek _Forward" msgstr "Saltar _avan" #: gaupol/agents/video.py:96 msgid "Seek forward" msgstr "Saltar avan" #: gaupol/agents/video.py:109 msgid "Volume" msgstr "Volúmine" #: gaupol/agents/video.py:189 msgid "Load Video" msgstr "Cargar un video" #: gaupol/agents/video.py:189 msgid "_Load" msgstr "_Cargar" #: gaupol/agents/video.py:361 msgid "Track {:d}" msgstr "Track {:d}" #: gaupol/agents/preview.py:105 msgid "Failed to encode subtitle file to temporary directory \"{}\"" msgstr "" "Ne successat codificar li file de subtutules in li fólder temporari «{}»" #: gaupol/agents/preview.py:106 msgid "" "Subtitle data could not be encoded to a temporary file for preview with the " "current character encoding. Please first save the subtitle file with a " "different character encoding." msgstr "" #: gaupol/agents/preview.py:114 msgid "Failed to save subtitle file to temporary directory \"{}\"" msgstr "Ne successat gardar li file de subtutules in li fólder temporari «{}»" #: gaupol/agents/preview.py:122 msgid "Video player not found" msgstr "Reproductor de video ne es trovat" #: gaupol/agents/preview.py:123 msgid "" "Please install one of the supported video players: mpv (recommended), " "MPlayer or VLC. See the preferences dialog to choose the video player or to " "customize the command." msgstr "" "Ples installar un de supportat reproductores de video: mpv (recomandat), " "MPlayer o VLC. Usa li dialog de preferenties por selecter o personalisar it." #: gaupol/agents/preview.py:131 msgid "Failed to launch video player" msgstr "Ne successat lansar li reproductor de video" #: gaupol/applicationman.py:105 msgid "gaupol [OPTION...] [FILE...] [+[NUM]]" msgstr "gaupol [OPTION...] [FILE...] [+[NUM]]" #: gaupol/applicationman.py:109 msgid "FILE..." msgstr "FILE..." #: gaupol/applicationman.py:112 msgid "subtitle files to open" msgstr "files de subtitules por aperter" #: gaupol/applicationman.py:122 msgid "ENCODING" msgstr "CODIFICATION" #: gaupol/applicationman.py:125 msgid "set the character encoding used to open files" msgstr "codification del apertet files" #: gaupol/applicationman.py:132 msgid "list all available character encodings" msgstr "monstrar un liste de omni codificationes" #: gaupol/applicationman.py:137 gaupol/applicationman.py:154 msgid "FILE" msgstr "FILE" #: gaupol/applicationman.py:140 msgid "open translation file" msgstr "aperter un file de traduction" #: gaupol/applicationman.py:145 msgid "METHOD" msgstr "METODE" #: gaupol/applicationman.py:149 msgid "method used to align translation subtitles: 'number' or 'position'" msgstr "" "metode de correspondentie del traduction: 'number' (númeres) o 'position'" #: gaupol/applicationman.py:157 msgid "select video file" msgstr "selecter un file de video" #: data/extensions/custom-framerates/custom-framerates.py:40 #: data/ui/spell-check-dialog.ui:152 msgid "_Add" msgstr "_Adjunter" #: data/extensions/custom-framerates/custom-framerates.py:171 msgid "{:.3f} fps" msgstr "{:.3f} fps" #: data/extensions/custom-framerates/add-framerate-dialog.ui:13 msgid "Add Framerate" msgstr "Adjunter un rapidore" #: data/extensions/custom-framerates/add-framerate-dialog.ui:44 msgid "_Framerate:" msgstr "_Rapidore de cadres:" #: data/extensions/custom-framerates/add-framerate-dialog.ui:73 msgid "fps" msgstr "fps" #: data/extensions/custom-framerates/preferences-dialog.ui:8 msgid "Framerates" msgstr "Rapidores de cadres" #: data/extensions/custom-framerates/preferences-dialog.ui:64 msgid "Add" msgstr "Adjunter" #: data/ui/columns-popup.ui:6 data/ui/menubar.ui:275 msgid "_No." msgstr "_Nró" #: data/ui/columns-popup.ui:10 data/ui/menubar.ui:279 msgid "_Start" msgstr "_Comense" #: data/ui/columns-popup.ui:14 data/ui/menubar.ui:283 msgid "_End" msgstr "_Fin" #: data/ui/columns-popup.ui:18 data/ui/menubar.ui:287 msgid "_Duration" msgstr "_Duration" #: data/ui/columns-popup.ui:22 data/ui/menubar.ui:291 data/ui/menubar.ui:303 msgid "_Text" msgstr "_Textu" #: data/ui/columns-popup.ui:26 data/ui/menubar.ui:295 msgid "T_ranslation" msgstr "T_raduction" #: data/ui/split-dialog.ui:15 msgid "Split Project" msgstr "Separar li project" #: data/ui/split-dialog.ui:48 msgid "_First subtitle of new project:" msgstr "Li _prim subtitul del nov projecte:" #: data/ui/search-dialog.ui:89 msgid "_Search for:" msgstr "_Serchar por:" #: data/ui/search-dialog.ui:103 data/ui/spell-check-dialog.ui:193 msgid "Replace _with:" msgstr "Substituer _per:" #: data/ui/search-dialog.ui:162 data/ui/menubar.ui:328 msgid "Find _Next" msgstr "Trovar _sequent" #: data/ui/search-dialog.ui:177 msgid "Find _Previous" msgstr "Trovar _precedent" #: data/ui/search-dialog.ui:207 msgid "Replace _All" msgstr "Substituer _omni" #: data/ui/search-dialog.ui:241 msgid "R_egular expression" msgstr "_Expression regulari" #: data/ui/search-dialog.ui:258 msgid "_Ignore case" msgstr "_Ignorar MAJ/min" #: data/ui/search-dialog.ui:304 data/ui/language-dialog.ui:108 msgid "Columns" msgstr "Columnes" #: data/ui/search-dialog.ui:324 msgid "Find in _text column" msgstr "In li columne de _textu" #: data/ui/search-dialog.ui:341 msgid "Find in t_ranslation column" msgstr "In li columne de t_raduction" #: data/ui/search-dialog.ui:381 data/ui/framerate-convert-dialog.ui:144 #: data/ui/language-dialog.ui:186 #: data/ui/text-assistant/line-break-options-page.ui:178 #: data/ui/duration-adjust-dialog.ui:388 data/ui/position-shift-dialog.ui:180 #: data/ui/position-transform-dialog.ui:444 msgid "Subtitles" msgstr "Subtitules" #: data/ui/search-dialog.ui:401 msgid "Find in c_urrent project" msgstr "In li act_ual projecte" #: data/ui/search-dialog.ui:419 msgid "Find in _all open projects" msgstr "In o_mni apertet projectes" #: data/ui/search-dialog.ui:452 msgid "Target" msgstr "Camp de action" #: data/ui/framerate-convert-dialog.ui:8 msgid "Convert Framerate" msgstr "Converter rapidore del cadres" #: data/ui/framerate-convert-dialog.ui:48 msgid "Framerate" msgstr "Rapidore de cadres" #: data/ui/framerate-convert-dialog.ui:71 msgid "_Input:" msgstr "_Original:" #: data/ui/framerate-convert-dialog.ui:86 msgid "_Output:" msgstr "_Nov:" #: data/ui/framerate-convert-dialog.ui:164 msgid "Convert c_urrent project" msgstr "Converter li act_ual projecte" #: data/ui/framerate-convert-dialog.ui:181 msgid "Convert _all open projects" msgstr "Converter omni _apertet projectes" #: data/ui/spell-check-dialog.ui:8 msgid "Check Spelling" msgstr "Controlar ortografie" #: data/ui/spell-check-dialog.ui:47 msgid "Join _Back" msgstr "Unir con _prec." #: data/ui/spell-check-dialog.ui:62 msgid "Join _Forward" msgstr "Unit con _seq." #: data/ui/spell-check-dialog.ui:77 data/ui/menubar.ui:62 msgid "_Edit" msgstr "_Redacter" #: data/ui/spell-check-dialog.ui:92 msgid "_Ignore" msgstr "_Ignorar" #: data/ui/spell-check-dialog.ui:107 msgid "Ig_nore All" msgstr "Ig_norar omni" #: data/ui/spell-check-dialog.ui:137 msgid "Rep_lace All" msgstr "Substituer _omni" #: data/ui/spell-check-dialog.ui:179 msgid "_Suggestions:" msgstr "_Suggestiones:" #: data/ui/multi-save-dialog.ui:8 msgid "Save All As" msgstr "Salvar omni quam" #: data/ui/multi-save-dialog.ui:46 msgid "Save in _folder:" msgstr "Gardar in li _fólder:" #: data/ui/multi-save-dialog.ui:60 data/ui/save-dialog.ui:25 msgid "For_mat:" msgstr "For_mate:" #: data/ui/multi-save-dialog.ui:74 data/ui/open-dialog.ui:25 #: data/ui/save-dialog.ui:39 msgid "_Encoding:" msgstr "_Codification:" #: data/ui/multi-save-dialog.ui:88 data/ui/save-dialog.ui:53 msgid "Ne_wlines:" msgstr "Fi_nes de linea:" #: data/ui/multi-save-dialog.ui:103 msgid "Select A Folder" msgstr "Selecte un fólder" #: data/ui/multi-save-dialog.ui:150 data/ui/save-dialog.ui:102 msgid "F_ramerate:" msgstr "_Rapidore de cadres:" #: data/ui/menubar.ui:5 msgid "_File" msgstr "_File" #: data/ui/menubar.ui:8 msgid "_New" msgstr "_Crear" #: data/ui/menubar.ui:12 msgid "_Open…" msgstr "_Aperter..." #: data/ui/menubar.ui:16 msgid "Open _Translation…" msgstr "Aperter un _traduction..." #: data/ui/menubar.ui:22 msgid "Open _Recent" msgstr "Aperte _recentis" #: data/ui/menubar.ui:27 msgid "Open R_ecent Translation" msgstr "Aperter un r_ecent traduction" #: data/ui/menubar.ui:38 msgid "Save _As…" msgstr "Salvar _quam..." #: data/ui/menubar.ui:42 msgid "Save Trans_lation" msgstr "Salvar li tra_duction" #: data/ui/menubar.ui:46 msgid "Save Translat_ion As…" msgstr "Gardar li trad_uction quam..." #: data/ui/menubar.ui:65 msgid "_Undo" msgstr "_Defar" #: data/ui/menubar.ui:69 msgid "_Redo" msgstr "_Refar" #: data/ui/menubar.ui:75 msgid "_Edit Cell" msgstr "R_edacter li cellul" #: data/ui/menubar.ui:79 msgid "Edit _Next Cell" msgstr "Seque_nt cellul" #: data/ui/menubar.ui:85 msgid "Stretc_h" msgstr "E_xtender" #: data/ui/menubar.ui:88 msgid "_Start Earlier" msgstr "_Comensar plu tost" #: data/ui/menubar.ui:92 msgid "S_tart Later" msgstr "C_omenser plu tard" #: data/ui/menubar.ui:98 msgid "E_nd Earlier" msgstr "_Finir plu tost" #: data/ui/menubar.ui:102 msgid "En_d Later" msgstr "Fi_nir plu tard" #: data/ui/menubar.ui:108 msgid "Set St_art From Video Position" msgstr "_Assignar li start ex li position" #: data/ui/menubar.ui:112 msgid "Set En_d From Video Position" msgstr "Assignar li _fin ex li position" #: data/ui/menubar.ui:118 data/ui/view-popup.ui:6 msgid "_Split Subtitle" msgstr "_Separar li subtitul" #: data/ui/menubar.ui:122 data/ui/view-popup.ui:10 msgid "_Merge Subtitles" msgstr "C_oalescer li subtitules" #: data/ui/menubar.ui:128 data/ui/view-popup.ui:16 msgid "_Insert Subtitles…" msgstr "_Inserter subtitules..." #: data/ui/menubar.ui:132 msgid "Inser_t Subtitle At Video Position" msgstr "Inser_ter un subtitul in li position del video" #: data/ui/menubar.ui:136 data/ui/view-popup.ui:20 msgid "Rem_ove Subtitles" msgstr "Remo_ver li subtitules" #: data/ui/menubar.ui:142 msgid "Sele_ction" msgstr "Sele_ction" #: data/ui/menubar.ui:145 msgid "Select _All" msgstr "Selecter _omnicos" #: data/ui/menubar.ui:149 msgid "_Invert Selection" msgstr "_Inverter li selection" #: data/ui/menubar.ui:155 msgid "Extend To _Beginning" msgstr "Extender al _inicie" #: data/ui/menubar.ui:159 msgid "Extend To _End" msgstr "Extender al _fin" #: data/ui/menubar.ui:165 msgid "_Previous From Video Position" msgstr "_Precedent ex li position" #: data/ui/menubar.ui:169 msgid "_Next From Video Position" msgstr "_Sequent ex li position" #: data/ui/menubar.ui:177 msgid "_Preferences" msgstr "_Preferenties" #: data/ui/menubar.ui:183 msgid "_View" msgstr "_Vise" #: data/ui/menubar.ui:186 msgid "Tool_bar" msgstr "P_anel de instrumentarium" #: data/ui/menubar.ui:190 msgid "_Video Player" msgstr "Reproductor de _video" #: data/ui/menubar.ui:196 msgid "_Layout" msgstr "_Arangeament" #: data/ui/menubar.ui:199 msgid "_Horizontal" msgstr "_Horizontal" #: data/ui/menubar.ui:204 msgid "_Vertical" msgstr "_Vertical" #: data/ui/menubar.ui:213 msgid "_Times" msgstr "_Témpores" #: data/ui/menubar.ui:218 msgid "_Frames" msgstr "_Cadres" #: data/ui/menubar.ui:225 msgid "F_ramerate" msgstr "_Rapidore de cadres" #: data/ui/menubar.ui:228 msgid "2_3.976 fps" msgstr "2_3.976 fps" #: data/ui/menubar.ui:233 msgid "2_4.000 fps" msgstr "2_4.000 fps" #: data/ui/menubar.ui:238 msgid "2_5.000 fps" msgstr "2_5.000 fps" #: data/ui/menubar.ui:243 msgid "2_9.970 fps" msgstr "2_9.970 fps" #: data/ui/menubar.ui:272 msgid "_Columns" msgstr "_Columnes" #: data/ui/menubar.ui:306 msgid "Cu_t" msgstr "Ci_ser" #: data/ui/menubar.ui:310 msgid "_Copy" msgstr "_Copiar" #: data/ui/menubar.ui:314 msgid "_Paste" msgstr "Co_llar" #: data/ui/menubar.ui:318 msgid "Cl_ear" msgstr "_Vacuar" #: data/ui/menubar.ui:324 msgid "_Find And Replace…" msgstr "_Serchar e substituer..." #: data/ui/menubar.ui:332 msgid "Find Pre_vious" msgstr "Trovar pre_cedent" #: data/ui/menubar.ui:338 msgid "_Italic" msgstr "_Italic" #: data/ui/menubar.ui:342 msgid "_Dialogue" msgstr "_Dialog" #: data/ui/menubar.ui:348 msgid "Ca_se" msgstr "Min/MA_J" #: data/ui/menubar.ui:351 msgid "_Title" msgstr "_Titul" #: data/ui/menubar.ui:355 msgid "_Sentence" msgstr "_Frase" #: data/ui/menubar.ui:359 msgid "_Upper" msgstr "MA_JUSCULES" #: data/ui/menubar.ui:363 msgid "_Lower" msgstr "mi_nuscules" #: data/ui/menubar.ui:371 msgid "Vi_deo" msgstr "Vi_deo" #: data/ui/menubar.ui:374 msgid "_Load Video…" msgstr "_Cargar un video..." #: data/ui/menubar.ui:384 data/ui/view-popup.ui:26 msgid "Play _Selection" msgstr "Reproducter li _selection" #: data/ui/menubar.ui:410 data/ui/view-popup.ui:30 msgid "S_eek Selection Start" msgstr "Saltar al inicie del s_election" #: data/ui/menubar.ui:414 msgid "See_k Selection End" msgstr "Al fin del sele_ction" #: data/ui/menubar.ui:420 msgid "_Audio" msgstr "_Audio" #: data/ui/menubar.ui:423 msgid "_Language" msgstr "_Lingue" #: data/ui/menubar.ui:430 msgid "Volume _Down" msgstr "_Augmentar li volúmine" #: data/ui/menubar.ui:434 msgid "Volume _Up" msgstr "_Diminuer li volúmine" #: data/ui/menubar.ui:440 msgid "T_ools" msgstr "_Instrumentarium" #: data/ui/menubar.ui:443 data/ui/text-assistant/confirmation-page.ui:97 #: data/ui/view-popup.ui:36 msgid "_Preview" msgstr "_Previder" #: data/ui/menubar.ui:447 msgid "Select _Video…" msgstr "Selecter un _video..." #: data/ui/menubar.ui:453 msgid "_Check Spelling" msgstr "Controlar _ortografie" #: data/ui/menubar.ui:457 msgid "Co_nfigure Spell-check…" msgstr "Co_nfigurar ortografie..." #: data/ui/menubar.ui:461 msgid "C_orrect Texts…" msgstr "C_orrecter textus" #: data/ui/menubar.ui:467 msgid "_Shift Positions…" msgstr "_Mover positiones..." #: data/ui/menubar.ui:471 msgid "_Transform Positions…" msgstr "_Transformar positiones…" #: data/ui/menubar.ui:475 msgid "Adjust _Durations…" msgstr "A_djustar durationes..." #: data/ui/menubar.ui:479 msgid "Convert _Framerate…" msgstr "Converter r_apiditá del cadres" #: data/ui/menubar.ui:485 msgid "_Append File…" msgstr "Apen_der un file..." #: data/ui/menubar.ui:489 msgid "Spli_t Project…" msgstr "S_eparar li projecte..." #: data/ui/menubar.ui:495 msgid "_Projects" msgstr "_Projectes" #: data/ui/menubar.ui:498 msgid "_Save All" msgstr "Salvar _omni" #: data/ui/menubar.ui:502 msgid "Save _All As…" msgstr "Salvar _omni quam..." #: data/ui/menubar.ui:506 msgid "_Close All" msgstr "_Clúder omni" #: data/ui/menubar.ui:512 msgid "_Previous" msgstr "_Precedent" #: data/ui/menubar.ui:516 msgid "_Next" msgstr "Seque_nt" #: data/ui/menubar.ui:527 msgid "_Documentation" msgstr "_Documentation" #: data/ui/menubar.ui:531 msgid "_Report A Bug" msgstr "_Raportar un defecte" #: data/ui/menubar.ui:535 msgid "_About" msgstr "_Pri" #: data/ui/open-dialog.ui:39 msgid "Align _method:" msgstr "Correspo_ndentie:" #: data/ui/preferences-dialog.ui:18 msgid "Preferences" msgstr "Preferenties" #: data/ui/preferences-dialog.ui:93 msgid "When opening files, try encodings in the following order:" msgstr "Apertente files, provar li sequent órdine de codificationes:" #: data/ui/preferences-dialog.ui:104 msgid "Curr_ent locale encoding" msgstr "Codification d_el locale" #: data/ui/preferences-dialog.ui:130 msgid "_Fallback encodings:" msgstr "A_lternativ codificationes:" #: data/ui/preferences-dialog.ui:246 msgid "Aut_o-detection" msgstr "Aut_o-detection" #: data/ui/preferences-dialog.ui:266 msgid "Encoding specified in the open dialog will always be tried first." msgstr "" "Li codification specificat in li dialog Aperter va esser usat in prim." #: data/ui/preferences-dialog.ui:296 msgid "File" msgstr "File" #: data/ui/preferences-dialog.ui:324 msgid "Font" msgstr "Fonde" #: data/ui/preferences-dialog.ui:344 msgid "Use _default theme fixed width font" msgstr "" #: data/ui/preferences-dialog.ui:368 msgid "_Editor font:" msgstr "Fond_e del redactor:" #: data/ui/preferences-dialog.ui:425 msgid "Line Lengths" msgstr "Longores de linea" #: data/ui/preferences-dialog.ui:445 msgid "_Show line lengths in list cells" msgstr "_Monstrar longores in li liste" #: data/ui/preferences-dialog.ui:462 msgid "S_how line lengths in editable text fields" msgstr "M_onstrar longores in text-campes" #: data/ui/preferences-dialog.ui:486 msgid "_Length unit:" msgstr "Unités de _longore:" #: data/ui/preferences-dialog.ui:540 msgid "Spell-Check" msgstr "Controlar ortografie" #: data/ui/preferences-dialog.ui:560 msgid "Chec_k spelling as you type" msgstr "_Controlar ortografie durante scrition" #: data/ui/preferences-dialog.ui:598 msgid "Editor" msgstr "Redactor" #: data/ui/preferences-dialog.ui:626 msgid "Fonts" msgstr "Fondes" #: data/ui/preferences-dialog.ui:649 msgid "_Subtitles:" msgstr "_Subtitules:" #: data/ui/preferences-dialog.ui:679 msgid "_Time:" msgstr "_Témpor:" #: data/ui/preferences-dialog.ui:729 msgid "Colors" msgstr "Colores" #: data/ui/preferences-dialog.ui:752 msgid "Su_btitles:" msgstr "Su_btitules:" #: data/ui/preferences-dialog.ui:777 msgid "_Use a background behind text" msgstr "_Usar un funde detra li textu" #: data/ui/preferences-dialog.ui:797 msgid "Ti_me:" msgstr "Té_mpor:" #: data/ui/preferences-dialog.ui:822 msgid "Us_e a background behind text" msgstr "Us_ar un funde detra li textu" #: data/ui/preferences-dialog.ui:862 msgid "Seek" msgstr "Saltar" #: data/ui/preferences-dialog.ui:883 msgid "_Length:" msgstr "_Longore:" #: data/ui/preferences-dialog.ui:971 msgid "Video Player" msgstr "Reproductor de video" #: data/ui/preferences-dialog.ui:994 msgid "_Application:" msgstr "_Application:" #: data/ui/preferences-dialog.ui:1008 msgid "Co_mmand:" msgstr "Co_mande:" #. Translators: Only the title is to be translated, field names not. #: data/ui/preferences-dialog.ui:1033 msgid "" "Fields:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" msgstr "" "Variabiles:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" #: data/ui/preferences-dialog.ui:1048 msgid "Al_ways use UTF-8 character encoding" msgstr "Sempre usar li codification UTF-_8" #: data/ui/preferences-dialog.ui:1089 msgid "Start Position" msgstr "Inicial position" #: data/ui/preferences-dialog.ui:1111 msgid "_Offset:" msgstr "P_ositionar" #: data/ui/preferences-dialog.ui:1142 msgid "seconds before selection" msgstr "secondes ante li selection" #: data/ui/preferences-dialog.ui:1281 msgid "Extensions" msgstr "Extensiones" #: data/ui/language-dialog.ui:8 msgid "Configure Spell-Check" msgstr "Configurar li control de ortografie" #: data/ui/language-dialog.ui:50 msgid "Language" msgstr "Lingue" #: data/ui/language-dialog.ui:128 msgid "Check _text column" msgstr "Controlar li _textu" #: data/ui/language-dialog.ui:146 msgid "Check t_ranslation column" msgstr "Controlar li t_raduction" #: data/ui/language-dialog.ui:206 msgid "Check c_urrent project" msgstr "Act_ual projecte" #: data/ui/language-dialog.ui:224 msgid "Check _all open projects" msgstr "_Omni apertet projectes" #: data/ui/text-assistant/confirmation-page.ui:22 msgid "Acc_ept, discard or edit changes:" msgstr "Acc_epter, rejecter o redacter modificationes:" #: data/ui/text-assistant/confirmation-page.ui:67 msgid "_Mark All" msgstr "Marcar _omni" #: data/ui/text-assistant/confirmation-page.ui:82 msgid "_Unmark All" msgstr "D_emarcar omni" #: data/ui/text-assistant/confirmation-page.ui:119 msgid "_Remove all blank subtitles" msgstr "_Remover omni blanc subtitules" #: data/ui/text-assistant/join-split-page.ui:28 msgid "Spell-Check Dictionary" msgstr "Dictionarium ortografic" #: data/ui/text-assistant/join-split-page.ui:49 #: data/ui/text-assistant/line-break-page.ui:81 #: data/ui/text-assistant/hearing-impaired-page.ui:81 #: data/ui/text-assistant/common-error-page.ui:80 #: data/ui/text-assistant/capitalization-page.ui:80 msgid "_Language:" msgstr "_Lingue:" #: data/ui/text-assistant/join-split-page.ui:97 msgid "Corrections" msgstr "Correctiones" #: data/ui/text-assistant/join-split-page.ui:117 msgid "_Join words not found in spell-check dictionary" msgstr "_Unir paroles que ne esser trovat in li dictionarium" #: data/ui/text-assistant/join-split-page.ui:134 msgid "_Split words not found in spell-check dictionary" msgstr "_Separar paroles que ne esser trovat in li dictionarium" #: data/ui/text-assistant/line-break-page.ui:22 msgid "S_elect preferred line-break points:" msgstr "S_electe preferet punctus a rupter lineas:" #: data/ui/text-assistant/line-break-page.ui:67 #: data/ui/text-assistant/hearing-impaired-page.ui:67 #: data/ui/text-assistant/common-error-page.ui:66 #: data/ui/text-assistant/capitalization-page.ui:66 msgid "_Script:" msgstr "_Scritura:" #: data/ui/text-assistant/line-break-page.ui:95 #: data/ui/text-assistant/hearing-impaired-page.ui:95 #: data/ui/text-assistant/common-error-page.ui:94 #: data/ui/text-assistant/capitalization-page.ui:94 msgid "Co_untry:" msgstr "La_nd:" #: data/ui/text-assistant/introduction-page.ui:28 msgid "_Select corrections to perform on texts:" msgstr "" #: data/ui/text-assistant/introduction-page.ui:79 msgid "Colu_mns:" msgstr "Colu_mnes:" #: data/ui/text-assistant/introduction-page.ui:93 msgid "S_ubtitles:" msgstr "S_ubtitules:" #: data/ui/text-assistant/line-break-options-page.ui:56 #: data/ui/duration-adjust-dialog.ui:207 msgid "Limits" msgstr "Límites" #: data/ui/text-assistant/line-break-options-page.ui:79 msgid "_Maximum line length:" msgstr "_Max longore de linea:" #: data/ui/text-assistant/line-break-options-page.ui:93 msgid "_Preferred maximum amount of lines:" msgstr "" #: data/ui/text-assistant/line-break-options-page.ui:198 msgid "_Skip subtitles with maximum line length of:" msgstr "" #: data/ui/text-assistant/line-break-options-page.ui:214 msgid "S_kip subtitles with maximum line amount of:" msgstr "" #: data/ui/text-assistant/hearing-impaired-page.ui:22 msgid "S_elect parts to remove:" msgstr "S_electer partes por remover:" #: data/ui/text-assistant/common-error-page.ui:22 msgid "S_elect errors to correct:" msgstr "S_electer errores por correcter:" #: data/ui/text-assistant/common-error-page.ui:108 msgid "Error types:" msgstr "Tipes de errores:" #: data/ui/text-assistant/common-error-page.ui:158 msgid "_Human errors" msgstr "_Human errores" #: data/ui/text-assistant/common-error-page.ui:175 msgid "_Image recognition errors" msgstr "Errores de OC_R" #: data/ui/text-assistant/capitalization-page.ui:22 msgid "S_elect parts to capitalize:" msgstr "S_electer partes por majusculisar:" #: data/ui/duration-adjust-dialog.ui:33 msgid "Adjust Durations" msgstr "Adjustar durationes" #: data/ui/duration-adjust-dialog.ui:73 msgid "Theoretic Duration" msgstr "Teoretic duration" #: data/ui/duration-adjust-dialog.ui:101 msgid "_Reading speed:" msgstr "_Velocitá de letion:" #: data/ui/duration-adjust-dialog.ui:133 msgid "characters per second" msgstr "caracteres per seconde" #: data/ui/duration-adjust-dialog.ui:150 msgid "_Lengthen duration to match reading speed" msgstr "" #: data/ui/duration-adjust-dialog.ui:167 msgid "_Shorten duration to match reading speed" msgstr "" #: data/ui/duration-adjust-dialog.ui:227 msgid "_Minimum duration:" msgstr "_Min duration:" #: data/ui/duration-adjust-dialog.ui:243 msgid "Ma_ximum duration:" msgstr "Ma_x duration:" #: data/ui/duration-adjust-dialog.ui:259 msgid "_Gap between subtitles:" msgstr "_Intersticie:" #: data/ui/duration-adjust-dialog.ui:294 msgid "s_econds" msgstr "s_econdes" #: data/ui/duration-adjust-dialog.ui:324 msgid "seco_nds" msgstr "seco_ndes" #: data/ui/duration-adjust-dialog.ui:354 msgid "secon_ds" msgstr "secon_des" #: data/ui/duration-adjust-dialog.ui:408 msgid "Adj_ust selected subtitles" msgstr "Adj_ustar selectet subtitules" #: data/ui/duration-adjust-dialog.ui:425 msgid "Adjus_t current project" msgstr "Adjustar li actual projecte" #: data/ui/duration-adjust-dialog.ui:442 msgid "Adjust all _open projects" msgstr "Adjustar _omni apertet projectes" #: data/ui/tab-popup.ui:6 msgid "Move Tab _Left" msgstr "Mover li carte a _levul" #: data/ui/tab-popup.ui:10 msgid "Move Tab _Right" msgstr "Mover li carte a _dextri" #: data/ui/insert-dialog.ui:15 msgid "Insert Subtitles" msgstr "Inserter nov subtitules" #: data/ui/insert-dialog.ui:48 data/ui/position-shift-dialog.ui:82 msgid "_Amount:" msgstr "Qu_antitá:" #: data/ui/insert-dialog.ui:62 msgid "_Position:" msgstr "_Position:" #: data/ui/position-shift-dialog.ui:14 msgid "Shift Positions" msgstr "Mover positiones" #: data/ui/position-shift-dialog.ui:54 msgid "Shift" msgstr "Mover" #: data/ui/position-shift-dialog.ui:135 #: data/ui/position-transform-dialog.ui:208 msgid "_Preview Changes" msgstr "_Previder modificationes" #: data/ui/position-shift-dialog.ui:200 msgid "Shift s_elected subtitles" msgstr "Mover s_electet subtitules" #: data/ui/position-shift-dialog.ui:217 msgid "Shift su_btitles from selection to end" msgstr "Mover su_btitules del inicie al fin" #: data/ui/position-shift-dialog.ui:234 msgid "Shift c_urrent project" msgstr "Mover li act_ual projecte" #: data/ui/position-shift-dialog.ui:251 msgid "Shift all _open projects" msgstr "Mover _omni apertet projectes" #: data/ui/position-transform-dialog.ui:22 msgid "Transform Positions" msgstr "Transformation" #: data/ui/position-transform-dialog.ui:62 msgid "First Point" msgstr "Prim punctu" #: data/ui/position-transform-dialog.ui:91 msgid "_Subtitle:" msgstr "_Subtitul:" #: data/ui/position-transform-dialog.ui:105 msgid "C_orrection:" msgstr "C_orrection:" #: data/ui/position-transform-dialog.ui:119 #: data/ui/position-transform-dialog.ui:310 msgid "Text:" msgstr "Textu:" #: data/ui/position-transform-dialog.ui:253 msgid "Second Point" msgstr "Secund punctu" #: data/ui/position-transform-dialog.ui:282 msgid "Su_btitle:" msgstr "Su_btitul:" #: data/ui/position-transform-dialog.ui:296 msgid "Co_rrection:" msgstr "Co_rrection:" #: data/ui/position-transform-dialog.ui:399 msgid "Pre_view Changes" msgstr "Pre_vider modificationes" #: data/ui/position-transform-dialog.ui:464 msgid "Transform se_lected subtitles" msgstr "Transformar li se_lectet subtitules" #: data/ui/position-transform-dialog.ui:482 msgid "Transform c_urrent project" msgstr "Transformar li act_ual projecte" #: data/extensions/custom-framerates/custom-framerates.extension.in:7 msgid "Custom Framerates" msgstr "Personal rapidores de cadres" #: data/extensions/custom-framerates/custom-framerates.extension.in:8 msgid "Allow use of non-standard framerates" msgstr "Permisser non-standard rapidores de cadres" #: data/patterns/Latn-en-US.common-error.in:5 msgid "Period after title" msgstr "Punctu pos un titul" #: data/patterns/Latn-en-US.common-error.in:6 msgid "Add period after a shortened title, such as \"Mr\" and \"Dr\"" msgstr "" #: data/patterns/Latn-en.capitalization.in:5 msgid "First person pronoun" msgstr "Pronomine «I»" #: data/patterns/Latn-en.capitalization.in:6 msgid "Capitalize the first person pronoun \"I\"" msgstr "Majusculisar li pronomine «I»" #: data/patterns/Latn-en.common-error.in:5 #: data/patterns/Latn-en.common-error.in:14 #: data/patterns/Latn-en.common-error.in:23 msgid "Letter \"I\" in a lower case word" msgstr "Líttere «I» inter li minuscules" #: data/patterns/Latn-en.common-error.in:6 #: data/patterns/Latn-en.common-error.in:15 #: data/patterns/Latn-en.common-error.in:24 msgid "Replace letter \"I\" with letter \"l\" in a lower case word" msgstr "Remplazzar li líttere «I» per «l» inter minuscules" #: data/patterns/Latn-en.common-error.in:32 #: data/patterns/Latn-en.common-error.in:41 #: data/patterns/Latn-en.common-error.in:50 #: data/patterns/Latn-en.common-error.in:62 msgid "Letter \"l\" in an upper case word" msgstr "Líttere «l» inter li majuscules" #: data/patterns/Latn-en.common-error.in:33 #: data/patterns/Latn-en.common-error.in:42 #: data/patterns/Latn-en.common-error.in:51 #: data/patterns/Latn-en.common-error.in:63 msgid "Replace letter \"l\" with letter \"I\" in an upper case word" msgstr "Remplazzar li líttere «l» per «I» inter majuscules" #: data/patterns/Latn-en.common-error.in:73 #: data/patterns/Latn-en.common-error.in:82 msgid "Zero in an upper case word" msgstr "Zero inter majuscules" #: data/patterns/Latn-en.common-error.in:74 #: data/patterns/Latn-en.common-error.in:83 msgid "Replace zero with letter \"O\" in an upper case word" msgstr "Remplazzar un zero per li líttere «O» inter majuscules" #: data/patterns/Latn-en.common-error.in:91 #: data/patterns/Latn.common-error.in:108 msgid "Space between number and unit" msgstr "Spacie inter un númere e unité" #: data/patterns/Latn-en.common-error.in:92 #: data/patterns/Latn.common-error.in:109 msgid "Add or remove space between a number and the associated unit" msgstr "" #: data/patterns/Latn-en.common-error.in:100 msgid "Spaces around an apostrophe" msgstr "Spacies circum un apostrof" #: data/patterns/Latn-en.common-error.in:101 msgid "Remove spaces around an apostrophe" msgstr "Remover spacies circum un apostrof" #: data/patterns/Latn-en.common-error.in:109 #: data/patterns/Latn-en.common-error.in:118 msgid "Okay" msgstr "Okay" #: data/patterns/Latn-en.common-error.in:110 #: data/patterns/Latn-en.common-error.in:119 msgid "Spell two-letter forms of \"okay\" in all upper case" msgstr "" #: data/patterns/Latn-en.hearing-impaired.in:5 msgid "Uppercase speaker before a colon" msgstr "Parlator scrit in majuscules ante un cólon" #: data/patterns/Latn-en.hearing-impaired.in:6 msgid "" "Replace the uppercase name of the speaker before a colon with a dialogue " "dash" msgstr "Remplazzar li nómine de parlator con un cólon per un strec de dialog" #: data/patterns/Latn-en.line-break.in:5 msgid "Title" msgstr "Titul" #: data/patterns/Latn-en.line-break.in:6 msgid "Do not break after a title, e.g. \" Dr.\"" msgstr "Ne rupter pos un titul, p.ex. «Dr.»" #: data/patterns/Latn-en.line-break.in:13 msgid "Article" msgstr "Articul" #: data/patterns/Latn-en.line-break.in:14 msgid "Do not break after an article" msgstr "Ne rupter pos un articul" #: data/patterns/Latn-en.line-break.in:21 msgid "Preposition" msgstr "Preposition" #: data/patterns/Latn-en.line-break.in:22 msgid "Do not break after a preposition" msgstr "Ne rupter pos un preposition" #: data/patterns/Latn-en.line-break.in:30 msgid "Possessive determiner" msgstr "Determinator possessiv" #: data/patterns/Latn-en.line-break.in:31 msgid "Do not break after a possessive determiner, e.g. \"my\"" msgstr "Ne rupter pos un determinator possessiv, p.ex. «my»" #: data/patterns/Latn-fi.common-error.in:5 #: data/patterns/Latn.common-error.in:182 msgid "Space after punctuation marks" msgstr "Spacie pos signes de punctuation" #: data/patterns/Latn-fi.common-error.in:6 #: data/patterns/Latn.common-error.in:183 msgid "Add space after various punctuation marks" msgstr "" #: data/patterns/Latn-fr.common-error.in:5 #: data/patterns/Latn-fr.common-error.in:14 #: data/patterns/Latn-fr.common-error.in:23 #: data/patterns/Latn-fr.common-error.in:32 msgid "Spaces around guillemets" msgstr "Spacie circum «»" #: data/patterns/Latn-fr.common-error.in:6 #: data/patterns/Latn-fr.common-error.in:15 #: data/patterns/Latn-fr.common-error.in:24 #: data/patterns/Latn-fr.common-error.in:33 msgid "Add spaces around guillemets" msgstr "Spacie circum «»" #: data/patterns/Latn-fr.common-error.in:41 #: data/patterns/Latn-fr.common-error.in:52 #: data/patterns/Latn.common-error.in:171 msgid "Space before punctuation marks" msgstr "Spacie ante signes de punctuation" #: data/patterns/Latn-fr.common-error.in:42 #: data/patterns/Latn-fr.common-error.in:53 msgid "Add or remove space before various punctuation marks" msgstr "" #: data/patterns/Latn.capitalization.in:5 msgid "Sentence" msgstr "Frase" #: data/patterns/Latn.capitalization.in:6 msgid "Capitalize the first word of a sentence" msgstr "Majusculisar li prim parole de un frase" #: data/patterns/Latn.capitalization.in:12 msgid "Ellipsis" msgstr "Punctus suspensiv" #: data/patterns/Latn.capitalization.in:13 msgid "Capitalize after an ellipsis" msgstr "Majuscule pos punctus suspensiv" #: data/patterns/Latn.common-error.in:8 data/patterns/Latn.common-error.in:17 #: data/patterns/Latn.common-error.in:26 data/patterns/Latn.common-error.in:35 #: data/patterns/Latn.common-error.in:44 data/patterns/Latn.common-error.in:53 #: data/patterns/Latn.common-error.in:62 msgid "Ligatures" msgstr "Ligaturas" #: data/patterns/Latn.common-error.in:9 data/patterns/Latn.common-error.in:18 #: data/patterns/Latn.common-error.in:27 data/patterns/Latn.common-error.in:36 #: data/patterns/Latn.common-error.in:45 data/patterns/Latn.common-error.in:54 #: data/patterns/Latn.common-error.in:63 msgid "Unpack ligatures to individual characters" msgstr "Separar ligaturas a individual caracteres" #: data/patterns/Latn.common-error.in:71 data/patterns/Latn.common-error.in:80 msgid "Spelling of a.m. and p.m." msgstr "Ortografie de a.m. e p.m." #: data/patterns/Latn.common-error.in:72 data/patterns/Latn.common-error.in:81 msgid "Change the various spellings of 12-hour periods to \"a.m.\" and \"p.m.\"" msgstr "" #: data/patterns/Latn.common-error.in:89 data/patterns/Latn.common-error.in:98 msgid "Letter \"O\" in a number" msgstr "Líttere «O» in un númere" #: data/patterns/Latn.common-error.in:90 data/patterns/Latn.common-error.in:99 msgid "Replace letter \"O\" with a zero in a number" msgstr "Remplazzar li líttere «O» per un zero in un númere" #: data/patterns/Latn.common-error.in:117 msgid "Double apostrophe" msgstr "Duplic apostrof" #: data/patterns/Latn.common-error.in:118 msgid "Replace a double apostrophe with a quotation mark" msgstr "Remplazzar un duplic apostrof per un signe de quotation" #: data/patterns/Latn.common-error.in:126 #: data/patterns/Latn.common-error.in:135 #: data/patterns/Latn.common-error.in:144 #: data/patterns/Latn.common-error.in:153 msgid "Spaces around brackets" msgstr "Spacie circum []" #: data/patterns/Latn.common-error.in:127 #: data/patterns/Latn.common-error.in:136 #: data/patterns/Latn.common-error.in:145 #: data/patterns/Latn.common-error.in:154 msgid "Add or remove spaces around parantheses and square brackets" msgstr "Adjunter o remover spacie circum parenteses e crampones" #: data/patterns/Latn.common-error.in:162 msgid "Space after a dialogue dash" msgstr "Spacie pos strec de dialog" #: data/patterns/Latn.common-error.in:163 msgid "Add space after a dialogue dash" msgstr "" #: data/patterns/Latn.common-error.in:172 msgid "Remove space before various punctuation marks" msgstr "Remover spacies ante alcun signes de punctuation" #: data/patterns/Latn.common-error.in:192 msgid "Space after an ellipsis" msgstr "Spacie pos punctus suspensiv" #: data/patterns/Latn.common-error.in:193 msgid "Add space after an ellipsis" msgstr "Adjunter un spacie pos punctus suspensiv" #: data/patterns/Latn.common-error.in:201 msgid "Space after a starting ellipsis" msgstr "Spacie pos un inicial punctus suspensiv" #: data/patterns/Latn.common-error.in:202 msgid "Remove space after an ellipsis that starts a line" msgstr "Remover spacies ante punctus suspensiv in li inicie de linea" #: data/patterns/Latn.common-error.in:210 #: data/patterns/Latn.common-error.in:221 #: data/patterns/Latn.common-error.in:232 #: data/patterns/Latn.common-error.in:242 msgid "Spaces around a quotation mark" msgstr "Spacies inter signes de citation" #: data/patterns/Latn.common-error.in:211 #: data/patterns/Latn.common-error.in:222 #: data/patterns/Latn.common-error.in:233 #: data/patterns/Latn.common-error.in:243 msgid "Remove space after a starting- and before an ending quotation mark" msgstr "" #: data/patterns/Latn.common-error.in:252 #: data/patterns/Latn.common-error.in:261 msgid "Spaces around musical notes" msgstr "Spacie circum musical notes" #: data/patterns/Latn.common-error.in:253 #: data/patterns/Latn.common-error.in:262 msgid "Add spaces between musical note characters and lyrics" msgstr "" #: data/patterns/Latn.common-error.in:270 #: data/patterns/Latn.common-error.in:279 msgid "Multiple question- and exclamation marks" msgstr "" #: data/patterns/Latn.common-error.in:271 #: data/patterns/Latn.common-error.in:280 msgid "" "Replace multiple consequtive question- and exclamation marks with only one" msgstr "" #: data/patterns/Latn.common-error.in:288 #: data/patterns/Latn.common-error.in:298 msgid "Periods around a punctuation mark" msgstr "Punctus apu punctuation" #: data/patterns/Latn.common-error.in:289 #: data/patterns/Latn.common-error.in:299 msgid "Remove period before or after various punctuation marks" msgstr "" #: data/patterns/Latn.common-error.in:308 msgid "Terminating double-dashes" msgstr "Final duplic tirés" #: data/patterns/Latn.common-error.in:309 msgid "Replace a single clause-terminating dash with two dashes" msgstr "" #: data/patterns/Latn.hearing-impaired.in:5 msgid "Sound in brackets" msgstr "Sones in []" #: data/patterns/Latn.hearing-impaired.in:6 msgid "Remove description of a sound between square brackets" msgstr "Remover descritiones de sones inter crampones" #: data/patterns/Latn.hearing-impaired.in:12 msgid "Sound in parantheses" msgstr "Sones in ()" #: data/patterns/Latn.hearing-impaired.in:13 msgid "Remove description of a sound between parantheses" msgstr "Remover descritiones de sones inter parenteses" #: data/patterns/Latn.hearing-impaired.in:19 msgid "Song lyrics between number signs" msgstr "Textu de canzones inter ##" #: data/patterns/Latn.hearing-impaired.in:20 msgid "Remove song lyrics starting with or between number signs" msgstr "Remover textu de canzones inter ##" #: data/patterns/Latn.hearing-impaired.in:27 msgid "One-line song lyrics between number signs" msgstr "" #: data/patterns/Latn.hearing-impaired.in:28 msgid "Remove one-line song lyrics starting with or between number signs" msgstr "" #: data/patterns/Latn.hearing-impaired.in:35 msgid "Speaker before a colon" msgstr "Parlator ante un cólon" #: data/patterns/Latn.hearing-impaired.in:36 msgid "Replace the name of the speaker before a colon with a dialogue dash" msgstr "" #: data/patterns/Latn.line-break.in:5 data/patterns/Latn.line-break.in:13 msgid "Dialogue" msgstr "Dialog" #: data/patterns/Latn.line-break.in:6 data/patterns/Latn.line-break.in:14 msgid "Break according to dialogue separated by dashes" msgstr "Rupter secun un dialog separat per tirés" #: data/patterns/Latn.line-break.in:21 data/patterns/Latn.line-break.in:30 msgid "Clause" msgstr "Cláusul" #: data/patterns/Latn.line-break.in:22 data/patterns/Latn.line-break.in:31 msgid "Break according to clauses terminated by a punctuation mark" msgstr "" #: data/patterns/Latn.line-break.in:38 msgid "Number and unit" msgstr "Númeres e unités" #: data/patterns/Latn.line-break.in:39 msgid "Do not break between a number and associated unit" msgstr "" #: data/patterns/Zyyy.common-error.in:5 data/patterns/Zyyy.common-error.in:14 msgid "Leading and trailing spaces" msgstr "Spacies inicial e final" #: data/patterns/Zyyy.common-error.in:6 data/patterns/Zyyy.common-error.in:15 msgid "Remove spaces from the beginning and end of lines" msgstr "Remover spacies ex li inicie e li fin de lineas" #: data/patterns/Zyyy.common-error.in:23 msgid "Multiple consecutive spaces" msgstr "Multiplic consequent spacies" #: data/patterns/Zyyy.common-error.in:24 msgid "Replace multiple consecutive spaces with only one" msgstr "Replazzar multiplic spacie per ún" #: data/patterns/Zyyy.common-error.in:32 data/patterns/Zyyy.common-error.in:45 #: data/patterns/Zyyy.common-error.in:55 data/patterns/Zyyy.common-error.in:65 msgid "Space between digits" msgstr "Spacie inter ciffres" #: data/patterns/Zyyy.common-error.in:33 data/patterns/Zyyy.common-error.in:46 #: data/patterns/Zyyy.common-error.in:56 data/patterns/Zyyy.common-error.in:66 msgid "Remove space between digits of a number" msgstr "Remover li spacie inter ciffres in un númere" #: data/patterns/Zyyy.common-error.in:79 msgid "Musical notes" msgstr "Musical notes" #: data/patterns/Zyyy.common-error.in:80 msgid "Replace Unicode musical note characters with number signs" msgstr "Vicear simboles de note de Unicode per #s" #: data/io.otsaloma.gaupol.appdata.xml.in:7 msgid "Editor for text-based subtitles" msgstr "Un redactor por textual subtitules" #: data/io.otsaloma.gaupol.appdata.xml.in:9 msgid "" "Gaupol is an editor for text-based subtitle files. It supports multiple " "subtitle file formats and provides means of creating subtitles, editing " "texts and timing subtitles to match video." msgstr "" "Gaupol es un redactor por files de textual subtitules. It supporta multiplic" " formates de file e permisse vos crear, redacter e colocar subtitules secun " "un video." #: data/io.otsaloma.gaupol.appdata.xml.in:40 msgid "Main window" msgstr "Li fenestre principal" #: data/io.otsaloma.gaupol.desktop.in:5 msgid "Subtitle Editor" msgstr "Redactor de subtitules" #: data/io.otsaloma.gaupol.desktop.in:6 msgid "Edit subtitle files" msgstr "Redacte files de subtitules" #. TRANSLATORS: Search terms to find this application. Do NOT translate or #. localize the semicolons! The list MUST also end with a semicolon! #: data/io.otsaloma.gaupol.desktop.in:12 msgid "video;subtitles;captions;" msgstr "video;film;subtitules;" gaupol-1.11/po/is.po000066400000000000000000002137121422217132500143210ustar00rootroot00000000000000# 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. # # Translators: # Sveinn í Felli , 2019 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-04-03 04:00+0300\n" "PO-Revision-Date: 2016-07-07 00:55+0000\n" "Last-Translator: Sveinn í Felli , 2019\n" "Language-Team: Icelandic (https://www.transifex.com/otsaloma/teams/64879/is/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: is\n" "Plural-Forms: nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);\n" #: aeidon/enums.py:40 gaupol/enums.py:38 msgid "Subtitle number" msgstr "Númer skjátexta" #: aeidon/enums.py:43 msgid "Subtitle position" msgstr "Staðsetning skjátexta" #: aeidon/enums.py:59 msgid "23.976 fps" msgstr "23.976 r/sek" #: aeidon/enums.py:63 msgid "24.000 fps" msgstr "24.000 r/sek" #: aeidon/enums.py:67 msgid "25.000 fps" msgstr "25.000 r/sek" #: aeidon/enums.py:71 msgid "29.970 fps" msgstr "29.970 r/sek" #: aeidon/enums.py:75 data/ui/menubar.ui:248 msgid "30.000 fps" msgstr "" #: aeidon/enums.py:79 data/ui/menubar.ui:253 msgid "50.000 fps" msgstr "" #: aeidon/enums.py:83 data/ui/menubar.ui:258 msgid "59.940 fps" msgstr "" #: aeidon/enums.py:87 data/ui/menubar.ui:263 msgid "60.000 fps" msgstr "" #: aeidon/enums.py:112 msgid "Mac (classic)" msgstr "Mac (klassísk)" #. TRANSLATORS: Most of the character encoding descriptions are copied from #. gedit, which is translated to very many languages. Check the gedit .po #. files for a reference: #. . #: aeidon/encodings.py:40 aeidon/encodings.py:43 aeidon/encodings.py:46 msgid "English" msgstr "Enska" #: aeidon/encodings.py:41 aeidon/encodings.py:42 aeidon/encodings.py:69 msgid "Chinese traditional" msgstr "Hefðbundin kínverska" #: aeidon/encodings.py:44 msgid "German" msgstr "Þýska" #: aeidon/encodings.py:45 aeidon/encodings.py:54 aeidon/encodings.py:59 #: aeidon/encodings.py:79 aeidon/encodings.py:105 msgid "Hebrew" msgstr "Hebreska" #: aeidon/encodings.py:47 aeidon/encodings.py:51 aeidon/encodings.py:56 #: aeidon/encodings.py:73 aeidon/encodings.py:76 aeidon/encodings.py:98 #: aeidon/encodings.py:111 aeidon/encodings.py:122 msgid "Western" msgstr "Vestrænt" #: aeidon/encodings.py:48 aeidon/encodings.py:61 aeidon/encodings.py:80 #: aeidon/encodings.py:103 msgid "Arabic" msgstr "Arabíska" #: aeidon/encodings.py:49 aeidon/encodings.py:64 aeidon/encodings.py:66 #: aeidon/encodings.py:77 aeidon/encodings.py:104 aeidon/encodings.py:119 msgid "Greek" msgstr "Gríska" #: aeidon/encodings.py:50 aeidon/encodings.py:81 aeidon/encodings.py:101 #: aeidon/encodings.py:109 msgid "Baltic" msgstr "Balkneskt" #: aeidon/encodings.py:52 aeidon/encodings.py:74 aeidon/encodings.py:99 #: aeidon/encodings.py:121 msgid "Central European" msgstr "Mið-evrópskt" #: aeidon/encodings.py:53 aeidon/encodings.py:75 aeidon/encodings.py:102 #: aeidon/encodings.py:118 msgid "Cyrillic" msgstr "Kýrílískt" #: aeidon/encodings.py:55 aeidon/encodings.py:71 aeidon/encodings.py:78 #: aeidon/encodings.py:106 aeidon/encodings.py:123 msgid "Turkish" msgstr "Tyrkneska" #: aeidon/encodings.py:57 msgid "Portuguese" msgstr "Portúgalska" #: aeidon/encodings.py:58 aeidon/encodings.py:120 msgid "Icelandic" msgstr "Íslenska" #: aeidon/encodings.py:60 msgid "Canadian" msgstr "Kanadíska" #: aeidon/encodings.py:62 aeidon/encodings.py:107 msgid "Nordic" msgstr "Norrænt" #: aeidon/encodings.py:63 aeidon/encodings.py:114 msgid "Russian" msgstr "Rússneska" #: aeidon/encodings.py:65 aeidon/encodings.py:108 msgid "Thai" msgstr "Tælenska" #: aeidon/encodings.py:67 aeidon/encodings.py:83 aeidon/encodings.py:84 #: aeidon/encodings.py:85 aeidon/encodings.py:91 aeidon/encodings.py:92 #: aeidon/encodings.py:93 aeidon/encodings.py:94 aeidon/encodings.py:95 #: aeidon/encodings.py:96 aeidon/encodings.py:125 aeidon/encodings.py:126 #: aeidon/encodings.py:127 msgid "Japanese" msgstr "Japanska" #: aeidon/encodings.py:68 aeidon/encodings.py:86 aeidon/encodings.py:97 #: aeidon/encodings.py:113 msgid "Korean" msgstr "Kóreska" #: aeidon/encodings.py:70 msgid "Urdu" msgstr "Úrdú" #: aeidon/encodings.py:72 aeidon/encodings.py:116 msgid "Ukrainian" msgstr "Úkraínska" #: aeidon/encodings.py:82 msgid "Vietnamese" msgstr "Víetnamska" #: aeidon/encodings.py:87 aeidon/encodings.py:90 msgid "Chinese simplified" msgstr "Einfölduð kínverska" #: aeidon/encodings.py:88 aeidon/encodings.py:89 msgid "Chinese unified" msgstr "Sameinuð kínverska" #: aeidon/encodings.py:100 aeidon/encodings.py:112 msgid "South European" msgstr "Suður-evrópskt" #: aeidon/encodings.py:110 msgid "Celtic" msgstr "Keltneskt" #: aeidon/encodings.py:115 msgid "Tajik" msgstr "Tadzjikiska" #: aeidon/encodings.py:117 msgid "Kazakh" msgstr "Kasakíska" #: aeidon/encodings.py:124 msgid "Cyrillic Asian" msgstr "Kýrílískt asískt" #: aeidon/encodings.py:128 aeidon/encodings.py:129 aeidon/encodings.py:130 #: aeidon/encodings.py:131 aeidon/encodings.py:132 aeidon/encodings.py:133 #: aeidon/encodings.py:134 aeidon/encodings.py:135 aeidon/encodings.py:136 msgid "Unicode" msgstr "Unicode (UTF-8)" #: aeidon/encodings.py:156 #, python-brace-format msgid "{description} ({name})" msgstr "{description} ({name})" #: aeidon/encodings.py:232 msgid "Current locale ({})" msgstr "Núverandi staðfærsla ({})" #: aeidon/locales.py:46 #, python-brace-format msgid "{language} ({country})" msgstr "{language} ({country})" #: aeidon/agents/search.py:227 msgid "Replacing" msgstr "Skipti út" #: aeidon/agents/search.py:256 aeidon/agents/search.py:258 msgid "Replacing all" msgstr "Skipti út öllu" #: aeidon/agents/position.py:74 msgid "Adjusting durations" msgstr "Aðlaga tímalengdir" #: aeidon/agents/position.py:96 msgid "Converting framerate" msgstr "Umbreyting á rammatíðni" #: aeidon/agents/position.py:146 msgid "Setting framerate" msgstr "Stilli rammatíðni" #: aeidon/agents/position.py:168 msgid "Shifting positions" msgstr "Hliðra staðsetningum" #: aeidon/agents/position.py:188 msgid "Transforming positions" msgstr "Umbreyting staðsetninga" #: aeidon/agents/clipboard.py:44 msgid "Cutting texts" msgstr "Klippi texta" #: aeidon/agents/clipboard.py:61 msgid "Pasting texts" msgstr "Lími texta" #: aeidon/agents/text.py:91 msgid "Breaking lines" msgstr "Skipti línum" #: aeidon/agents/text.py:128 msgid "Capitalizing texts" msgstr "Textar í hástafi" #: aeidon/agents/text.py:185 msgid "Correcting common errors" msgstr "Leiðrétting algengra villna" #: aeidon/agents/text.py:234 msgid "Removing hearing impaired texts" msgstr "Fjarlægi texta fyrir heyrnarskerta" #: aeidon/agents/text.py:315 msgid "Joining words by spell-check suggestions" msgstr "Sameina orð miðað við uppástungur" #: aeidon/agents/text.py:354 msgid "Splitting words by spell-check suggestions" msgstr "Skipta upp orðum miðað við uppástungur" #: aeidon/agents/set.py:58 aeidon/agents/set.py:80 aeidon/agents/set.py:113 msgid "Editing position" msgstr "Breyti staðsetningu" #: aeidon/agents/set.py:129 msgid "Editing text" msgstr "Breyting texta" #: aeidon/agents/edit.py:35 msgid "Clearing texts" msgstr "Hreinsa texta" #: aeidon/agents/edit.py:61 aeidon/agents/edit.py:83 msgid "Inserting subtitles" msgstr "Set inn skjátexta" #: aeidon/agents/edit.py:103 msgid "Merging subtitles" msgstr "Sameina skjátexta" #: aeidon/agents/edit.py:114 msgid "Removing subtitles" msgstr "Fjarlægi skjátexta" #: aeidon/agents/edit.py:131 msgid "Replacing positions" msgstr "Skipti út staðsetningum" #: aeidon/agents/edit.py:147 msgid "Replacing texts" msgstr "Skipti um texta" #: aeidon/agents/edit.py:171 msgid "Splitting subtitle" msgstr "Skipti upp skjátexta" #: aeidon/agents/format.py:49 msgid "Adding dialogue dashes" msgstr "Bæti við þankastrikum" #: aeidon/agents/format.py:68 msgid "Changing case" msgstr "Breyti stafstöðu" #: aeidon/agents/format.py:92 msgid "Italicizing" msgstr "Skáletra" #: aeidon/agents/format.py:108 msgid "Removing dialogue dashes" msgstr "Fjarlægi þankastrik" #: aeidon/agents/format.py:174 msgid "Unitalicizing" msgstr "Fjarlægi skáletrun" #: gaupol/application.py:219 gaupol/agents/open.py:203 msgid "Open" msgstr "Opna" #: gaupol/application.py:223 msgid "Open main files" msgstr "Opna aðalskrár" #: gaupol/application.py:230 msgid "Save" msgstr "Vista" #: gaupol/application.py:233 msgid "Save the current main document" msgstr "Vista í virku aðalskjali" #: gaupol/application.py:238 msgid "Undo" msgstr "Afturkalla" #: gaupol/application.py:242 msgid "Undo the last action" msgstr "Hætta við síðustu aðgerð" #: gaupol/application.py:249 msgid "Redo" msgstr "Endurtaka" #: gaupol/application.py:252 msgid "Redo the last undone action" msgstr "Endurtaka síðustu afturkölluðu aðgerð" #: gaupol/application.py:260 msgid "Insert" msgstr "Setja inn" #: gaupol/application.py:262 msgid "Insert new subtitles" msgstr "Setja inn nýja skjátexta" #: gaupol/application.py:266 #: data/extensions/custom-framerates/preferences-dialog.ui:78 msgid "Remove" msgstr "Fjarlægja" #: gaupol/application.py:268 msgid "Remove the selected subtitles" msgstr "Fjarlægja valda skjátexta" #: gaupol/application.py:273 data/ui/search-dialog.ui:283 msgid "Find" msgstr "Finna" #: gaupol/application.py:275 msgid "Search for and replace text" msgstr "Leita að og skipta út texta" #: gaupol/application.py:279 data/ui/preferences-dialog.ui:942 msgid "Video" msgstr "Myndskeið" #: gaupol/application.py:281 msgid "Show or hide the video player" msgstr "Birta eða fela myndspilara" #: gaupol/application.py:285 data/ui/preferences-dialog.ui:1173 msgid "Preview" msgstr "Forskoðun" #: gaupol/application.py:287 msgid "Preview from selected position with a video player" msgstr "Forskoða frá valinni staðsetningu í myndspilara" #: gaupol/enums.py:37 msgid "No." msgstr "Nr." #: gaupol/enums.py:43 msgid "Start" msgstr "Upphaf" #: gaupol/enums.py:44 msgid "Start position" msgstr "Upphafsstaða" #: gaupol/enums.py:49 msgid "End" msgstr "Endir" #: gaupol/enums.py:50 msgid "End position" msgstr "Endastaða" #. TRANSLATORS: 'Dur.' is short for duration. It is used in the header #. of a column that contains numbers five digits wide. #: gaupol/enums.py:57 msgid "Dur." msgstr "Len." #: gaupol/enums.py:58 msgid "Duration" msgstr "Tímalengd" #: gaupol/enums.py:63 gaupol/enums.py:64 msgid "Text" msgstr "Texti" #: gaupol/enums.py:69 gaupol/enums.py:70 msgid "Translation" msgstr "Þýðing" #: gaupol/enums.py:82 msgid "characters" msgstr "stafir" #: gaupol/enums.py:85 msgid "ems" msgstr "ems" #: gaupol/page.py:60 msgid "Untitled {:d}" msgstr "Ónefnt {:d}" #: gaupol/page.py:133 msgid "Close project" msgstr "Loka verkefni" #: gaupol/page.py:145 msgid "{} translation" msgstr "{} þýðing" #: gaupol/page.py:302 msgid "Path:" msgstr "Slóð:" #: gaupol/page.py:303 msgid "Format:" msgstr "Snið:" #: gaupol/page.py:304 msgid "Encoding:" msgstr "Stafatafla:" #: gaupol/page.py:305 msgid "Newlines:" msgstr "Nýlínumerki:" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:99 msgid "Tasks and Target" msgstr "Verk og útkoma" #: gaupol/assistants.py:128 msgid "Correct texts in the text column" msgstr "Leiðrétta texta í textadálkinum" #: gaupol/assistants.py:129 msgid "Correct texts in the translation column" msgstr "Leiðrétta texta í þýðingadálkinum" #: gaupol/assistants.py:138 msgid "Correct texts in selected subtitles" msgstr "Leiðrétta texta í völdum skjátextum" #: gaupol/assistants.py:139 msgid "Correct texts in current project" msgstr "Leiðrétta texta í þessu verkefni" #: gaupol/assistants.py:140 msgid "Correct texts in all open projects" msgstr "Leiðrétta texta í öllum opnum verkefnum" #: gaupol/assistants.py:363 msgid "Other" msgstr "Annað" #: gaupol/assistants.py:439 msgid "Capitalize texts written in lower case" msgstr "Setja lágletraðan texta í hástafi" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:443 msgid "Capitalization Patterns" msgstr "Mynstur við hástafaritun" #: gaupol/assistants.py:445 msgid "Capitalize texts" msgstr "Setja texta í hástafi" #: gaupol/assistants.py:468 msgid "Correct common errors made by humans or image recognition software" msgstr "Leiðrétta algengar villur gerðar af fólki eða ljóslestrarhugbúnaði" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:472 msgid "Common Error Patterns" msgstr "Algeng villumynstur" #: gaupol/assistants.py:474 msgid "Correct common errors" msgstr "Leiðrétta algengar villur" #: gaupol/assistants.py:526 msgid "Remove explanatory texts meant for the hearing impaired" msgstr "Fjarlægja skýringatexta sem ætlaðir eru fyrir heyrnarskerta" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:530 msgid "Hearing Impaired Patterns" msgstr "Mynstur fyrir heyrnarskerta" #: gaupol/assistants.py:532 msgid "Remove hearing impaired texts" msgstr "Fjarlægja texta fyrir heyrnarskerta" #: gaupol/assistants.py:544 msgid "" "Use spell-check suggestions to fix whitespace detection errors of image " "recognition software" msgstr "" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:548 msgid "Joining and Splitting Words" msgstr "Sameining eða skipting orða" #: gaupol/assistants.py:550 msgid "Join or Split Words" msgstr "Sameina eða skipta orðum" #: gaupol/assistants.py:599 gaupol/agents/tools.py:45 msgid "Failed to load dictionary for language \"{}\"" msgstr "Það mistókst að hlaða inn orðasafni fyrir tungumálið \"{}\"" #: gaupol/assistants.py:601 gaupol/player.py:263 gaupol/player.py:381 #: gaupol/dialogs/search.py:560 gaupol/dialogs/search.py:568 #: gaupol/dialogs/text_edit.py:49 gaupol/dialogs/encoding.py:56 #: gaupol/agents/open.py:328 gaupol/agents/open.py:337 #: gaupol/agents/open.py:345 gaupol/agents/open.py:354 #: gaupol/agents/tools.py:48 gaupol/agents/save.py:197 #: gaupol/agents/save.py:205 gaupol/agents/preview.py:108 #: gaupol/agents/preview.py:116 gaupol/agents/preview.py:125 #: gaupol/agents/preview.py:133 msgid "_OK" msgstr "Í _lagi" #: gaupol/assistants.py:635 msgid "Break text into lines of defined length" msgstr "Skipta texta í línur af skilgreindri lengd" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:639 msgid "Line-Break Patterns" msgstr "Mynstur línuskila" #: gaupol/assistants.py:641 msgid "Break lines" msgstr "Skipta línum" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:679 msgid "Line-Break Options" msgstr "Valkostir línuskila" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:763 msgid "Correcting Texts" msgstr "Leiðrétting texta" #: gaupol/assistants.py:769 msgid "Each task is now being run on each project." msgstr "" #: gaupol/assistants.py:793 #, python-brace-format msgid "{current:d} of {total:d} tasks complete" msgstr "{current:d} af {total:d} verkum lokið" #: gaupol/assistants.py:801 msgid "Project: {}" msgstr "Verkefni: {}" #: gaupol/assistants.py:807 msgid "Task: {}" msgstr "Verk: {}" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:832 msgid "Confirm Changes" msgstr "Staðfesta breytingar" #: gaupol/assistants.py:892 msgid "Accept" msgstr "Samþykkja" #: gaupol/assistants.py:898 msgid "Original Text" msgstr "Upprunalegur texti" #: gaupol/assistants.py:899 msgid "Corrected Text" msgstr "Leiðréttur texti" #: gaupol/assistants.py:1048 msgid "Correct Texts" msgstr "Leiðréttir textar" #: gaupol/assistants.py:1076 msgid "Correcting texts" msgstr "Leiðrétting texta" #: gaupol/assistants.py:1092 #, python-brace-format msgid "Edited {edits:d} and removed {removals:d} subtitles" msgstr "Breytti {edits:d} og fjarlægði {removals:d} skjátexta" #: gaupol/assistants.py:1126 msgid "Confirm {:d} Change" msgid_plural "Confirm {:d} Changes" msgstr[0] "Staðfesta {:d} breytingu" msgstr[1] "Staðfesta {:d} breytingar" #: gaupol/renderers/multiline.py:86 msgid "Italic" msgstr "Skáletrað" #: gaupol/player.py:372 msgid "No video streams found" msgstr "" #: gaupol/player.py:379 msgid "Failed to initialize playback" msgstr "Mistókst að ræsa afspilun" #: gaupol/dialogs/search.py:189 data/ui/menubar.ui:524 msgid "_Help" msgstr "_Hjálp" #: gaupol/dialogs/search.py:471 msgid "Found and replaced {:d} occurence" msgid_plural "Found and replaced {:d} occurences" msgstr[0] "Fann og skipti út {:d} tilviki" msgstr[1] "Fann og skipti út {:d} tilvikum" #: gaupol/dialogs/search.py:488 msgid "\"{}\" not found" msgstr "\"{}\" fannst ekki" #: gaupol/dialogs/search.py:558 msgid "Error in regular expression pattern" msgstr "Villa í mynstri reglulegrar segðar" #: gaupol/dialogs/search.py:566 msgid "Error in regular expression replacement" msgstr "Villa í reglulegri segð til útskiptingar" #: gaupol/dialogs/text_edit.py:48 gaupol/dialogs/framerate_convert.py:63 #: gaupol/dialogs/insert.py:44 gaupol/dialogs/encoding.py:55 #: gaupol/dialogs/split.py:44 gaupol/dialogs/multi_close.py:54 #: gaupol/dialogs/open.py:63 gaupol/dialogs/position_transform.py:69 #: gaupol/dialogs/position_shift.py:71 gaupol/dialogs/multi_save.py:83 #: gaupol/dialogs/multi_save.py:215 gaupol/dialogs/duration_adjust.py:86 #: gaupol/dialogs/save.py:73 gaupol/dialogs/video.py:41 #: gaupol/agents/open.py:363 gaupol/agents/open.py:375 #: gaupol/agents/open.py:387 gaupol/agents/close.py:71 #: data/extensions/custom-framerates/custom-framerates.py:39 msgid "_Cancel" msgstr "_Hætta við" #: gaupol/dialogs/text_edit.py:53 msgid "Edit Text" msgstr "Breyta texta" #: gaupol/dialogs/framerate_convert.py:64 msgid "Co_nvert" msgstr "Um_breyta" #: gaupol/dialogs/insert.py:45 msgid "_Insert" msgstr "Setja _inn" #: gaupol/dialogs/insert.py:54 msgid "Above selection" msgstr "Fyrir ofan valið" #: gaupol/dialogs/insert.py:55 msgid "Below selection" msgstr "Fyrir neðan valið" #: gaupol/dialogs/encoding.py:60 data/ui/preferences-dialog.ui:70 msgid "Character Encodings" msgstr "Stafatöflur" #: gaupol/dialogs/encoding.py:78 gaupol/dialogs/encoding.py:125 msgid "Description" msgstr "Lýsing" #: gaupol/dialogs/encoding.py:85 gaupol/dialogs/encoding.py:132 msgid "Encoding" msgstr "Stafatafla" #: gaupol/dialogs/encoding.py:141 msgid "Show in Menu" msgstr "Birta í valmynd" #: gaupol/dialogs/split.py:45 msgid "_Split" msgstr "_Skipta" #: gaupol/dialogs/split.py:76 msgid "Splitting project" msgstr "Skipta upp verkefni" #: gaupol/dialogs/split.py:97 #, python-brace-format msgid "Split {amount:d} subtitles to project \"{name}\"" msgstr "Skipta {amount:d} skjátextum yfir í verkefnið \"{name}\"" #: gaupol/dialogs/spell_check.py:269 msgid "Spell-checking" msgstr "Stafsetningaryfirferð" #: gaupol/dialogs/preferences.py:217 msgid "{} Extension Website" msgstr "Vefsvæði {} viðbótar" #: gaupol/dialogs/preferences.py:429 msgid "Custom" msgstr "Sérsniðið" #: gaupol/dialogs/multi_close.py:38 msgid "Save changes to documents before closing?" msgstr "Vista breytingar á skjölum áður en lokað er?" #: gaupol/dialogs/multi_close.py:39 gaupol/agents/open.py:384 #: gaupol/agents/close.py:68 msgid "If you don't save, changes will be permanently lost." msgstr "Ef þú vistar ekki, tapast allar breytingar endanlega." #: gaupol/dialogs/multi_close.py:53 gaupol/agents/close.py:70 msgid "Close _Without Saving" msgstr "Loka án þess að _vista" #: gaupol/dialogs/multi_close.py:55 gaupol/dialogs/multi_save.py:84 #: gaupol/dialogs/save.py:74 gaupol/agents/open.py:388 #: gaupol/agents/close.py:72 data/ui/menubar.ui:34 msgid "_Save" msgstr "Vi_sta" #: gaupol/dialogs/multi_close.py:70 msgid "Select the _main documents you want to save:" msgstr "Veldu aðals_kjölin sem þú vilt vista:" #: gaupol/dialogs/multi_close.py:95 msgid "Select the _translation documents you want to save:" msgstr "Vel_du þýðingarskjölin sem þú vilt vista:" #: gaupol/dialogs/open.py:64 gaupol/agents/open.py:364 #: gaupol/agents/open.py:376 msgid "_Open" msgstr "_Opna" #: gaupol/dialogs/position_transform.py:70 msgid "_Transform" msgstr "_Ummynda" #: gaupol/dialogs/position_shift.py:72 msgid "_Shift" msgstr "_Hliðra" #: gaupol/dialogs/position_shift.py:150 msgid "frames" msgstr "rammar" #: gaupol/dialogs/position_shift.py:168 data/ui/preferences-dialog.ui:911 msgid "seconds" msgstr "sekúndur" #: gaupol/dialogs/about.py:36 msgid "About Gaupol" msgstr "Um Gaupol" #: gaupol/dialogs/about.py:40 msgid "Subtitle editor" msgstr "Skjátextaritill" #. TRANSLATORS: This is a special message that shouldn't be translated #. literally. It is used in the about dialog to give credits to the #. translators. Thus, you should translate it to your name and email #. address. You can also include other translators who have contributed #. to this translation; in that case, please write them on separate #. lines seperated by newlines (\n). #: gaupol/dialogs/about.py:51 msgid "translator-credits" msgstr "Sveinn í Felli 2016, sv1@fellsnet.is" #: gaupol/dialogs/about.py:54 msgid "Gaupol Website" msgstr "Vefsvæði Gaupol" #: gaupol/dialogs/append.py:35 msgid "Append File" msgstr "Bæta við skrá" #: gaupol/dialogs/debug.py:43 msgid "Something went wrong" msgstr "Úbbs! Eitthvað fór úrskeiðis" #: gaupol/dialogs/debug.py:44 msgid "" "You have probably discovered a bug. Please report it by providing the below " "information and a description of what you were doing." msgstr "" "Þú hefur líklega rekist á villu. Endilega tilkynntu um hana og láttu þá " "fylgja með upplýsingarnar hér fyrir neðan ásamt stuttri lýsingu á því sem þú" " varst að gera þegar hún kom upp." #: gaupol/dialogs/debug.py:52 msgid "_Report Bug" msgstr "Til_kynna um villu" #: gaupol/dialogs/debug.py:53 data/ui/menubar.ui:56 msgid "_Quit" msgstr "_Hætta" #: gaupol/dialogs/debug.py:54 gaupol/dialogs/preview_error.py:45 #: data/ui/menubar.ui:52 data/ui/tab-popup.ui:16 msgid "_Close" msgstr "_Loka" #: gaupol/dialogs/multi_save.py:98 gaupol/dialogs/save.py:110 msgid "{} (recommended)" msgstr "{} (mælt með)" #: gaupol/dialogs/multi_save.py:212 msgid "" "{:d} of the files to be saved already exist. Do you want to replace them?" msgstr "" "{:d} af skjölunum sem á að vista eru þegar til staðar. Viltu skipta þeim út?" #: gaupol/dialogs/multi_save.py:213 msgid "" "The files already exist in \"{}\". Replacing them will overwrite their " "contents." msgstr "" "Þessar skrár eru þegar til í \"{}\". Verði þeim skipt út verður skrifað yfir" " innihald þeirra." #: gaupol/dialogs/multi_save.py:216 data/ui/search-dialog.ui:192 #: data/ui/spell-check-dialog.ui:122 msgid "_Replace" msgstr "_Skipta út" #: gaupol/dialogs/duration_adjust.py:70 msgid "Adjusted duration of {:d} subtitle" msgid_plural "Adjusted durations of {:d} subtitles" msgstr[0] "Aðlagaði tímalengd {:d} skjátexta" msgstr[1] "Aðlagaði tímalengdir {:d} skjátexta" #: gaupol/dialogs/duration_adjust.py:87 msgid "_Adjust" msgstr "_Aðlaga" #: gaupol/dialogs/preview_error.py:36 msgid "Preview in video player failed" msgstr "Forskoðun í myndspilara mistókst" #: gaupol/dialogs/preview_error.py:37 msgid "" "There is probably a problem with either the video file or the video player. " "See the preferences dialog to choose the video player or to customize the " "command." msgstr "" #: gaupol/dialogs/language.py:97 msgid "Set Language" msgstr "Stilla tungumál" #: gaupol/dialogs/video.py:52 gaupol/dialogs/file.py:59 msgid "All files" msgstr "Allar skrár" #: gaupol/dialogs/video.py:56 msgid "Video files" msgstr "Myndskeiðasskrár" #: gaupol/dialogs/file.py:63 msgid "All supported files" msgstr "Allar studdar skrár" #: gaupol/dialogs/file.py:77 #, python-brace-format msgid "{format} (*{extension})" msgstr "{format} (*{extension})" #: gaupol/dialogs/file.py:120 msgid "Auto-detected" msgstr "Sjálfuppgötvað" #: gaupol/dialogs/file.py:122 msgid "Other…" msgstr "Annað…" #: gaupol/agents/menu.py:94 gaupol/agents/menu.py:103 #: gaupol/agents/menu.py:110 msgid "File not found" msgstr "" #: gaupol/agents/open.py:85 #, python-brace-format msgid "Appended {amount:d} subtitles from \"{basename}\"" msgstr "Bætti við {amount:d} skjátextum úr \"{basename}\"" #: gaupol/agents/open.py:96 msgid "Appending file" msgstr "Viðbæting skráar" #: gaupol/agents/open.py:111 msgid "File \"{}\" is already open" msgstr "Skráin \"{}\" er þegar opin" #: gaupol/agents/open.py:214 msgid "Open Translation" msgstr "Opna þýðingu" #: gaupol/agents/open.py:223 msgid "Select Video" msgstr "Veldu myndskeið" #: gaupol/agents/open.py:224 msgid "_Select" msgstr "_Velja" #: gaupol/agents/open.py:325 msgid "Failed to decode file \"{}\" with all attempted codecs" msgstr "" "Mistókst að afkóða skrána \"{}\" með öllum þeim stafatöflum sem prófaðar " "voru" #: gaupol/agents/open.py:326 msgid "Please try to open the file with a different character encoding." msgstr "Prófaðu að opna skrána með annarri stafatöflu." #: gaupol/agents/open.py:334 msgid "Failed to recognize format of file \"{}\"" msgstr "Þekki ekki snið skrárinnar \"{}\"" #: gaupol/agents/open.py:335 msgid "" "Please check that the file you are trying to open is a subtitle file of a " "format supported by Gaupol." msgstr "" "Athugaðu hvort að skráin sem þú ert að reyna að opna sé skjátextaskrá á " "sniði sem Gaupol styður." #: gaupol/agents/open.py:343 msgid "Failed to open file \"{}\"" msgstr "Mistókst að opna skrá \"{}\"" #: gaupol/agents/open.py:351 msgid "Failed to parse file \"{}\"" msgstr "Mistókst að þátta skrána \"{}\"" #: gaupol/agents/open.py:352 msgid "Please check that the file you are trying to open is a valid {} file." msgstr "Athugaðu hvort að skráin sem þú ert að reyna að opna sé gild \"{}\" skrá." #: gaupol/agents/open.py:360 msgid "Open abnormally large file \"{}\"?" msgstr "Opna óeðlilega stóra skrá \"{}\"?" #: gaupol/agents/open.py:361 msgid "" "Size of the file is {:.1f} MB, which is abnormally large for a text-based " "subtitle file. Please, check that you are not trying to open a binary file." msgstr "" "Stærð skrárinnar er {:.1f} MB, sem er óeðlilega stórt fyrir textaskrá með " "skjátextum. Athugaðu hvort þú sért nokkuð að reyna að opna tvíundakerfisskrá" " (binary)." #: gaupol/agents/open.py:371 msgid "Open unsorted file \"{}\"?" msgstr "Opna óraðaða skrá \"{}\"?" #: gaupol/agents/open.py:372 msgid "" "The order of {:d} subtitles needs to be changed. If {:d} sounds like a lot, " "the file may be erroneously composed." msgstr "" #: gaupol/agents/open.py:383 msgid "Save changes to translation document \"{}\" before opening a new one?" msgstr "Vista breytingar á þýðingarskrá \"{}\" áður en ný er opnuð?" #: gaupol/agents/open.py:386 msgid "Open _Without Saving" msgstr "Opna án þess að _vista" #: gaupol/agents/close.py:66 msgid "Save changes to document \"{}\" before closing?" msgstr "Viltu vista breytingar á skjalinu “{}“ áður en þú lokar því?" #: gaupol/agents/edit.py:101 gaupol/agents/edit.py:119 msgid "Stretching end position" msgstr "Teygi endastöðu" #: gaupol/agents/edit.py:208 msgid "Inserted {:d} subtitle to fit clipboard contents" msgid_plural "Inserted {:d} subtitles to fit clipboard contents" msgstr[0] "" msgstr[1] "" #: gaupol/agents/edit.py:334 gaupol/agents/edit.py:352 msgid "Stretching start position" msgstr "Teygi upphafsstöðu" #: gaupol/agents/edit.py:411 msgid "Use Shift+Return for line-break" msgstr "Notaðu Shift+Enter fyrir línuskil" #: gaupol/agents/save.py:129 msgid "Save As" msgstr "Vista sem" #: gaupol/agents/save.py:135 msgid "Saved main document as \"{}\"" msgstr "Vistaði aðalskjal sem \"{}\"" #: gaupol/agents/save.py:153 msgid "Save Translation As" msgstr "Vista þýðingu sem" #: gaupol/agents/save.py:159 msgid "Saved translation document as \"{}\"" msgstr "Vistaði þýðingarskjal sem \"{}\"" #: gaupol/agents/save.py:194 #, python-brace-format msgid "Failed to encode file \"{basename}\" with codec \"{codec}\"" msgstr "Mistókst að kóða skrána \"{basename}\" með stafatöfluni \"{codec}\"" #: gaupol/agents/save.py:195 msgid "Please try to save the file with a different character encoding." msgstr "Prófaðu að vista skrána með annarri stafatöflu." #: gaupol/agents/save.py:203 msgid "Failed to save file \"{}\"" msgstr "Tókst ekki að vista skrá \"{}\"" #: gaupol/agents/video.py:67 data/ui/menubar.ui:380 msgid "_Play/Pause" msgstr "S_pila/stöðva" #: gaupol/agents/video.py:69 msgid "Play or pause video" msgstr "Spila eða setja myndskeið í bið" #: gaupol/agents/video.py:75 data/ui/menubar.ui:390 msgid "Seek _Previous" msgstr "Leita að f_yrra" #: gaupol/agents/video.py:77 msgid "Seek to the start of the previous subtitle" msgstr "Fara í byrjun fyrri skjátexta" #: gaupol/agents/video.py:81 data/ui/menubar.ui:394 msgid "Seek _Next" msgstr "Leita að _næsta" #: gaupol/agents/video.py:83 msgid "Seek to the start of the next subtitle" msgstr "Fara í byrjun næsta skjátexta" #: gaupol/agents/video.py:88 data/ui/menubar.ui:400 msgid "Seek _Backward" msgstr "Leita afturá_bak" #: gaupol/agents/video.py:90 msgid "Seek backward" msgstr "Leita afturábak" #: gaupol/agents/video.py:94 data/ui/menubar.ui:404 msgid "Seek _Forward" msgstr "Leita á_fram" #: gaupol/agents/video.py:96 msgid "Seek forward" msgstr "Leita áfram" #: gaupol/agents/video.py:109 msgid "Volume" msgstr "Hljóðstyrkur" #: gaupol/agents/video.py:189 msgid "Load Video" msgstr "Hlaða inn myndskeiði" #: gaupol/agents/video.py:189 msgid "_Load" msgstr "_Hlaða inn" #: gaupol/agents/video.py:361 msgid "Track {:d}" msgstr "" #: gaupol/agents/preview.py:105 msgid "Failed to encode subtitle file to temporary directory \"{}\"" msgstr "Mistókst að kóða skjátextaskrána í bráðabirgðamöppuna \"{}\"" #: gaupol/agents/preview.py:106 msgid "" "Subtitle data could not be encoded to a temporary file for preview with the " "current character encoding. Please first save the subtitle file with a " "different character encoding." msgstr "" #: gaupol/agents/preview.py:114 msgid "Failed to save subtitle file to temporary directory \"{}\"" msgstr "Mistókst að vista skjátextaskrána í bráðabirgðamöppuna \"{}\"" #: gaupol/agents/preview.py:122 msgid "Video player not found" msgstr "" #: gaupol/agents/preview.py:123 msgid "" "Please install one of the supported video players: mpv (recommended), " "MPlayer or VLC. See the preferences dialog to choose the video player or to " "customize the command." msgstr "" #: gaupol/agents/preview.py:131 msgid "Failed to launch video player" msgstr "Mistókst að ræsa myndspilara" #: gaupol/applicationman.py:105 msgid "gaupol [OPTION...] [FILE...] [+[NUM]]" msgstr "gaupol [ROFI...] [SKRÁ...] [+[NUM]]" #: gaupol/applicationman.py:109 msgid "FILE..." msgstr "SKRÁ..." #: gaupol/applicationman.py:112 msgid "subtitle files to open" msgstr "skjátextaskrár sem á að opna" #: gaupol/applicationman.py:122 msgid "ENCODING" msgstr "STAFATAFLA" #: gaupol/applicationman.py:125 msgid "set the character encoding used to open files" msgstr "veldu stafatöflu sem á að nota við að opna skrár" #: gaupol/applicationman.py:132 msgid "list all available character encodings" msgstr "telja upp allar tiltækar stafatöflur" #: gaupol/applicationman.py:137 gaupol/applicationman.py:154 msgid "FILE" msgstr "SKRÁ" #: gaupol/applicationman.py:140 msgid "open translation file" msgstr "opna þýðingarskrá" #: gaupol/applicationman.py:145 msgid "METHOD" msgstr "AÐFERÐ" #: gaupol/applicationman.py:149 msgid "method used to align translation subtitles: 'number' or 'position'" msgstr "" #: gaupol/applicationman.py:157 msgid "select video file" msgstr "veldu myndskeiðaskrá" #: data/extensions/custom-framerates/custom-framerates.py:40 #: data/ui/spell-check-dialog.ui:152 msgid "_Add" msgstr "Bæt_a við" #: data/extensions/custom-framerates/custom-framerates.py:171 msgid "{:.3f} fps" msgstr "{:.3f} r/sek" #: data/extensions/custom-framerates/add-framerate-dialog.ui:13 msgid "Add Framerate" msgstr "Setja inn rammatíðni" #: data/extensions/custom-framerates/add-framerate-dialog.ui:44 msgid "_Framerate:" msgstr "_Rammatíðni:" #: data/extensions/custom-framerates/add-framerate-dialog.ui:73 msgid "fps" msgstr "r/sek" #: data/extensions/custom-framerates/preferences-dialog.ui:8 msgid "Framerates" msgstr "Rammatíðnir" #: data/extensions/custom-framerates/preferences-dialog.ui:64 msgid "Add" msgstr "Bæta við" #: data/ui/columns-popup.ui:6 data/ui/menubar.ui:275 msgid "_No." msgstr "_Nr." #: data/ui/columns-popup.ui:10 data/ui/menubar.ui:279 msgid "_Start" msgstr "U_pphaf" #: data/ui/columns-popup.ui:14 data/ui/menubar.ui:283 msgid "_End" msgstr "_Endir" #: data/ui/columns-popup.ui:18 data/ui/menubar.ui:287 msgid "_Duration" msgstr "Tímalen_gd" #: data/ui/columns-popup.ui:22 data/ui/menubar.ui:291 data/ui/menubar.ui:303 msgid "_Text" msgstr "_Texti" #: data/ui/columns-popup.ui:26 data/ui/menubar.ui:295 msgid "T_ranslation" msgstr "Þýðin_g" #: data/ui/split-dialog.ui:15 msgid "Split Project" msgstr "Skipta upp verkefni" #: data/ui/split-dialog.ui:48 msgid "_First subtitle of new project:" msgstr "_Fyrsti skjátexti nýs verkefnis:" #: data/ui/search-dialog.ui:89 msgid "_Search for:" msgstr "_Leita að:" #: data/ui/search-dialog.ui:103 data/ui/spell-check-dialog.ui:193 msgid "Replace _with:" msgstr "Skipta út _með: " #: data/ui/search-dialog.ui:162 data/ui/menubar.ui:328 msgid "Find _Next" msgstr "Finna _næsta" #: data/ui/search-dialog.ui:177 msgid "Find _Previous" msgstr "Finna f_yrri" #: data/ui/search-dialog.ui:207 msgid "Replace _All" msgstr "Skipt_a út öllu" #: data/ui/search-dialog.ui:241 msgid "R_egular expression" msgstr "Re_gluleg segð" #: data/ui/search-dialog.ui:258 msgid "_Ignore case" msgstr "_Hunsa há/lágstafi" #: data/ui/search-dialog.ui:304 data/ui/language-dialog.ui:108 msgid "Columns" msgstr "Dálkar" #: data/ui/search-dialog.ui:324 msgid "Find in _text column" msgstr "Finna í _textadálki" #: data/ui/search-dialog.ui:341 msgid "Find in t_ranslation column" msgstr "Finna í þýðinga_rdálki" #: data/ui/search-dialog.ui:381 data/ui/framerate-convert-dialog.ui:144 #: data/ui/language-dialog.ui:186 #: data/ui/text-assistant/line-break-options-page.ui:178 #: data/ui/duration-adjust-dialog.ui:388 data/ui/position-shift-dialog.ui:180 #: data/ui/position-transform-dialog.ui:444 msgid "Subtitles" msgstr "Skjátextar" #: data/ui/search-dialog.ui:401 msgid "Find in c_urrent project" msgstr "Finna í þess_u verkefni" #: data/ui/search-dialog.ui:419 msgid "Find in _all open projects" msgstr "Finn_a í öllum opnum verkefnum" #: data/ui/search-dialog.ui:452 msgid "Target" msgstr "Útkoma" #: data/ui/framerate-convert-dialog.ui:8 msgid "Convert Framerate" msgstr "Umbreyta rammatíðni" #: data/ui/framerate-convert-dialog.ui:48 msgid "Framerate" msgstr "Rammatíðni" #: data/ui/framerate-convert-dialog.ui:71 msgid "_Input:" msgstr "_Inntak:" #: data/ui/framerate-convert-dialog.ui:86 msgid "_Output:" msgstr "Útta_k:" #: data/ui/framerate-convert-dialog.ui:164 msgid "Convert c_urrent project" msgstr "_Umbreyta þessu verkefni" #: data/ui/framerate-convert-dialog.ui:181 msgid "Convert _all open projects" msgstr "Umbreyt_a öllum opnum verkefnum" #: data/ui/spell-check-dialog.ui:8 msgid "Check Spelling" msgstr "Athuga stafsetningu" #: data/ui/spell-check-dialog.ui:47 msgid "Join _Back" msgstr "Sameina til _baka" #: data/ui/spell-check-dialog.ui:62 msgid "Join _Forward" msgstr "Sameina á_fram" #: data/ui/spell-check-dialog.ui:77 data/ui/menubar.ui:62 msgid "_Edit" msgstr "Br_eyta" #: data/ui/spell-check-dialog.ui:92 msgid "_Ignore" msgstr "_Hunsa" #: data/ui/spell-check-dialog.ui:107 msgid "Ig_nore All" msgstr "Hunsa _allt" #: data/ui/spell-check-dialog.ui:137 msgid "Rep_lace All" msgstr "S_kipta út öllu" #: data/ui/spell-check-dialog.ui:179 msgid "_Suggestions:" msgstr "_Uppástungur:" #: data/ui/multi-save-dialog.ui:8 msgid "Save All As" msgstr "Vista allt sem" #: data/ui/multi-save-dialog.ui:46 msgid "Save in _folder:" msgstr "Vista í _möppu:" #: data/ui/multi-save-dialog.ui:60 data/ui/save-dialog.ui:25 msgid "For_mat:" msgstr "S_nið:" #: data/ui/multi-save-dialog.ui:74 data/ui/open-dialog.ui:25 #: data/ui/save-dialog.ui:39 msgid "_Encoding:" msgstr "St_afatafla:" #: data/ui/multi-save-dialog.ui:88 data/ui/save-dialog.ui:53 msgid "Ne_wlines:" msgstr "Ný_línumerki:" #: data/ui/multi-save-dialog.ui:103 msgid "Select A Folder" msgstr "Veldu möppu" #: data/ui/multi-save-dialog.ui:150 data/ui/save-dialog.ui:102 msgid "F_ramerate:" msgstr "_Rammatíðni:" #: data/ui/menubar.ui:5 msgid "_File" msgstr "_Skrá" #: data/ui/menubar.ui:8 msgid "_New" msgstr "_Nýtt" #: data/ui/menubar.ui:12 msgid "_Open…" msgstr "_Opna…" #: data/ui/menubar.ui:16 msgid "Open _Translation…" msgstr "Op_na þýðingu…" #: data/ui/menubar.ui:22 msgid "Open _Recent" msgstr "O_pna nýlegt" #: data/ui/menubar.ui:27 msgid "Open R_ecent Translation" msgstr "Opn_a nýlega þýðingu" #: data/ui/menubar.ui:38 msgid "Save _As…" msgstr "Vist_a sem..." #: data/ui/menubar.ui:42 msgid "Save Trans_lation" msgstr "Vista þýðin_gu" #: data/ui/menubar.ui:46 msgid "Save Translat_ion As…" msgstr "V_ista þýðingu sem…" #: data/ui/menubar.ui:65 msgid "_Undo" msgstr "_Afturkalla" #: data/ui/menubar.ui:69 msgid "_Redo" msgstr "Endu_rtaka" #: data/ui/menubar.ui:75 msgid "_Edit Cell" msgstr "Br_eyta reit" #: data/ui/menubar.ui:79 msgid "Edit _Next Cell" msgstr "Breyta _næsta reit" #: data/ui/menubar.ui:85 msgid "Stretc_h" msgstr "Tey_gja" #: data/ui/menubar.ui:88 msgid "_Start Earlier" msgstr "_Byrja fyrr" #: data/ui/menubar.ui:92 msgid "S_tart Later" msgstr "B_yrja síðar" #: data/ui/menubar.ui:98 msgid "E_nd Earlier" msgstr "E_nda fyrr" #: data/ui/menubar.ui:102 msgid "En_d Later" msgstr "En_da síðar" #: data/ui/menubar.ui:108 msgid "Set St_art From Video Position" msgstr "" #: data/ui/menubar.ui:112 msgid "Set En_d From Video Position" msgstr "Setja en_da út frá stað í myndskeiði" #: data/ui/menubar.ui:118 data/ui/view-popup.ui:6 msgid "_Split Subtitle" msgstr "_Skipta upp skjátexta" #: data/ui/menubar.ui:122 data/ui/view-popup.ui:10 msgid "_Merge Subtitles" msgstr "Sa_meina skjátexta" #: data/ui/menubar.ui:128 data/ui/view-popup.ui:16 msgid "_Insert Subtitles…" msgstr "Setja _inn skjátexta…" #: data/ui/menubar.ui:132 msgid "Inser_t Subtitle At Video Position" msgstr "Se_tja inn skjátexta á stað í myndskeiði" #: data/ui/menubar.ui:136 data/ui/view-popup.ui:20 msgid "Rem_ove Subtitles" msgstr "F_jarlægja skjátexta" #: data/ui/menubar.ui:142 msgid "Sele_ction" msgstr "_Valið" #: data/ui/menubar.ui:145 msgid "Select _All" msgstr "Velja _allt" #: data/ui/menubar.ui:149 msgid "_Invert Selection" msgstr "_Umhverfa vali" #: data/ui/menubar.ui:155 msgid "Extend To _Beginning" msgstr "Fram_lengja að upphafi" #: data/ui/menubar.ui:159 msgid "Extend To _End" msgstr "Framlengja til _enda" #: data/ui/menubar.ui:165 msgid "_Previous From Video Position" msgstr "" #: data/ui/menubar.ui:169 msgid "_Next From Video Position" msgstr "" #: data/ui/menubar.ui:177 msgid "_Preferences" msgstr "_Kjörstillingar" #: data/ui/menubar.ui:183 msgid "_View" msgstr "S_koða" #: data/ui/menubar.ui:186 msgid "Tool_bar" msgstr "_Verkfærastika" #: data/ui/menubar.ui:190 msgid "_Video Player" msgstr "M_yndskeiðaspilari" #: data/ui/menubar.ui:196 msgid "_Layout" msgstr "_Framsetning" #: data/ui/menubar.ui:199 msgid "_Horizontal" msgstr "_Lárétt" #: data/ui/menubar.ui:204 msgid "_Vertical" msgstr "Lóð_rétt" #: data/ui/menubar.ui:213 msgid "_Times" msgstr "_Tími" #: data/ui/menubar.ui:218 msgid "_Frames" msgstr "_Rammar:" #: data/ui/menubar.ui:225 msgid "F_ramerate" msgstr "_Rammatíðni" #: data/ui/menubar.ui:228 msgid "2_3.976 fps" msgstr "2_3.976 r/sek" #: data/ui/menubar.ui:233 msgid "2_4.000 fps" msgstr "2_4.000 r/sek" #: data/ui/menubar.ui:238 msgid "2_5.000 fps" msgstr "2_5.000 r/sek" #: data/ui/menubar.ui:243 msgid "2_9.970 fps" msgstr "2_9.970 r/sek" #: data/ui/menubar.ui:272 msgid "_Columns" msgstr "_Dálkar" #: data/ui/menubar.ui:306 msgid "Cu_t" msgstr "_Klippa" #: data/ui/menubar.ui:310 msgid "_Copy" msgstr "_Afrita" #: data/ui/menubar.ui:314 msgid "_Paste" msgstr "_Líma" #: data/ui/menubar.ui:318 msgid "Cl_ear" msgstr "Hr_einsa" #: data/ui/menubar.ui:324 msgid "_Find And Replace…" msgstr "_Finna og skipta út…" #: data/ui/menubar.ui:332 msgid "Find Pre_vious" msgstr "Finna f_yrri" #: data/ui/menubar.ui:338 msgid "_Italic" msgstr "_Skáletrað" #: data/ui/menubar.ui:342 msgid "_Dialogue" msgstr "Samskipta_gluggi" #: data/ui/menubar.ui:348 msgid "Ca_se" msgstr "_Stafstaða" #: data/ui/menubar.ui:351 msgid "_Title" msgstr "_Fremst í orðum" #: data/ui/menubar.ui:355 msgid "_Sentence" msgstr "_Byrja setningu á hástaf" #: data/ui/menubar.ui:359 msgid "_Upper" msgstr "_Hástafir" #: data/ui/menubar.ui:363 msgid "_Lower" msgstr "_Lágstafir" #: data/ui/menubar.ui:371 msgid "Vi_deo" msgstr "_Myndskeið" #: data/ui/menubar.ui:374 msgid "_Load Video…" msgstr "H_laða inn myndskeiði..." #: data/ui/menubar.ui:384 data/ui/view-popup.ui:26 msgid "Play _Selection" msgstr "_Spila valið" #: data/ui/menubar.ui:410 data/ui/view-popup.ui:30 msgid "S_eek Selection Start" msgstr "L_eita að upphafi vals" #: data/ui/menubar.ui:414 msgid "See_k Selection End" msgstr "Leita að en_da vals" #: data/ui/menubar.ui:420 msgid "_Audio" msgstr "_Hljóð" #: data/ui/menubar.ui:423 msgid "_Language" msgstr "Tungumá_l" #: data/ui/menubar.ui:430 msgid "Volume _Down" msgstr "_Lækka hljóðstyrk" #: data/ui/menubar.ui:434 msgid "Volume _Up" msgstr "_Hækka hljóðstyrk" #: data/ui/menubar.ui:440 msgid "T_ools" msgstr "Verk_færi" #: data/ui/menubar.ui:443 data/ui/text-assistant/confirmation-page.ui:97 #: data/ui/view-popup.ui:36 msgid "_Preview" msgstr "_Forskoðun" #: data/ui/menubar.ui:447 msgid "Select _Video…" msgstr "_Veldu myndskeið..." #: data/ui/menubar.ui:453 msgid "_Check Spelling" msgstr "_Athuga stafsetningu" #: data/ui/menubar.ui:457 msgid "Co_nfigure Spell-check…" msgstr "Stilla sta_fsetningaryfirferð…" #: data/ui/menubar.ui:461 msgid "C_orrect Texts…" msgstr "Le_iðrétta texta..." #: data/ui/menubar.ui:467 msgid "_Shift Positions…" msgstr "Hliðra _staðsetningum..." #: data/ui/menubar.ui:471 msgid "_Transform Positions…" msgstr "_Umbreyta staðsetningum..." #: data/ui/menubar.ui:475 msgid "Adjust _Durations…" msgstr "Aðla_ga tímalengdir…" #: data/ui/menubar.ui:479 msgid "Convert _Framerate…" msgstr "Um_breyta rammatíðni…" #: data/ui/menubar.ui:485 msgid "_Append File…" msgstr "_Bæta við skrá…" #: data/ui/menubar.ui:489 msgid "Spli_t Project…" msgstr "Skip_ta upp verkefni…" #: data/ui/menubar.ui:495 msgid "_Projects" msgstr "_Verkefni" #: data/ui/menubar.ui:498 msgid "_Save All" msgstr "Vi_sta allt" #: data/ui/menubar.ui:502 msgid "Save _All As…" msgstr "Vista _allt sem…" #: data/ui/menubar.ui:506 msgid "_Close All" msgstr "_Loka öllu" #: data/ui/menubar.ui:512 msgid "_Previous" msgstr "_Fyrra" #: data/ui/menubar.ui:516 msgid "_Next" msgstr "_Næsta" #: data/ui/menubar.ui:527 msgid "_Documentation" msgstr "_Hjálparskjöl" #: data/ui/menubar.ui:531 msgid "_Report A Bug" msgstr "Til_kynna um villu" #: data/ui/menubar.ui:535 msgid "_About" msgstr "_Um hugbúnaðinn" #: data/ui/open-dialog.ui:39 msgid "Align _method:" msgstr "_Aðferð við jöfnun:" #: data/ui/preferences-dialog.ui:18 msgid "Preferences" msgstr "Kjörstillingar" #: data/ui/preferences-dialog.ui:93 msgid "When opening files, try encodings in the following order:" msgstr "Þegar skrár eru opnaðar, prófa stafatöflur í eftirfarandi röð:" #: data/ui/preferences-dialog.ui:104 msgid "Curr_ent locale encoding" msgstr "St_afatöflu núverandi staðfærslu" #: data/ui/preferences-dialog.ui:130 msgid "_Fallback encodings:" msgstr "Stafatö_flur til vara:" #: data/ui/preferences-dialog.ui:246 msgid "Aut_o-detection" msgstr "Sjálfvirk _greining" #: data/ui/preferences-dialog.ui:266 msgid "Encoding specified in the open dialog will always be tried first." msgstr "" #: data/ui/preferences-dialog.ui:296 msgid "File" msgstr "Skrá" #: data/ui/preferences-dialog.ui:324 msgid "Font" msgstr "Letur" #: data/ui/preferences-dialog.ui:344 msgid "Use _default theme fixed width font" msgstr "Nota _jafnbreitt letur úr sjálfgefnu þema" #: data/ui/preferences-dialog.ui:368 msgid "_Editor font:" msgstr "L_eturgerð ritils:" #: data/ui/preferences-dialog.ui:425 msgid "Line Lengths" msgstr "Lengdir lína" #: data/ui/preferences-dialog.ui:445 msgid "_Show line lengths in list cells" msgstr "_Birta lengdir lína í listareitum" #: data/ui/preferences-dialog.ui:462 msgid "S_how line lengths in editable text fields" msgstr "B_irta lengdir lína í breytanlegum textareitum" #: data/ui/preferences-dialog.ui:486 msgid "_Length unit:" msgstr "_Lengdareining:" #: data/ui/preferences-dialog.ui:540 msgid "Spell-Check" msgstr "Stafsetningaryfirferð" #: data/ui/preferences-dialog.ui:560 msgid "Chec_k spelling as you type" msgstr "Kanna stafsetningu jafnóðum" #: data/ui/preferences-dialog.ui:598 msgid "Editor" msgstr "Ritill" #: data/ui/preferences-dialog.ui:626 msgid "Fonts" msgstr "Leturgerðir" #: data/ui/preferences-dialog.ui:649 msgid "_Subtitles:" msgstr "_Skjátextar:" #: data/ui/preferences-dialog.ui:679 msgid "_Time:" msgstr "_Tími:" #: data/ui/preferences-dialog.ui:729 msgid "Colors" msgstr "Litir" #: data/ui/preferences-dialog.ui:752 msgid "Su_btitles:" msgstr "Skját_extar:" #: data/ui/preferences-dialog.ui:777 msgid "_Use a background behind text" msgstr "N_ota bakgrunnsfyllingu aftan við texta" #: data/ui/preferences-dialog.ui:797 msgid "Ti_me:" msgstr "Tí_mi:" #: data/ui/preferences-dialog.ui:822 msgid "Us_e a background behind text" msgstr "Not_a bakgrunnsfyllingu fyrir framan texta" #: data/ui/preferences-dialog.ui:862 msgid "Seek" msgstr "Leita" #: data/ui/preferences-dialog.ui:883 msgid "_Length:" msgstr "_Lengd:" #: data/ui/preferences-dialog.ui:971 msgid "Video Player" msgstr "Myndskeiðaspilari" #: data/ui/preferences-dialog.ui:994 msgid "_Application:" msgstr "_Forrit" #: data/ui/preferences-dialog.ui:1008 msgid "Co_mmand:" msgstr "Ski_pun:" #. Translators: Only the title is to be translated, field names not. #: data/ui/preferences-dialog.ui:1033 msgid "" "Fields:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" msgstr "" "Gagnasvið:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" #: data/ui/preferences-dialog.ui:1048 msgid "Al_ways use UTF-8 character encoding" msgstr "Alltaf nota UTF-_8 stafatöflu" #: data/ui/preferences-dialog.ui:1089 msgid "Start Position" msgstr "Upphafsstaða" #: data/ui/preferences-dialog.ui:1111 msgid "_Offset:" msgstr "_Hliðrun:" #: data/ui/preferences-dialog.ui:1142 msgid "seconds before selection" msgstr "sekúndur á undan vali" #: data/ui/preferences-dialog.ui:1281 msgid "Extensions" msgstr "Viðbætur" #: data/ui/language-dialog.ui:8 msgid "Configure Spell-Check" msgstr "Stilla stafsetningaryfirferð" #: data/ui/language-dialog.ui:50 msgid "Language" msgstr "Tungumál" #: data/ui/language-dialog.ui:128 msgid "Check _text column" msgstr "Yfirfara _textadálk" #: data/ui/language-dialog.ui:146 msgid "Check t_ranslation column" msgstr "Yfirfara þýðinga_rdálk" #: data/ui/language-dialog.ui:206 msgid "Check c_urrent project" msgstr "_Yfirfara þetta verkefni" #: data/ui/language-dialog.ui:224 msgid "Check _all open projects" msgstr "Yfirf_ara öll opin verkefni" #: data/ui/text-assistant/confirmation-page.ui:22 msgid "Acc_ept, discard or edit changes:" msgstr "Samþykkja, h_enda eða laga breytingar:" #: data/ui/text-assistant/confirmation-page.ui:67 msgid "_Mark All" msgstr "_Merkja allt" #: data/ui/text-assistant/confirmation-page.ui:82 msgid "_Unmark All" msgstr "A_fmerkja allt" #: data/ui/text-assistant/confirmation-page.ui:119 msgid "_Remove all blank subtitles" msgstr "Fja_rlægja alla auða skjátexta" #: data/ui/text-assistant/join-split-page.ui:28 msgid "Spell-Check Dictionary" msgstr "Stafsetningarorðasafn" #: data/ui/text-assistant/join-split-page.ui:49 #: data/ui/text-assistant/line-break-page.ui:81 #: data/ui/text-assistant/hearing-impaired-page.ui:81 #: data/ui/text-assistant/common-error-page.ui:80 #: data/ui/text-assistant/capitalization-page.ui:80 msgid "_Language:" msgstr "Tungumá_l:" #: data/ui/text-assistant/join-split-page.ui:97 msgid "Corrections" msgstr "Leiðréttingar" #: data/ui/text-assistant/join-split-page.ui:117 msgid "_Join words not found in spell-check dictionary" msgstr "Sameina _orð sem ekki finnast í stafsetningarorðasafni" #: data/ui/text-assistant/join-split-page.ui:134 msgid "_Split words not found in spell-check dictionary" msgstr "_Skipta upp orðum sem ekki finnast í stafsetningarorðasafni" #: data/ui/text-assistant/line-break-page.ui:22 msgid "S_elect preferred line-break points:" msgstr "" #: data/ui/text-assistant/line-break-page.ui:67 #: data/ui/text-assistant/hearing-impaired-page.ui:67 #: data/ui/text-assistant/common-error-page.ui:66 #: data/ui/text-assistant/capitalization-page.ui:66 msgid "_Script:" msgstr "_Ritun:" #: data/ui/text-assistant/line-break-page.ui:95 #: data/ui/text-assistant/hearing-impaired-page.ui:95 #: data/ui/text-assistant/common-error-page.ui:94 #: data/ui/text-assistant/capitalization-page.ui:94 msgid "Co_untry:" msgstr "_Land:" #: data/ui/text-assistant/introduction-page.ui:28 msgid "_Select corrections to perform on texts:" msgstr "_Veldu þær leiðréttingar sem á að beita á texta:" #: data/ui/text-assistant/introduction-page.ui:79 msgid "Colu_mns:" msgstr "_Dálkar:" #: data/ui/text-assistant/introduction-page.ui:93 msgid "S_ubtitles:" msgstr "S_kjátextar:" #: data/ui/text-assistant/line-break-options-page.ui:56 #: data/ui/duration-adjust-dialog.ui:207 msgid "Limits" msgstr "Takmörk" #: data/ui/text-assistant/line-break-options-page.ui:79 msgid "_Maximum line length:" msgstr "Há_markslengd lína:" #: data/ui/text-assistant/line-break-options-page.ui:93 msgid "_Preferred maximum amount of lines:" msgstr "Leið_beinandi hámarksfjöldi lína:" #: data/ui/text-assistant/line-break-options-page.ui:198 msgid "_Skip subtitles with maximum line length of:" msgstr "_Sleppa skjátextum með hámarkslengd lína:" #: data/ui/text-assistant/line-break-options-page.ui:214 msgid "S_kip subtitles with maximum line amount of:" msgstr "Sleppa s_kjátextum með hámarkslínufjölda:" #: data/ui/text-assistant/hearing-impaired-page.ui:22 msgid "S_elect parts to remove:" msgstr "V_eldu þá hluta sem á að fjarlægja:" #: data/ui/text-assistant/common-error-page.ui:22 msgid "S_elect errors to correct:" msgstr "V_eldu villur til að leiðrétta:" #: data/ui/text-assistant/common-error-page.ui:108 msgid "Error types:" msgstr "Gerðir af villum:" #: data/ui/text-assistant/common-error-page.ui:158 msgid "_Human errors" msgstr "_Mannlegar" #: data/ui/text-assistant/common-error-page.ui:175 msgid "_Image recognition errors" msgstr "Myndgre_iningarvillur" #: data/ui/text-assistant/capitalization-page.ui:22 msgid "S_elect parts to capitalize:" msgstr "V_eldu þá hluta sem á að setja í hástafi:" #: data/ui/duration-adjust-dialog.ui:33 msgid "Adjust Durations" msgstr "Aðlaga tímalengdir" #: data/ui/duration-adjust-dialog.ui:73 msgid "Theoretic Duration" msgstr "Marktímalengd" #: data/ui/duration-adjust-dialog.ui:101 msgid "_Reading speed:" msgstr "Lesh_raði:" #: data/ui/duration-adjust-dialog.ui:133 msgid "characters per second" msgstr "stafir á sekúndu" #: data/ui/duration-adjust-dialog.ui:150 msgid "_Lengthen duration to match reading speed" msgstr "_Lengja tíma til að samsvara leshraða" #: data/ui/duration-adjust-dialog.ui:167 msgid "_Shorten duration to match reading speed" msgstr "_Stytta tíma til að samsvara leshraða" #: data/ui/duration-adjust-dialog.ui:227 msgid "_Minimum duration:" msgstr "_Minnsta tímalengd:" #: data/ui/duration-adjust-dialog.ui:243 msgid "Ma_ximum duration:" msgstr "_Hámarks tímalengd:" #: data/ui/duration-adjust-dialog.ui:259 msgid "_Gap between subtitles:" msgstr "_Bil á milli skjátexta:" #: data/ui/duration-adjust-dialog.ui:294 msgid "s_econds" msgstr "s_ekúndur" #: data/ui/duration-adjust-dialog.ui:324 msgid "seco_nds" msgstr "sekú_ndur" #: data/ui/duration-adjust-dialog.ui:354 msgid "secon_ds" msgstr "sekún_dur" #: data/ui/duration-adjust-dialog.ui:408 msgid "Adj_ust selected subtitles" msgstr "Aðlaga val_da skjátexta" #: data/ui/duration-adjust-dialog.ui:425 msgid "Adjus_t current project" msgstr "Aðlaga þe_tta verkefni" #: data/ui/duration-adjust-dialog.ui:442 msgid "Adjust all _open projects" msgstr "Aðlaga öll _opin verkefni" #: data/ui/tab-popup.ui:6 msgid "Move Tab _Left" msgstr "Færa f_lipa til hægri" #: data/ui/tab-popup.ui:10 msgid "Move Tab _Right" msgstr "Fæ_ra flipa til hægri" #: data/ui/insert-dialog.ui:15 msgid "Insert Subtitles" msgstr "Setja inn skjátexta" #: data/ui/insert-dialog.ui:48 data/ui/position-shift-dialog.ui:82 msgid "_Amount:" msgstr "_Magn:" #: data/ui/insert-dialog.ui:62 msgid "_Position:" msgstr "_Staða:" #: data/ui/position-shift-dialog.ui:14 msgid "Shift Positions" msgstr "Hliðra staðsetningum" #: data/ui/position-shift-dialog.ui:54 msgid "Shift" msgstr "Hliðra" #: data/ui/position-shift-dialog.ui:135 #: data/ui/position-transform-dialog.ui:208 msgid "_Preview Changes" msgstr "Fors_koða breytingar" #: data/ui/position-shift-dialog.ui:200 msgid "Shift s_elected subtitles" msgstr "_Hliðra völdum skjátextum" #: data/ui/position-shift-dialog.ui:217 msgid "Shift su_btitles from selection to end" msgstr "Hliðra skjátextum frá vali að en_da" #: data/ui/position-shift-dialog.ui:234 msgid "Shift c_urrent project" msgstr "Hliðra þess_u verkefni" #: data/ui/position-shift-dialog.ui:251 msgid "Shift all _open projects" msgstr "" #: data/ui/position-transform-dialog.ui:22 msgid "Transform Positions" msgstr "Umbreyta staðsetningum" #: data/ui/position-transform-dialog.ui:62 msgid "First Point" msgstr "Fyrsti punktur" #: data/ui/position-transform-dialog.ui:91 msgid "_Subtitle:" msgstr "_Skjátexti:" #: data/ui/position-transform-dialog.ui:105 msgid "C_orrection:" msgstr "Leiðrétting:" #: data/ui/position-transform-dialog.ui:119 #: data/ui/position-transform-dialog.ui:310 msgid "Text:" msgstr "Texti:" #: data/ui/position-transform-dialog.ui:253 msgid "Second Point" msgstr "Annar punktur" #: data/ui/position-transform-dialog.ui:282 msgid "Su_btitle:" msgstr "Skjáte_xti:" #: data/ui/position-transform-dialog.ui:296 msgid "Co_rrection:" msgstr "Leið_rétting:" #: data/ui/position-transform-dialog.ui:399 msgid "Pre_view Changes" msgstr "Forskoða _breytingar" #: data/ui/position-transform-dialog.ui:464 msgid "Transform se_lected subtitles" msgstr "Umbreyta vö_ldum skjátextum" #: data/ui/position-transform-dialog.ui:482 msgid "Transform c_urrent project" msgstr "Umbreyta þess_u verkefni" #: data/extensions/custom-framerates/custom-framerates.extension.in:7 msgid "Custom Framerates" msgstr "Sérsniðin rammatíðni" #: data/extensions/custom-framerates/custom-framerates.extension.in:8 msgid "Allow use of non-standard framerates" msgstr "Leyfa að nota óstaðlaðar rammatíðnir" #: data/patterns/Latn-en-US.common-error.in:5 msgid "Period after title" msgstr "Punktur á eftir titli" #: data/patterns/Latn-en-US.common-error.in:6 msgid "Add period after a shortened title, such as \"Mr\" and \"Dr\"" msgstr "Bæta við punkti á eftir titli eins og \"Hr\" and \"Dr\"" #: data/patterns/Latn-en.capitalization.in:5 msgid "First person pronoun" msgstr "Fyrstu persónu fornafn" #: data/patterns/Latn-en.capitalization.in:6 msgid "Capitalize the first person pronoun \"I\"" msgstr "" #: data/patterns/Latn-en.common-error.in:5 #: data/patterns/Latn-en.common-error.in:14 #: data/patterns/Latn-en.common-error.in:23 msgid "Letter \"I\" in a lower case word" msgstr "" #: data/patterns/Latn-en.common-error.in:6 #: data/patterns/Latn-en.common-error.in:15 #: data/patterns/Latn-en.common-error.in:24 msgid "Replace letter \"I\" with letter \"l\" in a lower case word" msgstr "" #: data/patterns/Latn-en.common-error.in:32 #: data/patterns/Latn-en.common-error.in:41 #: data/patterns/Latn-en.common-error.in:50 #: data/patterns/Latn-en.common-error.in:62 msgid "Letter \"l\" in an upper case word" msgstr "" #: data/patterns/Latn-en.common-error.in:33 #: data/patterns/Latn-en.common-error.in:42 #: data/patterns/Latn-en.common-error.in:51 #: data/patterns/Latn-en.common-error.in:63 msgid "Replace letter \"l\" with letter \"I\" in an upper case word" msgstr "" #: data/patterns/Latn-en.common-error.in:73 #: data/patterns/Latn-en.common-error.in:82 msgid "Zero in an upper case word" msgstr "Núll í hástafa orði" #: data/patterns/Latn-en.common-error.in:74 #: data/patterns/Latn-en.common-error.in:83 msgid "Replace zero with letter \"O\" in an upper case word" msgstr "Skipta núlli út fyrir stafinn \"O\" í hástafa orði" #: data/patterns/Latn-en.common-error.in:91 #: data/patterns/Latn.common-error.in:108 msgid "Space between number and unit" msgstr "Fjarlægja bil á milli tölustafa og mælieininga" #: data/patterns/Latn-en.common-error.in:92 #: data/patterns/Latn.common-error.in:109 msgid "Add or remove space between a number and the associated unit" msgstr "Bæta við eða fjarlægja bil á milli tölustafa og mælieininga" #: data/patterns/Latn-en.common-error.in:100 msgid "Spaces around an apostrophe" msgstr "Bil í kringum úrfellingarmerki" #: data/patterns/Latn-en.common-error.in:101 msgid "Remove spaces around an apostrophe" msgstr "Fjarlægja bil í kringum úrfellingarmerki" #: data/patterns/Latn-en.common-error.in:109 #: data/patterns/Latn-en.common-error.in:118 msgid "Okay" msgstr "Í lagi" #: data/patterns/Latn-en.common-error.in:110 #: data/patterns/Latn-en.common-error.in:119 msgid "Spell two-letter forms of \"okay\" in all upper case" msgstr "" #: data/patterns/Latn-en.hearing-impaired.in:5 msgid "Uppercase speaker before a colon" msgstr "Nafn mælandans í hástöfum á undan tvípunkti" #: data/patterns/Latn-en.hearing-impaired.in:6 msgid "" "Replace the uppercase name of the speaker before a colon with a dialogue " "dash" msgstr "Skipta út nafni mælandans í hástöfum á undan tvípunkti og þankastriki" #: data/patterns/Latn-en.line-break.in:5 msgid "Title" msgstr "Titill" #: data/patterns/Latn-en.line-break.in:6 msgid "Do not break after a title, e.g. \" Dr.\"" msgstr "Ekki setja skil á eftir titli, t.d. \" Dr.\"" #: data/patterns/Latn-en.line-break.in:13 msgid "Article" msgstr "Greinir" #: data/patterns/Latn-en.line-break.in:14 msgid "Do not break after an article" msgstr "" #: data/patterns/Latn-en.line-break.in:21 msgid "Preposition" msgstr "Forsetning" #: data/patterns/Latn-en.line-break.in:22 msgid "Do not break after a preposition" msgstr "" #: data/patterns/Latn-en.line-break.in:30 msgid "Possessive determiner" msgstr "" #: data/patterns/Latn-en.line-break.in:31 msgid "Do not break after a possessive determiner, e.g. \"my\"" msgstr "" #: data/patterns/Latn-fi.common-error.in:5 #: data/patterns/Latn.common-error.in:182 msgid "Space after punctuation marks" msgstr "Bil á eftir greinamerkjum" #: data/patterns/Latn-fi.common-error.in:6 #: data/patterns/Latn.common-error.in:183 msgid "Add space after various punctuation marks" msgstr "Setja bil á eftir margskonar greinamerkjum" #: data/patterns/Latn-fr.common-error.in:5 #: data/patterns/Latn-fr.common-error.in:14 #: data/patterns/Latn-fr.common-error.in:23 #: data/patterns/Latn-fr.common-error.in:32 msgid "Spaces around guillemets" msgstr "Bil í kringum gæsalappir" #: data/patterns/Latn-fr.common-error.in:6 #: data/patterns/Latn-fr.common-error.in:15 #: data/patterns/Latn-fr.common-error.in:24 #: data/patterns/Latn-fr.common-error.in:33 msgid "Add spaces around guillemets" msgstr "Bæta við bilum í kringum gæsalappir" #: data/patterns/Latn-fr.common-error.in:41 #: data/patterns/Latn-fr.common-error.in:52 #: data/patterns/Latn.common-error.in:171 msgid "Space before punctuation marks" msgstr "Bil á undan greinamerkjum" #: data/patterns/Latn-fr.common-error.in:42 #: data/patterns/Latn-fr.common-error.in:53 msgid "Add or remove space before various punctuation marks" msgstr "Setja eða fjarlægja bil á undan margskonar greinamerkjum" #: data/patterns/Latn.capitalization.in:5 msgid "Sentence" msgstr "Setning" #: data/patterns/Latn.capitalization.in:6 msgid "Capitalize the first word of a sentence" msgstr "Setja hástaf á fyrsta staf í hverri setningu" #: data/patterns/Latn.capitalization.in:12 msgid "Ellipsis" msgstr "Brottfellingarpunktar" #: data/patterns/Latn.capitalization.in:13 msgid "Capitalize after an ellipsis" msgstr "Hástafur á eftir brottfellingarpunktum" #: data/patterns/Latn.common-error.in:8 data/patterns/Latn.common-error.in:17 #: data/patterns/Latn.common-error.in:26 data/patterns/Latn.common-error.in:35 #: data/patterns/Latn.common-error.in:44 data/patterns/Latn.common-error.in:53 #: data/patterns/Latn.common-error.in:62 msgid "Ligatures" msgstr "" #: data/patterns/Latn.common-error.in:9 data/patterns/Latn.common-error.in:18 #: data/patterns/Latn.common-error.in:27 data/patterns/Latn.common-error.in:36 #: data/patterns/Latn.common-error.in:45 data/patterns/Latn.common-error.in:54 #: data/patterns/Latn.common-error.in:63 msgid "Unpack ligatures to individual characters" msgstr "" #: data/patterns/Latn.common-error.in:71 data/patterns/Latn.common-error.in:80 msgid "Spelling of a.m. and p.m." msgstr "" #: data/patterns/Latn.common-error.in:72 data/patterns/Latn.common-error.in:81 msgid "Change the various spellings of 12-hour periods to \"a.m.\" and \"p.m.\"" msgstr "" #: data/patterns/Latn.common-error.in:89 data/patterns/Latn.common-error.in:98 msgid "Letter \"O\" in a number" msgstr "" #: data/patterns/Latn.common-error.in:90 data/patterns/Latn.common-error.in:99 msgid "Replace letter \"O\" with a zero in a number" msgstr "" #: data/patterns/Latn.common-error.in:117 msgid "Double apostrophe" msgstr "Tvöfalt úrfellingarmerki" #: data/patterns/Latn.common-error.in:118 msgid "Replace a double apostrophe with a quotation mark" msgstr "Skipta út tvöföldu úrfellingarmerki fyrir gæsalappir" #: data/patterns/Latn.common-error.in:126 #: data/patterns/Latn.common-error.in:135 #: data/patterns/Latn.common-error.in:144 #: data/patterns/Latn.common-error.in:153 msgid "Spaces around brackets" msgstr "Bil í kringum sviga" #: data/patterns/Latn.common-error.in:127 #: data/patterns/Latn.common-error.in:136 #: data/patterns/Latn.common-error.in:145 #: data/patterns/Latn.common-error.in:154 msgid "Add or remove spaces around parantheses and square brackets" msgstr "Bæta við eða fjarlægja bil í kringum sviga og hornklofa" #: data/patterns/Latn.common-error.in:162 msgid "Space after a dialogue dash" msgstr "Bil á eftir þankastriki" #: data/patterns/Latn.common-error.in:163 msgid "Add space after a dialogue dash" msgstr "Bæta við bili á eftir þankastriki" #: data/patterns/Latn.common-error.in:172 msgid "Remove space before various punctuation marks" msgstr "Fjarlægja bil á undan margskonar greinamerkjum" #: data/patterns/Latn.common-error.in:192 msgid "Space after an ellipsis" msgstr "Bil á eftir brottfellingarpunktum" #: data/patterns/Latn.common-error.in:193 msgid "Add space after an ellipsis" msgstr "Bæta við bili á eftir brottfellingarpunktum" #: data/patterns/Latn.common-error.in:201 msgid "Space after a starting ellipsis" msgstr "Bil á eftir brottfellingarpunktum í upphafi setningar" #: data/patterns/Latn.common-error.in:202 msgid "Remove space after an ellipsis that starts a line" msgstr "Fjarlægja bil á eftir brottfellingarpunktum í upphafi setningar" #: data/patterns/Latn.common-error.in:210 #: data/patterns/Latn.common-error.in:221 #: data/patterns/Latn.common-error.in:232 #: data/patterns/Latn.common-error.in:242 msgid "Spaces around a quotation mark" msgstr "Bil í kringum gæsalappir" #: data/patterns/Latn.common-error.in:211 #: data/patterns/Latn.common-error.in:222 #: data/patterns/Latn.common-error.in:233 #: data/patterns/Latn.common-error.in:243 msgid "Remove space after a starting- and before an ending quotation mark" msgstr "" #: data/patterns/Latn.common-error.in:252 #: data/patterns/Latn.common-error.in:261 msgid "Spaces around musical notes" msgstr "Bil í kringum nótnaskrift" #: data/patterns/Latn.common-error.in:253 #: data/patterns/Latn.common-error.in:262 msgid "Add spaces between musical note characters and lyrics" msgstr "" #: data/patterns/Latn.common-error.in:270 #: data/patterns/Latn.common-error.in:279 msgid "Multiple question- and exclamation marks" msgstr "" #: data/patterns/Latn.common-error.in:271 #: data/patterns/Latn.common-error.in:280 msgid "" "Replace multiple consequtive question- and exclamation marks with only one" msgstr "" #: data/patterns/Latn.common-error.in:288 #: data/patterns/Latn.common-error.in:298 msgid "Periods around a punctuation mark" msgstr "" #: data/patterns/Latn.common-error.in:289 #: data/patterns/Latn.common-error.in:299 msgid "Remove period before or after various punctuation marks" msgstr "" #: data/patterns/Latn.common-error.in:308 msgid "Terminating double-dashes" msgstr "" #: data/patterns/Latn.common-error.in:309 msgid "Replace a single clause-terminating dash with two dashes" msgstr "" #: data/patterns/Latn.hearing-impaired.in:5 msgid "Sound in brackets" msgstr "Hljóð í hornklofum" #: data/patterns/Latn.hearing-impaired.in:6 msgid "Remove description of a sound between square brackets" msgstr "Fjarlægja lýsingu á hljóði milli hornklofa" #: data/patterns/Latn.hearing-impaired.in:12 msgid "Sound in parantheses" msgstr "Hljóð í svigum" #: data/patterns/Latn.hearing-impaired.in:13 msgid "Remove description of a sound between parantheses" msgstr "Fjarlægja lýsingu á hljóði milli sviga" #: data/patterns/Latn.hearing-impaired.in:19 msgid "Song lyrics between number signs" msgstr "" #: data/patterns/Latn.hearing-impaired.in:20 msgid "Remove song lyrics starting with or between number signs" msgstr "" #: data/patterns/Latn.hearing-impaired.in:27 msgid "One-line song lyrics between number signs" msgstr "" #: data/patterns/Latn.hearing-impaired.in:28 msgid "Remove one-line song lyrics starting with or between number signs" msgstr "" #: data/patterns/Latn.hearing-impaired.in:35 msgid "Speaker before a colon" msgstr "Nafn mælandans á undan tvípunkti" #: data/patterns/Latn.hearing-impaired.in:36 msgid "Replace the name of the speaker before a colon with a dialogue dash" msgstr "Skipta út nafni mælandans á undan tvípunkti og þankastriki" #: data/patterns/Latn.line-break.in:5 data/patterns/Latn.line-break.in:13 msgid "Dialogue" msgstr "Samtal" #: data/patterns/Latn.line-break.in:6 data/patterns/Latn.line-break.in:14 msgid "Break according to dialogue separated by dashes" msgstr "" #: data/patterns/Latn.line-break.in:21 data/patterns/Latn.line-break.in:30 msgid "Clause" msgstr "" #: data/patterns/Latn.line-break.in:22 data/patterns/Latn.line-break.in:31 msgid "Break according to clauses terminated by a punctuation mark" msgstr "" #: data/patterns/Latn.line-break.in:38 msgid "Number and unit" msgstr "Tala og eining" #: data/patterns/Latn.line-break.in:39 msgid "Do not break between a number and associated unit" msgstr "Ekki rjúfa á milli tölustafa og mælieininga þeirra" #: data/patterns/Zyyy.common-error.in:5 data/patterns/Zyyy.common-error.in:14 msgid "Leading and trailing spaces" msgstr "Bil á undan og aftan við línu" #: data/patterns/Zyyy.common-error.in:6 data/patterns/Zyyy.common-error.in:15 msgid "Remove spaces from the beginning and end of lines" msgstr "Fjarlægja bil í upphafi og enda lína" #: data/patterns/Zyyy.common-error.in:23 msgid "Multiple consecutive spaces" msgstr "Mörg samhangandi bil" #: data/patterns/Zyyy.common-error.in:24 msgid "Replace multiple consecutive spaces with only one" msgstr "Skipta út mörgum samhangandi bilum með aðeins einu bili" #: data/patterns/Zyyy.common-error.in:32 data/patterns/Zyyy.common-error.in:45 #: data/patterns/Zyyy.common-error.in:55 data/patterns/Zyyy.common-error.in:65 msgid "Space between digits" msgstr "Bil á milli tölustafa" #: data/patterns/Zyyy.common-error.in:33 data/patterns/Zyyy.common-error.in:46 #: data/patterns/Zyyy.common-error.in:56 data/patterns/Zyyy.common-error.in:66 msgid "Remove space between digits of a number" msgstr "Fjarlægja bil á milli tölustafa" #: data/patterns/Zyyy.common-error.in:79 msgid "Musical notes" msgstr "Nótnaskrift" #: data/patterns/Zyyy.common-error.in:80 msgid "Replace Unicode musical note characters with number signs" msgstr "" #: data/io.otsaloma.gaupol.appdata.xml.in:7 msgid "Editor for text-based subtitles" msgstr "Ritill fyrir skjátexta á textaformi" #: data/io.otsaloma.gaupol.appdata.xml.in:9 msgid "" "Gaupol is an editor for text-based subtitle files. It supports multiple " "subtitle file formats and provides means of creating subtitles, editing " "texts and timing subtitles to match video." msgstr "" "Gaupol er ritill til meðhöndlunar á skjátextaskrám á textaformi. Hann styður" " margar gerðir skjátextaskráa og býður upp á að útbúa nýja skjátexta, " "breytingar texta og tímasetningu þeirra svo að þeir samsvari myndskeiðum." #: data/io.otsaloma.gaupol.appdata.xml.in:40 msgid "Main window" msgstr "Aðalgluggi" #: data/io.otsaloma.gaupol.desktop.in:5 msgid "Subtitle Editor" msgstr "Skjátextaritill" #: data/io.otsaloma.gaupol.desktop.in:6 msgid "Edit subtitle files" msgstr "Sýsla með skjátextaskrár" #. TRANSLATORS: Search terms to find this application. Do NOT translate or #. localize the semicolons! The list MUST also end with a semicolon! #: data/io.otsaloma.gaupol.desktop.in:12 msgid "video;subtitles;captions;" msgstr "myndskeið;skjátextar;þýðingartextar" gaupol-1.11/po/nl.po000066400000000000000000002211071422217132500143140ustar00rootroot00000000000000# 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. # # Translators: # Heimen Stoffels , 2021 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-04-03 04:00+0300\n" "PO-Revision-Date: 2016-07-07 00:55+0000\n" "Last-Translator: Heimen Stoffels , 2021\n" "Language-Team: Dutch (https://www.transifex.com/otsaloma/teams/64879/nl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: nl\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: aeidon/enums.py:40 gaupol/enums.py:38 msgid "Subtitle number" msgstr "Ondertitelnummer" #: aeidon/enums.py:43 msgid "Subtitle position" msgstr "Ondertitelpositie" #: aeidon/enums.py:59 msgid "23.976 fps" msgstr "23.976 fps" #: aeidon/enums.py:63 msgid "24.000 fps" msgstr "24.000 fps" #: aeidon/enums.py:67 msgid "25.000 fps" msgstr "25.000 fps" #: aeidon/enums.py:71 msgid "29.970 fps" msgstr "29.970 fps" #: aeidon/enums.py:75 data/ui/menubar.ui:248 msgid "30.000 fps" msgstr "30.000 fps" #: aeidon/enums.py:79 data/ui/menubar.ui:253 msgid "50.000 fps" msgstr "50.000 fps" #: aeidon/enums.py:83 data/ui/menubar.ui:258 msgid "59.940 fps" msgstr "59.940 fps" #: aeidon/enums.py:87 data/ui/menubar.ui:263 msgid "60.000 fps" msgstr "60.000 fps" #: aeidon/enums.py:112 msgid "Mac (classic)" msgstr "Mac (klassiek)" #. TRANSLATORS: Most of the character encoding descriptions are copied from #. gedit, which is translated to very many languages. Check the gedit .po #. files for a reference: #. . #: aeidon/encodings.py:40 aeidon/encodings.py:43 aeidon/encodings.py:46 msgid "English" msgstr "Engels" #: aeidon/encodings.py:41 aeidon/encodings.py:42 aeidon/encodings.py:69 msgid "Chinese traditional" msgstr "Chinees (Traditioneel)" #: aeidon/encodings.py:44 msgid "German" msgstr "Duits" #: aeidon/encodings.py:45 aeidon/encodings.py:54 aeidon/encodings.py:59 #: aeidon/encodings.py:79 aeidon/encodings.py:105 msgid "Hebrew" msgstr "Hebreeuws" #: aeidon/encodings.py:47 aeidon/encodings.py:51 aeidon/encodings.py:56 #: aeidon/encodings.py:73 aeidon/encodings.py:76 aeidon/encodings.py:98 #: aeidon/encodings.py:111 aeidon/encodings.py:122 msgid "Western" msgstr "Westers" #: aeidon/encodings.py:48 aeidon/encodings.py:61 aeidon/encodings.py:80 #: aeidon/encodings.py:103 msgid "Arabic" msgstr "Arabisch" #: aeidon/encodings.py:49 aeidon/encodings.py:64 aeidon/encodings.py:66 #: aeidon/encodings.py:77 aeidon/encodings.py:104 aeidon/encodings.py:119 msgid "Greek" msgstr "Grieks" #: aeidon/encodings.py:50 aeidon/encodings.py:81 aeidon/encodings.py:101 #: aeidon/encodings.py:109 msgid "Baltic" msgstr "Baltisch" #: aeidon/encodings.py:52 aeidon/encodings.py:74 aeidon/encodings.py:99 #: aeidon/encodings.py:121 msgid "Central European" msgstr "Centraal-Europees" #: aeidon/encodings.py:53 aeidon/encodings.py:75 aeidon/encodings.py:102 #: aeidon/encodings.py:118 msgid "Cyrillic" msgstr "Cyrillisch" #: aeidon/encodings.py:55 aeidon/encodings.py:71 aeidon/encodings.py:78 #: aeidon/encodings.py:106 aeidon/encodings.py:123 msgid "Turkish" msgstr "Turks" #: aeidon/encodings.py:57 msgid "Portuguese" msgstr "Portugees" #: aeidon/encodings.py:58 aeidon/encodings.py:120 msgid "Icelandic" msgstr "IJslands" #: aeidon/encodings.py:60 msgid "Canadian" msgstr "Canadees" #: aeidon/encodings.py:62 aeidon/encodings.py:107 msgid "Nordic" msgstr "Noors" #: aeidon/encodings.py:63 aeidon/encodings.py:114 msgid "Russian" msgstr "Russisch" #: aeidon/encodings.py:65 aeidon/encodings.py:108 msgid "Thai" msgstr "Thai" #: aeidon/encodings.py:67 aeidon/encodings.py:83 aeidon/encodings.py:84 #: aeidon/encodings.py:85 aeidon/encodings.py:91 aeidon/encodings.py:92 #: aeidon/encodings.py:93 aeidon/encodings.py:94 aeidon/encodings.py:95 #: aeidon/encodings.py:96 aeidon/encodings.py:125 aeidon/encodings.py:126 #: aeidon/encodings.py:127 msgid "Japanese" msgstr "Japans" #: aeidon/encodings.py:68 aeidon/encodings.py:86 aeidon/encodings.py:97 #: aeidon/encodings.py:113 msgid "Korean" msgstr "Koreaans" #: aeidon/encodings.py:70 msgid "Urdu" msgstr "Urdu" #: aeidon/encodings.py:72 aeidon/encodings.py:116 msgid "Ukrainian" msgstr "Oekraïens" #: aeidon/encodings.py:82 msgid "Vietnamese" msgstr "Vietnamees" #: aeidon/encodings.py:87 aeidon/encodings.py:90 msgid "Chinese simplified" msgstr "Chinees (Vereenvoudigd)" #: aeidon/encodings.py:88 aeidon/encodings.py:89 msgid "Chinese unified" msgstr "Chinees" #: aeidon/encodings.py:100 aeidon/encodings.py:112 msgid "South European" msgstr "Zuid-Europees" #: aeidon/encodings.py:110 msgid "Celtic" msgstr "Keltisch" #: aeidon/encodings.py:115 msgid "Tajik" msgstr "Tadzjieks" #: aeidon/encodings.py:117 msgid "Kazakh" msgstr "Kazachs" #: aeidon/encodings.py:124 msgid "Cyrillic Asian" msgstr "Cyrillisch (Azië)" #: aeidon/encodings.py:128 aeidon/encodings.py:129 aeidon/encodings.py:130 #: aeidon/encodings.py:131 aeidon/encodings.py:132 aeidon/encodings.py:133 #: aeidon/encodings.py:134 aeidon/encodings.py:135 aeidon/encodings.py:136 msgid "Unicode" msgstr "Unicode" #: aeidon/encodings.py:156 #, python-brace-format msgid "{description} ({name})" msgstr "{description} ({name})" #: aeidon/encodings.py:232 msgid "Current locale ({})" msgstr "Huidige taal ({})" #: aeidon/locales.py:46 #, python-brace-format msgid "{language} ({country})" msgstr "{language} ({country})" #: aeidon/agents/search.py:227 msgid "Replacing" msgstr "Vervangen" #: aeidon/agents/search.py:256 aeidon/agents/search.py:258 msgid "Replacing all" msgstr "Alles vervangen" #: aeidon/agents/position.py:74 msgid "Adjusting durations" msgstr "Duur aanpassen" #: aeidon/agents/position.py:96 msgid "Converting framerate" msgstr "Framesnelheid omzetten" #: aeidon/agents/position.py:146 msgid "Setting framerate" msgstr "Framesnelheid instellen" #: aeidon/agents/position.py:168 msgid "Shifting positions" msgstr "Posities verschuiven" #: aeidon/agents/position.py:188 msgid "Transforming positions" msgstr "Posities aanpassen" #: aeidon/agents/clipboard.py:44 msgid "Cutting texts" msgstr "Teksten knippen" #: aeidon/agents/clipboard.py:61 msgid "Pasting texts" msgstr "Teksten plakken" #: aeidon/agents/text.py:91 msgid "Breaking lines" msgstr "Regels afbreken" #: aeidon/agents/text.py:128 msgid "Capitalizing texts" msgstr "Teksten voorzien van hoofdletters" #: aeidon/agents/text.py:185 msgid "Correcting common errors" msgstr "Huidige fouten corrigeren" #: aeidon/agents/text.py:234 msgid "Removing hearing impaired texts" msgstr "Moeilijke teksten verwijderen" #: aeidon/agents/text.py:315 msgid "Joining words by spell-check suggestions" msgstr "Woorden samenvoegen door spellingcontrolesuggesties" #: aeidon/agents/text.py:354 msgid "Splitting words by spell-check suggestions" msgstr "Woorden splitsen door spellingcontrolesuggesties" #: aeidon/agents/set.py:58 aeidon/agents/set.py:80 aeidon/agents/set.py:113 msgid "Editing position" msgstr "Positie aanpassen" #: aeidon/agents/set.py:129 msgid "Editing text" msgstr "Tekst aanpassen" #: aeidon/agents/edit.py:35 msgid "Clearing texts" msgstr "Teksten wissen" #: aeidon/agents/edit.py:61 aeidon/agents/edit.py:83 msgid "Inserting subtitles" msgstr "Ondertiteling invoegen" #: aeidon/agents/edit.py:103 msgid "Merging subtitles" msgstr "Ondertiteling samenvoegen" #: aeidon/agents/edit.py:114 msgid "Removing subtitles" msgstr "Ondertiteling verwijderen" #: aeidon/agents/edit.py:131 msgid "Replacing positions" msgstr "Ondertiteling vervangen" #: aeidon/agents/edit.py:147 msgid "Replacing texts" msgstr "Teksten vervangen" #: aeidon/agents/edit.py:171 msgid "Splitting subtitle" msgstr "Ondertiteling splitsen" #: aeidon/agents/format.py:49 msgid "Adding dialogue dashes" msgstr "Dialoogstreepjes toevoegen" #: aeidon/agents/format.py:68 msgid "Changing case" msgstr "Hoofdlettergebruik aanpassen" #: aeidon/agents/format.py:92 msgid "Italicizing" msgstr "Omzetten naar cursief" #: aeidon/agents/format.py:108 msgid "Removing dialogue dashes" msgstr "Dialoogstreepjes verwijderen" #: aeidon/agents/format.py:174 msgid "Unitalicizing" msgstr "Omzetten naar normale tekst" #: gaupol/application.py:219 gaupol/agents/open.py:203 msgid "Open" msgstr "Openen" #: gaupol/application.py:223 msgid "Open main files" msgstr "Open hoofdbestanden" #: gaupol/application.py:230 msgid "Save" msgstr "Opslaan" #: gaupol/application.py:233 msgid "Save the current main document" msgstr "Sla het huidige hoofdbestand op" #: gaupol/application.py:238 msgid "Undo" msgstr "Ongedaan maken" #: gaupol/application.py:242 msgid "Undo the last action" msgstr "Maak de recentste actie ongedaan" #: gaupol/application.py:249 msgid "Redo" msgstr "Opnieuw uitvoeren" #: gaupol/application.py:252 msgid "Redo the last undone action" msgstr "Voer de recentste actie opnieuw uit" #: gaupol/application.py:260 msgid "Insert" msgstr "Invoegen" #: gaupol/application.py:262 msgid "Insert new subtitles" msgstr "Voeg ondertiteling in" #: gaupol/application.py:266 #: data/extensions/custom-framerates/preferences-dialog.ui:78 msgid "Remove" msgstr "Verwijderen" #: gaupol/application.py:268 msgid "Remove the selected subtitles" msgstr "Verwijder de geselecteerde ondertiteling" #: gaupol/application.py:273 data/ui/search-dialog.ui:283 msgid "Find" msgstr "Zoeken" #: gaupol/application.py:275 msgid "Search for and replace text" msgstr "Zoek en vervang tekst" #: gaupol/application.py:279 data/ui/preferences-dialog.ui:942 msgid "Video" msgstr "Video" #: gaupol/application.py:281 msgid "Show or hide the video player" msgstr "Toon of verberg de videospeler" #: gaupol/application.py:285 data/ui/preferences-dialog.ui:1173 msgid "Preview" msgstr "Voorvertoning" #: gaupol/application.py:287 msgid "Preview from selected position with a video player" msgstr "Voorvertoning, van de gekozen positie, in een videospeler" #: gaupol/enums.py:37 msgid "No." msgstr "No." #: gaupol/enums.py:43 msgid "Start" msgstr "Begin" #: gaupol/enums.py:44 msgid "Start position" msgstr "Beginpositie" #: gaupol/enums.py:49 msgid "End" msgstr "Einde" #: gaupol/enums.py:50 msgid "End position" msgstr "Eindpositie" #. TRANSLATORS: 'Dur.' is short for duration. It is used in the header #. of a column that contains numbers five digits wide. #: gaupol/enums.py:57 msgid "Dur." msgstr "Duur" #: gaupol/enums.py:58 msgid "Duration" msgstr "Duur" #: gaupol/enums.py:63 gaupol/enums.py:64 msgid "Text" msgstr "Tekst" #: gaupol/enums.py:69 gaupol/enums.py:70 msgid "Translation" msgstr "Vertaling" #: gaupol/enums.py:82 msgid "characters" msgstr "tekens" #: gaupol/enums.py:85 msgid "ems" msgstr "ems" #: gaupol/page.py:60 msgid "Untitled {:d}" msgstr "Naamloos {:d}" #: gaupol/page.py:133 msgid "Close project" msgstr "Project sluiten" #: gaupol/page.py:145 msgid "{} translation" msgstr "Vertaling: {}" #: gaupol/page.py:302 msgid "Path:" msgstr "Pad:" #: gaupol/page.py:303 msgid "Format:" msgstr "Formaat:" #: gaupol/page.py:304 msgid "Encoding:" msgstr "Encodering:" #: gaupol/page.py:305 msgid "Newlines:" msgstr "Nieuwe regels:" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:99 msgid "Tasks and Target" msgstr "Taken en doelen" #: gaupol/assistants.py:128 msgid "Correct texts in the text column" msgstr "Teksten corrigeren in de tekstkolom" #: gaupol/assistants.py:129 msgid "Correct texts in the translation column" msgstr "Teksten corrigeren in de vertaalkolom" #: gaupol/assistants.py:138 msgid "Correct texts in selected subtitles" msgstr "Teksten corrigeren in de geselecteerde ondertitels" #: gaupol/assistants.py:139 msgid "Correct texts in current project" msgstr "Teksten corrigeren in huidige project" #: gaupol/assistants.py:140 msgid "Correct texts in all open projects" msgstr "Teksten corrigeren in alle geopende projecten" #: gaupol/assistants.py:363 msgid "Other" msgstr "Overig" #: gaupol/assistants.py:439 msgid "Capitalize texts written in lower case" msgstr "Zet kleine letters om naar hoofdletters" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:443 msgid "Capitalization Patterns" msgstr "Hoofdletterpatronen" #: gaupol/assistants.py:445 msgid "Capitalize texts" msgstr "Teksten omzetten naar hoofdletters" #: gaupol/assistants.py:468 msgid "Correct common errors made by humans or image recognition software" msgstr "" "Corrigeer veelgemaakte fouten, zowel menselijke als van " "afbeeldingsherkenningssoftware" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:472 msgid "Common Error Patterns" msgstr "Veelgemaaktefoutpatronen" #: gaupol/assistants.py:474 msgid "Correct common errors" msgstr "Veelgemaakte fouten corrigeren" #: gaupol/assistants.py:526 msgid "Remove explanatory texts meant for the hearing impaired" msgstr "Verwijder uitleg die moeilijk te begrijpen is door slechthorenden" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:530 msgid "Hearing Impaired Patterns" msgstr "Slechthorendenpatronen" #: gaupol/assistants.py:532 msgid "Remove hearing impaired texts" msgstr "Moeilijke teksten verwijderen" #: gaupol/assistants.py:544 msgid "" "Use spell-check suggestions to fix whitespace detection errors of image " "recognition software" msgstr "" "Gebruik spellingcontrolesuggesties om witruimtefouten van " "afbeeldingsherkenningssoftware te repareren" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:548 msgid "Joining and Splitting Words" msgstr "Woorden splitsen en samenvoegen" #: gaupol/assistants.py:550 msgid "Join or Split Words" msgstr "Splits woorden of voeg ze samen" #: gaupol/assistants.py:599 gaupol/agents/tools.py:45 msgid "Failed to load dictionary for language \"{}\"" msgstr "Het woordenboek ‘{}’ kan niet worden geladen" #: gaupol/assistants.py:601 gaupol/player.py:263 gaupol/player.py:381 #: gaupol/dialogs/search.py:560 gaupol/dialogs/search.py:568 #: gaupol/dialogs/text_edit.py:49 gaupol/dialogs/encoding.py:56 #: gaupol/agents/open.py:328 gaupol/agents/open.py:337 #: gaupol/agents/open.py:345 gaupol/agents/open.py:354 #: gaupol/agents/tools.py:48 gaupol/agents/save.py:197 #: gaupol/agents/save.py:205 gaupol/agents/preview.py:108 #: gaupol/agents/preview.py:116 gaupol/agents/preview.py:125 #: gaupol/agents/preview.py:133 msgid "_OK" msgstr "_Oké" #: gaupol/assistants.py:635 msgid "Break text into lines of defined length" msgstr "Breek tekst af naar nieuwe regels of een vooringestelde lengtie" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:639 msgid "Line-Break Patterns" msgstr "Regelafbrekingspatronen" #: gaupol/assistants.py:641 msgid "Break lines" msgstr "Regels afbreken" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:679 msgid "Line-Break Options" msgstr "Regelafbrekingsopties" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:763 msgid "Correcting Texts" msgstr "Teksten corrigeren" #: gaupol/assistants.py:769 msgid "Each task is now being run on each project." msgstr "Elke taak wordt uitgevoerd op elk project." #: gaupol/assistants.py:793 #, python-brace-format msgid "{current:d} of {total:d} tasks complete" msgstr "Afgerond: {current:d}/{total:d}" #: gaupol/assistants.py:801 msgid "Project: {}" msgstr "Project: {}" #: gaupol/assistants.py:807 msgid "Task: {}" msgstr "Taak: {}" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:832 msgid "Confirm Changes" msgstr "Wijzigingen toepassen" #: gaupol/assistants.py:892 msgid "Accept" msgstr "Toepassen" #: gaupol/assistants.py:898 msgid "Original Text" msgstr "Oorspronkelijke tekst" #: gaupol/assistants.py:899 msgid "Corrected Text" msgstr "Gecorrigeerde tekst" #: gaupol/assistants.py:1048 msgid "Correct Texts" msgstr "Teksten corrigeren" #: gaupol/assistants.py:1076 msgid "Correcting texts" msgstr "Teksten corrigeren" #: gaupol/assistants.py:1092 #, python-brace-format msgid "Edited {edits:d} and removed {removals:d} subtitles" msgstr "Bewerkt: {edits:d} - Verwijderd: {removals:d}" #: gaupol/assistants.py:1126 msgid "Confirm {:d} Change" msgid_plural "Confirm {:d} Changes" msgstr[0] "{:d} wijziging toepassen?" msgstr[1] "{:d} wijzigingen toepassen?" #: gaupol/renderers/multiline.py:86 msgid "Italic" msgstr "Cursief" #: gaupol/player.py:372 msgid "No video streams found" msgstr "Geen videostreams aangetroffen" #: gaupol/player.py:379 msgid "Failed to initialize playback" msgstr "Afspelen mislukt" #: gaupol/dialogs/search.py:189 data/ui/menubar.ui:524 msgid "_Help" msgstr "_Hulp" #: gaupol/dialogs/search.py:471 msgid "Found and replaced {:d} occurence" msgid_plural "Found and replaced {:d} occurences" msgstr[0] "{:d} item aangetroffen en vervangen" msgstr[1] "{:d} items aangetroffen en vervangen" #: gaupol/dialogs/search.py:488 msgid "\"{}\" not found" msgstr "‘{}’ is niet aangetroffen" #: gaupol/dialogs/search.py:558 msgid "Error in regular expression pattern" msgstr "Fout in reguliere-expressiepatroon" #: gaupol/dialogs/search.py:566 msgid "Error in regular expression replacement" msgstr "Fout in reguliere-expressievervanging" #: gaupol/dialogs/text_edit.py:48 gaupol/dialogs/framerate_convert.py:63 #: gaupol/dialogs/insert.py:44 gaupol/dialogs/encoding.py:55 #: gaupol/dialogs/split.py:44 gaupol/dialogs/multi_close.py:54 #: gaupol/dialogs/open.py:63 gaupol/dialogs/position_transform.py:69 #: gaupol/dialogs/position_shift.py:71 gaupol/dialogs/multi_save.py:83 #: gaupol/dialogs/multi_save.py:215 gaupol/dialogs/duration_adjust.py:86 #: gaupol/dialogs/save.py:73 gaupol/dialogs/video.py:41 #: gaupol/agents/open.py:363 gaupol/agents/open.py:375 #: gaupol/agents/open.py:387 gaupol/agents/close.py:71 #: data/extensions/custom-framerates/custom-framerates.py:39 msgid "_Cancel" msgstr "_Annuleren" #: gaupol/dialogs/text_edit.py:53 msgid "Edit Text" msgstr "Tekst aanpassen" #: gaupol/dialogs/framerate_convert.py:64 msgid "Co_nvert" msgstr "Omzette_n" #: gaupol/dialogs/insert.py:45 msgid "_Insert" msgstr "_Invoegen" #: gaupol/dialogs/insert.py:54 msgid "Above selection" msgstr "Boven selectie" #: gaupol/dialogs/insert.py:55 msgid "Below selection" msgstr "Onder selectie" #: gaupol/dialogs/encoding.py:60 data/ui/preferences-dialog.ui:70 msgid "Character Encodings" msgstr "Tekenreeksen" #: gaupol/dialogs/encoding.py:78 gaupol/dialogs/encoding.py:125 msgid "Description" msgstr "Omschrijving" #: gaupol/dialogs/encoding.py:85 gaupol/dialogs/encoding.py:132 msgid "Encoding" msgstr "Encodering" #: gaupol/dialogs/encoding.py:141 msgid "Show in Menu" msgstr "Tonen in menu" #: gaupol/dialogs/split.py:45 msgid "_Split" msgstr "_Splitsen" #: gaupol/dialogs/split.py:76 msgid "Splitting project" msgstr "Project splitsen" #: gaupol/dialogs/split.py:97 #, python-brace-format msgid "Split {amount:d} subtitles to project \"{name}\"" msgstr "{amount:d} ondertitels afsplitsen naar ‘{name}’" #: gaupol/dialogs/spell_check.py:269 msgid "Spell-checking" msgstr "Spellingcontrole" #: gaupol/dialogs/preferences.py:217 msgid "{} Extension Website" msgstr "{}-uitbreidingspagina" #: gaupol/dialogs/preferences.py:429 msgid "Custom" msgstr "Aangepast" #: gaupol/dialogs/multi_close.py:38 msgid "Save changes to documents before closing?" msgstr "Wil je de aanpassingen opslaan alvorens te sluiten?" #: gaupol/dialogs/multi_close.py:39 gaupol/agents/open.py:384 #: gaupol/agents/close.py:68 msgid "If you don't save, changes will be permanently lost." msgstr "Als je niks opslaat, dan worden de aanpassingen permament verwijderd." #: gaupol/dialogs/multi_close.py:53 gaupol/agents/close.py:70 msgid "Close _Without Saving" msgstr "Sl_uiten zonder opslaan" #: gaupol/dialogs/multi_close.py:55 gaupol/dialogs/multi_save.py:84 #: gaupol/dialogs/save.py:74 gaupol/agents/open.py:388 #: gaupol/agents/close.py:72 data/ui/menubar.ui:34 msgid "_Save" msgstr "Op_slaan" #: gaupol/dialogs/multi_close.py:70 msgid "Select the _main documents you want to save:" msgstr "Selecteer de hoofddocu_menten die je wilt opslaan:" #: gaupol/dialogs/multi_close.py:95 msgid "Select the _translation documents you want to save:" msgstr "Selecteer de ver_taaldocumenten die je wilt opslaan:" #: gaupol/dialogs/open.py:64 gaupol/agents/open.py:364 #: gaupol/agents/open.py:376 msgid "_Open" msgstr "_Openen" #: gaupol/dialogs/position_transform.py:70 msgid "_Transform" msgstr "_Transformeren" #: gaupol/dialogs/position_shift.py:72 msgid "_Shift" msgstr "Ver_schuiven" #: gaupol/dialogs/position_shift.py:150 msgid "frames" msgstr "frames" #: gaupol/dialogs/position_shift.py:168 data/ui/preferences-dialog.ui:911 msgid "seconds" msgstr "seconden" #: gaupol/dialogs/about.py:36 msgid "About Gaupol" msgstr "Over Gaupol" #: gaupol/dialogs/about.py:40 msgid "Subtitle editor" msgstr "Ondertitelbewerker" #. TRANSLATORS: This is a special message that shouldn't be translated #. literally. It is used in the about dialog to give credits to the #. translators. Thus, you should translate it to your name and email #. address. You can also include other translators who have contributed #. to this translation; in that case, please write them on separate #. lines seperated by newlines (\n). #: gaupol/dialogs/about.py:51 msgid "translator-credits" msgstr "Heimen Stoffels " #: gaupol/dialogs/about.py:54 msgid "Gaupol Website" msgstr "Gaupol-website" #: gaupol/dialogs/append.py:35 msgid "Append File" msgstr "Bestand invoegen" #: gaupol/dialogs/debug.py:43 msgid "Something went wrong" msgstr "Er is iets misgegaan" #: gaupol/dialogs/debug.py:44 msgid "" "You have probably discovered a bug. Please report it by providing the below " "information and a description of what you were doing." msgstr "" "Je bent waarschijnlijk tegen een bug aangelopen. Meld deze en voeg " "onderstaande informatie bij, evenals een beschrijving van wat je aan het " "doen was toen dit gebeurde." #: gaupol/dialogs/debug.py:52 msgid "_Report Bug" msgstr "Bug _melden" #: gaupol/dialogs/debug.py:53 data/ui/menubar.ui:56 msgid "_Quit" msgstr "_Afsluiten" #: gaupol/dialogs/debug.py:54 gaupol/dialogs/preview_error.py:45 #: data/ui/menubar.ui:52 data/ui/tab-popup.ui:16 msgid "_Close" msgstr "_Sluiten" #: gaupol/dialogs/multi_save.py:98 gaupol/dialogs/save.py:110 msgid "{} (recommended)" msgstr "{} (aanbevolen)" #: gaupol/dialogs/multi_save.py:212 msgid "" "{:d} of the files to be saved already exist. Do you want to replace them?" msgstr "" "{:d} van de bestanden die moeten worden opgeslagen bestaan al. Wil je ze " "vervangen?" #: gaupol/dialogs/multi_save.py:213 msgid "" "The files already exist in \"{}\". Replacing them will overwrite their " "contents." msgstr "" "De bestanden in ‘{}’ bestaan al. Als je ze vervangt, dan wordt de inhoud " "ervan overschreven." #: gaupol/dialogs/multi_save.py:216 data/ui/search-dialog.ui:192 #: data/ui/spell-check-dialog.ui:122 msgid "_Replace" msgstr "Ve_rvangen" #: gaupol/dialogs/duration_adjust.py:70 msgid "Adjusted duration of {:d} subtitle" msgid_plural "Adjusted durations of {:d} subtitles" msgstr[0] "De duur van {:d} ondertitel is aangepast" msgstr[1] "De duur van {:d} ondertitels is aangepast" #: gaupol/dialogs/duration_adjust.py:87 msgid "_Adjust" msgstr "_Aanpassen" #: gaupol/dialogs/preview_error.py:36 msgid "Preview in video player failed" msgstr "Voorvertonen mislukt" #: gaupol/dialogs/preview_error.py:37 msgid "" "There is probably a problem with either the video file or the video player. " "See the preferences dialog to choose the video player or to customize the " "command." msgstr "" "Er is iets mis met het videobestand of de videospeler. Ga naar de " "instellingen en stel de videospeler(opdracht) in." #: gaupol/dialogs/language.py:97 msgid "Set Language" msgstr "Taal instellen" #: gaupol/dialogs/video.py:52 gaupol/dialogs/file.py:59 msgid "All files" msgstr "Alle bestanden" #: gaupol/dialogs/video.py:56 msgid "Video files" msgstr "Videobestanden" #: gaupol/dialogs/file.py:63 msgid "All supported files" msgstr "Alle ondersteunde bestanden" #: gaupol/dialogs/file.py:77 #, python-brace-format msgid "{format} (*{extension})" msgstr "{format} (*{extension})" #: gaupol/dialogs/file.py:120 msgid "Auto-detected" msgstr "Automatische detectie" #: gaupol/dialogs/file.py:122 msgid "Other…" msgstr "Overig…" #: gaupol/agents/menu.py:94 gaupol/agents/menu.py:103 #: gaupol/agents/menu.py:110 msgid "File not found" msgstr "Bestand niet aangetroffen" #: gaupol/agents/open.py:85 #, python-brace-format msgid "Appended {amount:d} subtitles from \"{basename}\"" msgstr "{amount:d} ondertitels toegevoegd uit ‘{basename}’" #: gaupol/agents/open.py:96 msgid "Appending file" msgstr "Bestand invoegen" #: gaupol/agents/open.py:111 msgid "File \"{}\" is already open" msgstr "‘{}’ is al geopend" #: gaupol/agents/open.py:214 msgid "Open Translation" msgstr "Vertaling openen" #: gaupol/agents/open.py:223 msgid "Select Video" msgstr "Video kiezen" #: gaupol/agents/open.py:224 msgid "_Select" msgstr "_Selecteren" #: gaupol/agents/open.py:325 msgid "Failed to decode file \"{}\" with all attempted codecs" msgstr "‘{}’ kan niet worden gedecodeerd met de beschikbare codecs" #: gaupol/agents/open.py:326 msgid "Please try to open the file with a different character encoding." msgstr "Open het bestand met een andere tekenreeks." #: gaupol/agents/open.py:334 msgid "Failed to recognize format of file \"{}\"" msgstr "Het formaat van ‘{}’ wordt niet herkend" #: gaupol/agents/open.py:335 msgid "" "Please check that the file you are trying to open is a subtitle file of a " "format supported by Gaupol." msgstr "" "Controleer of het te openen bestand een ondertitelbestand is dat wordt " "ondersteund door Gaupol." #: gaupol/agents/open.py:343 msgid "Failed to open file \"{}\"" msgstr "‘{}’ kan niet worden geopend" #: gaupol/agents/open.py:351 msgid "Failed to parse file \"{}\"" msgstr "‘{}’ kan niet worden verwerkt" #: gaupol/agents/open.py:352 msgid "Please check that the file you are trying to open is a valid {} file." msgstr "Controleer of het te openen bestand een geldig {}bestand is." #: gaupol/agents/open.py:360 msgid "Open abnormally large file \"{}\"?" msgstr "Weet je zeker dat je ‘{}’ wilt openen?" #: gaupol/agents/open.py:361 msgid "" "Size of the file is {:.1f} MB, which is abnormally large for a text-based " "subtitle file. Please, check that you are not trying to open a binary file." msgstr "" "De bestandsgrootte bedraagt {:.1f} MB, wat abnormaal groot is voor een op " "tekst gebaseerd ondertitelbestand. Controleer of je geen uitvoerbaar bestand" " probeert te openen." #: gaupol/agents/open.py:371 msgid "Open unsorted file \"{}\"?" msgstr "Weet je zeker dat je ‘{}’ wilt openen?" #: gaupol/agents/open.py:372 msgid "" "The order of {:d} subtitles needs to be changed. If {:d} sounds like a lot, " "the file may be erroneously composed." msgstr "" "De volgorde van {:d} ondertitels moet worden aangepast. Als {:d} klinkt als " "veel, dan is het bestand mogelijk onjuist opgemaakt." #: gaupol/agents/open.py:383 msgid "Save changes to translation document \"{}\" before opening a new one?" msgstr "" "Wil je de aanpassingen aan ‘{}’ opslaan alvorens een nieuw bestand te " "openen?" #: gaupol/agents/open.py:386 msgid "Open _Without Saving" msgstr "Openen _zonder opslaan" #: gaupol/agents/close.py:66 msgid "Save changes to document \"{}\" before closing?" msgstr "Wil je de aanpassingen aan ‘{}’ opslaan alvorens te sluiten?" #: gaupol/agents/edit.py:101 gaupol/agents/edit.py:119 msgid "Stretching end position" msgstr "Eindpositie vergroten" #: gaupol/agents/edit.py:208 msgid "Inserted {:d} subtitle to fit clipboard contents" msgid_plural "Inserted {:d} subtitles to fit clipboard contents" msgstr[0] "" "{:d} ondertitel ingevoerd om de klembordgrootte niet te overschrijden" msgstr[1] "" "{:d} ondertitels ingevoerd om de klembordgrootte niet te overschrijden" #: gaupol/agents/edit.py:334 gaupol/agents/edit.py:352 msgid "Stretching start position" msgstr "Beginpositie vergroten" #: gaupol/agents/edit.py:411 msgid "Use Shift+Return for line-break" msgstr "Druk op Shift+Enter om een regeleinde in te voegen" #: gaupol/agents/save.py:129 msgid "Save As" msgstr "Opslaan als" #: gaupol/agents/save.py:135 msgid "Saved main document as \"{}\"" msgstr "Het hoofdbestand is opgeslagen als ‘{}’" #: gaupol/agents/save.py:153 msgid "Save Translation As" msgstr "Vertaling opslaan als" #: gaupol/agents/save.py:159 msgid "Saved translation document as \"{}\"" msgstr "Het vertaalbestand is opgeslagen als ‘{}’" #: gaupol/agents/save.py:194 #, python-brace-format msgid "Failed to encode file \"{basename}\" with codec \"{codec}\"" msgstr "‘{basename}’ kan niet worden geëncodeerd met de codec ‘{codec}’" #: gaupol/agents/save.py:195 msgid "Please try to save the file with a different character encoding." msgstr "Sla het bestand op met een andere tekenreeks." #: gaupol/agents/save.py:203 msgid "Failed to save file \"{}\"" msgstr "‘{}’ kan niet worden opgeslagen" #: gaupol/agents/video.py:67 data/ui/menubar.ui:380 msgid "_Play/Pause" msgstr "Afs_pelen/Pauzeren" #: gaupol/agents/video.py:69 msgid "Play or pause video" msgstr "Pauzeer of start de video" #: gaupol/agents/video.py:75 data/ui/menubar.ui:390 msgid "Seek _Previous" msgstr "Terugs_poelen" #: gaupol/agents/video.py:77 msgid "Seek to the start of the previous subtitle" msgstr "Spoel terug naar het begin van de vorige ondertitel" #: gaupol/agents/video.py:81 data/ui/menubar.ui:394 msgid "Seek _Next" msgstr "Verderspoele_n" #: gaupol/agents/video.py:83 msgid "Seek to the start of the next subtitle" msgstr "Spoel door naar het begin van de volgende ondertitel" #: gaupol/agents/video.py:88 data/ui/menubar.ui:400 msgid "Seek _Backward" msgstr "_Terugspoelen" #: gaupol/agents/video.py:90 msgid "Seek backward" msgstr "Spoel terug" #: gaupol/agents/video.py:94 data/ui/menubar.ui:404 msgid "Seek _Forward" msgstr "Vooruitspoelen" #: gaupol/agents/video.py:96 msgid "Seek forward" msgstr "Spoel vooruit" #: gaupol/agents/video.py:109 msgid "Volume" msgstr "Volume" #: gaupol/agents/video.py:189 msgid "Load Video" msgstr "Video laden" #: gaupol/agents/video.py:189 msgid "_Load" msgstr "_Laden" #: gaupol/agents/video.py:361 msgid "Track {:d}" msgstr "Spoor {:d}" #: gaupol/agents/preview.py:105 msgid "Failed to encode subtitle file to temporary directory \"{}\"" msgstr "" "Het ondertitelbestand kan niet worden geëncodeerd naar de tijdelijke map " "‘{}’" #: gaupol/agents/preview.py:106 msgid "" "Subtitle data could not be encoded to a temporary file for preview with the " "current character encoding. Please first save the subtitle file with a " "different character encoding." msgstr "" "De ondertitelgegevens kunnen niet worden geëncodeerd naar een tijdelijk " "bestand om te worden voorvertoond met de huidige tekenreeks. Sla het " "ondertitelbestand op met een andere tekenreeks." #: gaupol/agents/preview.py:114 msgid "Failed to save subtitle file to temporary directory \"{}\"" msgstr "" "Het ondertitelbestand kan niet worden opgeslagen in de tijdelijke map ‘{}’" #: gaupol/agents/preview.py:122 msgid "Video player not found" msgstr "Geen videospeler beschikbaar" #: gaupol/agents/preview.py:123 msgid "" "Please install one of the supported video players: mpv (recommended), " "MPlayer or VLC. See the preferences dialog to choose the video player or to " "customize the command." msgstr "" "Installeer één van de ondersteunde videospelers: mpv (aanbevolen), Mplayer " "of VLC. Kies de gewenste videospeler in de instellingen of pas, aldaar, de " "uit te voeren opdracht aan." #: gaupol/agents/preview.py:131 msgid "Failed to launch video player" msgstr "De videospeler kan niet worden gestart" #: gaupol/applicationman.py:105 msgid "gaupol [OPTION...] [FILE...] [+[NUM]]" msgstr "gaupol [OPTIE…] [BESTAND…] [+[NUM]]" #: gaupol/applicationman.py:109 msgid "FILE..." msgstr "BESTAND…" #: gaupol/applicationman.py:112 msgid "subtitle files to open" msgstr "de te openen ondertitelbestanden" #: gaupol/applicationman.py:122 msgid "ENCODING" msgstr "TEKENREEKS" #: gaupol/applicationman.py:125 msgid "set the character encoding used to open files" msgstr "de te gebruiken tekenreeks bij het openen van bestanden" #: gaupol/applicationman.py:132 msgid "list all available character encodings" msgstr "toon alle beschikbare tekenreeksen" #: gaupol/applicationman.py:137 gaupol/applicationman.py:154 msgid "FILE" msgstr "BESTAND" #: gaupol/applicationman.py:140 msgid "open translation file" msgstr "open een vertaalbestand" #: gaupol/applicationman.py:145 msgid "METHOD" msgstr "METHODE" #: gaupol/applicationman.py:149 msgid "method used to align translation subtitles: 'number' or 'position'" msgstr "" "de te gebruiken methode voor het uitlijnen van vertalingen: ‘number’ of " "‘position’" #: gaupol/applicationman.py:157 msgid "select video file" msgstr "kies een videobestand" #: data/extensions/custom-framerates/custom-framerates.py:40 #: data/ui/spell-check-dialog.ui:152 msgid "_Add" msgstr "_Toevoegen" #: data/extensions/custom-framerates/custom-framerates.py:171 msgid "{:.3f} fps" msgstr "{:.3f} fps" #: data/extensions/custom-framerates/add-framerate-dialog.ui:13 msgid "Add Framerate" msgstr "Framesnelheid toevoegen" #: data/extensions/custom-framerates/add-framerate-dialog.ui:44 msgid "_Framerate:" msgstr "_Framesnelheid:" #: data/extensions/custom-framerates/add-framerate-dialog.ui:73 msgid "fps" msgstr "fps" #: data/extensions/custom-framerates/preferences-dialog.ui:8 msgid "Framerates" msgstr "Framesnelheden" #: data/extensions/custom-framerates/preferences-dialog.ui:64 msgid "Add" msgstr "Toevoegen" #: data/ui/columns-popup.ui:6 data/ui/menubar.ui:275 msgid "_No." msgstr "_Nummer" #: data/ui/columns-popup.ui:10 data/ui/menubar.ui:279 msgid "_Start" msgstr "_Begin" #: data/ui/columns-popup.ui:14 data/ui/menubar.ui:283 msgid "_End" msgstr "_Einde" #: data/ui/columns-popup.ui:18 data/ui/menubar.ui:287 msgid "_Duration" msgstr "_Duur" #: data/ui/columns-popup.ui:22 data/ui/menubar.ui:291 data/ui/menubar.ui:303 msgid "_Text" msgstr "_Tekst" #: data/ui/columns-popup.ui:26 data/ui/menubar.ui:295 msgid "T_ranslation" msgstr "Ve_rtaling" #: data/ui/split-dialog.ui:15 msgid "Split Project" msgstr "Project splitsen" #: data/ui/split-dialog.ui:48 msgid "_First subtitle of new project:" msgstr "Eerste ondertitel _van nieuwe project:" #: data/ui/search-dialog.ui:89 msgid "_Search for:" msgstr "_Zoeken naar:" #: data/ui/search-dialog.ui:103 data/ui/spell-check-dialog.ui:193 msgid "Replace _with:" msgstr "Ver_vangen door:" #: data/ui/search-dialog.ui:162 data/ui/menubar.ui:328 msgid "Find _Next" msgstr "Volge_nde zoeken" #: data/ui/search-dialog.ui:177 msgid "Find _Previous" msgstr "Vo_rige zoeken" #: data/ui/search-dialog.ui:207 msgid "Replace _All" msgstr "_Alles vervangen" #: data/ui/search-dialog.ui:241 msgid "R_egular expression" msgstr "R_eguliere expressie" #: data/ui/search-dialog.ui:258 msgid "_Ignore case" msgstr "Hoofdlettergebru_ik negeren" #: data/ui/search-dialog.ui:304 data/ui/language-dialog.ui:108 msgid "Columns" msgstr "Kolommen" #: data/ui/search-dialog.ui:324 msgid "Find in _text column" msgstr "_Tekstkolom doorzoeken" #: data/ui/search-dialog.ui:341 msgid "Find in t_ranslation column" msgstr "Ve_rtaalkolom doorzoeken" #: data/ui/search-dialog.ui:381 data/ui/framerate-convert-dialog.ui:144 #: data/ui/language-dialog.ui:186 #: data/ui/text-assistant/line-break-options-page.ui:178 #: data/ui/duration-adjust-dialog.ui:388 data/ui/position-shift-dialog.ui:180 #: data/ui/position-transform-dialog.ui:444 msgid "Subtitles" msgstr "Ondertiteling" #: data/ui/search-dialog.ui:401 msgid "Find in c_urrent project" msgstr "H_uidig project doorzoeken" #: data/ui/search-dialog.ui:419 msgid "Find in _all open projects" msgstr "_Alle geopende projecten doorzoeken" #: data/ui/search-dialog.ui:452 msgid "Target" msgstr "Doel" #: data/ui/framerate-convert-dialog.ui:8 msgid "Convert Framerate" msgstr "Framesnelheid omzetten" #: data/ui/framerate-convert-dialog.ui:48 msgid "Framerate" msgstr "Framesnelheid" #: data/ui/framerate-convert-dialog.ui:71 msgid "_Input:" msgstr "_Invoer:" #: data/ui/framerate-convert-dialog.ui:86 msgid "_Output:" msgstr "Uitv_oer:" #: data/ui/framerate-convert-dialog.ui:164 msgid "Convert c_urrent project" msgstr "H_uidig project omzetten" #: data/ui/framerate-convert-dialog.ui:181 msgid "Convert _all open projects" msgstr "_Alle geopende projecten omzetten" #: data/ui/spell-check-dialog.ui:8 msgid "Check Spelling" msgstr "Spelling controleren" #: data/ui/spell-check-dialog.ui:47 msgid "Join _Back" msgstr "Samenvoegen (achter_waarts)" #: data/ui/spell-check-dialog.ui:62 msgid "Join _Forward" msgstr "Samenvoegen (_voorwaarts)" #: data/ui/spell-check-dialog.ui:77 data/ui/menubar.ui:62 msgid "_Edit" msgstr "Aanpass_en" #: data/ui/spell-check-dialog.ui:92 msgid "_Ignore" msgstr "_Negeren" #: data/ui/spell-check-dialog.ui:107 msgid "Ig_nore All" msgstr "Alles negere_n" #: data/ui/spell-check-dialog.ui:137 msgid "Rep_lace All" msgstr "A_lles vervangen" #: data/ui/spell-check-dialog.ui:179 msgid "_Suggestions:" msgstr "_Suggesties:" #: data/ui/multi-save-dialog.ui:8 msgid "Save All As" msgstr "Alles opslaan als" #: data/ui/multi-save-dialog.ui:46 msgid "Save in _folder:" msgstr "O_pslaan in map:" #: data/ui/multi-save-dialog.ui:60 data/ui/save-dialog.ui:25 msgid "For_mat:" msgstr "For_maat:" #: data/ui/multi-save-dialog.ui:74 data/ui/open-dialog.ui:25 #: data/ui/save-dialog.ui:39 msgid "_Encoding:" msgstr "T_ekenreeks:" #: data/ui/multi-save-dialog.ui:88 data/ui/save-dialog.ui:53 msgid "Ne_wlines:" msgstr "_Witregels" #: data/ui/multi-save-dialog.ui:103 msgid "Select A Folder" msgstr "Map kiezen" #: data/ui/multi-save-dialog.ui:150 data/ui/save-dialog.ui:102 msgid "F_ramerate:" msgstr "F_ramesnelheid:" #: data/ui/menubar.ui:5 msgid "_File" msgstr "_Bestand" #: data/ui/menubar.ui:8 msgid "_New" msgstr "_Nieuw" #: data/ui/menubar.ui:12 msgid "_Open…" msgstr "_Openen…" #: data/ui/menubar.ui:16 msgid "Open _Translation…" msgstr "Ver_taling openen…" #: data/ui/menubar.ui:22 msgid "Open _Recent" msgstr "_Recent" #: data/ui/menubar.ui:27 msgid "Open R_ecent Translation" msgstr "R_ecente vertaling openen" #: data/ui/menubar.ui:38 msgid "Save _As…" msgstr "Opsl_aan als…" #: data/ui/menubar.ui:42 msgid "Save Trans_lation" msgstr "Verta_ling opslaan" #: data/ui/menubar.ui:46 msgid "Save Translat_ion As…" msgstr "Vertal_ing opslaan als…" #: data/ui/menubar.ui:65 msgid "_Undo" msgstr "_Ongedaan maken" #: data/ui/menubar.ui:69 msgid "_Redo" msgstr "_Opnieuw uitvoeren" #: data/ui/menubar.ui:75 msgid "_Edit Cell" msgstr "Cel aanpass_en" #: data/ui/menubar.ui:79 msgid "Edit _Next Cell" msgstr "Volge_nde cel aanpassen" #: data/ui/menubar.ui:85 msgid "Stretc_h" msgstr "Uitre_kken" #: data/ui/menubar.ui:88 msgid "_Start Earlier" msgstr "_Eerder beginnen" #: data/ui/menubar.ui:92 msgid "S_tart Later" msgstr "La_ter beginnen" #: data/ui/menubar.ui:98 msgid "E_nd Earlier" msgstr "Eerder ei_ndigen" #: data/ui/menubar.ui:102 msgid "En_d Later" msgstr "Later ein_digen" #: data/ui/menubar.ui:108 msgid "Set St_art From Video Position" msgstr "Begin instellen op b_asis van videopositie" #: data/ui/menubar.ui:112 msgid "Set En_d From Video Position" msgstr "Ein_de instellen op basis van videopositie" #: data/ui/menubar.ui:118 data/ui/view-popup.ui:6 msgid "_Split Subtitle" msgstr "Ondertitel _splitsen" #: data/ui/menubar.ui:122 data/ui/view-popup.ui:10 msgid "_Merge Subtitles" msgstr "Ondertitels sa_menvoegen" #: data/ui/menubar.ui:128 data/ui/view-popup.ui:16 msgid "_Insert Subtitles…" msgstr "Ondertiteling _invoegen…" #: data/ui/menubar.ui:132 msgid "Inser_t Subtitle At Video Position" msgstr "Onder_titel invoegen op videopositie" #: data/ui/menubar.ui:136 data/ui/view-popup.ui:20 msgid "Rem_ove Subtitles" msgstr "_Ondertiteling verwijderen" #: data/ui/menubar.ui:142 msgid "Sele_ction" msgstr "Sele_ctie" #: data/ui/menubar.ui:145 msgid "Select _All" msgstr "_Alles selecteren" #: data/ui/menubar.ui:149 msgid "_Invert Selection" msgstr "Select_ie omkeren" #: data/ui/menubar.ui:155 msgid "Extend To _Beginning" msgstr "Uitbreiden naar _begin" #: data/ui/menubar.ui:159 msgid "Extend To _End" msgstr "Uitbreiden naar _einde" #: data/ui/menubar.ui:165 msgid "_Previous From Video Position" msgstr "Vorige vanaf video_positie" #: data/ui/menubar.ui:169 msgid "_Next From Video Position" msgstr "Volge_nde vanaf videopositie" #: data/ui/menubar.ui:177 msgid "_Preferences" msgstr "_Instellingen" #: data/ui/menubar.ui:183 msgid "_View" msgstr "_Beeld" #: data/ui/menubar.ui:186 msgid "Tool_bar" msgstr "Werk_balk" #: data/ui/menubar.ui:190 msgid "_Video Player" msgstr "_Videospeler" #: data/ui/menubar.ui:196 msgid "_Layout" msgstr "Inde_ling" #: data/ui/menubar.ui:199 msgid "_Horizontal" msgstr "_Horizontaal" #: data/ui/menubar.ui:204 msgid "_Vertical" msgstr "_Verticaal" #: data/ui/menubar.ui:213 msgid "_Times" msgstr "_Tijdstippen" #: data/ui/menubar.ui:218 msgid "_Frames" msgstr "_Frames" #: data/ui/menubar.ui:225 msgid "F_ramerate" msgstr "F_ramesnelheid" #: data/ui/menubar.ui:228 msgid "2_3.976 fps" msgstr "2_3.976 fps" #: data/ui/menubar.ui:233 msgid "2_4.000 fps" msgstr "2_4.000 fps" #: data/ui/menubar.ui:238 msgid "2_5.000 fps" msgstr "2_5.000 fps" #: data/ui/menubar.ui:243 msgid "2_9.970 fps" msgstr "2_9.970 fps" #: data/ui/menubar.ui:272 msgid "_Columns" msgstr "_Kolommen" #: data/ui/menubar.ui:306 msgid "Cu_t" msgstr "Kni_ppen" #: data/ui/menubar.ui:310 msgid "_Copy" msgstr "_Kopiëren" #: data/ui/menubar.ui:314 msgid "_Paste" msgstr "_Plakken" #: data/ui/menubar.ui:318 msgid "Cl_ear" msgstr "Wiss_en" #: data/ui/menubar.ui:324 msgid "_Find And Replace…" msgstr "Zoeken en _vervangen…" #: data/ui/menubar.ui:332 msgid "Find Pre_vious" msgstr "Vo_rige zoeken" #: data/ui/menubar.ui:338 msgid "_Italic" msgstr "Curs_ief" #: data/ui/menubar.ui:342 msgid "_Dialogue" msgstr "_Dialoog" #: data/ui/menubar.ui:348 msgid "Ca_se" msgstr "Grote/Kleine tek_st" #: data/ui/menubar.ui:351 msgid "_Title" msgstr "_Titel" #: data/ui/menubar.ui:355 msgid "_Sentence" msgstr "_Zin" #: data/ui/menubar.ui:359 msgid "_Upper" msgstr "_Groot" #: data/ui/menubar.ui:363 msgid "_Lower" msgstr "K_lein" #: data/ui/menubar.ui:371 msgid "Vi_deo" msgstr "Vi_deo" #: data/ui/menubar.ui:374 msgid "_Load Video…" msgstr "Video _laden…" #: data/ui/menubar.ui:384 data/ui/view-popup.ui:26 msgid "Play _Selection" msgstr "_Selectie afspelen" #: data/ui/menubar.ui:410 data/ui/view-popup.ui:30 msgid "S_eek Selection Start" msgstr "Spo_elen naar begin van selectie" #: data/ui/menubar.ui:414 msgid "See_k Selection End" msgstr "Spo_elen naar einde van selectie" #: data/ui/menubar.ui:420 msgid "_Audio" msgstr "_Audio" #: data/ui/menubar.ui:423 msgid "_Language" msgstr "Taa_l" #: data/ui/menubar.ui:430 msgid "Volume _Down" msgstr "Volume omlaa_g" #: data/ui/menubar.ui:434 msgid "Volume _Up" msgstr "Vol_ume omhoog" #: data/ui/menubar.ui:440 msgid "T_ools" msgstr "Gereedsch_ap" #: data/ui/menubar.ui:443 data/ui/text-assistant/confirmation-page.ui:97 #: data/ui/view-popup.ui:36 msgid "_Preview" msgstr "_Voorvertoning" #: data/ui/menubar.ui:447 msgid "Select _Video…" msgstr "_Video kiezen…" #: data/ui/menubar.ui:453 msgid "_Check Spelling" msgstr "Spelling _controleren" #: data/ui/menubar.ui:457 msgid "Co_nfigure Spell-check…" msgstr "Spellingcontrole i_nstellen…" #: data/ui/menubar.ui:461 msgid "C_orrect Texts…" msgstr "Teksten c_orrigeren…" #: data/ui/menubar.ui:467 msgid "_Shift Positions…" msgstr "Po_sities verschuiven…" #: data/ui/menubar.ui:471 msgid "_Transform Positions…" msgstr "Posi_ties aanpassen…" #: data/ui/menubar.ui:475 msgid "Adjust _Durations…" msgstr "_Duur aanpassen…" #: data/ui/menubar.ui:479 msgid "Convert _Framerate…" msgstr "_Framesnelheid omzetten…" #: data/ui/menubar.ui:485 msgid "_Append File…" msgstr "Best_and invoegen…" #: data/ui/menubar.ui:489 msgid "Spli_t Project…" msgstr "Project spli_tsen…" #: data/ui/menubar.ui:495 msgid "_Projects" msgstr "_Projecten" #: data/ui/menubar.ui:498 msgid "_Save All" msgstr "Alles op_slaan" #: data/ui/menubar.ui:502 msgid "Save _All As…" msgstr "_Alles opslaan als…" #: data/ui/menubar.ui:506 msgid "_Close All" msgstr "Alles _sluiten" #: data/ui/menubar.ui:512 msgid "_Previous" msgstr "_Vorige" #: data/ui/menubar.ui:516 msgid "_Next" msgstr "Volge_nde" #: data/ui/menubar.ui:527 msgid "_Documentation" msgstr "_Documentatie" #: data/ui/menubar.ui:531 msgid "_Report A Bug" msgstr "Bug me_lden" #: data/ui/menubar.ui:535 msgid "_About" msgstr "_Over" #: data/ui/open-dialog.ui:39 msgid "Align _method:" msgstr "Uitlijn_methode:" #: data/ui/preferences-dialog.ui:18 msgid "Preferences" msgstr "Instellingen" #: data/ui/preferences-dialog.ui:93 msgid "When opening files, try encodings in the following order:" msgstr "Probeer de volgende tekenreeksen bij het openen van bestanden:" #: data/ui/preferences-dialog.ui:104 msgid "Curr_ent locale encoding" msgstr "Huidig_e tekenreeks" #: data/ui/preferences-dialog.ui:130 msgid "_Fallback encodings:" msgstr "Terug_vallen op:" #: data/ui/preferences-dialog.ui:246 msgid "Aut_o-detection" msgstr "Aut_omatisch detecteren:" #: data/ui/preferences-dialog.ui:266 msgid "Encoding specified in the open dialog will always be tried first." msgstr "" "De in het venster ‘Openen’ opgegeven tekenreeks wordt te allen tijde als " "eerste geprobeerd." #: data/ui/preferences-dialog.ui:296 msgid "File" msgstr "Bestand" #: data/ui/preferences-dialog.ui:324 msgid "Font" msgstr "Lettertype" #: data/ui/preferences-dialog.ui:344 msgid "Use _default theme fixed width font" msgstr "Vastebreedtelettertype van stan_daardthema gebruiken" #: data/ui/preferences-dialog.ui:368 msgid "_Editor font:" msgstr "Lettertype van invo_ervelden:" #: data/ui/preferences-dialog.ui:425 msgid "Line Lengths" msgstr "Regellengtes" #: data/ui/preferences-dialog.ui:445 msgid "_Show line lengths in list cells" msgstr "Regellengte_s tonen in lijstkolommen" #: data/ui/preferences-dialog.ui:462 msgid "S_how line lengths in editable text fields" msgstr "Regellengtes tonen in in_voervelden" #: data/ui/preferences-dialog.ui:486 msgid "_Length unit:" msgstr "_Lengte-eenheid:" #: data/ui/preferences-dialog.ui:540 msgid "Spell-Check" msgstr "Spellingcontrole" #: data/ui/preferences-dialog.ui:560 msgid "Chec_k spelling as you type" msgstr "Spelling _controleren tijdens typen" #: data/ui/preferences-dialog.ui:598 msgid "Editor" msgstr "Bewerker" #: data/ui/preferences-dialog.ui:626 msgid "Fonts" msgstr "Lettertypen" #: data/ui/preferences-dialog.ui:649 msgid "_Subtitles:" msgstr "_Ondertitelingen:" #: data/ui/preferences-dialog.ui:679 msgid "_Time:" msgstr "_Tijdstip:" #: data/ui/preferences-dialog.ui:729 msgid "Colors" msgstr "Kleuren" #: data/ui/preferences-dialog.ui:752 msgid "Su_btitles:" msgstr "On_dertitelingen:" #: data/ui/preferences-dialog.ui:777 msgid "_Use a background behind text" msgstr "Tekstachtergrond gebr_uiken" #: data/ui/preferences-dialog.ui:797 msgid "Ti_me:" msgstr "Ti_jdstip:" #: data/ui/preferences-dialog.ui:822 msgid "Us_e a background behind text" msgstr "Tekstacht_ergrond gebruiken" #: data/ui/preferences-dialog.ui:862 msgid "Seek" msgstr "Doorspoelen" #: data/ui/preferences-dialog.ui:883 msgid "_Length:" msgstr "_Lengte:" #: data/ui/preferences-dialog.ui:971 msgid "Video Player" msgstr "Videospeler" #: data/ui/preferences-dialog.ui:994 msgid "_Application:" msgstr "Progr_amma:" #: data/ui/preferences-dialog.ui:1008 msgid "Co_mmand:" msgstr "Op_dracht:" #. Translators: Only the title is to be translated, field names not. #: data/ui/preferences-dialog.ui:1033 msgid "" "Fields:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" msgstr "" "Velden:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" #: data/ui/preferences-dialog.ui:1048 msgid "Al_ways use UTF-8 character encoding" msgstr "Al_tijd UTF-8-tekenreeks gebruiken" #: data/ui/preferences-dialog.ui:1089 msgid "Start Position" msgstr "Beginpositie" #: data/ui/preferences-dialog.ui:1111 msgid "_Offset:" msgstr "C_ompensatie:" #: data/ui/preferences-dialog.ui:1142 msgid "seconds before selection" msgstr "seconden vóór de selectie" #: data/ui/preferences-dialog.ui:1281 msgid "Extensions" msgstr "Uitbreidingen" #: data/ui/language-dialog.ui:8 msgid "Configure Spell-Check" msgstr "Spellingcontrole instellen" #: data/ui/language-dialog.ui:50 msgid "Language" msgstr "Taal" #: data/ui/language-dialog.ui:128 msgid "Check _text column" msgstr "_Tekstkolom controleren" #: data/ui/language-dialog.ui:146 msgid "Check t_ranslation column" msgstr "Ve_rtaalkolom controleren" #: data/ui/language-dialog.ui:206 msgid "Check c_urrent project" msgstr "H_uidig protect controleren" #: data/ui/language-dialog.ui:224 msgid "Check _all open projects" msgstr "_Alle geopende projecten controleren" #: data/ui/text-assistant/confirmation-page.ui:22 msgid "Acc_ept, discard or edit changes:" msgstr "Bewerkingen goedk_euren, verwerpen of aanpassen:" #: data/ui/text-assistant/confirmation-page.ui:67 msgid "_Mark All" msgstr "Alles _markeren" #: data/ui/text-assistant/confirmation-page.ui:82 msgid "_Unmark All" msgstr "Alles _demarkeren" #: data/ui/text-assistant/confirmation-page.ui:119 msgid "_Remove all blank subtitles" msgstr "Alle blanco ondertitels ve_rwijderen" #: data/ui/text-assistant/join-split-page.ui:28 msgid "Spell-Check Dictionary" msgstr "Woordenboek" #: data/ui/text-assistant/join-split-page.ui:49 #: data/ui/text-assistant/line-break-page.ui:81 #: data/ui/text-assistant/hearing-impaired-page.ui:81 #: data/ui/text-assistant/common-error-page.ui:80 #: data/ui/text-assistant/capitalization-page.ui:80 msgid "_Language:" msgstr "Taa_l:" #: data/ui/text-assistant/join-split-page.ui:97 msgid "Corrections" msgstr "Correcties" #: data/ui/text-assistant/join-split-page.ui:117 msgid "_Join words not found in spell-check dictionary" msgstr "Woorden samenvoegen d_ie niet in het woordenboek staan" #: data/ui/text-assistant/join-split-page.ui:134 msgid "_Split words not found in spell-check dictionary" msgstr "Woorden _splitsen die niet in het woordenboek staan" #: data/ui/text-assistant/line-break-page.ui:22 msgid "S_elect preferred line-break points:" msgstr "Voorkeursregelafbrekingen s_electeren:" #: data/ui/text-assistant/line-break-page.ui:67 #: data/ui/text-assistant/hearing-impaired-page.ui:67 #: data/ui/text-assistant/common-error-page.ui:66 #: data/ui/text-assistant/capitalization-page.ui:66 msgid "_Script:" msgstr "_Script:" #: data/ui/text-assistant/line-break-page.ui:95 #: data/ui/text-assistant/hearing-impaired-page.ui:95 #: data/ui/text-assistant/common-error-page.ui:94 #: data/ui/text-assistant/capitalization-page.ui:94 msgid "Co_untry:" msgstr "La_nd:" #: data/ui/text-assistant/introduction-page.ui:28 msgid "_Select corrections to perform on texts:" msgstr "_Selecteer de toe te passen correcties:" #: data/ui/text-assistant/introduction-page.ui:79 msgid "Colu_mns:" msgstr "Kolo_mmen:" #: data/ui/text-assistant/introduction-page.ui:93 msgid "S_ubtitles:" msgstr "Ond_ertitels:" #: data/ui/text-assistant/line-break-options-page.ui:56 #: data/ui/duration-adjust-dialog.ui:207 msgid "Limits" msgstr "Beperkingen" #: data/ui/text-assistant/line-break-options-page.ui:79 msgid "_Maximum line length:" msgstr "_Maximale regellengte:" #: data/ui/text-assistant/line-break-options-page.ui:93 msgid "_Preferred maximum amount of lines:" msgstr "Ma_ximaal aantal regels:" #: data/ui/text-assistant/line-break-options-page.ui:198 msgid "_Skip subtitles with maximum line length of:" msgstr "Ondertitel_s overslaan met maximale regellengte:" #: data/ui/text-assistant/line-break-options-page.ui:214 msgid "S_kip subtitles with maximum line amount of:" msgstr "Ondertitels ove_rslaan met maximaal aantal regels:" #: data/ui/text-assistant/hearing-impaired-page.ui:22 msgid "S_elect parts to remove:" msgstr "S_electeer de te verwijderen delen:" #: data/ui/text-assistant/common-error-page.ui:22 msgid "S_elect errors to correct:" msgstr "S_electeer de te corrigeren fouten:" #: data/ui/text-assistant/common-error-page.ui:108 msgid "Error types:" msgstr "Soort fouten:" #: data/ui/text-assistant/common-error-page.ui:158 msgid "_Human errors" msgstr "_Menselijke fouten" #: data/ui/text-assistant/common-error-page.ui:175 msgid "_Image recognition errors" msgstr "Afbeeld_ingsherkenningfouten" #: data/ui/text-assistant/capitalization-page.ui:22 msgid "S_elect parts to capitalize:" msgstr "S_electeer de delen die moeten worden omgezet naar hoofdletters:" #: data/ui/duration-adjust-dialog.ui:33 msgid "Adjust Durations" msgstr "Duur aanpassen" #: data/ui/duration-adjust-dialog.ui:73 msgid "Theoretic Duration" msgstr "Theoretische duur" #: data/ui/duration-adjust-dialog.ui:101 msgid "_Reading speed:" msgstr "Lee_ssnelheid:" #: data/ui/duration-adjust-dialog.ui:133 msgid "characters per second" msgstr "tekens per seconde" #: data/ui/duration-adjust-dialog.ui:150 msgid "_Lengthen duration to match reading speed" msgstr "Duur ver_lengen om overeen te komen met leessnelheid" #: data/ui/duration-adjust-dialog.ui:167 msgid "_Shorten duration to match reading speed" msgstr "Duur verkorten om overeen te komen met lee_ssnelheid" #: data/ui/duration-adjust-dialog.ui:227 msgid "_Minimum duration:" msgstr "_Minimale duur:" #: data/ui/duration-adjust-dialog.ui:243 msgid "Ma_ximum duration:" msgstr "Ma_ximale duur:" #: data/ui/duration-adjust-dialog.ui:259 msgid "_Gap between subtitles:" msgstr "Ruimte tussen onder_titels:" #: data/ui/duration-adjust-dialog.ui:294 msgid "s_econds" msgstr "s_econden" #: data/ui/duration-adjust-dialog.ui:324 msgid "seco_nds" msgstr "seco_nden" #: data/ui/duration-adjust-dialog.ui:354 msgid "secon_ds" msgstr "secon_den" #: data/ui/duration-adjust-dialog.ui:408 msgid "Adj_ust selected subtitles" msgstr "Geselecteerde ondert_itels aanpassen" #: data/ui/duration-adjust-dialog.ui:425 msgid "Adjus_t current project" msgstr "H_uidig project aanpassen" #: data/ui/duration-adjust-dialog.ui:442 msgid "Adjust all _open projects" msgstr "_Alle geopende projecten aanpassen" #: data/ui/tab-popup.ui:6 msgid "Move Tab _Left" msgstr "Tabblad verplaatsen naar _links" #: data/ui/tab-popup.ui:10 msgid "Move Tab _Right" msgstr "Tabblad verplaatsen naar _rechts" #: data/ui/insert-dialog.ui:15 msgid "Insert Subtitles" msgstr "Ondertitel invoegen" #: data/ui/insert-dialog.ui:48 data/ui/position-shift-dialog.ui:82 msgid "_Amount:" msgstr "_Aantal:" #: data/ui/insert-dialog.ui:62 msgid "_Position:" msgstr "_Positie:" #: data/ui/position-shift-dialog.ui:14 msgid "Shift Positions" msgstr "Posities verschuiven" #: data/ui/position-shift-dialog.ui:54 msgid "Shift" msgstr "Verschuiven" #: data/ui/position-shift-dialog.ui:135 #: data/ui/position-transform-dialog.ui:208 msgid "_Preview Changes" msgstr "Aanpassingen _voorvertonen" #: data/ui/position-shift-dialog.ui:200 msgid "Shift s_elected subtitles" msgstr "Ges_electeerde ondertitels verschuiven" #: data/ui/position-shift-dialog.ui:217 msgid "Shift su_btitles from selection to end" msgstr "On_dertitels verschuiven van selectie tot einde" #: data/ui/position-shift-dialog.ui:234 msgid "Shift c_urrent project" msgstr "Huidig proje_ct verschuiven" #: data/ui/position-shift-dialog.ui:251 msgid "Shift all _open projects" msgstr "Alle ge_opende projecten verschuiven" #: data/ui/position-transform-dialog.ui:22 msgid "Transform Positions" msgstr "Posi_ties aanpassen" #: data/ui/position-transform-dialog.ui:62 msgid "First Point" msgstr "Eerste punt" #: data/ui/position-transform-dialog.ui:91 msgid "_Subtitle:" msgstr "_Ondertitel:" #: data/ui/position-transform-dialog.ui:105 msgid "C_orrection:" msgstr "C_orrectie:" #: data/ui/position-transform-dialog.ui:119 #: data/ui/position-transform-dialog.ui:310 msgid "Text:" msgstr "Tekst:" #: data/ui/position-transform-dialog.ui:253 msgid "Second Point" msgstr "Tweede punt" #: data/ui/position-transform-dialog.ui:282 msgid "Su_btitle:" msgstr "On_dertitel:" #: data/ui/position-transform-dialog.ui:296 msgid "Co_rrection:" msgstr "Co_rrectie:" #: data/ui/position-transform-dialog.ui:399 msgid "Pre_view Changes" msgstr "Aanpassingen _voorvertonen" #: data/ui/position-transform-dialog.ui:464 msgid "Transform se_lected subtitles" msgstr "Geselecteerde ondert_itels aanpassen" #: data/ui/position-transform-dialog.ui:482 msgid "Transform c_urrent project" msgstr "H_uidig project aanpassen" #: data/extensions/custom-framerates/custom-framerates.extension.in:7 msgid "Custom Framerates" msgstr "Aangepaste framesnelheden" #: data/extensions/custom-framerates/custom-framerates.extension.in:8 msgid "Allow use of non-standard framerates" msgstr "Gebruik van ongewone framesnelheden toestaan" #: data/patterns/Latn-en-US.common-error.in:5 msgid "Period after title" msgstr "Punt achter titel" #: data/patterns/Latn-en-US.common-error.in:6 msgid "Add period after a shortened title, such as \"Mr\" and \"Dr\"" msgstr "Voeg een punt toe achter een afkorting, zoals die van ‘Mr’ en ‘Dr’" #: data/patterns/Latn-en.capitalization.in:5 msgid "First person pronoun" msgstr "Voornaamwoord" #: data/patterns/Latn-en.capitalization.in:6 msgid "Capitalize the first person pronoun \"I\"" msgstr "‘I’ in Engelstalige teksten met hoofdletter schrijven" #: data/patterns/Latn-en.common-error.in:5 #: data/patterns/Latn-en.common-error.in:14 #: data/patterns/Latn-en.common-error.in:23 msgid "Letter \"I\" in a lower case word" msgstr "‘I’ in Engelstalige teksten in kleine letters schrijven" #: data/patterns/Latn-en.common-error.in:6 #: data/patterns/Latn-en.common-error.in:15 #: data/patterns/Latn-en.common-error.in:24 msgid "Replace letter \"I\" with letter \"l\" in a lower case word" msgstr "‘I’ in Engelstalige woorden met kleine letter schrijven" #: data/patterns/Latn-en.common-error.in:32 #: data/patterns/Latn-en.common-error.in:41 #: data/patterns/Latn-en.common-error.in:50 #: data/patterns/Latn-en.common-error.in:62 msgid "Letter \"l\" in an upper case word" msgstr "‘I’ in Engelstalige woorden met hoofdletter schrijven" #: data/patterns/Latn-en.common-error.in:33 #: data/patterns/Latn-en.common-error.in:42 #: data/patterns/Latn-en.common-error.in:51 #: data/patterns/Latn-en.common-error.in:63 msgid "Replace letter \"l\" with letter \"I\" in an upper case word" msgstr "‘i’ in Engelstalige woorden met hoofdletter schrijven" #: data/patterns/Latn-en.common-error.in:73 #: data/patterns/Latn-en.common-error.in:82 msgid "Zero in an upper case word" msgstr "Nul in woord met hoofdletters" #: data/patterns/Latn-en.common-error.in:74 #: data/patterns/Latn-en.common-error.in:83 msgid "Replace zero with letter \"O\" in an upper case word" msgstr "‘0’ in woorden met hoofdletters vervangen door ‘O’" #: data/patterns/Latn-en.common-error.in:91 #: data/patterns/Latn.common-error.in:108 msgid "Space between number and unit" msgstr "Spatie tussen getal en eenheid" #: data/patterns/Latn-en.common-error.in:92 #: data/patterns/Latn.common-error.in:109 msgid "Add or remove space between a number and the associated unit" msgstr "Voeg een spatie toe (of verwijder deze) tussen een getal en eenheid" #: data/patterns/Latn-en.common-error.in:100 msgid "Spaces around an apostrophe" msgstr "Spaties rondom aanhalingstekens" #: data/patterns/Latn-en.common-error.in:101 msgid "Remove spaces around an apostrophe" msgstr "Verwijder spaties rondom aanhalingstekens" #: data/patterns/Latn-en.common-error.in:109 #: data/patterns/Latn-en.common-error.in:118 msgid "Okay" msgstr "Oké" #: data/patterns/Latn-en.common-error.in:110 #: data/patterns/Latn-en.common-error.in:119 msgid "Spell two-letter forms of \"okay\" in all upper case" msgstr "‘okay’ vervangen door ‘OK’" #: data/patterns/Latn-en.hearing-impaired.in:5 msgid "Uppercase speaker before a colon" msgstr "Hoofdletters voor dubbele punten" #: data/patterns/Latn-en.hearing-impaired.in:6 msgid "" "Replace the uppercase name of the speaker before a colon with a dialogue " "dash" msgstr "" "Vervang de naam van een spreker voor een dubbele punt door een streepje" #: data/patterns/Latn-en.line-break.in:5 msgid "Title" msgstr "Titel" #: data/patterns/Latn-en.line-break.in:6 msgid "Do not break after a title, e.g. \" Dr.\"" msgstr "Geen spatie na een titel, zoals die van ‘ Dr.’" #: data/patterns/Latn-en.line-break.in:13 msgid "Article" msgstr "Lidwoord" #: data/patterns/Latn-en.line-break.in:14 msgid "Do not break after an article" msgstr "Geen spatie na lidwoorden" #: data/patterns/Latn-en.line-break.in:21 msgid "Preposition" msgstr "Voorzetsel" #: data/patterns/Latn-en.line-break.in:22 msgid "Do not break after a preposition" msgstr "Geen spatie na voorzetsels" #: data/patterns/Latn-en.line-break.in:30 msgid "Possessive determiner" msgstr "Bezittelijk voornaamwoord" #: data/patterns/Latn-en.line-break.in:31 msgid "Do not break after a possessive determiner, e.g. \"my\"" msgstr "Geen spatie na bezittelijke voornaamwoorden, zoals in ‘mijn’" #: data/patterns/Latn-fi.common-error.in:5 #: data/patterns/Latn.common-error.in:182 msgid "Space after punctuation marks" msgstr "Spatie na punctuatie" #: data/patterns/Latn-fi.common-error.in:6 #: data/patterns/Latn.common-error.in:183 msgid "Add space after various punctuation marks" msgstr "Voeg een spatie toe na punctuatie" #: data/patterns/Latn-fr.common-error.in:5 #: data/patterns/Latn-fr.common-error.in:14 #: data/patterns/Latn-fr.common-error.in:23 #: data/patterns/Latn-fr.common-error.in:32 msgid "Spaces around guillemets" msgstr "Spaties rondom guillemets" #: data/patterns/Latn-fr.common-error.in:6 #: data/patterns/Latn-fr.common-error.in:15 #: data/patterns/Latn-fr.common-error.in:24 #: data/patterns/Latn-fr.common-error.in:33 msgid "Add spaces around guillemets" msgstr "Voeg spaties toe rondom guillemets" #: data/patterns/Latn-fr.common-error.in:41 #: data/patterns/Latn-fr.common-error.in:52 #: data/patterns/Latn.common-error.in:171 msgid "Space before punctuation marks" msgstr "Spaties voor punctuatie" #: data/patterns/Latn-fr.common-error.in:42 #: data/patterns/Latn-fr.common-error.in:53 msgid "Add or remove space before various punctuation marks" msgstr "Voeg een spatie toe (of verwijder deze) voor punctuatie" #: data/patterns/Latn.capitalization.in:5 msgid "Sentence" msgstr "Zin" #: data/patterns/Latn.capitalization.in:6 msgid "Capitalize the first word of a sentence" msgstr "Zinnen beginnen met een hoofdletter" #: data/patterns/Latn.capitalization.in:12 msgid "Ellipsis" msgstr "Ellips" #: data/patterns/Latn.capitalization.in:13 msgid "Capitalize after an ellipsis" msgstr "Hoofdletter na ellipsen" #: data/patterns/Latn.common-error.in:8 data/patterns/Latn.common-error.in:17 #: data/patterns/Latn.common-error.in:26 data/patterns/Latn.common-error.in:35 #: data/patterns/Latn.common-error.in:44 data/patterns/Latn.common-error.in:53 #: data/patterns/Latn.common-error.in:62 msgid "Ligatures" msgstr "Ligaturen" #: data/patterns/Latn.common-error.in:9 data/patterns/Latn.common-error.in:18 #: data/patterns/Latn.common-error.in:27 data/patterns/Latn.common-error.in:36 #: data/patterns/Latn.common-error.in:45 data/patterns/Latn.common-error.in:54 #: data/patterns/Latn.common-error.in:63 msgid "Unpack ligatures to individual characters" msgstr "Ligaturen omzetten naar losse tekens" #: data/patterns/Latn.common-error.in:71 data/patterns/Latn.common-error.in:80 msgid "Spelling of a.m. and p.m." msgstr "Spelling van a.m. en p.m." #: data/patterns/Latn.common-error.in:72 data/patterns/Latn.common-error.in:81 msgid "Change the various spellings of 12-hour periods to \"a.m.\" and \"p.m.\"" msgstr "Verander de spelling van 12-uurnotaties in ‘a.m.’ en ‘p.m.’" #: data/patterns/Latn.common-error.in:89 data/patterns/Latn.common-error.in:98 msgid "Letter \"O\" in a number" msgstr "Letter ‘O’ als getal" #: data/patterns/Latn.common-error.in:90 data/patterns/Latn.common-error.in:99 msgid "Replace letter \"O\" with a zero in a number" msgstr "Vervang de letter ‘O’ door een nul in een getal" #: data/patterns/Latn.common-error.in:117 msgid "Double apostrophe" msgstr "Dubbele aanhalingstekens" #: data/patterns/Latn.common-error.in:118 msgid "Replace a double apostrophe with a quotation mark" msgstr "Vervang dubbele aanhalingstekens door citaataanduidingen" #: data/patterns/Latn.common-error.in:126 #: data/patterns/Latn.common-error.in:135 #: data/patterns/Latn.common-error.in:144 #: data/patterns/Latn.common-error.in:153 msgid "Spaces around brackets" msgstr "Spaties rondom haakjes" #: data/patterns/Latn.common-error.in:127 #: data/patterns/Latn.common-error.in:136 #: data/patterns/Latn.common-error.in:145 #: data/patterns/Latn.common-error.in:154 msgid "Add or remove spaces around parantheses and square brackets" msgstr "Voeg een spatie toe (of verwijder deze) rondom alle soorten haakjes" #: data/patterns/Latn.common-error.in:162 msgid "Space after a dialogue dash" msgstr "Spatie na dialoogstreepje" #: data/patterns/Latn.common-error.in:163 msgid "Add space after a dialogue dash" msgstr "Voeg een spatie toe na een dialoogstreepje" #: data/patterns/Latn.common-error.in:172 msgid "Remove space before various punctuation marks" msgstr "Verwijder een spatie voor punctuatie" #: data/patterns/Latn.common-error.in:192 msgid "Space after an ellipsis" msgstr "Spatie na ellips" #: data/patterns/Latn.common-error.in:193 msgid "Add space after an ellipsis" msgstr "Voeg een spatie toe na een ellips" #: data/patterns/Latn.common-error.in:201 msgid "Space after a starting ellipsis" msgstr "Spatie na ellips aan begin" #: data/patterns/Latn.common-error.in:202 msgid "Remove space after an ellipsis that starts a line" msgstr "Verwijder een spatie na een ellips aan het begin van een zin" #: data/patterns/Latn.common-error.in:210 #: data/patterns/Latn.common-error.in:221 #: data/patterns/Latn.common-error.in:232 #: data/patterns/Latn.common-error.in:242 msgid "Spaces around a quotation mark" msgstr "Spaties rondom citaataanduidingen" #: data/patterns/Latn.common-error.in:211 #: data/patterns/Latn.common-error.in:222 #: data/patterns/Latn.common-error.in:233 #: data/patterns/Latn.common-error.in:243 msgid "Remove space after a starting- and before an ending quotation mark" msgstr "" "Verwijder een spatie na het begin en voor het einde van een citaataanduiding" #: data/patterns/Latn.common-error.in:252 #: data/patterns/Latn.common-error.in:261 msgid "Spaces around musical notes" msgstr "Spaties rondom muzieknoten" #: data/patterns/Latn.common-error.in:253 #: data/patterns/Latn.common-error.in:262 msgid "Add spaces between musical note characters and lyrics" msgstr "Voeg spaties toe tussen muzieknoten en songteksten" #: data/patterns/Latn.common-error.in:270 #: data/patterns/Latn.common-error.in:279 msgid "Multiple question- and exclamation marks" msgstr "Meerdere vraag- en uitroeptekens" #: data/patterns/Latn.common-error.in:271 #: data/patterns/Latn.common-error.in:280 msgid "" "Replace multiple consequtive question- and exclamation marks with only one" msgstr "Vervang meerdere opeenvolgende vraag- en uitroeptekens door één" #: data/patterns/Latn.common-error.in:288 #: data/patterns/Latn.common-error.in:298 msgid "Periods around a punctuation mark" msgstr "Punt na punctuatie" #: data/patterns/Latn.common-error.in:289 #: data/patterns/Latn.common-error.in:299 msgid "Remove period before or after various punctuation marks" msgstr "Verwijder een punt voor of na punctuatie" #: data/patterns/Latn.common-error.in:308 msgid "Terminating double-dashes" msgstr "Dubbele streepjes" #: data/patterns/Latn.common-error.in:309 msgid "Replace a single clause-terminating dash with two dashes" msgstr "Vervang dubbele streepjes door twee streepjes" #: data/patterns/Latn.hearing-impaired.in:5 msgid "Sound in brackets" msgstr "Geluid tussen rechte haakjes" #: data/patterns/Latn.hearing-impaired.in:6 msgid "Remove description of a sound between square brackets" msgstr "Verwijder de geluidsomschrijving tussen rechte haakjes" #: data/patterns/Latn.hearing-impaired.in:12 msgid "Sound in parantheses" msgstr "Geluid tussen haakjes" #: data/patterns/Latn.hearing-impaired.in:13 msgid "Remove description of a sound between parantheses" msgstr "Verwijder de geluidsomschrijving tussen haakjes" #: data/patterns/Latn.hearing-impaired.in:19 msgid "Song lyrics between number signs" msgstr "Songteksten tussen getalaanduidingen" #: data/patterns/Latn.hearing-impaired.in:20 msgid "Remove song lyrics starting with or between number signs" msgstr "Verwijder songteksten die beginnen met een getal" #: data/patterns/Latn.hearing-impaired.in:27 msgid "One-line song lyrics between number signs" msgstr "Eénregelige songteksten tussen getalaanduidingen" #: data/patterns/Latn.hearing-impaired.in:28 msgid "Remove one-line song lyrics starting with or between number signs" msgstr "Verwijder éénregelige songteksten die beginnen met een getal" #: data/patterns/Latn.hearing-impaired.in:35 msgid "Speaker before a colon" msgstr "Spreker voor dubbele punt" #: data/patterns/Latn.hearing-impaired.in:36 msgid "Replace the name of the speaker before a colon with a dialogue dash" msgstr "" "Vervang de naam van een spreker voor een dubbele punt door een streepje" #: data/patterns/Latn.line-break.in:5 data/patterns/Latn.line-break.in:13 msgid "Dialogue" msgstr "Dialoog" #: data/patterns/Latn.line-break.in:6 data/patterns/Latn.line-break.in:14 msgid "Break according to dialogue separated by dashes" msgstr "Regelafbreking met streepjes op basis van dialoog" #: data/patterns/Latn.line-break.in:21 data/patterns/Latn.line-break.in:30 msgid "Clause" msgstr "Zinnen opdelen" #: data/patterns/Latn.line-break.in:22 data/patterns/Latn.line-break.in:31 msgid "Break according to clauses terminated by a punctuation mark" msgstr "Zinnen opdelen op basis van punctuatie" #: data/patterns/Latn.line-break.in:38 msgid "Number and unit" msgstr "Getal en eenheid" #: data/patterns/Latn.line-break.in:39 msgid "Do not break between a number and associated unit" msgstr "Geen regelafbreking tussen een getal en eenheid" #: data/patterns/Zyyy.common-error.in:5 data/patterns/Zyyy.common-error.in:14 msgid "Leading and trailing spaces" msgstr "Voor- en achterloopspaties" #: data/patterns/Zyyy.common-error.in:6 data/patterns/Zyyy.common-error.in:15 msgid "Remove spaces from the beginning and end of lines" msgstr "Verwijder spaties aan het begin en einde van regels" #: data/patterns/Zyyy.common-error.in:23 msgid "Multiple consecutive spaces" msgstr "Meerdere opeenvolgende spaties" #: data/patterns/Zyyy.common-error.in:24 msgid "Replace multiple consecutive spaces with only one" msgstr "Vervang meerdere opeenvolgende spaties door één" #: data/patterns/Zyyy.common-error.in:32 data/patterns/Zyyy.common-error.in:45 #: data/patterns/Zyyy.common-error.in:55 data/patterns/Zyyy.common-error.in:65 msgid "Space between digits" msgstr "Spaties tussen getallen" #: data/patterns/Zyyy.common-error.in:33 data/patterns/Zyyy.common-error.in:46 #: data/patterns/Zyyy.common-error.in:56 data/patterns/Zyyy.common-error.in:66 msgid "Remove space between digits of a number" msgstr "Verwijder spaties tussen getallen" #: data/patterns/Zyyy.common-error.in:79 msgid "Musical notes" msgstr "Muzieknoten" #: data/patterns/Zyyy.common-error.in:80 msgid "Replace Unicode musical note characters with number signs" msgstr "Vervang Unicode-muzieknoten door getalaanduidingen" #: data/io.otsaloma.gaupol.appdata.xml.in:7 msgid "Editor for text-based subtitles" msgstr "Bewerker voor op tekst gebaseerde ondertitels" #: data/io.otsaloma.gaupol.appdata.xml.in:9 msgid "" "Gaupol is an editor for text-based subtitle files. It supports multiple " "subtitle file formats and provides means of creating subtitles, editing " "texts and timing subtitles to match video." msgstr "" "Gaupol is een bewerker voor op tekst gebaseerde ondertitels. Gaupol " "ondersteunt meerdere soorten ondertitelformaten, en kan ook worden gebruikt " "om nieuwe ondertitels te maken, teksten aan te passen en ondertitels te " "timen met video's." #: data/io.otsaloma.gaupol.appdata.xml.in:40 msgid "Main window" msgstr "Hoofdvenster" #: data/io.otsaloma.gaupol.desktop.in:5 msgid "Subtitle Editor" msgstr "Ondertitels aanpassen" #: data/io.otsaloma.gaupol.desktop.in:6 msgid "Edit subtitle files" msgstr "Ondertitelbestanden aanpassen" #. TRANSLATORS: Search terms to find this application. Do NOT translate or #. localize the semicolons! The list MUST also end with a semicolon! #: data/io.otsaloma.gaupol.desktop.in:12 msgid "video;subtitles;captions;" msgstr "video;ondertitel;bijschrift;" gaupol-1.11/po/pl.po000066400000000000000000002213361422217132500143220ustar00rootroot00000000000000# 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. # # Translators: # Osmo Salomaa , 2016 # mkkot , 2019 # edasmax , 2020 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-04-03 04:00+0300\n" "PO-Revision-Date: 2016-07-07 00:55+0000\n" "Last-Translator: edasmax , 2020\n" "Language-Team: Polish (https://www.transifex.com/otsaloma/teams/64879/pl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pl\n" "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" #: aeidon/enums.py:40 gaupol/enums.py:38 msgid "Subtitle number" msgstr "Numer napisu" #: aeidon/enums.py:43 msgid "Subtitle position" msgstr "Pozycja napisu" #: aeidon/enums.py:59 msgid "23.976 fps" msgstr "23.976 fps" #: aeidon/enums.py:63 msgid "24.000 fps" msgstr "24.000 fps" #: aeidon/enums.py:67 msgid "25.000 fps" msgstr "25.000 fps" #: aeidon/enums.py:71 msgid "29.970 fps" msgstr "29.970 fps" #: aeidon/enums.py:75 data/ui/menubar.ui:248 msgid "30.000 fps" msgstr "" #: aeidon/enums.py:79 data/ui/menubar.ui:253 msgid "50.000 fps" msgstr "" #: aeidon/enums.py:83 data/ui/menubar.ui:258 msgid "59.940 fps" msgstr "" #: aeidon/enums.py:87 data/ui/menubar.ui:263 msgid "60.000 fps" msgstr "" #: aeidon/enums.py:112 msgid "Mac (classic)" msgstr "Mac (klasyczny)" #. TRANSLATORS: Most of the character encoding descriptions are copied from #. gedit, which is translated to very many languages. Check the gedit .po #. files for a reference: #. . #: aeidon/encodings.py:40 aeidon/encodings.py:43 aeidon/encodings.py:46 msgid "English" msgstr "Angielski" #: aeidon/encodings.py:41 aeidon/encodings.py:42 aeidon/encodings.py:69 msgid "Chinese traditional" msgstr "Chiński tradycyjny" #: aeidon/encodings.py:44 msgid "German" msgstr "Niemiecki" #: aeidon/encodings.py:45 aeidon/encodings.py:54 aeidon/encodings.py:59 #: aeidon/encodings.py:79 aeidon/encodings.py:105 msgid "Hebrew" msgstr "Hebrajski" #: aeidon/encodings.py:47 aeidon/encodings.py:51 aeidon/encodings.py:56 #: aeidon/encodings.py:73 aeidon/encodings.py:76 aeidon/encodings.py:98 #: aeidon/encodings.py:111 aeidon/encodings.py:122 msgid "Western" msgstr "Zachodni" #: aeidon/encodings.py:48 aeidon/encodings.py:61 aeidon/encodings.py:80 #: aeidon/encodings.py:103 msgid "Arabic" msgstr "Arabski" #: aeidon/encodings.py:49 aeidon/encodings.py:64 aeidon/encodings.py:66 #: aeidon/encodings.py:77 aeidon/encodings.py:104 aeidon/encodings.py:119 msgid "Greek" msgstr "Grecki" #: aeidon/encodings.py:50 aeidon/encodings.py:81 aeidon/encodings.py:101 #: aeidon/encodings.py:109 msgid "Baltic" msgstr "Bałtycki" #: aeidon/encodings.py:52 aeidon/encodings.py:74 aeidon/encodings.py:99 #: aeidon/encodings.py:121 msgid "Central European" msgstr "Środkowoeuropejski" #: aeidon/encodings.py:53 aeidon/encodings.py:75 aeidon/encodings.py:102 #: aeidon/encodings.py:118 msgid "Cyrillic" msgstr "Cyrylica" #: aeidon/encodings.py:55 aeidon/encodings.py:71 aeidon/encodings.py:78 #: aeidon/encodings.py:106 aeidon/encodings.py:123 msgid "Turkish" msgstr "Turecki" #: aeidon/encodings.py:57 msgid "Portuguese" msgstr "Portugalski" #: aeidon/encodings.py:58 aeidon/encodings.py:120 msgid "Icelandic" msgstr "Islandzki" #: aeidon/encodings.py:60 msgid "Canadian" msgstr "Kanadyjski" #: aeidon/encodings.py:62 aeidon/encodings.py:107 msgid "Nordic" msgstr "Nordycki" #: aeidon/encodings.py:63 aeidon/encodings.py:114 msgid "Russian" msgstr "Rosyjski" #: aeidon/encodings.py:65 aeidon/encodings.py:108 msgid "Thai" msgstr "Tajski" #: aeidon/encodings.py:67 aeidon/encodings.py:83 aeidon/encodings.py:84 #: aeidon/encodings.py:85 aeidon/encodings.py:91 aeidon/encodings.py:92 #: aeidon/encodings.py:93 aeidon/encodings.py:94 aeidon/encodings.py:95 #: aeidon/encodings.py:96 aeidon/encodings.py:125 aeidon/encodings.py:126 #: aeidon/encodings.py:127 msgid "Japanese" msgstr "Japoński" #: aeidon/encodings.py:68 aeidon/encodings.py:86 aeidon/encodings.py:97 #: aeidon/encodings.py:113 msgid "Korean" msgstr "Koreański" #: aeidon/encodings.py:70 msgid "Urdu" msgstr "Urdyjski" #: aeidon/encodings.py:72 aeidon/encodings.py:116 msgid "Ukrainian" msgstr "Ukraiński" #: aeidon/encodings.py:82 msgid "Vietnamese" msgstr "Wietnamski" #: aeidon/encodings.py:87 aeidon/encodings.py:90 msgid "Chinese simplified" msgstr "Chiński uproszczony" #: aeidon/encodings.py:88 aeidon/encodings.py:89 msgid "Chinese unified" msgstr "Chiński ujednolicony" #: aeidon/encodings.py:100 aeidon/encodings.py:112 msgid "South European" msgstr "Południowoeuropejski" #: aeidon/encodings.py:110 msgid "Celtic" msgstr "Celtycki" #: aeidon/encodings.py:115 msgid "Tajik" msgstr "Tadżycki" #: aeidon/encodings.py:117 msgid "Kazakh" msgstr "Kazachski" #: aeidon/encodings.py:124 msgid "Cyrillic Asian" msgstr "Cyrilica azjatycka" #: aeidon/encodings.py:128 aeidon/encodings.py:129 aeidon/encodings.py:130 #: aeidon/encodings.py:131 aeidon/encodings.py:132 aeidon/encodings.py:133 #: aeidon/encodings.py:134 aeidon/encodings.py:135 aeidon/encodings.py:136 msgid "Unicode" msgstr "Unicode" #: aeidon/encodings.py:156 #, python-brace-format msgid "{description} ({name})" msgstr "{description} ({name})" #: aeidon/encodings.py:232 msgid "Current locale ({})" msgstr "Bieżąca lokalizacja ({})" #: aeidon/locales.py:46 #, python-brace-format msgid "{language} ({country})" msgstr "{language} ({country})" #: aeidon/agents/search.py:227 msgid "Replacing" msgstr "Zastępowanie" #: aeidon/agents/search.py:256 aeidon/agents/search.py:258 msgid "Replacing all" msgstr "Zastępowanie wszystkiego" #: aeidon/agents/position.py:74 msgid "Adjusting durations" msgstr "Dopasowywanie czasów trwania" #: aeidon/agents/position.py:96 msgid "Converting framerate" msgstr "Konwertowanie liczby klatek" #: aeidon/agents/position.py:146 msgid "Setting framerate" msgstr "Ustawianie liczby klatek" #: aeidon/agents/position.py:168 msgid "Shifting positions" msgstr "Przesuń czasy" #: aeidon/agents/position.py:188 msgid "Transforming positions" msgstr "Transformowanie pozycji" #: aeidon/agents/clipboard.py:44 msgid "Cutting texts" msgstr "Wycinanie tekstu" #: aeidon/agents/clipboard.py:61 msgid "Pasting texts" msgstr "Wklejanie tekstu" #: aeidon/agents/text.py:91 msgid "Breaking lines" msgstr "Łamanie linii" #: aeidon/agents/text.py:128 msgid "Capitalizing texts" msgstr "Zamiana na wielkie litery" #: aeidon/agents/text.py:185 msgid "Correcting common errors" msgstr "Korygowanie typowych błędów" #: aeidon/agents/text.py:234 msgid "Removing hearing impaired texts" msgstr "Usuwanie niesłyszanlych tekstów" #: aeidon/agents/text.py:315 msgid "Joining words by spell-check suggestions" msgstr "Łączenie słów za pomocą sugestii sprawdzania pisowni" #: aeidon/agents/text.py:354 msgid "Splitting words by spell-check suggestions" msgstr "Dzielenie słów przez sugestie sprawdzania pisowni" #: aeidon/agents/set.py:58 aeidon/agents/set.py:80 aeidon/agents/set.py:113 msgid "Editing position" msgstr "Edytowanie pozycji" #: aeidon/agents/set.py:129 msgid "Editing text" msgstr "Edycja tekstu" #: aeidon/agents/edit.py:35 msgid "Clearing texts" msgstr "Czyszczenie tekstu" #: aeidon/agents/edit.py:61 aeidon/agents/edit.py:83 msgid "Inserting subtitles" msgstr "Wstawianie napisów" #: aeidon/agents/edit.py:103 msgid "Merging subtitles" msgstr "Wstawianie napisów" #: aeidon/agents/edit.py:114 msgid "Removing subtitles" msgstr "Usuwanie napisów" #: aeidon/agents/edit.py:131 msgid "Replacing positions" msgstr "Zastępowanie pozycji" #: aeidon/agents/edit.py:147 msgid "Replacing texts" msgstr "Zastępowanie tekstu" #: aeidon/agents/edit.py:171 msgid "Splitting subtitle" msgstr "Podział napisów" #: aeidon/agents/format.py:49 msgid "Adding dialogue dashes" msgstr "Dodanie kresek dialogowych" #: aeidon/agents/format.py:68 msgid "Changing case" msgstr "Zmiana wielkości liter" #: aeidon/agents/format.py:92 msgid "Italicizing" msgstr "Kursywa" #: aeidon/agents/format.py:108 msgid "Removing dialogue dashes" msgstr "Usuwanie linii dialogowych" #: aeidon/agents/format.py:174 msgid "Unitalicizing" msgstr "Usuwanie kursywy" #: gaupol/application.py:219 gaupol/agents/open.py:203 msgid "Open" msgstr "Otwórz" #: gaupol/application.py:223 msgid "Open main files" msgstr "Otwiera główne pliki" #: gaupol/application.py:230 msgid "Save" msgstr "Zapisz" #: gaupol/application.py:233 msgid "Save the current main document" msgstr "Zapisuje bieżący plik" #: gaupol/application.py:238 msgid "Undo" msgstr "Cofnij" #: gaupol/application.py:242 msgid "Undo the last action" msgstr "Cofa ostatnią akcję" #: gaupol/application.py:249 msgid "Redo" msgstr "Ponów" #: gaupol/application.py:252 msgid "Redo the last undone action" msgstr "Ponów ostatnio cofniętą akcję" #: gaupol/application.py:260 msgid "Insert" msgstr "Wstaw" #: gaupol/application.py:262 msgid "Insert new subtitles" msgstr "Wstaw nowe napisy" #: gaupol/application.py:266 #: data/extensions/custom-framerates/preferences-dialog.ui:78 msgid "Remove" msgstr "Usuń" #: gaupol/application.py:268 msgid "Remove the selected subtitles" msgstr "Usuń zaznaczone napisy" #: gaupol/application.py:273 data/ui/search-dialog.ui:283 msgid "Find" msgstr "Znajdź" #: gaupol/application.py:275 msgid "Search for and replace text" msgstr "Wyszukaj i zamień tekst" #: gaupol/application.py:279 data/ui/preferences-dialog.ui:942 msgid "Video" msgstr "Wideo" #: gaupol/application.py:281 msgid "Show or hide the video player" msgstr "Pokaż lub ukryj odtwarzacz wideo" #: gaupol/application.py:285 data/ui/preferences-dialog.ui:1173 msgid "Preview" msgstr "Podgląd" #: gaupol/application.py:287 msgid "Preview from selected position with a video player" msgstr "Podejrzyj w odtwarzaczu filmów od wybranego miejsca" #: gaupol/enums.py:37 msgid "No." msgstr "Nr" #: gaupol/enums.py:43 msgid "Start" msgstr "Początek" #: gaupol/enums.py:44 msgid "Start position" msgstr "Pozycja początkowa" #: gaupol/enums.py:49 msgid "End" msgstr "Koniec" #: gaupol/enums.py:50 msgid "End position" msgstr "Pozycja końcowa" #. TRANSLATORS: 'Dur.' is short for duration. It is used in the header #. of a column that contains numbers five digits wide. #: gaupol/enums.py:57 msgid "Dur." msgstr "cz. tr." #: gaupol/enums.py:58 msgid "Duration" msgstr "Czas trwania" #: gaupol/enums.py:63 gaupol/enums.py:64 msgid "Text" msgstr "Tekst" #: gaupol/enums.py:69 gaupol/enums.py:70 msgid "Translation" msgstr "Tłumaczenie" #: gaupol/enums.py:82 msgid "characters" msgstr "Znaki" #: gaupol/enums.py:85 msgid "ems" msgstr "ems" #: gaupol/page.py:60 msgid "Untitled {:d}" msgstr "Bez tytułu {:d}" #: gaupol/page.py:133 msgid "Close project" msgstr "Zamknij projekt" #: gaupol/page.py:145 msgid "{} translation" msgstr "{} tłumaczenie" #: gaupol/page.py:302 msgid "Path:" msgstr "Ścieżka:" #: gaupol/page.py:303 msgid "Format:" msgstr "Format:" #: gaupol/page.py:304 msgid "Encoding:" msgstr "Kodowanie:" #: gaupol/page.py:305 msgid "Newlines:" msgstr "Linie:" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:99 msgid "Tasks and Target" msgstr "Zadania i cel" #: gaupol/assistants.py:128 msgid "Correct texts in the text column" msgstr "Popraw tekst w kolumnie tekst" #: gaupol/assistants.py:129 msgid "Correct texts in the translation column" msgstr "Popraw tekst w kolumnie tłumaczenie" #: gaupol/assistants.py:138 msgid "Correct texts in selected subtitles" msgstr "Popraw teksty w wybranych napisach" #: gaupol/assistants.py:139 msgid "Correct texts in current project" msgstr "Popraw teksty w bieżącym projekcie" #: gaupol/assistants.py:140 msgid "Correct texts in all open projects" msgstr "Popraw teksty we wszystkich otwartych projektach" #: gaupol/assistants.py:363 msgid "Other" msgstr "Inny" #: gaupol/assistants.py:439 msgid "Capitalize texts written in lower case" msgstr "Zamień w tekście małe litery na wielkie" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:443 msgid "Capitalization Patterns" msgstr "Wzorce wielkich liter" #: gaupol/assistants.py:445 msgid "Capitalize texts" msgstr "Zamień na wielkie litery" #: gaupol/assistants.py:468 msgid "Correct common errors made by humans or image recognition software" msgstr "" "Popraw typowe błędy popełniane przez ludzi lub oprogramowanie do " "rozpoznawania obrazów" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:472 msgid "Common Error Patterns" msgstr "Typowe wzorce błędów" #: gaupol/assistants.py:474 msgid "Correct common errors" msgstr "Popraw typowe błędy" #: gaupol/assistants.py:526 msgid "Remove explanatory texts meant for the hearing impaired" msgstr "Usuń teksty wyjaśniające przeznaczone dla osób niedosłyszących" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:530 msgid "Hearing Impaired Patterns" msgstr "Wzory dla niedosłyszących" #: gaupol/assistants.py:532 msgid "Remove hearing impaired texts" msgstr "Usuń teksty dla niedosłyszących" #: gaupol/assistants.py:544 msgid "" "Use spell-check suggestions to fix whitespace detection errors of image " "recognition software" msgstr "" "Użyj sugestii sprawdzania pisowni, aby naprawić błędy wykrywania odstępów " "oprogramowania do rozpoznawania obrazów" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:548 msgid "Joining and Splitting Words" msgstr "Łączenie i dzielenie słów" #: gaupol/assistants.py:550 msgid "Join or Split Words" msgstr "Łączenie lub dzielenie wyrazów" #: gaupol/assistants.py:599 gaupol/agents/tools.py:45 msgid "Failed to load dictionary for language \"{}\"" msgstr "Nie można uruchomić słownika dla języka \"{}\"" #: gaupol/assistants.py:601 gaupol/player.py:263 gaupol/player.py:381 #: gaupol/dialogs/search.py:560 gaupol/dialogs/search.py:568 #: gaupol/dialogs/text_edit.py:49 gaupol/dialogs/encoding.py:56 #: gaupol/agents/open.py:328 gaupol/agents/open.py:337 #: gaupol/agents/open.py:345 gaupol/agents/open.py:354 #: gaupol/agents/tools.py:48 gaupol/agents/save.py:197 #: gaupol/agents/save.py:205 gaupol/agents/preview.py:108 #: gaupol/agents/preview.py:116 gaupol/agents/preview.py:125 #: gaupol/agents/preview.py:133 msgid "_OK" msgstr "_OK" #: gaupol/assistants.py:635 msgid "Break text into lines of defined length" msgstr "Podziel tekst na linie o określonej długości" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:639 msgid "Line-Break Patterns" msgstr "Wzorce podziału linii" #: gaupol/assistants.py:641 msgid "Break lines" msgstr "Podziel linie" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:679 msgid "Line-Break Options" msgstr "Opcje podziału linii" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:763 msgid "Correcting Texts" msgstr "Poprawianie tekstów" #: gaupol/assistants.py:769 msgid "Each task is now being run on each project." msgstr "Każde zadanie jest teraz uruchamiane w każdym projekcie." #: gaupol/assistants.py:793 #, python-brace-format msgid "{current:d} of {total:d} tasks complete" msgstr "{current:d} z {total:d} zadań ukończone" #: gaupol/assistants.py:801 msgid "Project: {}" msgstr "Projekt: {}" #: gaupol/assistants.py:807 msgid "Task: {}" msgstr "Zadanie: {}" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:832 msgid "Confirm Changes" msgstr "Potwierdź zmiany" #: gaupol/assistants.py:892 msgid "Accept" msgstr "Zaakceptuj" #: gaupol/assistants.py:898 msgid "Original Text" msgstr "Oryginalny tekst" #: gaupol/assistants.py:899 msgid "Corrected Text" msgstr "Poprawiony tekst" #: gaupol/assistants.py:1048 msgid "Correct Texts" msgstr "Popraw teksty" #: gaupol/assistants.py:1076 msgid "Correcting texts" msgstr "Poprawianie tekstów" #: gaupol/assistants.py:1092 #, python-brace-format msgid "Edited {edits:d} and removed {removals:d} subtitles" msgstr "Edytowane {edits:d} i usunięte {removals:d} napisy" #: gaupol/assistants.py:1126 msgid "Confirm {:d} Change" msgid_plural "Confirm {:d} Changes" msgstr[0] "Potwierdź {:d} zmianę" msgstr[1] "Potwierdź {:d} zmiany" msgstr[2] "Potwierdź {:d} zmiany" msgstr[3] "Potwierdź {:d} zmiany" #: gaupol/renderers/multiline.py:86 msgid "Italic" msgstr "Kursywa" #: gaupol/player.py:372 msgid "No video streams found" msgstr "" #: gaupol/player.py:379 msgid "Failed to initialize playback" msgstr "Nie można zainicjować odtwarzania" #: gaupol/dialogs/search.py:189 data/ui/menubar.ui:524 msgid "_Help" msgstr "_Pomoc" #: gaupol/dialogs/search.py:471 msgid "Found and replaced {:d} occurence" msgid_plural "Found and replaced {:d} occurences" msgstr[0] "Znaleziono i zastąpiono {:d} wystąpienie" msgstr[1] "Znaleziono i zastąpiono {:d} wystąpień" msgstr[2] "Znaleziono i zastąpiono {:d} wystąpień" msgstr[3] "Znaleziono i zastąpiono {:d} wystąpień" #: gaupol/dialogs/search.py:488 msgid "\"{}\" not found" msgstr "\"{}\" nie znaleziono" #: gaupol/dialogs/search.py:558 msgid "Error in regular expression pattern" msgstr "Błąd we wzorcu wyrażenia regularnego" #: gaupol/dialogs/search.py:566 msgid "Error in regular expression replacement" msgstr "Błąd podczas zastępowania wyrażenia regularnego" #: gaupol/dialogs/text_edit.py:48 gaupol/dialogs/framerate_convert.py:63 #: gaupol/dialogs/insert.py:44 gaupol/dialogs/encoding.py:55 #: gaupol/dialogs/split.py:44 gaupol/dialogs/multi_close.py:54 #: gaupol/dialogs/open.py:63 gaupol/dialogs/position_transform.py:69 #: gaupol/dialogs/position_shift.py:71 gaupol/dialogs/multi_save.py:83 #: gaupol/dialogs/multi_save.py:215 gaupol/dialogs/duration_adjust.py:86 #: gaupol/dialogs/save.py:73 gaupol/dialogs/video.py:41 #: gaupol/agents/open.py:363 gaupol/agents/open.py:375 #: gaupol/agents/open.py:387 gaupol/agents/close.py:71 #: data/extensions/custom-framerates/custom-framerates.py:39 msgid "_Cancel" msgstr "_Anuluj" #: gaupol/dialogs/text_edit.py:53 msgid "Edit Text" msgstr "Edytuj tekst" #: gaupol/dialogs/framerate_convert.py:64 msgid "Co_nvert" msgstr "Ko_nwertuj" #: gaupol/dialogs/insert.py:45 msgid "_Insert" msgstr "_Wstaw" #: gaupol/dialogs/insert.py:54 msgid "Above selection" msgstr "Powyżej wyboru" #: gaupol/dialogs/insert.py:55 msgid "Below selection" msgstr "Poniżej wyboru" #: gaupol/dialogs/encoding.py:60 data/ui/preferences-dialog.ui:70 msgid "Character Encodings" msgstr "Kodowanie znaków" #: gaupol/dialogs/encoding.py:78 gaupol/dialogs/encoding.py:125 msgid "Description" msgstr "Opis" #: gaupol/dialogs/encoding.py:85 gaupol/dialogs/encoding.py:132 msgid "Encoding" msgstr "Kodowanie znaków" #: gaupol/dialogs/encoding.py:141 msgid "Show in Menu" msgstr "Pokaż w menu" #: gaupol/dialogs/split.py:45 msgid "_Split" msgstr "_Podziel" #: gaupol/dialogs/split.py:76 msgid "Splitting project" msgstr "Dzielenie projektu" #: gaupol/dialogs/split.py:97 #, python-brace-format msgid "Split {amount:d} subtitles to project \"{name}\"" msgstr "Wydziel {amount:d} linii do projektu \"{name}\"" #: gaupol/dialogs/spell_check.py:269 msgid "Spell-checking" msgstr "Sprawdzanie pisowni" #: gaupol/dialogs/preferences.py:217 msgid "{} Extension Website" msgstr "{} Witryna rozszerzeń" #: gaupol/dialogs/preferences.py:429 msgid "Custom" msgstr "Dostosuj" #: gaupol/dialogs/multi_close.py:38 msgid "Save changes to documents before closing?" msgstr "Zapisz zmiany w dokumentach przed zamknięciem?" #: gaupol/dialogs/multi_close.py:39 gaupol/agents/open.py:384 #: gaupol/agents/close.py:68 msgid "If you don't save, changes will be permanently lost." msgstr "Jeśli nie zapiszesz zmian zostaną one bezpowrotnie utracone." #: gaupol/dialogs/multi_close.py:53 gaupol/agents/close.py:70 msgid "Close _Without Saving" msgstr "Zamknij _bez zapisywania" #: gaupol/dialogs/multi_close.py:55 gaupol/dialogs/multi_save.py:84 #: gaupol/dialogs/save.py:74 gaupol/agents/open.py:388 #: gaupol/agents/close.py:72 data/ui/menubar.ui:34 msgid "_Save" msgstr "_Zapisz" #: gaupol/dialogs/multi_close.py:70 msgid "Select the _main documents you want to save:" msgstr "Wybierz pliki _główne, które chcesz zapisać:" #: gaupol/dialogs/multi_close.py:95 msgid "Select the _translation documents you want to save:" msgstr "Wybierz pliki _tłumaczenia, które chcesz zapisać:" #: gaupol/dialogs/open.py:64 gaupol/agents/open.py:364 #: gaupol/agents/open.py:376 msgid "_Open" msgstr "_Otwórz" #: gaupol/dialogs/position_transform.py:70 msgid "_Transform" msgstr "_Przekształcać" #: gaupol/dialogs/position_shift.py:72 msgid "_Shift" msgstr "_Przesuń" #: gaupol/dialogs/position_shift.py:150 msgid "frames" msgstr "klatki" #: gaupol/dialogs/position_shift.py:168 data/ui/preferences-dialog.ui:911 msgid "seconds" msgstr "sekundy" #: gaupol/dialogs/about.py:36 msgid "About Gaupol" msgstr "O Gaupolu" #: gaupol/dialogs/about.py:40 msgid "Subtitle editor" msgstr "Edytor napisów" #. TRANSLATORS: This is a special message that shouldn't be translated #. literally. It is used in the about dialog to give credits to the #. translators. Thus, you should translate it to your name and email #. address. You can also include other translators who have contributed #. to this translation; in that case, please write them on separate #. lines seperated by newlines (\n). #: gaupol/dialogs/about.py:51 msgid "translator-credits" msgstr "napisy tłumacza" #: gaupol/dialogs/about.py:54 msgid "Gaupol Website" msgstr "Strona programu Gaupol" #: gaupol/dialogs/append.py:35 msgid "Append File" msgstr "Dołącz plik" #: gaupol/dialogs/debug.py:43 msgid "Something went wrong" msgstr "Coś poszło nie tak" #: gaupol/dialogs/debug.py:44 msgid "" "You have probably discovered a bug. Please report it by providing the below " "information and a description of what you were doing." msgstr "" "Prawdopodobnie odkryłeś błąd. Zgłoś go, podając poniższe informacje i opis " "tego, co robiłeś." #: gaupol/dialogs/debug.py:52 msgid "_Report Bug" msgstr "_Zgłoś błąd" #: gaupol/dialogs/debug.py:53 data/ui/menubar.ui:56 msgid "_Quit" msgstr "_Zakończ" #: gaupol/dialogs/debug.py:54 gaupol/dialogs/preview_error.py:45 #: data/ui/menubar.ui:52 data/ui/tab-popup.ui:16 msgid "_Close" msgstr "Za_mknij" #: gaupol/dialogs/multi_save.py:98 gaupol/dialogs/save.py:110 msgid "{} (recommended)" msgstr "{} (Zalecane)" #: gaupol/dialogs/multi_save.py:212 msgid "" "{:d} of the files to be saved already exist. Do you want to replace them?" msgstr "{:d} plik/ów, które mają zostać zapisane, już istnieje. Czy zastąpić?" #: gaupol/dialogs/multi_save.py:213 msgid "" "The files already exist in \"{}\". Replacing them will overwrite their " "contents." msgstr "" "Pliki już istnieją w \"{}\". Zastąpienie ich spowoduje nadpisanie ich " "zawartości." #: gaupol/dialogs/multi_save.py:216 data/ui/search-dialog.ui:192 #: data/ui/spell-check-dialog.ui:122 msgid "_Replace" msgstr "_Zastąp" #: gaupol/dialogs/duration_adjust.py:70 msgid "Adjusted duration of {:d} subtitle" msgid_plural "Adjusted durations of {:d} subtitles" msgstr[0] "Dostosowano czas trwania {:d} napisu" msgstr[1] "Dostosowano czas trwania {:d} napisów" msgstr[2] "Adjusted durations of {:d} subtitles" msgstr[3] "Adjusted durations of {:d} subtitles" #: gaupol/dialogs/duration_adjust.py:87 msgid "_Adjust" msgstr "Dopasuj" #: gaupol/dialogs/preview_error.py:36 msgid "Preview in video player failed" msgstr "Podgląd w odtwarzaczu wideo nie powiódł się" #: gaupol/dialogs/preview_error.py:37 msgid "" "There is probably a problem with either the video file or the video player. " "See the preferences dialog to choose the video player or to customize the " "command." msgstr "" "Prawdopodobnie wystąpił problem z plikiem wideo lub odtwarzaczem wideo. " "Zobacz okno dialogowe preferencji, aby wybrać odtwarzacz wideo lub " "dostosować polecenie." #: gaupol/dialogs/language.py:97 msgid "Set Language" msgstr "Ustaw język" #: gaupol/dialogs/video.py:52 gaupol/dialogs/file.py:59 msgid "All files" msgstr "Wszystkie pliki" #: gaupol/dialogs/video.py:56 msgid "Video files" msgstr "Pliki wideo" #: gaupol/dialogs/file.py:63 msgid "All supported files" msgstr "Wszystkie obsługiwane pliki" #: gaupol/dialogs/file.py:77 #, python-brace-format msgid "{format} (*{extension})" msgstr "{format} (*{extension})" #: gaupol/dialogs/file.py:120 msgid "Auto-detected" msgstr "Automatyczne wykrywanie" #: gaupol/dialogs/file.py:122 msgid "Other…" msgstr "Inny…" #: gaupol/agents/menu.py:94 gaupol/agents/menu.py:103 #: gaupol/agents/menu.py:110 msgid "File not found" msgstr "" #: gaupol/agents/open.py:85 #, python-brace-format msgid "Appended {amount:d} subtitles from \"{basename}\"" msgstr "Dołączone {amount:d} napisy z \"{basename}\"" #: gaupol/agents/open.py:96 msgid "Appending file" msgstr "Dołączanie pliku" #: gaupol/agents/open.py:111 msgid "File \"{}\" is already open" msgstr "Plik \"{}\" jest już otwarty" #: gaupol/agents/open.py:214 msgid "Open Translation" msgstr "Otwórz tłumaczenie" #: gaupol/agents/open.py:223 msgid "Select Video" msgstr "Wybierz plik wideo" #: gaupol/agents/open.py:224 msgid "_Select" msgstr "_Wybierz" #: gaupol/agents/open.py:325 msgid "Failed to decode file \"{}\" with all attempted codecs" msgstr "Nie udało się zdekodować pliku \"{}\" w żadnym z próbowanych kodowań" #: gaupol/agents/open.py:326 msgid "Please try to open the file with a different character encoding." msgstr "Spróbuj otworzyć plik z innym kodowaniem znaków." #: gaupol/agents/open.py:334 msgid "Failed to recognize format of file \"{}\"" msgstr "Nie rozpoznano formatu pliku \"{}\"" #: gaupol/agents/open.py:335 msgid "" "Please check that the file you are trying to open is a subtitle file of a " "format supported by Gaupol." msgstr "" "Sprawdź czy plik który starasz się otworzyć jest plikiem napisóww formacie " "obsługiwanym przez Gaupol." #: gaupol/agents/open.py:343 msgid "Failed to open file \"{}\"" msgstr "Nie można otworzyć pliku \"{}\"" #: gaupol/agents/open.py:351 msgid "Failed to parse file \"{}\"" msgstr "Nie można przeanalizować pliku \"{}\"" #: gaupol/agents/open.py:352 msgid "Please check that the file you are trying to open is a valid {} file." msgstr "" "Sprawdź, czy plik, który próbujesz otworzyć, jest prawidłowym plikiem {}." #: gaupol/agents/open.py:360 msgid "Open abnormally large file \"{}\"?" msgstr "Otworzyć zbyt duży plik \"{}\"?" #: gaupol/agents/open.py:361 msgid "" "Size of the file is {:.1f} MB, which is abnormally large for a text-based " "subtitle file. Please, check that you are not trying to open a binary file." msgstr "" "Rozmiar pliku to {:.1f} MB, co jest normalnie zbyt dużo dla tekstowegopliku " "napisów. Sprawdź czy nie próbujesz otworzyć pliku binarnego." #: gaupol/agents/open.py:371 msgid "Open unsorted file \"{}\"?" msgstr "Otwórz nieposortowany plik \"{}\"?" #: gaupol/agents/open.py:372 msgid "" "The order of {:d} subtitles needs to be changed. If {:d} sounds like a lot, " "the file may be erroneously composed." msgstr "" "Kolejność {:d} napisów musi zostać zmieniona. Jeśli {:d} to dużo, być może " "plik ma dużo błędów." #: gaupol/agents/open.py:383 msgid "Save changes to translation document \"{}\" before opening a new one?" msgstr "Zapisać zmiany w pliku tłumaczenia \"{}\" przed otwarciem nowego?" #: gaupol/agents/open.py:386 msgid "Open _Without Saving" msgstr "Otwórz _bez zapisywania" #: gaupol/agents/close.py:66 msgid "Save changes to document \"{}\" before closing?" msgstr "Zapisać zmiany w dokumencie \"{} \" przed zamknięciem?" #: gaupol/agents/edit.py:101 gaupol/agents/edit.py:119 msgid "Stretching end position" msgstr "Rozciąganie pozycji końcowej" #: gaupol/agents/edit.py:208 msgid "Inserted {:d} subtitle to fit clipboard contents" msgid_plural "Inserted {:d} subtitles to fit clipboard contents" msgstr[0] "Wstawiono {:d} napis na podstawie schowka" msgstr[1] "Wstawiono {:d} napisów na podstawie schowka" msgstr[2] "Wstawiono {:d} napisów na podstawie schowka" msgstr[3] "Wstawiono {:d} napisów na podstawie schowka" #: gaupol/agents/edit.py:334 gaupol/agents/edit.py:352 msgid "Stretching start position" msgstr "Rozciąganie pozycji początkowej" #: gaupol/agents/edit.py:411 msgid "Use Shift+Return for line-break" msgstr "Użyj Shift+Enter aby przejść do następnej linii" #: gaupol/agents/save.py:129 msgid "Save As" msgstr "Zapisz jako" #: gaupol/agents/save.py:135 msgid "Saved main document as \"{}\"" msgstr "Zapisano główny plik jako \"{}\"" #: gaupol/agents/save.py:153 msgid "Save Translation As" msgstr "Zapisz tłumaczenie jako" #: gaupol/agents/save.py:159 msgid "Saved translation document as \"{}\"" msgstr "Zapisano plik tłumaczenia jako \"{}\"" #: gaupol/agents/save.py:194 #, python-brace-format msgid "Failed to encode file \"{basename}\" with codec \"{codec}\"" msgstr "Nie można zakodować pliku \"{basename}\" przy użyciu kodeku \"{codec}\"" #: gaupol/agents/save.py:195 msgid "Please try to save the file with a different character encoding." msgstr "Proszę spróbuj zapisać plik z innym kodowaniem znaków." #: gaupol/agents/save.py:203 msgid "Failed to save file \"{}\"" msgstr "Nieudane zapisywanie pliku \"{}\"" #: gaupol/agents/video.py:67 data/ui/menubar.ui:380 msgid "_Play/Pause" msgstr "_Odtwarzaj/Wstrzymaj" #: gaupol/agents/video.py:69 msgid "Play or pause video" msgstr "Odtwarzaj lub wstrzymaj wideo" #: gaupol/agents/video.py:75 data/ui/menubar.ui:390 msgid "Seek _Previous" msgstr "Szukaj _Poprzednich" #: gaupol/agents/video.py:77 msgid "Seek to the start of the previous subtitle" msgstr "Szukaj na początku poprzedniego napisu" #: gaupol/agents/video.py:81 data/ui/menubar.ui:394 msgid "Seek _Next" msgstr "Szukaj _Dalej" #: gaupol/agents/video.py:83 msgid "Seek to the start of the next subtitle" msgstr "Szukaj na początku następnego napisu" #: gaupol/agents/video.py:88 data/ui/menubar.ui:400 msgid "Seek _Backward" msgstr "Szukaj _Wstecz" #: gaupol/agents/video.py:90 msgid "Seek backward" msgstr "Szukaj wstecz" #: gaupol/agents/video.py:94 data/ui/menubar.ui:404 msgid "Seek _Forward" msgstr "Szukaj _Dalej" #: gaupol/agents/video.py:96 msgid "Seek forward" msgstr "Szukaj dalej" #: gaupol/agents/video.py:109 msgid "Volume" msgstr "Głośność" #: gaupol/agents/video.py:189 msgid "Load Video" msgstr "Wczytaj wideo" #: gaupol/agents/video.py:189 msgid "_Load" msgstr "_Wczytaj" #: gaupol/agents/video.py:361 msgid "Track {:d}" msgstr "" #: gaupol/agents/preview.py:105 msgid "Failed to encode subtitle file to temporary directory \"{}\"" msgstr "Nieudane kodowanie pliku napisów do tymczasowego katalogu \"{}\"" #: gaupol/agents/preview.py:106 msgid "" "Subtitle data could not be encoded to a temporary file for preview with the " "current character encoding. Please first save the subtitle file with a " "different character encoding." msgstr "" "Dane napisów nie mogą być zakodowane do pliku tymczasowego dla podglądu z " "aktualnym kodowaniem znaków. Najpierw zapisz plik z napisami w innym " "kodowaniu znaków." #: gaupol/agents/preview.py:114 msgid "Failed to save subtitle file to temporary directory \"{}\"" msgstr "Nieudany zapis pliku napisów do tymczasowego katalogu \"{}\"" #: gaupol/agents/preview.py:122 msgid "Video player not found" msgstr "Nie znaleziono odtwarzacza wideo" #: gaupol/agents/preview.py:123 msgid "" "Please install one of the supported video players: mpv (recommended), " "MPlayer or VLC. See the preferences dialog to choose the video player or to " "customize the command." msgstr "" "Zainstaluj jeden z obsługiwanych odtwarzaczy wideo: mpv (zalecane), MPlayer " "lub VLC. Zobacz okno dialogowe preferencji, aby wybrać odtwarzacz wideo lub " "dostosować polecenie." #: gaupol/agents/preview.py:131 msgid "Failed to launch video player" msgstr "Nie można uruchomić odtwarzacza wideo" #: gaupol/applicationman.py:105 msgid "gaupol [OPTION...] [FILE...] [+[NUM]]" msgstr "gaupol [OPTION...] [FILE...] [+[NUM]]" #: gaupol/applicationman.py:109 msgid "FILE..." msgstr "PLIK..." #: gaupol/applicationman.py:112 msgid "subtitle files to open" msgstr "pliki napisów do otwarcia" #: gaupol/applicationman.py:122 msgid "ENCODING" msgstr "KODOWANIE" #: gaupol/applicationman.py:125 msgid "set the character encoding used to open files" msgstr "ustaw kodowanie znaków używane do otwierania plików" #: gaupol/applicationman.py:132 msgid "list all available character encodings" msgstr "wymień wszystkie dostępne kodowania znaków" #: gaupol/applicationman.py:137 gaupol/applicationman.py:154 msgid "FILE" msgstr "PLIK" #: gaupol/applicationman.py:140 msgid "open translation file" msgstr "otwórz plik tłumaczenia" #: gaupol/applicationman.py:145 msgid "METHOD" msgstr "METODA" #: gaupol/applicationman.py:149 msgid "method used to align translation subtitles: 'number' or 'position'" msgstr "" "metoda używana do wyrównania napisów do tłumaczenia: \"liczba\" lub " "\"pozycja\"" #: gaupol/applicationman.py:157 msgid "select video file" msgstr "wybierz plik wideo" #: data/extensions/custom-framerates/custom-framerates.py:40 #: data/ui/spell-check-dialog.ui:152 msgid "_Add" msgstr "_Dodaj" #: data/extensions/custom-framerates/custom-framerates.py:171 msgid "{:.3f} fps" msgstr "{:.3f} fps" #: data/extensions/custom-framerates/add-framerate-dialog.ui:13 msgid "Add Framerate" msgstr "Dodaj ilość klatek" #: data/extensions/custom-framerates/add-framerate-dialog.ui:44 msgid "_Framerate:" msgstr "Ilość klatek:" #: data/extensions/custom-framerates/add-framerate-dialog.ui:73 msgid "fps" msgstr "fps" #: data/extensions/custom-framerates/preferences-dialog.ui:8 msgid "Framerates" msgstr "Ilości klatek" #: data/extensions/custom-framerates/preferences-dialog.ui:64 msgid "Add" msgstr "Dodaj" #: data/ui/columns-popup.ui:6 data/ui/menubar.ui:275 msgid "_No." msgstr "_Nr" #: data/ui/columns-popup.ui:10 data/ui/menubar.ui:279 msgid "_Start" msgstr "_Początek" #: data/ui/columns-popup.ui:14 data/ui/menubar.ui:283 msgid "_End" msgstr "_Koniec" #: data/ui/columns-popup.ui:18 data/ui/menubar.ui:287 msgid "_Duration" msgstr "_Czas trwania" #: data/ui/columns-popup.ui:22 data/ui/menubar.ui:291 data/ui/menubar.ui:303 msgid "_Text" msgstr "_Tekst" #: data/ui/columns-popup.ui:26 data/ui/menubar.ui:295 msgid "T_ranslation" msgstr "Tłumaczenie" #: data/ui/split-dialog.ui:15 msgid "Split Project" msgstr "Podziel projekt" #: data/ui/split-dialog.ui:48 msgid "_First subtitle of new project:" msgstr "_Pierwsze napisy w nowym projekcie:" #: data/ui/search-dialog.ui:89 msgid "_Search for:" msgstr "Szukaj:" #: data/ui/search-dialog.ui:103 data/ui/spell-check-dialog.ui:193 msgid "Replace _with:" msgstr "Zastąp _za pomocą:" #: data/ui/search-dialog.ui:162 data/ui/menubar.ui:328 msgid "Find _Next" msgstr "Znajdź _następny" #: data/ui/search-dialog.ui:177 msgid "Find _Previous" msgstr "Znajdź _poprzedni" #: data/ui/search-dialog.ui:207 msgid "Replace _All" msgstr "Zastąp _wszystko" #: data/ui/search-dialog.ui:241 msgid "R_egular expression" msgstr "Wyraż_enie regularne" #: data/ui/search-dialog.ui:258 msgid "_Ignore case" msgstr "_Ignoruj wielkość znaków" #: data/ui/search-dialog.ui:304 data/ui/language-dialog.ui:108 msgid "Columns" msgstr "Kolumny" #: data/ui/search-dialog.ui:324 msgid "Find in _text column" msgstr "Znajdź w kolumnie _tekst" #: data/ui/search-dialog.ui:341 msgid "Find in t_ranslation column" msgstr "Znajdź w kolumnie tłumaczenie" #: data/ui/search-dialog.ui:381 data/ui/framerate-convert-dialog.ui:144 #: data/ui/language-dialog.ui:186 #: data/ui/text-assistant/line-break-options-page.ui:178 #: data/ui/duration-adjust-dialog.ui:388 data/ui/position-shift-dialog.ui:180 #: data/ui/position-transform-dialog.ui:444 msgid "Subtitles" msgstr "Napisy" #: data/ui/search-dialog.ui:401 msgid "Find in c_urrent project" msgstr "Szukaj w _bieżącym projekcie" #: data/ui/search-dialog.ui:419 msgid "Find in _all open projects" msgstr "Szukaj we _wszystkich otwartych projektach" #: data/ui/search-dialog.ui:452 msgid "Target" msgstr "Cel" #: data/ui/framerate-convert-dialog.ui:8 msgid "Convert Framerate" msgstr "Konwertuj liczbę klatek" #: data/ui/framerate-convert-dialog.ui:48 msgid "Framerate" msgstr "Liczba klatek" #: data/ui/framerate-convert-dialog.ui:71 msgid "_Input:" msgstr "Wejście" #: data/ui/framerate-convert-dialog.ui:86 msgid "_Output:" msgstr "Wyjście" #: data/ui/framerate-convert-dialog.ui:164 msgid "Convert c_urrent project" msgstr "Konwert_uj bieżący projekt" #: data/ui/framerate-convert-dialog.ui:181 msgid "Convert _all open projects" msgstr "Konwertuj _wszystkie otwarte projekty" #: data/ui/spell-check-dialog.ui:8 msgid "Check Spelling" msgstr "Sprawdź pisownię" #: data/ui/spell-check-dialog.ui:47 msgid "Join _Back" msgstr "Połącz w _tył" #: data/ui/spell-check-dialog.ui:62 msgid "Join _Forward" msgstr "Połącz w _przód" #: data/ui/spell-check-dialog.ui:77 data/ui/menubar.ui:62 msgid "_Edit" msgstr "_Edycja" #: data/ui/spell-check-dialog.ui:92 msgid "_Ignore" msgstr "_Ignoruj" #: data/ui/spell-check-dialog.ui:107 msgid "Ig_nore All" msgstr "Ignoruj wszystko" #: data/ui/spell-check-dialog.ui:137 msgid "Rep_lace All" msgstr "Zastąp wszystko" #: data/ui/spell-check-dialog.ui:179 msgid "_Suggestions:" msgstr "_Sugestie:" #: data/ui/multi-save-dialog.ui:8 msgid "Save All As" msgstr "Zapisz wszystkie jako" #: data/ui/multi-save-dialog.ui:46 msgid "Save in _folder:" msgstr "Zapisz w _folderze" #: data/ui/multi-save-dialog.ui:60 data/ui/save-dialog.ui:25 msgid "For_mat:" msgstr "For_mat:" #: data/ui/multi-save-dialog.ui:74 data/ui/open-dialog.ui:25 #: data/ui/save-dialog.ui:39 msgid "_Encoding:" msgstr "Kodowani_e:" #: data/ui/multi-save-dialog.ui:88 data/ui/save-dialog.ui:53 msgid "Ne_wlines:" msgstr "No_we linie:" #: data/ui/multi-save-dialog.ui:103 msgid "Select A Folder" msgstr "Wybierz folder" #: data/ui/multi-save-dialog.ui:150 data/ui/save-dialog.ui:102 msgid "F_ramerate:" msgstr "Ilość klatek:" #: data/ui/menubar.ui:5 msgid "_File" msgstr "_Plik" #: data/ui/menubar.ui:8 msgid "_New" msgstr "_Nowy" #: data/ui/menubar.ui:12 msgid "_Open…" msgstr "_Otwórz…" #: data/ui/menubar.ui:16 msgid "Open _Translation…" msgstr "_Otwórz tłumaczenie…" #: data/ui/menubar.ui:22 msgid "Open _Recent" msgstr "Otwó_rz ostatnie" #: data/ui/menubar.ui:27 msgid "Open R_ecent Translation" msgstr "Otwó_rz ostatnie tłumaczenie" #: data/ui/menubar.ui:38 msgid "Save _As…" msgstr "Z_apisz jako…" #: data/ui/menubar.ui:42 msgid "Save Trans_lation" msgstr "Zapisz tłumaczenie" #: data/ui/menubar.ui:46 msgid "Save Translat_ion As…" msgstr "Zapisz tłumaczen_ie jako..." #: data/ui/menubar.ui:65 msgid "_Undo" msgstr "Cof_nij" #: data/ui/menubar.ui:69 msgid "_Redo" msgstr "P_onów" #: data/ui/menubar.ui:75 msgid "_Edit Cell" msgstr "_Edytuj komórkę" #: data/ui/menubar.ui:79 msgid "Edit _Next Cell" msgstr "Edytuj _następną komórkę" #: data/ui/menubar.ui:85 msgid "Stretc_h" msgstr "Rozciągnij" #: data/ui/menubar.ui:88 msgid "_Start Earlier" msgstr "Zacznij wcześniej" #: data/ui/menubar.ui:92 msgid "S_tart Later" msgstr "Zacznij później" #: data/ui/menubar.ui:98 msgid "E_nd Earlier" msgstr "Skończ wcześniej" #: data/ui/menubar.ui:102 msgid "En_d Later" msgstr "Skończ później" #: data/ui/menubar.ui:108 msgid "Set St_art From Video Position" msgstr "Ustaw St_art z pozycji wideo" #: data/ui/menubar.ui:112 msgid "Set En_d From Video Position" msgstr "Ustaw koniec z pozycji wideo" #: data/ui/menubar.ui:118 data/ui/view-popup.ui:6 msgid "_Split Subtitle" msgstr "Podziel napi_sy" #: data/ui/menubar.ui:122 data/ui/view-popup.ui:10 msgid "_Merge Subtitles" msgstr "_Połącz napisy" #: data/ui/menubar.ui:128 data/ui/view-popup.ui:16 msgid "_Insert Subtitles…" msgstr "Wstaw napisy..." #: data/ui/menubar.ui:132 msgid "Inser_t Subtitle At Video Position" msgstr "Wstaw napisy do pozycji wideo..." #: data/ui/menubar.ui:136 data/ui/view-popup.ui:20 msgid "Rem_ove Subtitles" msgstr "_Usuń napisy" #: data/ui/menubar.ui:142 msgid "Sele_ction" msgstr "Zaznaczenie" #: data/ui/menubar.ui:145 msgid "Select _All" msgstr "Z_aznacz wszystko" #: data/ui/menubar.ui:149 msgid "_Invert Selection" msgstr "Odwróć zaznaczenie" #: data/ui/menubar.ui:155 msgid "Extend To _Beginning" msgstr "Rozszerz do początku" #: data/ui/menubar.ui:159 msgid "Extend To _End" msgstr "Rozszerz do końca" #: data/ui/menubar.ui:165 msgid "_Previous From Video Position" msgstr "" #: data/ui/menubar.ui:169 msgid "_Next From Video Position" msgstr "" #: data/ui/menubar.ui:177 msgid "_Preferences" msgstr "Ustawienia" #: data/ui/menubar.ui:183 msgid "_View" msgstr "_Widok" #: data/ui/menubar.ui:186 msgid "Tool_bar" msgstr "Pasek narzędziowy" #: data/ui/menubar.ui:190 msgid "_Video Player" msgstr "Odtwarzacz wideo" #: data/ui/menubar.ui:196 msgid "_Layout" msgstr "Układ" #: data/ui/menubar.ui:199 msgid "_Horizontal" msgstr "Poziomy" #: data/ui/menubar.ui:204 msgid "_Vertical" msgstr "Pionowy" #: data/ui/menubar.ui:213 msgid "_Times" msgstr "Czasy" #: data/ui/menubar.ui:218 msgid "_Frames" msgstr "Klatki" #: data/ui/menubar.ui:225 msgid "F_ramerate" msgstr "Ilość klatek" #: data/ui/menubar.ui:228 msgid "2_3.976 fps" msgstr "2_3.976 fps" #: data/ui/menubar.ui:233 msgid "2_4.000 fps" msgstr "2_4.000 fps" #: data/ui/menubar.ui:238 msgid "2_5.000 fps" msgstr "2_5.000 fps" #: data/ui/menubar.ui:243 msgid "2_9.970 fps" msgstr "2_9.970 fps" #: data/ui/menubar.ui:272 msgid "_Columns" msgstr "_Kolumny" #: data/ui/menubar.ui:306 msgid "Cu_t" msgstr "Wytnij" #: data/ui/menubar.ui:310 msgid "_Copy" msgstr "S_kopiuj" #: data/ui/menubar.ui:314 msgid "_Paste" msgstr "_Wklej" #: data/ui/menubar.ui:318 msgid "Cl_ear" msgstr "Wyczyść" #: data/ui/menubar.ui:324 msgid "_Find And Replace…" msgstr "Znajdź i zamień..." #: data/ui/menubar.ui:332 msgid "Find Pre_vious" msgstr "Znajdź poprzedni" #: data/ui/menubar.ui:338 msgid "_Italic" msgstr "_Pochylenie" #: data/ui/menubar.ui:342 msgid "_Dialogue" msgstr "_Dialog" #: data/ui/menubar.ui:348 msgid "Ca_se" msgstr "_Rozmiar" #: data/ui/menubar.ui:351 msgid "_Title" msgstr "_Tytuł" #: data/ui/menubar.ui:355 msgid "_Sentence" msgstr "_Zdanie" #: data/ui/menubar.ui:359 msgid "_Upper" msgstr "D_uże litery" #: data/ui/menubar.ui:363 msgid "_Lower" msgstr "Małe _litery" #: data/ui/menubar.ui:371 msgid "Vi_deo" msgstr "Wideo" #: data/ui/menubar.ui:374 msgid "_Load Video…" msgstr "Załaduj wideo ..." #: data/ui/menubar.ui:384 data/ui/view-popup.ui:26 msgid "Play _Selection" msgstr "Odtwórz zaznaczenie" #: data/ui/menubar.ui:410 data/ui/view-popup.ui:30 msgid "S_eek Selection Start" msgstr "idź na początek zaznaczenia" #: data/ui/menubar.ui:414 msgid "See_k Selection End" msgstr "idź na koniec zaznaczenia" #: data/ui/menubar.ui:420 msgid "_Audio" msgstr "_Audio" #: data/ui/menubar.ui:423 msgid "_Language" msgstr "Język" #: data/ui/menubar.ui:430 msgid "Volume _Down" msgstr "Ścisz" #: data/ui/menubar.ui:434 msgid "Volume _Up" msgstr "Zwiększ głośność" #: data/ui/menubar.ui:440 msgid "T_ools" msgstr "Narzędzia" #: data/ui/menubar.ui:443 data/ui/text-assistant/confirmation-page.ui:97 #: data/ui/view-popup.ui:36 msgid "_Preview" msgstr "_Podgląd" #: data/ui/menubar.ui:447 msgid "Select _Video…" msgstr "Wybierz wideo ..." #: data/ui/menubar.ui:453 msgid "_Check Spelling" msgstr "_Sprawdź pisownię" #: data/ui/menubar.ui:457 msgid "Co_nfigure Spell-check…" msgstr "Konfiguruj sprawdzanie pisowni ..." #: data/ui/menubar.ui:461 msgid "C_orrect Texts…" msgstr "Popraw teksty ..." #: data/ui/menubar.ui:467 msgid "_Shift Positions…" msgstr "Przesuń pozycje..." #: data/ui/menubar.ui:471 msgid "_Transform Positions…" msgstr "Przekształć pozycje..." #: data/ui/menubar.ui:475 msgid "Adjust _Durations…" msgstr "Dostosuj czas trwania..." #: data/ui/menubar.ui:479 msgid "Convert _Framerate…" msgstr "Konwersja ilości klatek..." #: data/ui/menubar.ui:485 msgid "_Append File…" msgstr "Dołącz plik..." #: data/ui/menubar.ui:489 msgid "Spli_t Project…" msgstr "Podziel projekt..." #: data/ui/menubar.ui:495 msgid "_Projects" msgstr "_Projekty" #: data/ui/menubar.ui:498 msgid "_Save All" msgstr "_Zapisz wszystko" #: data/ui/menubar.ui:502 msgid "Save _All As…" msgstr "_Zapisz wszystko jako..." #: data/ui/menubar.ui:506 msgid "_Close All" msgstr "Za_mknij wszystko" #: data/ui/menubar.ui:512 msgid "_Previous" msgstr "_Poprzedni" #: data/ui/menubar.ui:516 msgid "_Next" msgstr "_Następny" #: data/ui/menubar.ui:527 msgid "_Documentation" msgstr "_Dokumentacja" #: data/ui/menubar.ui:531 msgid "_Report A Bug" msgstr "Zgłoś _błąd" #: data/ui/menubar.ui:535 msgid "_About" msgstr "_O programie" #: data/ui/open-dialog.ui:39 msgid "Align _method:" msgstr "Metoda Wyrównania:" #: data/ui/preferences-dialog.ui:18 msgid "Preferences" msgstr "Preferencje" #: data/ui/preferences-dialog.ui:93 msgid "When opening files, try encodings in the following order:" msgstr "" "Podczas otwierania plików spróbuj kodowania w następującej kolejności:" #: data/ui/preferences-dialog.ui:104 msgid "Curr_ent locale encoding" msgstr "Bi_erzące kodowanie znaków" #: data/ui/preferences-dialog.ui:130 msgid "_Fallback encodings:" msgstr "_Używane kodowania:" #: data/ui/preferences-dialog.ui:246 msgid "Aut_o-detection" msgstr "Automatyczne wykrywanie" #: data/ui/preferences-dialog.ui:266 msgid "Encoding specified in the open dialog will always be tried first." msgstr "" "Kodowanie określone w oknie dialogowym Otwórz zawsze będzie jako pierwsze." #: data/ui/preferences-dialog.ui:296 msgid "File" msgstr "Plik" #: data/ui/preferences-dialog.ui:324 msgid "Font" msgstr "Czcionka" #: data/ui/preferences-dialog.ui:344 msgid "Use _default theme fixed width font" msgstr "Użyj domyślnej czcionki o stałej szerokości" #: data/ui/preferences-dialog.ui:368 msgid "_Editor font:" msgstr "Czcionka _edytora:" #: data/ui/preferences-dialog.ui:425 msgid "Line Lengths" msgstr "Długości linii" #: data/ui/preferences-dialog.ui:445 msgid "_Show line lengths in list cells" msgstr "Pokaż długości linii w komórkach listy" #: data/ui/preferences-dialog.ui:462 msgid "S_how line lengths in editable text fields" msgstr "Pokaż długości linii w edytowalnych polach tekstowych" #: data/ui/preferences-dialog.ui:486 msgid "_Length unit:" msgstr "Jednostka długości:" #: data/ui/preferences-dialog.ui:540 msgid "Spell-Check" msgstr "Sprawdzanie pisowni" #: data/ui/preferences-dialog.ui:560 msgid "Chec_k spelling as you type" msgstr "Sprawdź pisownię podczas pisania" #: data/ui/preferences-dialog.ui:598 msgid "Editor" msgstr "Edytor" #: data/ui/preferences-dialog.ui:626 msgid "Fonts" msgstr "Czcionki" #: data/ui/preferences-dialog.ui:649 msgid "_Subtitles:" msgstr "Napisy:" #: data/ui/preferences-dialog.ui:679 msgid "_Time:" msgstr "Czas:" #: data/ui/preferences-dialog.ui:729 msgid "Colors" msgstr "Kolory" #: data/ui/preferences-dialog.ui:752 msgid "Su_btitles:" msgstr "Napisy:" #: data/ui/preferences-dialog.ui:777 msgid "_Use a background behind text" msgstr "Użyj tła za tekstem" #: data/ui/preferences-dialog.ui:797 msgid "Ti_me:" msgstr "Czas:" #: data/ui/preferences-dialog.ui:822 msgid "Us_e a background behind text" msgstr "Użyj tła za tekstem" #: data/ui/preferences-dialog.ui:862 msgid "Seek" msgstr "Skocz" #: data/ui/preferences-dialog.ui:883 msgid "_Length:" msgstr "Długość:" #: data/ui/preferences-dialog.ui:971 msgid "Video Player" msgstr "Odtwarzacz wideo" #: data/ui/preferences-dialog.ui:994 msgid "_Application:" msgstr "_Aplikacja:" #: data/ui/preferences-dialog.ui:1008 msgid "Co_mmand:" msgstr "_Polecenie:" #. Translators: Only the title is to be translated, field names not. #: data/ui/preferences-dialog.ui:1033 msgid "" "Fields:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" msgstr "" "Pola:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" #: data/ui/preferences-dialog.ui:1048 msgid "Al_ways use UTF-8 character encoding" msgstr "Zawsze używaj kodowania znaków UTF-8" #: data/ui/preferences-dialog.ui:1089 msgid "Start Position" msgstr "Pozycja początkowa" #: data/ui/preferences-dialog.ui:1111 msgid "_Offset:" msgstr "_Przesunięcie:" #: data/ui/preferences-dialog.ui:1142 msgid "seconds before selection" msgstr "sekund przed zaznaczeniem" #: data/ui/preferences-dialog.ui:1281 msgid "Extensions" msgstr "Rozszerzenia" #: data/ui/language-dialog.ui:8 msgid "Configure Spell-Check" msgstr "Konfiguruj sprawdzanie pisowni" #: data/ui/language-dialog.ui:50 msgid "Language" msgstr "Język" #: data/ui/language-dialog.ui:128 msgid "Check _text column" msgstr "Sprawdź kolumnę tekst" #: data/ui/language-dialog.ui:146 msgid "Check t_ranslation column" msgstr "Sprawdź kolumnę tłumaczenie" #: data/ui/language-dialog.ui:206 msgid "Check c_urrent project" msgstr "Sprawdź _bieżący projekt" #: data/ui/language-dialog.ui:224 msgid "Check _all open projects" msgstr "Sprawdź _wszystkie otwarte projekty" #: data/ui/text-assistant/confirmation-page.ui:22 msgid "Acc_ept, discard or edit changes:" msgstr "Zaakceptuj, odrzuć lub edytuj zmiany:" #: data/ui/text-assistant/confirmation-page.ui:67 msgid "_Mark All" msgstr "Zaznacz wszystko" #: data/ui/text-assistant/confirmation-page.ui:82 msgid "_Unmark All" msgstr "Odznacz wszystko" #: data/ui/text-assistant/confirmation-page.ui:119 msgid "_Remove all blank subtitles" msgstr "Usuń wszystkie puste napisy" #: data/ui/text-assistant/join-split-page.ui:28 msgid "Spell-Check Dictionary" msgstr "Słownik sprawdzania pisowni" #: data/ui/text-assistant/join-split-page.ui:49 #: data/ui/text-assistant/line-break-page.ui:81 #: data/ui/text-assistant/hearing-impaired-page.ui:81 #: data/ui/text-assistant/common-error-page.ui:80 #: data/ui/text-assistant/capitalization-page.ui:80 msgid "_Language:" msgstr "Język:" #: data/ui/text-assistant/join-split-page.ui:97 msgid "Corrections" msgstr "Poprawki" #: data/ui/text-assistant/join-split-page.ui:117 msgid "_Join words not found in spell-check dictionary" msgstr "Dołącz do słowa nie odnalezione w słowniku sprawdzania pisowni" #: data/ui/text-assistant/join-split-page.ui:134 msgid "_Split words not found in spell-check dictionary" msgstr "Podziel słowa nie odnalezione w słowniku sprawdzania pisowni" #: data/ui/text-assistant/line-break-page.ui:22 msgid "S_elect preferred line-break points:" msgstr "Wybierz preferowane punkty podziału linii:" #: data/ui/text-assistant/line-break-page.ui:67 #: data/ui/text-assistant/hearing-impaired-page.ui:67 #: data/ui/text-assistant/common-error-page.ui:66 #: data/ui/text-assistant/capitalization-page.ui:66 msgid "_Script:" msgstr "Skrypt:" #: data/ui/text-assistant/line-break-page.ui:95 #: data/ui/text-assistant/hearing-impaired-page.ui:95 #: data/ui/text-assistant/common-error-page.ui:94 #: data/ui/text-assistant/capitalization-page.ui:94 msgid "Co_untry:" msgstr "Kraj:" #: data/ui/text-assistant/introduction-page.ui:28 msgid "_Select corrections to perform on texts:" msgstr "Wybierz poprawki do wykonania w tekście:" #: data/ui/text-assistant/introduction-page.ui:79 msgid "Colu_mns:" msgstr "Kolumny:" #: data/ui/text-assistant/introduction-page.ui:93 msgid "S_ubtitles:" msgstr "Napisy:" #: data/ui/text-assistant/line-break-options-page.ui:56 #: data/ui/duration-adjust-dialog.ui:207 msgid "Limits" msgstr "Limity" #: data/ui/text-assistant/line-break-options-page.ui:79 msgid "_Maximum line length:" msgstr "Maksymalna długość linii:" #: data/ui/text-assistant/line-break-options-page.ui:93 msgid "_Preferred maximum amount of lines:" msgstr "Preferowana maksymalna liczba linii:" #: data/ui/text-assistant/line-break-options-page.ui:198 msgid "_Skip subtitles with maximum line length of:" msgstr "Pomiń napisy o maksymalnej długości linii:" #: data/ui/text-assistant/line-break-options-page.ui:214 msgid "S_kip subtitles with maximum line amount of:" msgstr "Pomiń napisy z maksymalną ilością wierszy:" #: data/ui/text-assistant/hearing-impaired-page.ui:22 msgid "S_elect parts to remove:" msgstr "Wybierz części do usunięcia:" #: data/ui/text-assistant/common-error-page.ui:22 msgid "S_elect errors to correct:" msgstr "Wybierz błędy do poprawienia:" #: data/ui/text-assistant/common-error-page.ui:108 msgid "Error types:" msgstr "Rodzaje błędów:" #: data/ui/text-assistant/common-error-page.ui:158 msgid "_Human errors" msgstr "Błędy ludzkie " #: data/ui/text-assistant/common-error-page.ui:175 msgid "_Image recognition errors" msgstr "Błędy rozpoznawania obrazu" #: data/ui/text-assistant/capitalization-page.ui:22 msgid "S_elect parts to capitalize:" msgstr "Zaznacz części do powiększenia liter:" #: data/ui/duration-adjust-dialog.ui:33 msgid "Adjust Durations" msgstr "Dopasuj czasy trwania" #: data/ui/duration-adjust-dialog.ui:73 msgid "Theoretic Duration" msgstr "Teoretyczny czas trwania" #: data/ui/duration-adjust-dialog.ui:101 msgid "_Reading speed:" msgstr "Szybkość czytania:" #: data/ui/duration-adjust-dialog.ui:133 msgid "characters per second" msgstr "ilość znaków na sekundę" #: data/ui/duration-adjust-dialog.ui:150 msgid "_Lengthen duration to match reading speed" msgstr "Wydłuż czas trwania, aby dopasować szybkości czytania" #: data/ui/duration-adjust-dialog.ui:167 msgid "_Shorten duration to match reading speed" msgstr "Skróć czas trwania, aby dopasować do szybkości czytania" #: data/ui/duration-adjust-dialog.ui:227 msgid "_Minimum duration:" msgstr "_Minimalny czas trwania:" #: data/ui/duration-adjust-dialog.ui:243 msgid "Ma_ximum duration:" msgstr "Ma_ksymalny czas trwania:" #: data/ui/duration-adjust-dialog.ui:259 msgid "_Gap between subtitles:" msgstr "_Przerwa pomiędzy napisami:" #: data/ui/duration-adjust-dialog.ui:294 msgid "s_econds" msgstr "s_ekundy" #: data/ui/duration-adjust-dialog.ui:324 msgid "seco_nds" msgstr "se_kundy" #: data/ui/duration-adjust-dialog.ui:354 msgid "secon_ds" msgstr "sek_undy" #: data/ui/duration-adjust-dialog.ui:408 msgid "Adj_ust selected subtitles" msgstr "Dostosuj wybrane napisy" #: data/ui/duration-adjust-dialog.ui:425 msgid "Adjus_t current project" msgstr "Dostosuj bieżący projekt" #: data/ui/duration-adjust-dialog.ui:442 msgid "Adjust all _open projects" msgstr "Dostosuj wszystkie otwarte projekty" #: data/ui/tab-popup.ui:6 msgid "Move Tab _Left" msgstr "Przesuń tabulację w lewo" #: data/ui/tab-popup.ui:10 msgid "Move Tab _Right" msgstr "Przesuń tabulację w prawo" #: data/ui/insert-dialog.ui:15 msgid "Insert Subtitles" msgstr "Wstaw napisy" #: data/ui/insert-dialog.ui:48 data/ui/position-shift-dialog.ui:82 msgid "_Amount:" msgstr "_Ilość:" #: data/ui/insert-dialog.ui:62 msgid "_Position:" msgstr "_Pozycja:" #: data/ui/position-shift-dialog.ui:14 msgid "Shift Positions" msgstr "Przesuń pozycje" #: data/ui/position-shift-dialog.ui:54 msgid "Shift" msgstr "Przesuń" #: data/ui/position-shift-dialog.ui:135 #: data/ui/position-transform-dialog.ui:208 msgid "_Preview Changes" msgstr "_Podejrzyj zmiany" #: data/ui/position-shift-dialog.ui:200 msgid "Shift s_elected subtitles" msgstr "Przesuń _zaznaczone napisy" #: data/ui/position-shift-dialog.ui:217 msgid "Shift su_btitles from selection to end" msgstr "Przesuń napisy od zaznaczenia do końca" #: data/ui/position-shift-dialog.ui:234 msgid "Shift c_urrent project" msgstr "Przesuń w b_ierzącym projekcie" #: data/ui/position-shift-dialog.ui:251 msgid "Shift all _open projects" msgstr "" #: data/ui/position-transform-dialog.ui:22 msgid "Transform Positions" msgstr "Przekształć pozycje" #: data/ui/position-transform-dialog.ui:62 msgid "First Point" msgstr "Pierwszy punkt" #: data/ui/position-transform-dialog.ui:91 msgid "_Subtitle:" msgstr "Napi_sy:" #: data/ui/position-transform-dialog.ui:105 msgid "C_orrection:" msgstr "Korekta:" #: data/ui/position-transform-dialog.ui:119 #: data/ui/position-transform-dialog.ui:310 msgid "Text:" msgstr "Tekst:" #: data/ui/position-transform-dialog.ui:253 msgid "Second Point" msgstr "Drugi punkt" #: data/ui/position-transform-dialog.ui:282 msgid "Su_btitle:" msgstr "Na_pisy:" #: data/ui/position-transform-dialog.ui:296 msgid "Co_rrection:" msgstr "Korekta:" #: data/ui/position-transform-dialog.ui:399 msgid "Pre_view Changes" msgstr "Pode_jrzyj zmiany" #: data/ui/position-transform-dialog.ui:464 msgid "Transform se_lected subtitles" msgstr "Przekształć wybrane napisy" #: data/ui/position-transform-dialog.ui:482 msgid "Transform c_urrent project" msgstr "Przekształć bieżący projekt" #: data/extensions/custom-framerates/custom-framerates.extension.in:7 msgid "Custom Framerates" msgstr "Niestandardowe szybkości klatek" #: data/extensions/custom-framerates/custom-framerates.extension.in:8 msgid "Allow use of non-standard framerates" msgstr "Zezwalaj na używanie niestandardowych szybkości klatek" #: data/patterns/Latn-en-US.common-error.in:5 msgid "Period after title" msgstr "Okres po tytule" #: data/patterns/Latn-en-US.common-error.in:6 msgid "Add period after a shortened title, such as \"Mr\" and \"Dr\"" msgstr "Dodaj okres po skróconym tytule, np. \"Mr\" i \"Dr\"" #: data/patterns/Latn-en.capitalization.in:5 msgid "First person pronoun" msgstr "Zaimek pierwszej osoby" #: data/patterns/Latn-en.capitalization.in:6 msgid "Capitalize the first person pronoun \"I\"" msgstr "Kapitalizuj zaimek pierwszej osoby \"I\"" #: data/patterns/Latn-en.common-error.in:5 #: data/patterns/Latn-en.common-error.in:14 #: data/patterns/Latn-en.common-error.in:23 msgid "Letter \"I\" in a lower case word" msgstr "Litera \"I\" w słowie pisanym małymi literami" #: data/patterns/Latn-en.common-error.in:6 #: data/patterns/Latn-en.common-error.in:15 #: data/patterns/Latn-en.common-error.in:24 msgid "Replace letter \"I\" with letter \"l\" in a lower case word" msgstr "Zastąp literę \"I\" literą \"l\" w słowie pisanym małymi literami" #: data/patterns/Latn-en.common-error.in:32 #: data/patterns/Latn-en.common-error.in:41 #: data/patterns/Latn-en.common-error.in:50 #: data/patterns/Latn-en.common-error.in:62 msgid "Letter \"l\" in an upper case word" msgstr "Litera \"l\" w słowie pisanym wielkimi literami" #: data/patterns/Latn-en.common-error.in:33 #: data/patterns/Latn-en.common-error.in:42 #: data/patterns/Latn-en.common-error.in:51 #: data/patterns/Latn-en.common-error.in:63 msgid "Replace letter \"l\" with letter \"I\" in an upper case word" msgstr "Zastąp literę \"l\" literą \"I\" w słowie pisanym wielkimi literami" #: data/patterns/Latn-en.common-error.in:73 #: data/patterns/Latn-en.common-error.in:82 msgid "Zero in an upper case word" msgstr "Zero w wyrazie pisanym wielkimi literami" #: data/patterns/Latn-en.common-error.in:74 #: data/patterns/Latn-en.common-error.in:83 msgid "Replace zero with letter \"O\" in an upper case word" msgstr "Zastąpić zero literą \"O\" w słowie pisanym wielkimi literami" #: data/patterns/Latn-en.common-error.in:91 #: data/patterns/Latn.common-error.in:108 msgid "Space between number and unit" msgstr "Odstęp między liczbą a jednostką" #: data/patterns/Latn-en.common-error.in:92 #: data/patterns/Latn.common-error.in:109 msgid "Add or remove space between a number and the associated unit" msgstr "Dodaj lub usuń spację między liczbą a powiązaną jednostką" #: data/patterns/Latn-en.common-error.in:100 msgid "Spaces around an apostrophe" msgstr "Spacje wokół apostrofu" #: data/patterns/Latn-en.common-error.in:101 msgid "Remove spaces around an apostrophe" msgstr "Usuń spacje wokół apostrofu" #: data/patterns/Latn-en.common-error.in:109 #: data/patterns/Latn-en.common-error.in:118 msgid "Okay" msgstr "Okay" #: data/patterns/Latn-en.common-error.in:110 #: data/patterns/Latn-en.common-error.in:119 msgid "Spell two-letter forms of \"okay\" in all upper case" msgstr "Przetłumacz dwuliterowe formy \"okay\" we wszystkich wielkich literach" #: data/patterns/Latn-en.hearing-impaired.in:5 msgid "Uppercase speaker before a colon" msgstr "Wielkie dźwięki przed dwukropkiem" #: data/patterns/Latn-en.hearing-impaired.in:6 msgid "" "Replace the uppercase name of the speaker before a colon with a dialogue " "dash" msgstr "Zastąp wielką nazwę dźwięku przed dwukropkiem za pomocą myślnika" #: data/patterns/Latn-en.line-break.in:5 msgid "Title" msgstr "Tytuł" #: data/patterns/Latn-en.line-break.in:6 msgid "Do not break after a title, e.g. \" Dr.\"" msgstr "Nie dziel po tytule, np. \" Dr.\"" #: data/patterns/Latn-en.line-break.in:13 msgid "Article" msgstr "Artykuł" #: data/patterns/Latn-en.line-break.in:14 msgid "Do not break after an article" msgstr "Nie dziel po artykule" #: data/patterns/Latn-en.line-break.in:21 msgid "Preposition" msgstr "Przyimek" #: data/patterns/Latn-en.line-break.in:22 msgid "Do not break after a preposition" msgstr "Nie dziel po przyimku" #: data/patterns/Latn-en.line-break.in:30 msgid "Possessive determiner" msgstr "Zaimek dzierżawczy" #: data/patterns/Latn-en.line-break.in:31 msgid "Do not break after a possessive determiner, e.g. \"my\"" msgstr "Nie dziel po zaimku dzierżawczym, np. \"my\"" #: data/patterns/Latn-fi.common-error.in:5 #: data/patterns/Latn.common-error.in:182 msgid "Space after punctuation marks" msgstr "Spacja po znakach interpunkcyjnych" #: data/patterns/Latn-fi.common-error.in:6 #: data/patterns/Latn.common-error.in:183 msgid "Add space after various punctuation marks" msgstr "Dodaj spację po różnych znakach interpunkcyjnych" #: data/patterns/Latn-fr.common-error.in:5 #: data/patterns/Latn-fr.common-error.in:14 #: data/patterns/Latn-fr.common-error.in:23 #: data/patterns/Latn-fr.common-error.in:32 msgid "Spaces around guillemets" msgstr "Spacje wokół cytatów" #: data/patterns/Latn-fr.common-error.in:6 #: data/patterns/Latn-fr.common-error.in:15 #: data/patterns/Latn-fr.common-error.in:24 #: data/patterns/Latn-fr.common-error.in:33 msgid "Add spaces around guillemets" msgstr "Dodaj spacje wokół cytatów" #: data/patterns/Latn-fr.common-error.in:41 #: data/patterns/Latn-fr.common-error.in:52 #: data/patterns/Latn.common-error.in:171 msgid "Space before punctuation marks" msgstr "Spacja przed znakami interpunkcyjnymi" #: data/patterns/Latn-fr.common-error.in:42 #: data/patterns/Latn-fr.common-error.in:53 msgid "Add or remove space before various punctuation marks" msgstr "Dodaj lub usuń spacje przed różnymi znakami interpunkcyjnymi" #: data/patterns/Latn.capitalization.in:5 msgid "Sentence" msgstr "Zdanie" #: data/patterns/Latn.capitalization.in:6 msgid "Capitalize the first word of a sentence" msgstr "Pierwsze słowo zdania wielką literą" #: data/patterns/Latn.capitalization.in:12 msgid "Ellipsis" msgstr "Wielokropki" #: data/patterns/Latn.capitalization.in:13 msgid "Capitalize after an ellipsis" msgstr "Wielka litera po wielokropku" #: data/patterns/Latn.common-error.in:8 data/patterns/Latn.common-error.in:17 #: data/patterns/Latn.common-error.in:26 data/patterns/Latn.common-error.in:35 #: data/patterns/Latn.common-error.in:44 data/patterns/Latn.common-error.in:53 #: data/patterns/Latn.common-error.in:62 msgid "Ligatures" msgstr "Ligatury" #: data/patterns/Latn.common-error.in:9 data/patterns/Latn.common-error.in:18 #: data/patterns/Latn.common-error.in:27 data/patterns/Latn.common-error.in:36 #: data/patterns/Latn.common-error.in:45 data/patterns/Latn.common-error.in:54 #: data/patterns/Latn.common-error.in:63 msgid "Unpack ligatures to individual characters" msgstr "Rozpakuj ligatury do poszczególnych znaków" #: data/patterns/Latn.common-error.in:71 data/patterns/Latn.common-error.in:80 msgid "Spelling of a.m. and p.m." msgstr "Pisownia a.m. i p.m." #: data/patterns/Latn.common-error.in:72 data/patterns/Latn.common-error.in:81 msgid "Change the various spellings of 12-hour periods to \"a.m.\" and \"p.m.\"" msgstr "Zmieniaj pisownię z 12-godzinnych okresów na \"a.m.\" i \"p.m.\"" #: data/patterns/Latn.common-error.in:89 data/patterns/Latn.common-error.in:98 msgid "Letter \"O\" in a number" msgstr "Litera \"O\" w liczbie" #: data/patterns/Latn.common-error.in:90 data/patterns/Latn.common-error.in:99 msgid "Replace letter \"O\" with a zero in a number" msgstr "Zamień literę \"O\" na zero w liczbie" #: data/patterns/Latn.common-error.in:117 msgid "Double apostrophe" msgstr "Podwójny apostrof" #: data/patterns/Latn.common-error.in:118 msgid "Replace a double apostrophe with a quotation mark" msgstr "Zastąp podwójny apostrof cudzysłowem" #: data/patterns/Latn.common-error.in:126 #: data/patterns/Latn.common-error.in:135 #: data/patterns/Latn.common-error.in:144 #: data/patterns/Latn.common-error.in:153 msgid "Spaces around brackets" msgstr "Spacje w nawiasach" #: data/patterns/Latn.common-error.in:127 #: data/patterns/Latn.common-error.in:136 #: data/patterns/Latn.common-error.in:145 #: data/patterns/Latn.common-error.in:154 msgid "Add or remove spaces around parantheses and square brackets" msgstr "Dodaj lub usuń spacje wokół nawiasów okrągłych i kwadratowych" #: data/patterns/Latn.common-error.in:162 msgid "Space after a dialogue dash" msgstr "Spacja po myślniku" #: data/patterns/Latn.common-error.in:163 msgid "Add space after a dialogue dash" msgstr "Dodaj spację po myślniku" #: data/patterns/Latn.common-error.in:172 msgid "Remove space before various punctuation marks" msgstr "Usuń spacje przed różnymi znakami interpunkcyjnymi" #: data/patterns/Latn.common-error.in:192 msgid "Space after an ellipsis" msgstr "Spacje po wielokropkach" #: data/patterns/Latn.common-error.in:193 msgid "Add space after an ellipsis" msgstr "Dodaj spację po wielokropkach" #: data/patterns/Latn.common-error.in:201 msgid "Space after a starting ellipsis" msgstr "Spacje po rozpoczęciu wielokropków" #: data/patterns/Latn.common-error.in:202 msgid "Remove space after an ellipsis that starts a line" msgstr "Usuń spację po wielokropku, który rozpoczyna linię" #: data/patterns/Latn.common-error.in:210 #: data/patterns/Latn.common-error.in:221 #: data/patterns/Latn.common-error.in:232 #: data/patterns/Latn.common-error.in:242 msgid "Spaces around a quotation mark" msgstr "Spacje wokół znaku cudzysłowu" #: data/patterns/Latn.common-error.in:211 #: data/patterns/Latn.common-error.in:222 #: data/patterns/Latn.common-error.in:233 #: data/patterns/Latn.common-error.in:243 msgid "Remove space after a starting- and before an ending quotation mark" msgstr "Usuń spację po początkowym i przed końcowym cudzysłowem" #: data/patterns/Latn.common-error.in:252 #: data/patterns/Latn.common-error.in:261 msgid "Spaces around musical notes" msgstr "Spacje wokół nut" #: data/patterns/Latn.common-error.in:253 #: data/patterns/Latn.common-error.in:262 msgid "Add spaces between musical note characters and lyrics" msgstr "Dodaj spacje między nutami i tekstem" #: data/patterns/Latn.common-error.in:270 #: data/patterns/Latn.common-error.in:279 msgid "Multiple question- and exclamation marks" msgstr "Wiele pytajników i znaków wykrzyknika" #: data/patterns/Latn.common-error.in:271 #: data/patterns/Latn.common-error.in:280 msgid "" "Replace multiple consequtive question- and exclamation marks with only one" msgstr "Zastąp wiele kolejnych pytajników i wykrzykników tylko jednym" #: data/patterns/Latn.common-error.in:288 #: data/patterns/Latn.common-error.in:298 msgid "Periods around a punctuation mark" msgstr "Kropki wokół znaku interpunkcyjnego" #: data/patterns/Latn.common-error.in:289 #: data/patterns/Latn.common-error.in:299 msgid "Remove period before or after various punctuation marks" msgstr "Usuń kropki przed lub po różnych znakach interpunkcyjnych" #: data/patterns/Latn.common-error.in:308 msgid "Terminating double-dashes" msgstr "Kończenie podwójnych myślników" #: data/patterns/Latn.common-error.in:309 msgid "Replace a single clause-terminating dash with two dashes" msgstr "Zastąp pojedynczą kreskę kończącą dwoma kreskami" #: data/patterns/Latn.hearing-impaired.in:5 msgid "Sound in brackets" msgstr "Dźwięk w nawiasach" #: data/patterns/Latn.hearing-impaired.in:6 msgid "Remove description of a sound between square brackets" msgstr "Usuń opis dźwięku między nawiasami kwadratowymi" #: data/patterns/Latn.hearing-impaired.in:12 msgid "Sound in parantheses" msgstr "Dźwięk w zdaniach wtrąconych" #: data/patterns/Latn.hearing-impaired.in:13 msgid "Remove description of a sound between parantheses" msgstr "Usuń opis dźwięku w zdaniach wtrąconych" #: data/patterns/Latn.hearing-impaired.in:19 msgid "Song lyrics between number signs" msgstr "Teksty piosenek między znakami liczb" #: data/patterns/Latn.hearing-impaired.in:20 msgid "Remove song lyrics starting with or between number signs" msgstr "Usuń teksty piosenek zaczynające się od lub między znakami liczb" #: data/patterns/Latn.hearing-impaired.in:27 msgid "One-line song lyrics between number signs" msgstr "Jedno liniowe teksty piosenek między znakami liczb" #: data/patterns/Latn.hearing-impaired.in:28 msgid "Remove one-line song lyrics starting with or between number signs" msgstr "" "Usuń jedno linijkowe teksty piosenek zaczynające się od lub między znakami " "liczbowymi" #: data/patterns/Latn.hearing-impaired.in:35 msgid "Speaker before a colon" msgstr "Dźwięk przed dwukropkiem" #: data/patterns/Latn.hearing-impaired.in:36 msgid "Replace the name of the speaker before a colon with a dialogue dash" msgstr "Zastąp nazwę dźwięku przed dwukropkiem za pomocą myślnika" #: data/patterns/Latn.line-break.in:5 data/patterns/Latn.line-break.in:13 msgid "Dialogue" msgstr "Dialog" #: data/patterns/Latn.line-break.in:6 data/patterns/Latn.line-break.in:14 msgid "Break according to dialogue separated by dashes" msgstr "Podziel zgodnie z dialogami oddzielonymi myślnikami" #: data/patterns/Latn.line-break.in:21 data/patterns/Latn.line-break.in:30 msgid "Clause" msgstr "Klauzula" #: data/patterns/Latn.line-break.in:22 data/patterns/Latn.line-break.in:31 msgid "Break according to clauses terminated by a punctuation mark" msgstr "podziel zgodnie z klauzulami zakończonymi znakiem interpunkcyjnym" #: data/patterns/Latn.line-break.in:38 msgid "Number and unit" msgstr "Liczba i jednostka" #: data/patterns/Latn.line-break.in:39 msgid "Do not break between a number and associated unit" msgstr "Nie dziel między liczbą a powiązaną jednostką" #: data/patterns/Zyyy.common-error.in:5 data/patterns/Zyyy.common-error.in:14 msgid "Leading and trailing spaces" msgstr "Spacje początkowe i końcowe" #: data/patterns/Zyyy.common-error.in:6 data/patterns/Zyyy.common-error.in:15 msgid "Remove spaces from the beginning and end of lines" msgstr "Usuń spacje z początku i końca linii" #: data/patterns/Zyyy.common-error.in:23 msgid "Multiple consecutive spaces" msgstr "Wiele kolejnych spacji" #: data/patterns/Zyyy.common-error.in:24 msgid "Replace multiple consecutive spaces with only one" msgstr "Zastąp kilka kolejnych spacji tylko jedną" #: data/patterns/Zyyy.common-error.in:32 data/patterns/Zyyy.common-error.in:45 #: data/patterns/Zyyy.common-error.in:55 data/patterns/Zyyy.common-error.in:65 msgid "Space between digits" msgstr "Odstęp między cyframi" #: data/patterns/Zyyy.common-error.in:33 data/patterns/Zyyy.common-error.in:46 #: data/patterns/Zyyy.common-error.in:56 data/patterns/Zyyy.common-error.in:66 msgid "Remove space between digits of a number" msgstr "Usuń spacje między cyframi numeru" #: data/patterns/Zyyy.common-error.in:79 msgid "Musical notes" msgstr "Nuty" #: data/patterns/Zyyy.common-error.in:80 msgid "Replace Unicode musical note characters with number signs" msgstr "Zastąp znaki nutowe Unicode znakami numerycznymi" #: data/io.otsaloma.gaupol.appdata.xml.in:7 msgid "Editor for text-based subtitles" msgstr "Edytor napisów tekstowych" #: data/io.otsaloma.gaupol.appdata.xml.in:9 msgid "" "Gaupol is an editor for text-based subtitle files. It supports multiple " "subtitle file formats and provides means of creating subtitles, editing " "texts and timing subtitles to match video." msgstr "" "Gaupol to edytor tekstowych plików napisów. Obsługuje wiele formatów plików " "napisów i zapewnia środki do tworzenia napisów, edycji tekstów i " "synchronizacji napisów w celu dopasowania do wideo." #: data/io.otsaloma.gaupol.appdata.xml.in:40 msgid "Main window" msgstr "Okno główne" #: data/io.otsaloma.gaupol.desktop.in:5 msgid "Subtitle Editor" msgstr "Edytor napisów" #: data/io.otsaloma.gaupol.desktop.in:6 msgid "Edit subtitle files" msgstr "Edytuj pliki napisów" #. TRANSLATORS: Search terms to find this application. Do NOT translate or #. localize the semicolons! The list MUST also end with a semicolon! #: data/io.otsaloma.gaupol.desktop.in:12 msgid "video;subtitles;captions;" msgstr "wideo;napisy;film;" gaupol-1.11/po/pt.po000066400000000000000000002230521422217132500143270ustar00rootroot00000000000000# 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. # # Translators: # Hugo Carvalho , 2021 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-04-03 04:00+0300\n" "PO-Revision-Date: 2016-07-07 00:55+0000\n" "Last-Translator: Hugo Carvalho , 2021\n" "Language-Team: Portuguese (https://www.transifex.com/otsaloma/teams/64879/pt/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pt\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: aeidon/enums.py:40 gaupol/enums.py:38 msgid "Subtitle number" msgstr "Número da legenda" #: aeidon/enums.py:43 msgid "Subtitle position" msgstr "Posição da legenda" #: aeidon/enums.py:59 msgid "23.976 fps" msgstr "23.976 fps" #: aeidon/enums.py:63 msgid "24.000 fps" msgstr "24.000 fps" #: aeidon/enums.py:67 msgid "25.000 fps" msgstr "25.000 fps" #: aeidon/enums.py:71 msgid "29.970 fps" msgstr "29.970 fps" #: aeidon/enums.py:75 data/ui/menubar.ui:248 msgid "30.000 fps" msgstr "30.000 fps" #: aeidon/enums.py:79 data/ui/menubar.ui:253 msgid "50.000 fps" msgstr "50.000 fps" #: aeidon/enums.py:83 data/ui/menubar.ui:258 msgid "59.940 fps" msgstr "59.940 fps" #: aeidon/enums.py:87 data/ui/menubar.ui:263 msgid "60.000 fps" msgstr "60.000 fps" #: aeidon/enums.py:112 msgid "Mac (classic)" msgstr "Mac (clássico)" #. TRANSLATORS: Most of the character encoding descriptions are copied from #. gedit, which is translated to very many languages. Check the gedit .po #. files for a reference: #. . #: aeidon/encodings.py:40 aeidon/encodings.py:43 aeidon/encodings.py:46 msgid "English" msgstr "Inglês" #: aeidon/encodings.py:41 aeidon/encodings.py:42 aeidon/encodings.py:69 msgid "Chinese traditional" msgstr "Chinês tradicional" #: aeidon/encodings.py:44 msgid "German" msgstr "Alemão" #: aeidon/encodings.py:45 aeidon/encodings.py:54 aeidon/encodings.py:59 #: aeidon/encodings.py:79 aeidon/encodings.py:105 msgid "Hebrew" msgstr "Hebraico" #: aeidon/encodings.py:47 aeidon/encodings.py:51 aeidon/encodings.py:56 #: aeidon/encodings.py:73 aeidon/encodings.py:76 aeidon/encodings.py:98 #: aeidon/encodings.py:111 aeidon/encodings.py:122 msgid "Western" msgstr "Ocidental" #: aeidon/encodings.py:48 aeidon/encodings.py:61 aeidon/encodings.py:80 #: aeidon/encodings.py:103 msgid "Arabic" msgstr "Árabe" #: aeidon/encodings.py:49 aeidon/encodings.py:64 aeidon/encodings.py:66 #: aeidon/encodings.py:77 aeidon/encodings.py:104 aeidon/encodings.py:119 msgid "Greek" msgstr "Grego" #: aeidon/encodings.py:50 aeidon/encodings.py:81 aeidon/encodings.py:101 #: aeidon/encodings.py:109 msgid "Baltic" msgstr "Báltico" #: aeidon/encodings.py:52 aeidon/encodings.py:74 aeidon/encodings.py:99 #: aeidon/encodings.py:121 msgid "Central European" msgstr "Centro Europeu" #: aeidon/encodings.py:53 aeidon/encodings.py:75 aeidon/encodings.py:102 #: aeidon/encodings.py:118 msgid "Cyrillic" msgstr "Cirílico" #: aeidon/encodings.py:55 aeidon/encodings.py:71 aeidon/encodings.py:78 #: aeidon/encodings.py:106 aeidon/encodings.py:123 msgid "Turkish" msgstr "Turco" #: aeidon/encodings.py:57 msgid "Portuguese" msgstr "Português" #: aeidon/encodings.py:58 aeidon/encodings.py:120 msgid "Icelandic" msgstr "Islandês" #: aeidon/encodings.py:60 msgid "Canadian" msgstr "Canadiano" #: aeidon/encodings.py:62 aeidon/encodings.py:107 msgid "Nordic" msgstr "Nórdico" #: aeidon/encodings.py:63 aeidon/encodings.py:114 msgid "Russian" msgstr "Russo" #: aeidon/encodings.py:65 aeidon/encodings.py:108 msgid "Thai" msgstr "Tailandês" #: aeidon/encodings.py:67 aeidon/encodings.py:83 aeidon/encodings.py:84 #: aeidon/encodings.py:85 aeidon/encodings.py:91 aeidon/encodings.py:92 #: aeidon/encodings.py:93 aeidon/encodings.py:94 aeidon/encodings.py:95 #: aeidon/encodings.py:96 aeidon/encodings.py:125 aeidon/encodings.py:126 #: aeidon/encodings.py:127 msgid "Japanese" msgstr "Japonês" #: aeidon/encodings.py:68 aeidon/encodings.py:86 aeidon/encodings.py:97 #: aeidon/encodings.py:113 msgid "Korean" msgstr "Coreano" #: aeidon/encodings.py:70 msgid "Urdu" msgstr "Urdo" #: aeidon/encodings.py:72 aeidon/encodings.py:116 msgid "Ukrainian" msgstr "Ucraniano" #: aeidon/encodings.py:82 msgid "Vietnamese" msgstr "Vietnamita" #: aeidon/encodings.py:87 aeidon/encodings.py:90 msgid "Chinese simplified" msgstr "Chinês simplificado" #: aeidon/encodings.py:88 aeidon/encodings.py:89 msgid "Chinese unified" msgstr "Chinês unificado" #: aeidon/encodings.py:100 aeidon/encodings.py:112 msgid "South European" msgstr "Sul Europeu" #: aeidon/encodings.py:110 msgid "Celtic" msgstr "Celta" #: aeidon/encodings.py:115 msgid "Tajik" msgstr "Tajique" #: aeidon/encodings.py:117 msgid "Kazakh" msgstr "Cazaque" #: aeidon/encodings.py:124 msgid "Cyrillic Asian" msgstr "Cirílico Asiático" #: aeidon/encodings.py:128 aeidon/encodings.py:129 aeidon/encodings.py:130 #: aeidon/encodings.py:131 aeidon/encodings.py:132 aeidon/encodings.py:133 #: aeidon/encodings.py:134 aeidon/encodings.py:135 aeidon/encodings.py:136 msgid "Unicode" msgstr "Unicode" #: aeidon/encodings.py:156 #, python-brace-format msgid "{description} ({name})" msgstr "{description} ({name})" #: aeidon/encodings.py:232 msgid "Current locale ({})" msgstr "Idioma atual ({})" #: aeidon/locales.py:46 #, python-brace-format msgid "{language} ({country})" msgstr "{language} ({country})" #: aeidon/agents/search.py:227 msgid "Replacing" msgstr "A substituir" #: aeidon/agents/search.py:256 aeidon/agents/search.py:258 msgid "Replacing all" msgstr "A substituir tudo" #: aeidon/agents/position.py:74 msgid "Adjusting durations" msgstr "A ajustar durações" #: aeidon/agents/position.py:96 msgid "Converting framerate" msgstr "A converter taxa de imagens" #: aeidon/agents/position.py:146 msgid "Setting framerate" msgstr "A definir taxa de imagens" #: aeidon/agents/position.py:168 msgid "Shifting positions" msgstr "A mudar posições" #: aeidon/agents/position.py:188 msgid "Transforming positions" msgstr "A transformar posições" #: aeidon/agents/clipboard.py:44 msgid "Cutting texts" msgstr "A recortar textos" #: aeidon/agents/clipboard.py:61 msgid "Pasting texts" msgstr "A colar textos" #: aeidon/agents/text.py:91 msgid "Breaking lines" msgstr "Quebra de linhas" #: aeidon/agents/text.py:128 msgid "Capitalizing texts" msgstr "A capitalizar textos" #: aeidon/agents/text.py:185 msgid "Correcting common errors" msgstr "A corrigir erros comuns" #: aeidon/agents/text.py:234 msgid "Removing hearing impaired texts" msgstr "A remover textos para deficientes auditivos" #: aeidon/agents/text.py:315 msgid "Joining words by spell-check suggestions" msgstr "A juntar palavras por sugestão do corretor ortográfico" #: aeidon/agents/text.py:354 msgid "Splitting words by spell-check suggestions" msgstr "A dividir palavras por sugestão do corretor ortográfico" #: aeidon/agents/set.py:58 aeidon/agents/set.py:80 aeidon/agents/set.py:113 msgid "Editing position" msgstr "A editar posição" #: aeidon/agents/set.py:129 msgid "Editing text" msgstr "A editar texto" #: aeidon/agents/edit.py:35 msgid "Clearing texts" msgstr "A limpar textos" #: aeidon/agents/edit.py:61 aeidon/agents/edit.py:83 msgid "Inserting subtitles" msgstr "A inserir legendas" #: aeidon/agents/edit.py:103 msgid "Merging subtitles" msgstr "A unir legendas" #: aeidon/agents/edit.py:114 msgid "Removing subtitles" msgstr "A remover legendas" #: aeidon/agents/edit.py:131 msgid "Replacing positions" msgstr "A substituir posições" #: aeidon/agents/edit.py:147 msgid "Replacing texts" msgstr "A substituir textos" #: aeidon/agents/edit.py:171 msgid "Splitting subtitle" msgstr "A dividir legenda" #: aeidon/agents/format.py:49 msgid "Adding dialogue dashes" msgstr "A adicionar hífenes de diálogo" #: aeidon/agents/format.py:68 msgid "Changing case" msgstr "A mudar maiusculização" #: aeidon/agents/format.py:92 msgid "Italicizing" msgstr "A tornar itálico" #: aeidon/agents/format.py:108 msgid "Removing dialogue dashes" msgstr "A remover hífenes de diálogo" #: aeidon/agents/format.py:174 msgid "Unitalicizing" msgstr "A tornar não-itálico" #: gaupol/application.py:219 gaupol/agents/open.py:203 msgid "Open" msgstr "Abrir" #: gaupol/application.py:223 msgid "Open main files" msgstr "Abrir ficheiros principais" #: gaupol/application.py:230 msgid "Save" msgstr "Guardar" #: gaupol/application.py:233 msgid "Save the current main document" msgstr "Guarda o documento principal atual" #: gaupol/application.py:238 msgid "Undo" msgstr "Desfazer" #: gaupol/application.py:242 msgid "Undo the last action" msgstr "Desfaz a última ação" #: gaupol/application.py:249 msgid "Redo" msgstr "Refazer" #: gaupol/application.py:252 msgid "Redo the last undone action" msgstr "Refaz a última ação desfeita" #: gaupol/application.py:260 msgid "Insert" msgstr "Inserir" #: gaupol/application.py:262 msgid "Insert new subtitles" msgstr "Insere novas legendas" #: gaupol/application.py:266 #: data/extensions/custom-framerates/preferences-dialog.ui:78 msgid "Remove" msgstr "Remover" #: gaupol/application.py:268 msgid "Remove the selected subtitles" msgstr "Remove as legendas selecionadas" #: gaupol/application.py:273 data/ui/search-dialog.ui:283 msgid "Find" msgstr "Localizar" #: gaupol/application.py:275 msgid "Search for and replace text" msgstr "Procurar e substituir texto" #: gaupol/application.py:279 data/ui/preferences-dialog.ui:942 msgid "Video" msgstr "Vídeo" #: gaupol/application.py:281 msgid "Show or hide the video player" msgstr "Mostra ou oculta o reprodutor de vídeo" #: gaupol/application.py:285 data/ui/preferences-dialog.ui:1173 msgid "Preview" msgstr "Pré-visualizar" #: gaupol/application.py:287 msgid "Preview from selected position with a video player" msgstr "Pré-visualiza da posição selecionada com um reprodutor de vídeo" #: gaupol/enums.py:37 msgid "No." msgstr "Nº." #: gaupol/enums.py:43 msgid "Start" msgstr "Início" #: gaupol/enums.py:44 msgid "Start position" msgstr "Posição inicial" #: gaupol/enums.py:49 msgid "End" msgstr "Fim" #: gaupol/enums.py:50 msgid "End position" msgstr "Posição final" #. TRANSLATORS: 'Dur.' is short for duration. It is used in the header #. of a column that contains numbers five digits wide. #: gaupol/enums.py:57 msgid "Dur." msgstr "Dur." #: gaupol/enums.py:58 msgid "Duration" msgstr "Duração" #: gaupol/enums.py:63 gaupol/enums.py:64 msgid "Text" msgstr "Texto" #: gaupol/enums.py:69 gaupol/enums.py:70 msgid "Translation" msgstr "Tradução" #: gaupol/enums.py:82 msgid "characters" msgstr "caracteres" #: gaupol/enums.py:85 msgid "ems" msgstr "ems" #: gaupol/page.py:60 msgid "Untitled {:d}" msgstr "Sem-título {:d}" #: gaupol/page.py:133 msgid "Close project" msgstr "Fechar projeto" #: gaupol/page.py:145 msgid "{} translation" msgstr "{} tradução" #: gaupol/page.py:302 msgid "Path:" msgstr "Caminho:" #: gaupol/page.py:303 msgid "Format:" msgstr "Formato:" #: gaupol/page.py:304 msgid "Encoding:" msgstr "Codificação:" #: gaupol/page.py:305 msgid "Newlines:" msgstr "Novas linhas:" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:99 msgid "Tasks and Target" msgstr "Tarefas e alvos" #: gaupol/assistants.py:128 msgid "Correct texts in the text column" msgstr "Corrigir textos na coluna de texto" #: gaupol/assistants.py:129 msgid "Correct texts in the translation column" msgstr "Corrigir textos na coluna de tradução" #: gaupol/assistants.py:138 msgid "Correct texts in selected subtitles" msgstr "Corrigir textos nas legendas selecionadas" #: gaupol/assistants.py:139 msgid "Correct texts in current project" msgstr "Corrigir textos no projeto atual" #: gaupol/assistants.py:140 msgid "Correct texts in all open projects" msgstr "Corrigir textos em todos projetos abertos" #: gaupol/assistants.py:363 msgid "Other" msgstr "Outros" #: gaupol/assistants.py:439 msgid "Capitalize texts written in lower case" msgstr "Capitaliza textos escritos em minúsculo" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:443 msgid "Capitalization Patterns" msgstr "Padrões de capitalização" #: gaupol/assistants.py:445 msgid "Capitalize texts" msgstr "Capitalizar textos" #: gaupol/assistants.py:468 msgid "Correct common errors made by humans or image recognition software" msgstr "" "Corrige erros comuns feitos por humanos ou programa de reconhecimento de " "imagem" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:472 msgid "Common Error Patterns" msgstr "Padrão de erro comum" #: gaupol/assistants.py:474 msgid "Correct common errors" msgstr "Corrigir erros comuns" #: gaupol/assistants.py:526 msgid "Remove explanatory texts meant for the hearing impaired" msgstr "Remove textos explanatórios destinados a deficientes auditivos" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:530 msgid "Hearing Impaired Patterns" msgstr "Padrão de deficiência auditiva" #: gaupol/assistants.py:532 msgid "Remove hearing impaired texts" msgstr "Remove textos para deficientes auditivos" #: gaupol/assistants.py:544 msgid "" "Use spell-check suggestions to fix whitespace detection errors of image " "recognition software" msgstr "" "Usa as sugestões do corretor ortográfico para corrigir erros de detecção de " "espaços em branco do programa de reconhecimento de imagem" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:548 msgid "Joining and Splitting Words" msgstr "A juntar e a dividir palavras" #: gaupol/assistants.py:550 msgid "Join or Split Words" msgstr "Juntar ou dividir palavras" #: gaupol/assistants.py:599 gaupol/agents/tools.py:45 msgid "Failed to load dictionary for language \"{}\"" msgstr "Erro ao carregar dicionário para idioma “{}”" #: gaupol/assistants.py:601 gaupol/player.py:263 gaupol/player.py:381 #: gaupol/dialogs/search.py:560 gaupol/dialogs/search.py:568 #: gaupol/dialogs/text_edit.py:49 gaupol/dialogs/encoding.py:56 #: gaupol/agents/open.py:328 gaupol/agents/open.py:337 #: gaupol/agents/open.py:345 gaupol/agents/open.py:354 #: gaupol/agents/tools.py:48 gaupol/agents/save.py:197 #: gaupol/agents/save.py:205 gaupol/agents/preview.py:108 #: gaupol/agents/preview.py:116 gaupol/agents/preview.py:125 #: gaupol/agents/preview.py:133 msgid "_OK" msgstr "_OK" #: gaupol/assistants.py:635 msgid "Break text into lines of defined length" msgstr "Divide texto em linhas de tamanho definido" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:639 msgid "Line-Break Patterns" msgstr "Padrão de quebra-de-linha" #: gaupol/assistants.py:641 msgid "Break lines" msgstr "Quebra de linhas" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:679 msgid "Line-Break Options" msgstr "Opções de quebra-de-linha" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:763 msgid "Correcting Texts" msgstr "A corrigir textos" #: gaupol/assistants.py:769 msgid "Each task is now being run on each project." msgstr "Cada tarefa está agora a ser executada em cada projecto." #: gaupol/assistants.py:793 #, python-brace-format msgid "{current:d} of {total:d} tasks complete" msgstr "{current:d} de {total:d} tarefas concluídas" #: gaupol/assistants.py:801 msgid "Project: {}" msgstr "Projeto: {}" #: gaupol/assistants.py:807 msgid "Task: {}" msgstr "Tarefa: {}" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:832 msgid "Confirm Changes" msgstr "Confirmar alterações" #: gaupol/assistants.py:892 msgid "Accept" msgstr "Aceitar" #: gaupol/assistants.py:898 msgid "Original Text" msgstr "Texto original" #: gaupol/assistants.py:899 msgid "Corrected Text" msgstr "Texto corrigido" #: gaupol/assistants.py:1048 msgid "Correct Texts" msgstr "Corrigir textos" #: gaupol/assistants.py:1076 msgid "Correcting texts" msgstr "A corrigir textos" #: gaupol/assistants.py:1092 #, python-brace-format msgid "Edited {edits:d} and removed {removals:d} subtitles" msgstr "{edits:d} legendas editadas e {removals:d} legendas removidas" #: gaupol/assistants.py:1126 msgid "Confirm {:d} Change" msgid_plural "Confirm {:d} Changes" msgstr[0] "Confirmar {:d} alteração" msgstr[1] "Confirmar {:d} alterações" #: gaupol/renderers/multiline.py:86 msgid "Italic" msgstr "Itálico" #: gaupol/player.py:372 msgid "No video streams found" msgstr "Nenhuma transmissão de vídeo encontrada" #: gaupol/player.py:379 msgid "Failed to initialize playback" msgstr "Erro ao iniciar a reprodução" #: gaupol/dialogs/search.py:189 data/ui/menubar.ui:524 msgid "_Help" msgstr "_Ajuda" #: gaupol/dialogs/search.py:471 msgid "Found and replaced {:d} occurence" msgid_plural "Found and replaced {:d} occurences" msgstr[0] "Encontrada e substituída {:d} ocorrência" msgstr[1] "Encontradas e substituídas {:d} ocorrências" #: gaupol/dialogs/search.py:488 msgid "\"{}\" not found" msgstr "“{}” não encontrado" #: gaupol/dialogs/search.py:558 msgid "Error in regular expression pattern" msgstr "Erro no padrão da expressão regular" #: gaupol/dialogs/search.py:566 msgid "Error in regular expression replacement" msgstr "Erro na expressão regular de substituição" #: gaupol/dialogs/text_edit.py:48 gaupol/dialogs/framerate_convert.py:63 #: gaupol/dialogs/insert.py:44 gaupol/dialogs/encoding.py:55 #: gaupol/dialogs/split.py:44 gaupol/dialogs/multi_close.py:54 #: gaupol/dialogs/open.py:63 gaupol/dialogs/position_transform.py:69 #: gaupol/dialogs/position_shift.py:71 gaupol/dialogs/multi_save.py:83 #: gaupol/dialogs/multi_save.py:215 gaupol/dialogs/duration_adjust.py:86 #: gaupol/dialogs/save.py:73 gaupol/dialogs/video.py:41 #: gaupol/agents/open.py:363 gaupol/agents/open.py:375 #: gaupol/agents/open.py:387 gaupol/agents/close.py:71 #: data/extensions/custom-framerates/custom-framerates.py:39 msgid "_Cancel" msgstr "_Cancelar" #: gaupol/dialogs/text_edit.py:53 msgid "Edit Text" msgstr "Editar Texto" #: gaupol/dialogs/framerate_convert.py:64 msgid "Co_nvert" msgstr "Co_nverter" #: gaupol/dialogs/insert.py:45 msgid "_Insert" msgstr "_Inserir" #: gaupol/dialogs/insert.py:54 msgid "Above selection" msgstr "Acima da seleção" #: gaupol/dialogs/insert.py:55 msgid "Below selection" msgstr "Abaixo da seleção" #: gaupol/dialogs/encoding.py:60 data/ui/preferences-dialog.ui:70 msgid "Character Encodings" msgstr "Codificação de caracteres" #: gaupol/dialogs/encoding.py:78 gaupol/dialogs/encoding.py:125 msgid "Description" msgstr "Descrição" #: gaupol/dialogs/encoding.py:85 gaupol/dialogs/encoding.py:132 msgid "Encoding" msgstr "Codificação" #: gaupol/dialogs/encoding.py:141 msgid "Show in Menu" msgstr "Mostrar no menu" #: gaupol/dialogs/split.py:45 msgid "_Split" msgstr "_Dividir" #: gaupol/dialogs/split.py:76 msgid "Splitting project" msgstr "A dividir projeto" #: gaupol/dialogs/split.py:97 #, python-brace-format msgid "Split {amount:d} subtitles to project \"{name}\"" msgstr "Dividir {amount:d} legendas para projeto “{name}”" #: gaupol/dialogs/spell_check.py:269 msgid "Spell-checking" msgstr "Verificar ortografia" #: gaupol/dialogs/preferences.py:217 msgid "{} Extension Website" msgstr "Website da extensão {}" #: gaupol/dialogs/preferences.py:429 msgid "Custom" msgstr "Personalizado" #: gaupol/dialogs/multi_close.py:38 msgid "Save changes to documents before closing?" msgstr "Guardar alterações no documento antes de fechar?" #: gaupol/dialogs/multi_close.py:39 gaupol/agents/open.py:384 #: gaupol/agents/close.py:68 msgid "If you don't save, changes will be permanently lost." msgstr "Caso não guarde, as alterações serão perdidas permanentemente." #: gaupol/dialogs/multi_close.py:53 gaupol/agents/close.py:70 msgid "Close _Without Saving" msgstr "Fechar _sem guardar" #: gaupol/dialogs/multi_close.py:55 gaupol/dialogs/multi_save.py:84 #: gaupol/dialogs/save.py:74 gaupol/agents/open.py:388 #: gaupol/agents/close.py:72 data/ui/menubar.ui:34 msgid "_Save" msgstr "_Guardar" #: gaupol/dialogs/multi_close.py:70 msgid "Select the _main documents you want to save:" msgstr "Selecione os _documentos principais que deseja guardar:" #: gaupol/dialogs/multi_close.py:95 msgid "Select the _translation documents you want to save:" msgstr "Selecione os documentos de _tradução que deseja guardar:" #: gaupol/dialogs/open.py:64 gaupol/agents/open.py:364 #: gaupol/agents/open.py:376 msgid "_Open" msgstr "_Abrir" #: gaupol/dialogs/position_transform.py:70 msgid "_Transform" msgstr "_Transformar" #: gaupol/dialogs/position_shift.py:72 msgid "_Shift" msgstr "_Mudar" #: gaupol/dialogs/position_shift.py:150 msgid "frames" msgstr "imagens" #: gaupol/dialogs/position_shift.py:168 data/ui/preferences-dialog.ui:911 msgid "seconds" msgstr "segundos" #: gaupol/dialogs/about.py:36 msgid "About Gaupol" msgstr "Acerca do Gaupol" #: gaupol/dialogs/about.py:40 msgid "Subtitle editor" msgstr "Editor de legendas" #. TRANSLATORS: This is a special message that shouldn't be translated #. literally. It is used in the about dialog to give credits to the #. translators. Thus, you should translate it to your name and email #. address. You can also include other translators who have contributed #. to this translation; in that case, please write them on separate #. lines seperated by newlines (\n). #: gaupol/dialogs/about.py:51 msgid "translator-credits" msgstr "Hugo Carvalho " #: gaupol/dialogs/about.py:54 msgid "Gaupol Website" msgstr "Website do Gaupol" #: gaupol/dialogs/append.py:35 msgid "Append File" msgstr "Anexar ficheiro" #: gaupol/dialogs/debug.py:43 msgid "Something went wrong" msgstr "Algo correu mal" #: gaupol/dialogs/debug.py:44 msgid "" "You have probably discovered a bug. Please report it by providing the below " "information and a description of what you were doing." msgstr "" "Você provavelmente descobriu um erro. Por favor, relate-o fornecendo as " "informações abaixo e uma descrição do que você estava a fazer." #: gaupol/dialogs/debug.py:52 msgid "_Report Bug" msgstr "_Reportar Erro" #: gaupol/dialogs/debug.py:53 data/ui/menubar.ui:56 msgid "_Quit" msgstr "_Sair" #: gaupol/dialogs/debug.py:54 gaupol/dialogs/preview_error.py:45 #: data/ui/menubar.ui:52 data/ui/tab-popup.ui:16 msgid "_Close" msgstr "_Fechar" #: gaupol/dialogs/multi_save.py:98 gaupol/dialogs/save.py:110 msgid "{} (recommended)" msgstr "{} (recomendado)" #: gaupol/dialogs/multi_save.py:212 msgid "" "{:d} of the files to be saved already exist. Do you want to replace them?" msgstr "" "{:d} dos ficheiros a serem guardados já existem. Deseja substituí-los?" #: gaupol/dialogs/multi_save.py:213 msgid "" "The files already exist in \"{}\". Replacing them will overwrite their " "contents." msgstr "" "Os ficheiros já existem em “{}”. Substituí-los irá sobrescrever seu " "conteúdo." #: gaupol/dialogs/multi_save.py:216 data/ui/search-dialog.ui:192 #: data/ui/spell-check-dialog.ui:122 msgid "_Replace" msgstr "_Substituir" #: gaupol/dialogs/duration_adjust.py:70 msgid "Adjusted duration of {:d} subtitle" msgid_plural "Adjusted durations of {:d} subtitles" msgstr[0] "Ajustada duração de {:d} legenda" msgstr[1] "Ajustadas durações de {:d} legendas" #: gaupol/dialogs/duration_adjust.py:87 msgid "_Adjust" msgstr "_Ajustar" #: gaupol/dialogs/preview_error.py:36 msgid "Preview in video player failed" msgstr "Pré-visualização no reprodutor de vídeo falhou" #: gaupol/dialogs/preview_error.py:37 msgid "" "There is probably a problem with either the video file or the video player. " "See the preferences dialog to choose the video player or to customize the " "command." msgstr "" "Provavelmente, há um problema com o ficheiro de vídeo ou o reprodutor de " "vídeo. Veja o diálogo de preferências para escolher o reprodutor de vídeo ou" " para personalizar o comando." #: gaupol/dialogs/language.py:97 msgid "Set Language" msgstr "Definir Idioma" #: gaupol/dialogs/video.py:52 gaupol/dialogs/file.py:59 msgid "All files" msgstr "Todos os ficheiros" #: gaupol/dialogs/video.py:56 msgid "Video files" msgstr "Ficheiros de vídeo" #: gaupol/dialogs/file.py:63 msgid "All supported files" msgstr "Todos os ficheiros suportados" #: gaupol/dialogs/file.py:77 #, python-brace-format msgid "{format} (*{extension})" msgstr "{format} (*{extension})" #: gaupol/dialogs/file.py:120 msgid "Auto-detected" msgstr "Auto-detecção" #: gaupol/dialogs/file.py:122 msgid "Other…" msgstr "Outro…" #: gaupol/agents/menu.py:94 gaupol/agents/menu.py:103 #: gaupol/agents/menu.py:110 msgid "File not found" msgstr "Ficheiro não encontrado" #: gaupol/agents/open.py:85 #, python-brace-format msgid "Appended {amount:d} subtitles from \"{basename}\"" msgstr "Adicionar ao fim {amount:d} legendas de “{basename}”" #: gaupol/agents/open.py:96 msgid "Appending file" msgstr "A anexar ficheiro" #: gaupol/agents/open.py:111 msgid "File \"{}\" is already open" msgstr "Ficheiro “{}” já está aberto" #: gaupol/agents/open.py:214 msgid "Open Translation" msgstr "Abrir tradução" #: gaupol/agents/open.py:223 msgid "Select Video" msgstr "Selecionar vídeo" #: gaupol/agents/open.py:224 msgid "_Select" msgstr "_Selecionar" #: gaupol/agents/open.py:325 msgid "Failed to decode file \"{}\" with all attempted codecs" msgstr "Erro ao decodificar ficheiro “{}” com todos os codecs tentados" #: gaupol/agents/open.py:326 msgid "Please try to open the file with a different character encoding." msgstr "Por favor, tente abrir o ficheiro com uma codificação diferente." #: gaupol/agents/open.py:334 msgid "Failed to recognize format of file \"{}\"" msgstr "Erro ao reconhecer formato do ficheiro “{}”" #: gaupol/agents/open.py:335 msgid "" "Please check that the file you are trying to open is a subtitle file of a " "format supported by Gaupol." msgstr "" "Por favor, verifique se o ficheiro que está a tentar abrir é um ficheiro de " "legenda com formato suportado pelo Gaupol." #: gaupol/agents/open.py:343 msgid "Failed to open file \"{}\"" msgstr "Erro ao abrir ficheiro “{}”" #: gaupol/agents/open.py:351 msgid "Failed to parse file \"{}\"" msgstr "Erro ao processar ficheiro “{}”" #: gaupol/agents/open.py:352 msgid "Please check that the file you are trying to open is a valid {} file." msgstr "" "Por favor, verifique se o ficheiro que está a tentar abrir é um ficheiro {} " "válido." #: gaupol/agents/open.py:360 msgid "Open abnormally large file \"{}\"?" msgstr "Abrir ficheiro demasiado grande “{}”?" #: gaupol/agents/open.py:361 msgid "" "Size of the file is {:.1f} MB, which is abnormally large for a text-based " "subtitle file. Please, check that you are not trying to open a binary file." msgstr "" "O tamanho do ficheiro é {:.1f} MB, o qual é demasiado grande para um " "ficheiro texto de legenda. Por favor, verifique se não está a tentar abrir " "um ficheiro binário." #: gaupol/agents/open.py:371 msgid "Open unsorted file \"{}\"?" msgstr "Abrir ficheiro não classificado “{}”?" #: gaupol/agents/open.py:372 msgid "" "The order of {:d} subtitles needs to be changed. If {:d} sounds like a lot, " "the file may be erroneously composed." msgstr "" "A ordem de {:d} legendas precisa de ser alterada. Se {:d} parece muita " "coisa, o ficheiro pode estar escrito incorretamente." #: gaupol/agents/open.py:383 msgid "Save changes to translation document \"{}\" before opening a new one?" msgstr "" "Guardar alterações para documento de tradução “{}” antes de abrir outro?" #: gaupol/agents/open.py:386 msgid "Open _Without Saving" msgstr "Abrir _sem guardar" #: gaupol/agents/close.py:66 msgid "Save changes to document \"{}\" before closing?" msgstr "Guardar alterações no documento “{}” antes de fechar?" #: gaupol/agents/edit.py:101 gaupol/agents/edit.py:119 msgid "Stretching end position" msgstr "Alongar posição final" #: gaupol/agents/edit.py:208 msgid "Inserted {:d} subtitle to fit clipboard contents" msgid_plural "Inserted {:d} subtitles to fit clipboard contents" msgstr[0] "" "Inseridas {:d} legenda para o conteúdo caber na área de transferência" msgstr[1] "" "Inseridas {:d} legendas para o conteúdo caber na área de transferência" #: gaupol/agents/edit.py:334 gaupol/agents/edit.py:352 msgid "Stretching start position" msgstr "Alongar posição inicial" #: gaupol/agents/edit.py:411 msgid "Use Shift+Return for line-break" msgstr "Usar Shift+Enter para quebra de linha" #: gaupol/agents/save.py:129 msgid "Save As" msgstr "Guardar como" #: gaupol/agents/save.py:135 msgid "Saved main document as \"{}\"" msgstr "Documento principal guardado como “{}”" #: gaupol/agents/save.py:153 msgid "Save Translation As" msgstr "Guardar tradução como" #: gaupol/agents/save.py:159 msgid "Saved translation document as \"{}\"" msgstr "Guardar documento de tradução como “{}”" #: gaupol/agents/save.py:194 #, python-brace-format msgid "Failed to encode file \"{basename}\" with codec \"{codec}\"" msgstr "Erro ao codificar ficheiro “{basename}” com codificação “{codec}”" #: gaupol/agents/save.py:195 msgid "Please try to save the file with a different character encoding." msgstr "Tente guardar o ficheiro com uma codificação diferente." #: gaupol/agents/save.py:203 msgid "Failed to save file \"{}\"" msgstr "Erro ao guardar ficheiro “{}”" #: gaupol/agents/video.py:67 data/ui/menubar.ui:380 msgid "_Play/Pause" msgstr "_Reproduzir/Parar" #: gaupol/agents/video.py:69 msgid "Play or pause video" msgstr "Reproduz ou para o vídeo" #: gaupol/agents/video.py:75 data/ui/menubar.ui:390 msgid "Seek _Previous" msgstr "Procurar _anterior" #: gaupol/agents/video.py:77 msgid "Seek to the start of the previous subtitle" msgstr "Procura o início da legenda anterior" #: gaupol/agents/video.py:81 data/ui/menubar.ui:394 msgid "Seek _Next" msgstr "Procurar _seguinte" #: gaupol/agents/video.py:83 msgid "Seek to the start of the next subtitle" msgstr "Procura o início da próxima legenda" #: gaupol/agents/video.py:88 data/ui/menubar.ui:400 msgid "Seek _Backward" msgstr "Procurar para _atrás" #: gaupol/agents/video.py:90 msgid "Seek backward" msgstr "Procurar para trás" #: gaupol/agents/video.py:94 data/ui/menubar.ui:404 msgid "Seek _Forward" msgstr "Procurar à _frente" #: gaupol/agents/video.py:96 msgid "Seek forward" msgstr "Procurar à frente" #: gaupol/agents/video.py:109 msgid "Volume" msgstr "Volume" #: gaupol/agents/video.py:189 msgid "Load Video" msgstr "Carregar vídeo" #: gaupol/agents/video.py:189 msgid "_Load" msgstr "_Carregar" #: gaupol/agents/video.py:361 msgid "Track {:d}" msgstr "Faixa {:d}" #: gaupol/agents/preview.py:105 msgid "Failed to encode subtitle file to temporary directory \"{}\"" msgstr "" "Erro ao codificar ficheiro de legenda para o diretório temporário “{}”" #: gaupol/agents/preview.py:106 msgid "" "Subtitle data could not be encoded to a temporary file for preview with the " "current character encoding. Please first save the subtitle file with a " "different character encoding." msgstr "" "A legenda não pode ser codificada para um ficheiro temporário para pré-" "visualização com a codificação atual. Por favor, guarde antes a legenda com " "uma codificação diferente." #: gaupol/agents/preview.py:114 msgid "Failed to save subtitle file to temporary directory \"{}\"" msgstr "Erro ao guardar ficheiro de legenda para o diretório temporário “{}”" #: gaupol/agents/preview.py:122 msgid "Video player not found" msgstr "Reprodutor de vídeo não encontrado" #: gaupol/agents/preview.py:123 msgid "" "Please install one of the supported video players: mpv (recommended), " "MPlayer or VLC. See the preferences dialog to choose the video player or to " "customize the command." msgstr "" "Instale um dos reprodutores de vídeo compatíveis: mpv (recomendado), MPlayer" " ou VLC. Veja o diálogo de preferências para escolher o reprodutor de vídeo " "ou para personalizar o comando." #: gaupol/agents/preview.py:131 msgid "Failed to launch video player" msgstr "Erro ao executar reprodutor de vídeo" #: gaupol/applicationman.py:105 msgid "gaupol [OPTION...] [FILE...] [+[NUM]]" msgstr "gaupol [OPÇÃO…] [FICHEIRO…] [+[NÚM]]" #: gaupol/applicationman.py:109 msgid "FILE..." msgstr "FICHEIRO…" #: gaupol/applicationman.py:112 msgid "subtitle files to open" msgstr "ficheiro de legendas para abrir" #: gaupol/applicationman.py:122 msgid "ENCODING" msgstr "CODIFICAÇÃO" #: gaupol/applicationman.py:125 msgid "set the character encoding used to open files" msgstr "definir a codificação usada para abrir ficheiros" #: gaupol/applicationman.py:132 msgid "list all available character encodings" msgstr "lista todas as codificações disponíveis" #: gaupol/applicationman.py:137 gaupol/applicationman.py:154 msgid "FILE" msgstr "FICHEIRO" #: gaupol/applicationman.py:140 msgid "open translation file" msgstr "abrir o ficheiro de tradução" #: gaupol/applicationman.py:145 msgid "METHOD" msgstr "MÉTODO" #: gaupol/applicationman.py:149 msgid "method used to align translation subtitles: 'number' or 'position'" msgstr "método usado para alinhar legendas traduzidas: “número” ou “posição”" #: gaupol/applicationman.py:157 msgid "select video file" msgstr "selecionar um ficheiro de vídeo" #: data/extensions/custom-framerates/custom-framerates.py:40 #: data/ui/spell-check-dialog.ui:152 msgid "_Add" msgstr "_Adicionar" #: data/extensions/custom-framerates/custom-framerates.py:171 msgid "{:.3f} fps" msgstr "{:.3f} fps" #: data/extensions/custom-framerates/add-framerate-dialog.ui:13 msgid "Add Framerate" msgstr "Adicionar taxa de imagens" #: data/extensions/custom-framerates/add-framerate-dialog.ui:44 msgid "_Framerate:" msgstr "_Taxa de imagens:" #: data/extensions/custom-framerates/add-framerate-dialog.ui:73 msgid "fps" msgstr "fps" #: data/extensions/custom-framerates/preferences-dialog.ui:8 msgid "Framerates" msgstr "Taxas de imagens" #: data/extensions/custom-framerates/preferences-dialog.ui:64 msgid "Add" msgstr "Adicionar" #: data/ui/columns-popup.ui:6 data/ui/menubar.ui:275 msgid "_No." msgstr "_Num." #: data/ui/columns-popup.ui:10 data/ui/menubar.ui:279 msgid "_Start" msgstr "_Início" #: data/ui/columns-popup.ui:14 data/ui/menubar.ui:283 msgid "_End" msgstr "_Fim" #: data/ui/columns-popup.ui:18 data/ui/menubar.ui:287 msgid "_Duration" msgstr "_Duração" #: data/ui/columns-popup.ui:22 data/ui/menubar.ui:291 data/ui/menubar.ui:303 msgid "_Text" msgstr "_Texto" #: data/ui/columns-popup.ui:26 data/ui/menubar.ui:295 msgid "T_ranslation" msgstr "T_radução" #: data/ui/split-dialog.ui:15 msgid "Split Project" msgstr "Dividir projeto" #: data/ui/split-dialog.ui:48 msgid "_First subtitle of new project:" msgstr "_Primeira legenda do novo projeto:" #: data/ui/search-dialog.ui:89 msgid "_Search for:" msgstr "_Procurar por:" #: data/ui/search-dialog.ui:103 data/ui/spell-check-dialog.ui:193 msgid "Replace _with:" msgstr "Substituir _por:" #: data/ui/search-dialog.ui:162 data/ui/menubar.ui:328 msgid "Find _Next" msgstr "Localizar _seguinte" #: data/ui/search-dialog.ui:177 msgid "Find _Previous" msgstr "Localizar _anterior" #: data/ui/search-dialog.ui:207 msgid "Replace _All" msgstr "Substituir _tudo" #: data/ui/search-dialog.ui:241 msgid "R_egular expression" msgstr "Expressão r_egular" #: data/ui/search-dialog.ui:258 msgid "_Ignore case" msgstr "_Ignorar maiúsculas/minúsculas" #: data/ui/search-dialog.ui:304 data/ui/language-dialog.ui:108 msgid "Columns" msgstr "Colunas" #: data/ui/search-dialog.ui:324 msgid "Find in _text column" msgstr "Localizar na coluna de _texto" #: data/ui/search-dialog.ui:341 msgid "Find in t_ranslation column" msgstr "Localizar na coluna de t_radução" #: data/ui/search-dialog.ui:381 data/ui/framerate-convert-dialog.ui:144 #: data/ui/language-dialog.ui:186 #: data/ui/text-assistant/line-break-options-page.ui:178 #: data/ui/duration-adjust-dialog.ui:388 data/ui/position-shift-dialog.ui:180 #: data/ui/position-transform-dialog.ui:444 msgid "Subtitles" msgstr "Legendas" #: data/ui/search-dialog.ui:401 msgid "Find in c_urrent project" msgstr "Localizar no projeto at_ual" #: data/ui/search-dialog.ui:419 msgid "Find in _all open projects" msgstr "Loc_alizar em todos os projetos abertos" #: data/ui/search-dialog.ui:452 msgid "Target" msgstr "Destino" #: data/ui/framerate-convert-dialog.ui:8 msgid "Convert Framerate" msgstr "Converter taxa de imagens" #: data/ui/framerate-convert-dialog.ui:48 msgid "Framerate" msgstr "Taxa de imagens" #: data/ui/framerate-convert-dialog.ui:71 msgid "_Input:" msgstr "_Entrada:" #: data/ui/framerate-convert-dialog.ui:86 msgid "_Output:" msgstr "_Saída:" #: data/ui/framerate-convert-dialog.ui:164 msgid "Convert c_urrent project" msgstr "Converter projeto at_ual" #: data/ui/framerate-convert-dialog.ui:181 msgid "Convert _all open projects" msgstr "Converter todos os projetos _abertos" #: data/ui/spell-check-dialog.ui:8 msgid "Check Spelling" msgstr "Verificar ortografia" #: data/ui/spell-check-dialog.ui:47 msgid "Join _Back" msgstr "Juntar para _trás" #: data/ui/spell-check-dialog.ui:62 msgid "Join _Forward" msgstr "Juntar para _frente" #: data/ui/spell-check-dialog.ui:77 data/ui/menubar.ui:62 msgid "_Edit" msgstr "_Editar" #: data/ui/spell-check-dialog.ui:92 msgid "_Ignore" msgstr "_Ignorar" #: data/ui/spell-check-dialog.ui:107 msgid "Ig_nore All" msgstr "Ig_norar tudo" #: data/ui/spell-check-dialog.ui:137 msgid "Rep_lace All" msgstr "Sub_stituir tudo" #: data/ui/spell-check-dialog.ui:179 msgid "_Suggestions:" msgstr "_Sugestões:" #: data/ui/multi-save-dialog.ui:8 msgid "Save All As" msgstr "Guardar tudo como" #: data/ui/multi-save-dialog.ui:46 msgid "Save in _folder:" msgstr "Guardar na _pasta:" #: data/ui/multi-save-dialog.ui:60 data/ui/save-dialog.ui:25 msgid "For_mat:" msgstr "For_mato:" #: data/ui/multi-save-dialog.ui:74 data/ui/open-dialog.ui:25 #: data/ui/save-dialog.ui:39 msgid "_Encoding:" msgstr "_Codificação:" #: data/ui/multi-save-dialog.ui:88 data/ui/save-dialog.ui:53 msgid "Ne_wlines:" msgstr "No_vas linhas:" #: data/ui/multi-save-dialog.ui:103 msgid "Select A Folder" msgstr "Selecione uma pasta" #: data/ui/multi-save-dialog.ui:150 data/ui/save-dialog.ui:102 msgid "F_ramerate:" msgstr "Ta_xa de imagem:" #: data/ui/menubar.ui:5 msgid "_File" msgstr "_Ficheiro" #: data/ui/menubar.ui:8 msgid "_New" msgstr "_Novo" #: data/ui/menubar.ui:12 msgid "_Open…" msgstr "_Abrir…" #: data/ui/menubar.ui:16 msgid "Open _Translation…" msgstr "Abrir _tradução…" #: data/ui/menubar.ui:22 msgid "Open _Recent" msgstr "Abrir _recente" #: data/ui/menubar.ui:27 msgid "Open R_ecent Translation" msgstr "Abrir tradução r_ecente" #: data/ui/menubar.ui:38 msgid "Save _As…" msgstr "G_uardar como…" #: data/ui/menubar.ui:42 msgid "Save Trans_lation" msgstr "Gu_ardar tradução" #: data/ui/menubar.ui:46 msgid "Save Translat_ion As…" msgstr "Guardar t_radução como…" #: data/ui/menubar.ui:65 msgid "_Undo" msgstr "_Desfazer" #: data/ui/menubar.ui:69 msgid "_Redo" msgstr "_Refazer" #: data/ui/menubar.ui:75 msgid "_Edit Cell" msgstr "_Editar célula" #: data/ui/menubar.ui:79 msgid "Edit _Next Cell" msgstr "Editar pró_xima célula" #: data/ui/menubar.ui:85 msgid "Stretc_h" msgstr "A_longar" #: data/ui/menubar.ui:88 msgid "_Start Earlier" msgstr "_Iniciar mais cedo" #: data/ui/menubar.ui:92 msgid "S_tart Later" msgstr "I_niciar mais tarde" #: data/ui/menubar.ui:98 msgid "E_nd Earlier" msgstr "Termi_nar mais cedo" #: data/ui/menubar.ui:102 msgid "En_d Later" msgstr "_Terminar mais tarde" #: data/ui/menubar.ui:108 msgid "Set St_art From Video Position" msgstr "Definir iníci_o da posição do vídeo" #: data/ui/menubar.ui:112 msgid "Set En_d From Video Position" msgstr "Definir _fim da posição do vídeo" #: data/ui/menubar.ui:118 data/ui/view-popup.ui:6 msgid "_Split Subtitle" msgstr "_Dividir legenda" #: data/ui/menubar.ui:122 data/ui/view-popup.ui:10 msgid "_Merge Subtitles" msgstr "_Unir legendas" #: data/ui/menubar.ui:128 data/ui/view-popup.ui:16 msgid "_Insert Subtitles…" msgstr "_Inserir legendas…" #: data/ui/menubar.ui:132 msgid "Inser_t Subtitle At Video Position" msgstr "Inseri_r legenda na posição do vídeo" #: data/ui/menubar.ui:136 data/ui/view-popup.ui:20 msgid "Rem_ove Subtitles" msgstr "Rem_over legendas" #: data/ui/menubar.ui:142 msgid "Sele_ction" msgstr "S_eleção" #: data/ui/menubar.ui:145 msgid "Select _All" msgstr "Selecion_ar tudo" #: data/ui/menubar.ui:149 msgid "_Invert Selection" msgstr "I_nverter seleção" #: data/ui/menubar.ui:155 msgid "Extend To _Beginning" msgstr "Prolongar até o _início" #: data/ui/menubar.ui:159 msgid "Extend To _End" msgstr "Prolongar até o _fim" #: data/ui/menubar.ui:165 msgid "_Previous From Video Position" msgstr "_Anterior à posição do vídeo" #: data/ui/menubar.ui:169 msgid "_Next From Video Position" msgstr "_Posterior à posição do vídeo" #: data/ui/menubar.ui:177 msgid "_Preferences" msgstr "_Preferências" #: data/ui/menubar.ui:183 msgid "_View" msgstr "_Ver" #: data/ui/menubar.ui:186 msgid "Tool_bar" msgstr "_Barra de ferramentas" #: data/ui/menubar.ui:190 msgid "_Video Player" msgstr "Reprodutor de _vídeo" #: data/ui/menubar.ui:196 msgid "_Layout" msgstr "_Esquema" #: data/ui/menubar.ui:199 msgid "_Horizontal" msgstr "_Horizontal" #: data/ui/menubar.ui:204 msgid "_Vertical" msgstr "_Vertical" #: data/ui/menubar.ui:213 msgid "_Times" msgstr "_Tempos" #: data/ui/menubar.ui:218 msgid "_Frames" msgstr "_Imagens" #: data/ui/menubar.ui:225 msgid "F_ramerate" msgstr "T_axa de imagens" #: data/ui/menubar.ui:228 msgid "2_3.976 fps" msgstr "2_3.976 fps" #: data/ui/menubar.ui:233 msgid "2_4.000 fps" msgstr "2_4.000 fps" #: data/ui/menubar.ui:238 msgid "2_5.000 fps" msgstr "2_5.000 fps" #: data/ui/menubar.ui:243 msgid "2_9.970 fps" msgstr "2_9.970 fps" #: data/ui/menubar.ui:272 msgid "_Columns" msgstr "_Colunas" #: data/ui/menubar.ui:306 msgid "Cu_t" msgstr "Cor_tar" #: data/ui/menubar.ui:310 msgid "_Copy" msgstr "_Copiar" #: data/ui/menubar.ui:314 msgid "_Paste" msgstr "C_olar" #: data/ui/menubar.ui:318 msgid "Cl_ear" msgstr "Lim_par" #: data/ui/menubar.ui:324 msgid "_Find And Replace…" msgstr "_Localizar e substituir…" #: data/ui/menubar.ui:332 msgid "Find Pre_vious" msgstr "Localizar _anterior" #: data/ui/menubar.ui:338 msgid "_Italic" msgstr "_Itálico" #: data/ui/menubar.ui:342 msgid "_Dialogue" msgstr "_Diálogo" #: data/ui/menubar.ui:348 msgid "Ca_se" msgstr "Maiú_sculo/Minúsculo" #: data/ui/menubar.ui:351 msgid "_Title" msgstr "_Título" #: data/ui/menubar.ui:355 msgid "_Sentence" msgstr "_Sentença" #: data/ui/menubar.ui:359 msgid "_Upper" msgstr "Ma_iúsculo" #: data/ui/menubar.ui:363 msgid "_Lower" msgstr "Minúscu_lo" #: data/ui/menubar.ui:371 msgid "Vi_deo" msgstr "Ví_deo" #: data/ui/menubar.ui:374 msgid "_Load Video…" msgstr "_Carregar vídeo…" #: data/ui/menubar.ui:384 data/ui/view-popup.ui:26 msgid "Play _Selection" msgstr "Reproduzir _seleção" #: data/ui/menubar.ui:410 data/ui/view-popup.ui:30 msgid "S_eek Selection Start" msgstr "Procurar _início da seleção" #: data/ui/menubar.ui:414 msgid "See_k Selection End" msgstr "Procurar fi_m da seleção" #: data/ui/menubar.ui:420 msgid "_Audio" msgstr "Á_udio" #: data/ui/menubar.ui:423 msgid "_Language" msgstr "_Idioma" #: data/ui/menubar.ui:430 msgid "Volume _Down" msgstr "A_baixar volume" #: data/ui/menubar.ui:434 msgid "Volume _Up" msgstr "A_umentar volume" #: data/ui/menubar.ui:440 msgid "T_ools" msgstr "_Ferramentas" #: data/ui/menubar.ui:443 data/ui/text-assistant/confirmation-page.ui:97 #: data/ui/view-popup.ui:36 msgid "_Preview" msgstr "_Pré-visualizar" #: data/ui/menubar.ui:447 msgid "Select _Video…" msgstr "Selecionar _vídeo…" #: data/ui/menubar.ui:453 msgid "_Check Spelling" msgstr "_Verificação ortográfica" #: data/ui/menubar.ui:457 msgid "Co_nfigure Spell-check…" msgstr "Co_nfigurar corretor ortográfico…" #: data/ui/menubar.ui:461 msgid "C_orrect Texts…" msgstr "C_orrigir textos…" #: data/ui/menubar.ui:467 msgid "_Shift Positions…" msgstr "_Deslocar posições…" #: data/ui/menubar.ui:471 msgid "_Transform Positions…" msgstr "_Transformar posições…" #: data/ui/menubar.ui:475 msgid "Adjust _Durations…" msgstr "Ajustar _durações…" #: data/ui/menubar.ui:479 msgid "Convert _Framerate…" msgstr "Converter taxa de _imagens…" #: data/ui/menubar.ui:485 msgid "_Append File…" msgstr "_Anexar ficheiro…" #: data/ui/menubar.ui:489 msgid "Spli_t Project…" msgstr "Dividir proje_to…" #: data/ui/menubar.ui:495 msgid "_Projects" msgstr "_Projetos" #: data/ui/menubar.ui:498 msgid "_Save All" msgstr "_Guardar tudo" #: data/ui/menubar.ui:502 msgid "Save _All As…" msgstr "G_uardar tudo como…" #: data/ui/menubar.ui:506 msgid "_Close All" msgstr "Fe_char tudo" #: data/ui/menubar.ui:512 msgid "_Previous" msgstr "A_nterior" #: data/ui/menubar.ui:516 msgid "_Next" msgstr "_Próximo" #: data/ui/menubar.ui:527 msgid "_Documentation" msgstr "_Documentação" #: data/ui/menubar.ui:531 msgid "_Report A Bug" msgstr "_Reportar um problema" #: data/ui/menubar.ui:535 msgid "_About" msgstr "_Sobre" #: data/ui/open-dialog.ui:39 msgid "Align _method:" msgstr "_Método de alinhamento:" #: data/ui/preferences-dialog.ui:18 msgid "Preferences" msgstr "Preferências" #: data/ui/preferences-dialog.ui:93 msgid "When opening files, try encodings in the following order:" msgstr "Quando abrir ficheiros, tentar codificações na seguinte ordem:" #: data/ui/preferences-dialog.ui:104 msgid "Curr_ent locale encoding" msgstr "Codificação local at_ual" #: data/ui/preferences-dialog.ui:130 msgid "_Fallback encodings:" msgstr "Codificações _secundárias:" #: data/ui/preferences-dialog.ui:246 msgid "Aut_o-detection" msgstr "Aut_o-detecção" #: data/ui/preferences-dialog.ui:266 msgid "Encoding specified in the open dialog will always be tried first." msgstr "" "Codificação especificada no diálogo Abrir sempre será tentada primeiro." #: data/ui/preferences-dialog.ui:296 msgid "File" msgstr "Ficheiro" #: data/ui/preferences-dialog.ui:324 msgid "Font" msgstr "Fonte" #: data/ui/preferences-dialog.ui:344 msgid "Use _default theme fixed width font" msgstr "Usar fonte de largura fixa _padrão do tema" #: data/ui/preferences-dialog.ui:368 msgid "_Editor font:" msgstr "Fonte do _editor:" #: data/ui/preferences-dialog.ui:425 msgid "Line Lengths" msgstr "Tamanho das linhas" #: data/ui/preferences-dialog.ui:445 msgid "_Show line lengths in list cells" msgstr "Mostrar comprimentos das linhas nas _células da lista" #: data/ui/preferences-dialog.ui:462 msgid "S_how line lengths in editable text fields" msgstr "Mostrar comprimentos das linhas em c_ampos texto editáveis" #: data/ui/preferences-dialog.ui:486 msgid "_Length unit:" msgstr "Unidade de _comprimento:" #: data/ui/preferences-dialog.ui:540 msgid "Spell-Check" msgstr "Verificação ortográfica" #: data/ui/preferences-dialog.ui:560 msgid "Chec_k spelling as you type" msgstr "_Verificar a ortográfica ao digitar" #: data/ui/preferences-dialog.ui:598 msgid "Editor" msgstr "Editor" #: data/ui/preferences-dialog.ui:626 msgid "Fonts" msgstr "Fontes" #: data/ui/preferences-dialog.ui:649 msgid "_Subtitles:" msgstr "_Legendas:" #: data/ui/preferences-dialog.ui:679 msgid "_Time:" msgstr "_Tempo:" #: data/ui/preferences-dialog.ui:729 msgid "Colors" msgstr "Cores" #: data/ui/preferences-dialog.ui:752 msgid "Su_btitles:" msgstr "Le_gendas:" #: data/ui/preferences-dialog.ui:777 msgid "_Use a background behind text" msgstr "_Usar um plano de fundo por trás do texto" #: data/ui/preferences-dialog.ui:797 msgid "Ti_me:" msgstr "Te_mpos:" #: data/ui/preferences-dialog.ui:822 msgid "Us_e a background behind text" msgstr "U_sar um plano de fundo por trás do texto" #: data/ui/preferences-dialog.ui:862 msgid "Seek" msgstr "Procurar" #: data/ui/preferences-dialog.ui:883 msgid "_Length:" msgstr "Taman_ho:" #: data/ui/preferences-dialog.ui:971 msgid "Video Player" msgstr "Reprodutor de vídeo" #: data/ui/preferences-dialog.ui:994 msgid "_Application:" msgstr "_Aplicação:" #: data/ui/preferences-dialog.ui:1008 msgid "Co_mmand:" msgstr "Co_mando:" #. Translators: Only the title is to be translated, field names not. #: data/ui/preferences-dialog.ui:1033 msgid "" "Fields:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" msgstr "" "Campos:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" #: data/ui/preferences-dialog.ui:1048 msgid "Al_ways use UTF-8 character encoding" msgstr "Us_ar sempre codificação UTF-8" #: data/ui/preferences-dialog.ui:1089 msgid "Start Position" msgstr "Posição inicial" #: data/ui/preferences-dialog.ui:1111 msgid "_Offset:" msgstr "Desl_ocar:" #: data/ui/preferences-dialog.ui:1142 msgid "seconds before selection" msgstr "segundos antes da seleção" #: data/ui/preferences-dialog.ui:1281 msgid "Extensions" msgstr "Extensões" #: data/ui/language-dialog.ui:8 msgid "Configure Spell-Check" msgstr "Configurar verificação ortográfica" #: data/ui/language-dialog.ui:50 msgid "Language" msgstr "Idioma" #: data/ui/language-dialog.ui:128 msgid "Check _text column" msgstr "Verificar coluna de _texto" #: data/ui/language-dialog.ui:146 msgid "Check t_ranslation column" msgstr "Verificar coluna de t_radução" #: data/ui/language-dialog.ui:206 msgid "Check c_urrent project" msgstr "Verificar projeto at_ual" #: data/ui/language-dialog.ui:224 msgid "Check _all open projects" msgstr "Verificar todos os projetos _abertos" #: data/ui/text-assistant/confirmation-page.ui:22 msgid "Acc_ept, discard or edit changes:" msgstr "Ac_eitar, descartar ou editar mudanças:" #: data/ui/text-assistant/confirmation-page.ui:67 msgid "_Mark All" msgstr "_Marcar tudo" #: data/ui/text-assistant/confirmation-page.ui:82 msgid "_Unmark All" msgstr "_Desmarcar tudo" #: data/ui/text-assistant/confirmation-page.ui:119 msgid "_Remove all blank subtitles" msgstr "_Remover todas as legendas em branco" #: data/ui/text-assistant/join-split-page.ui:28 msgid "Spell-Check Dictionary" msgstr "Dicionário do corretor ortográfico" #: data/ui/text-assistant/join-split-page.ui:49 #: data/ui/text-assistant/line-break-page.ui:81 #: data/ui/text-assistant/hearing-impaired-page.ui:81 #: data/ui/text-assistant/common-error-page.ui:80 #: data/ui/text-assistant/capitalization-page.ui:80 msgid "_Language:" msgstr "_Idioma:" #: data/ui/text-assistant/join-split-page.ui:97 msgid "Corrections" msgstr "Correções" #: data/ui/text-assistant/join-split-page.ui:117 msgid "_Join words not found in spell-check dictionary" msgstr "" "_Juntar palavras não encontradas no dicionário do corretor ortográfico" #: data/ui/text-assistant/join-split-page.ui:134 msgid "_Split words not found in spell-check dictionary" msgstr "" "_Dividir palavras não encontradas no dicionário do corretor ortográfico" #: data/ui/text-assistant/line-break-page.ui:22 msgid "S_elect preferred line-break points:" msgstr "S_elecionar pontos de quebra de linha preferidos:" #: data/ui/text-assistant/line-break-page.ui:67 #: data/ui/text-assistant/hearing-impaired-page.ui:67 #: data/ui/text-assistant/common-error-page.ui:66 #: data/ui/text-assistant/capitalization-page.ui:66 msgid "_Script:" msgstr "_Script:" #: data/ui/text-assistant/line-break-page.ui:95 #: data/ui/text-assistant/hearing-impaired-page.ui:95 #: data/ui/text-assistant/common-error-page.ui:94 #: data/ui/text-assistant/capitalization-page.ui:94 msgid "Co_untry:" msgstr "_País:" #: data/ui/text-assistant/introduction-page.ui:28 msgid "_Select corrections to perform on texts:" msgstr "_Selecione as correções a serem aplicadas nos textos:" #: data/ui/text-assistant/introduction-page.ui:79 msgid "Colu_mns:" msgstr "Colu_nas:" #: data/ui/text-assistant/introduction-page.ui:93 msgid "S_ubtitles:" msgstr "L_egendas:" #: data/ui/text-assistant/line-break-options-page.ui:56 #: data/ui/duration-adjust-dialog.ui:207 msgid "Limits" msgstr "Limites" #: data/ui/text-assistant/line-break-options-page.ui:79 msgid "_Maximum line length:" msgstr "Tamanho _máximo da linha:" #: data/ui/text-assistant/line-break-options-page.ui:93 msgid "_Preferred maximum amount of lines:" msgstr "_Preferir quantidade máxima de linhas:" #: data/ui/text-assistant/line-break-options-page.ui:198 msgid "_Skip subtitles with maximum line length of:" msgstr "_Ignorar legendas com linha de tamanho máximo de:" #: data/ui/text-assistant/line-break-options-page.ui:214 msgid "S_kip subtitles with maximum line amount of:" msgstr "_Ignorar legendas com quantidade máxima de linhas:" #: data/ui/text-assistant/hearing-impaired-page.ui:22 msgid "S_elect parts to remove:" msgstr "S_elecionar partes para remover:" #: data/ui/text-assistant/common-error-page.ui:22 msgid "S_elect errors to correct:" msgstr "S_elecionar erros para correção:" #: data/ui/text-assistant/common-error-page.ui:108 msgid "Error types:" msgstr "Tipos de erro:" #: data/ui/text-assistant/common-error-page.ui:158 msgid "_Human errors" msgstr "Erros _humanos" #: data/ui/text-assistant/common-error-page.ui:175 msgid "_Image recognition errors" msgstr "Erros no reconhecimento da _imagem" #: data/ui/text-assistant/capitalization-page.ui:22 msgid "S_elect parts to capitalize:" msgstr "S_elecionar partes para capitalizar:" #: data/ui/duration-adjust-dialog.ui:33 msgid "Adjust Durations" msgstr "Ajustar durações" #: data/ui/duration-adjust-dialog.ui:73 msgid "Theoretic Duration" msgstr "Duração teórica" #: data/ui/duration-adjust-dialog.ui:101 msgid "_Reading speed:" msgstr "Velocidade de leitu_ra:" #: data/ui/duration-adjust-dialog.ui:133 msgid "characters per second" msgstr "caracteres por segundo" #: data/ui/duration-adjust-dialog.ui:150 msgid "_Lengthen duration to match reading speed" msgstr "_Aumentar duração para coincidir com a velocidade de leitura" #: data/ui/duration-adjust-dialog.ui:167 msgid "_Shorten duration to match reading speed" msgstr "_Diminuir duração para coincidir com a velocidade de leitura" #: data/ui/duration-adjust-dialog.ui:227 msgid "_Minimum duration:" msgstr "Duração _mínima:" #: data/ui/duration-adjust-dialog.ui:243 msgid "Ma_ximum duration:" msgstr "Duração má_xima:" #: data/ui/duration-adjust-dialog.ui:259 msgid "_Gap between subtitles:" msgstr "_Intervalo entre legendas:" #: data/ui/duration-adjust-dialog.ui:294 msgid "s_econds" msgstr "s_egundos" #: data/ui/duration-adjust-dialog.ui:324 msgid "seco_nds" msgstr "segu_ndos" #: data/ui/duration-adjust-dialog.ui:354 msgid "secon_ds" msgstr "segun_dos" #: data/ui/duration-adjust-dialog.ui:408 msgid "Adj_ust selected subtitles" msgstr "Aj_ustar legendas selecionadas" #: data/ui/duration-adjust-dialog.ui:425 msgid "Adjus_t current project" msgstr "Ajus_tar projeto atual" #: data/ui/duration-adjust-dialog.ui:442 msgid "Adjust all _open projects" msgstr "Ajustar todos projetos _abertos" #: data/ui/tab-popup.ui:6 msgid "Move Tab _Left" msgstr "Mover separador para _esquerda" #: data/ui/tab-popup.ui:10 msgid "Move Tab _Right" msgstr "Mover separador para _direita" #: data/ui/insert-dialog.ui:15 msgid "Insert Subtitles" msgstr "Inserir legendas" #: data/ui/insert-dialog.ui:48 data/ui/position-shift-dialog.ui:82 msgid "_Amount:" msgstr "Qu_antidade:" #: data/ui/insert-dialog.ui:62 msgid "_Position:" msgstr "_Posição:" #: data/ui/position-shift-dialog.ui:14 msgid "Shift Positions" msgstr "Deslocar posições" #: data/ui/position-shift-dialog.ui:54 msgid "Shift" msgstr "Deslocar" #: data/ui/position-shift-dialog.ui:135 #: data/ui/position-transform-dialog.ui:208 msgid "_Preview Changes" msgstr "_Pré-visualizar alterações" #: data/ui/position-shift-dialog.ui:200 msgid "Shift s_elected subtitles" msgstr "Deslocar legendas s_elecionadas" #: data/ui/position-shift-dialog.ui:217 msgid "Shift su_btitles from selection to end" msgstr "Deslocar legendas da seleção até o _final" #: data/ui/position-shift-dialog.ui:234 msgid "Shift c_urrent project" msgstr "Deslocar projeto at_ual" #: data/ui/position-shift-dialog.ui:251 msgid "Shift all _open projects" msgstr "Mudar todos _os projetos abertos" #: data/ui/position-transform-dialog.ui:22 msgid "Transform Positions" msgstr "Transformar posições" #: data/ui/position-transform-dialog.ui:62 msgid "First Point" msgstr "Primeiro ponto" #: data/ui/position-transform-dialog.ui:91 msgid "_Subtitle:" msgstr "_Legenda:" #: data/ui/position-transform-dialog.ui:105 msgid "C_orrection:" msgstr "C_orreção:" #: data/ui/position-transform-dialog.ui:119 #: data/ui/position-transform-dialog.ui:310 msgid "Text:" msgstr "Texto:" #: data/ui/position-transform-dialog.ui:253 msgid "Second Point" msgstr "Segundo ponto" #: data/ui/position-transform-dialog.ui:282 msgid "Su_btitle:" msgstr "Le_genda:" #: data/ui/position-transform-dialog.ui:296 msgid "Co_rrection:" msgstr "Co_rreção:" #: data/ui/position-transform-dialog.ui:399 msgid "Pre_view Changes" msgstr "_Pré-visualizar alterações" #: data/ui/position-transform-dialog.ui:464 msgid "Transform se_lected subtitles" msgstr "Transformar legendas se_lecionadas" #: data/ui/position-transform-dialog.ui:482 msgid "Transform c_urrent project" msgstr "Transformar projeto at_ual" #: data/extensions/custom-framerates/custom-framerates.extension.in:7 msgid "Custom Framerates" msgstr "Taxa de imagens personalizada" #: data/extensions/custom-framerates/custom-framerates.extension.in:8 msgid "Allow use of non-standard framerates" msgstr "Permite o uso de taxa de imagens fora do padrão" #: data/patterns/Latn-en-US.common-error.in:5 msgid "Period after title" msgstr "Ponto após título" #: data/patterns/Latn-en-US.common-error.in:6 msgid "Add period after a shortened title, such as \"Mr\" and \"Dr\"" msgstr "Adiciona ponto após uma abreviação, exemplo “Sr” e “Dr”" #: data/patterns/Latn-en.capitalization.in:5 msgid "First person pronoun" msgstr "Pronome de primeira pessoa" #: data/patterns/Latn-en.capitalization.in:6 msgid "Capitalize the first person pronoun \"I\"" msgstr "Capitaliza a primeira letra do pronome pessoal “Eu”" #: data/patterns/Latn-en.common-error.in:5 #: data/patterns/Latn-en.common-error.in:14 #: data/patterns/Latn-en.common-error.in:23 msgid "Letter \"I\" in a lower case word" msgstr "Letra “I” numa palavra minúscula" #: data/patterns/Latn-en.common-error.in:6 #: data/patterns/Latn-en.common-error.in:15 #: data/patterns/Latn-en.common-error.in:24 msgid "Replace letter \"I\" with letter \"l\" in a lower case word" msgstr "Substitui letra “I” pela letra “l” numa palavra minúscula" #: data/patterns/Latn-en.common-error.in:32 #: data/patterns/Latn-en.common-error.in:41 #: data/patterns/Latn-en.common-error.in:50 #: data/patterns/Latn-en.common-error.in:62 msgid "Letter \"l\" in an upper case word" msgstr "Letra “l” numa palavra maiúscula" #: data/patterns/Latn-en.common-error.in:33 #: data/patterns/Latn-en.common-error.in:42 #: data/patterns/Latn-en.common-error.in:51 #: data/patterns/Latn-en.common-error.in:63 msgid "Replace letter \"l\" with letter \"I\" in an upper case word" msgstr "Substitui letra “l” pela letra “I” numa palavra maiúscula" #: data/patterns/Latn-en.common-error.in:73 #: data/patterns/Latn-en.common-error.in:82 msgid "Zero in an upper case word" msgstr "Zero numa palavra maiúscula" #: data/patterns/Latn-en.common-error.in:74 #: data/patterns/Latn-en.common-error.in:83 msgid "Replace zero with letter \"O\" in an upper case word" msgstr "Substitui zero pela letra “O” numa palavra maiúscula" #: data/patterns/Latn-en.common-error.in:91 #: data/patterns/Latn.common-error.in:108 msgid "Space between number and unit" msgstr "Espaço entre número e unidade" #: data/patterns/Latn-en.common-error.in:92 #: data/patterns/Latn.common-error.in:109 msgid "Add or remove space between a number and the associated unit" msgstr "Adiciona ou remove espaço entre um número e a unidade associada" #: data/patterns/Latn-en.common-error.in:100 msgid "Spaces around an apostrophe" msgstr "Espaços ao redor de uma apóstrofe" #: data/patterns/Latn-en.common-error.in:101 msgid "Remove spaces around an apostrophe" msgstr "Remove espaços ao redor de apóstrofe" #: data/patterns/Latn-en.common-error.in:109 #: data/patterns/Latn-en.common-error.in:118 msgid "Okay" msgstr "Okay" #: data/patterns/Latn-en.common-error.in:110 #: data/patterns/Latn-en.common-error.in:119 msgid "Spell two-letter forms of \"okay\" in all upper case" msgstr "Escreve formas de duas letras de “okay” em todas as maiúsculas" #: data/patterns/Latn-en.hearing-impaired.in:5 msgid "Uppercase speaker before a colon" msgstr "Locutor em maiúsculo antes de um dois-pontos" #: data/patterns/Latn-en.hearing-impaired.in:6 msgid "" "Replace the uppercase name of the speaker before a colon with a dialogue " "dash" msgstr "" "Substitui o nome do locutor em maiúsculo antes de um dois-pontos por um " "hífen" #: data/patterns/Latn-en.line-break.in:5 msgid "Title" msgstr "Título" #: data/patterns/Latn-en.line-break.in:6 msgid "Do not break after a title, e.g. \" Dr.\"" msgstr "Não quebrar após um título, ex.: “ Dr.”" #: data/patterns/Latn-en.line-break.in:13 msgid "Article" msgstr "Artigo" #: data/patterns/Latn-en.line-break.in:14 msgid "Do not break after an article" msgstr "Não quebra após um artigo" #: data/patterns/Latn-en.line-break.in:21 msgid "Preposition" msgstr "Preposição" #: data/patterns/Latn-en.line-break.in:22 msgid "Do not break after a preposition" msgstr "Não quebra após uma preposição" #: data/patterns/Latn-en.line-break.in:30 msgid "Possessive determiner" msgstr "Determinante possessivo" #: data/patterns/Latn-en.line-break.in:31 msgid "Do not break after a possessive determiner, e.g. \"my\"" msgstr "Não quebra após um determinante possessivo, ex.: “meu”" #: data/patterns/Latn-fi.common-error.in:5 #: data/patterns/Latn.common-error.in:182 msgid "Space after punctuation marks" msgstr "Espaços após sinais de pontuação" #: data/patterns/Latn-fi.common-error.in:6 #: data/patterns/Latn.common-error.in:183 msgid "Add space after various punctuation marks" msgstr "Adiciona espaço em branco após vários sinais de pontuação" #: data/patterns/Latn-fr.common-error.in:5 #: data/patterns/Latn-fr.common-error.in:14 #: data/patterns/Latn-fr.common-error.in:23 #: data/patterns/Latn-fr.common-error.in:32 msgid "Spaces around guillemets" msgstr "Espaços em volta de aspas angulares" #: data/patterns/Latn-fr.common-error.in:6 #: data/patterns/Latn-fr.common-error.in:15 #: data/patterns/Latn-fr.common-error.in:24 #: data/patterns/Latn-fr.common-error.in:33 msgid "Add spaces around guillemets" msgstr "Adiciona espaços em volta de aspas angulares" #: data/patterns/Latn-fr.common-error.in:41 #: data/patterns/Latn-fr.common-error.in:52 #: data/patterns/Latn.common-error.in:171 msgid "Space before punctuation marks" msgstr "Espaços antes de sinais de pontuação" #: data/patterns/Latn-fr.common-error.in:42 #: data/patterns/Latn-fr.common-error.in:53 msgid "Add or remove space before various punctuation marks" msgstr "Adiciona o remover espaço antes de vários sinais de pontuação" #: data/patterns/Latn.capitalization.in:5 msgid "Sentence" msgstr "Sentença" #: data/patterns/Latn.capitalization.in:6 msgid "Capitalize the first word of a sentence" msgstr "Capitaliza a primeira letra de uma frase" #: data/patterns/Latn.capitalization.in:12 msgid "Ellipsis" msgstr "Elipse" #: data/patterns/Latn.capitalization.in:13 msgid "Capitalize after an ellipsis" msgstr "Maiúsculo após uma elipse" #: data/patterns/Latn.common-error.in:8 data/patterns/Latn.common-error.in:17 #: data/patterns/Latn.common-error.in:26 data/patterns/Latn.common-error.in:35 #: data/patterns/Latn.common-error.in:44 data/patterns/Latn.common-error.in:53 #: data/patterns/Latn.common-error.in:62 msgid "Ligatures" msgstr "Ligações" #: data/patterns/Latn.common-error.in:9 data/patterns/Latn.common-error.in:18 #: data/patterns/Latn.common-error.in:27 data/patterns/Latn.common-error.in:36 #: data/patterns/Latn.common-error.in:45 data/patterns/Latn.common-error.in:54 #: data/patterns/Latn.common-error.in:63 msgid "Unpack ligatures to individual characters" msgstr "Desempacota ligações para caracteres individuais" #: data/patterns/Latn.common-error.in:71 data/patterns/Latn.common-error.in:80 msgid "Spelling of a.m. and p.m." msgstr "Formato a.m. e p.m." #: data/patterns/Latn.common-error.in:72 data/patterns/Latn.common-error.in:81 msgid "Change the various spellings of 12-hour periods to \"a.m.\" and \"p.m.\"" msgstr "Muda os vários formatos de período 12-horas para “a.m.” e “p.m.”" #: data/patterns/Latn.common-error.in:89 data/patterns/Latn.common-error.in:98 msgid "Letter \"O\" in a number" msgstr "Letra “O” num número" #: data/patterns/Latn.common-error.in:90 data/patterns/Latn.common-error.in:99 msgid "Replace letter \"O\" with a zero in a number" msgstr "Substitui letra “O” por zero num número" #: data/patterns/Latn.common-error.in:117 msgid "Double apostrophe" msgstr "Duplo apóstrofe" #: data/patterns/Latn.common-error.in:118 msgid "Replace a double apostrophe with a quotation mark" msgstr "Substitui duplo apóstrofe por aspas" #: data/patterns/Latn.common-error.in:126 #: data/patterns/Latn.common-error.in:135 #: data/patterns/Latn.common-error.in:144 #: data/patterns/Latn.common-error.in:153 msgid "Spaces around brackets" msgstr "Espaços ao redor de parênteses" #: data/patterns/Latn.common-error.in:127 #: data/patterns/Latn.common-error.in:136 #: data/patterns/Latn.common-error.in:145 #: data/patterns/Latn.common-error.in:154 msgid "Add or remove spaces around parantheses and square brackets" msgstr "Adiciona ou remove espaços ao redor de parênteses e parênteses rectos" #: data/patterns/Latn.common-error.in:162 msgid "Space after a dialogue dash" msgstr "Espaço após um hífen de diálogo" #: data/patterns/Latn.common-error.in:163 msgid "Add space after a dialogue dash" msgstr "Adicionar espaço em branco após um hífen de diálogo" #: data/patterns/Latn.common-error.in:172 msgid "Remove space before various punctuation marks" msgstr "Remover espaço antes de vários sinais de pontuação" #: data/patterns/Latn.common-error.in:192 msgid "Space after an ellipsis" msgstr "Espaço após reticências" #: data/patterns/Latn.common-error.in:193 msgid "Add space after an ellipsis" msgstr "Adicionar espaço em branco após reticências" #: data/patterns/Latn.common-error.in:201 msgid "Space after a starting ellipsis" msgstr "Espaço em branco após a partir de reticências" #: data/patterns/Latn.common-error.in:202 msgid "Remove space after an ellipsis that starts a line" msgstr "Remover espaço após reticências que iniciam uma linha" #: data/patterns/Latn.common-error.in:210 #: data/patterns/Latn.common-error.in:221 #: data/patterns/Latn.common-error.in:232 #: data/patterns/Latn.common-error.in:242 msgid "Spaces around a quotation mark" msgstr "Espaços ao redor das aspas" #: data/patterns/Latn.common-error.in:211 #: data/patterns/Latn.common-error.in:222 #: data/patterns/Latn.common-error.in:233 #: data/patterns/Latn.common-error.in:243 msgid "Remove space after a starting- and before an ending quotation mark" msgstr "Remover espaço após- e depois do fim de aspas" #: data/patterns/Latn.common-error.in:252 #: data/patterns/Latn.common-error.in:261 msgid "Spaces around musical notes" msgstr "Espaços em volta de notas musicais" #: data/patterns/Latn.common-error.in:253 #: data/patterns/Latn.common-error.in:262 msgid "Add spaces between musical note characters and lyrics" msgstr "Adiciona espaços entre letras e caracteres de nota musical" #: data/patterns/Latn.common-error.in:270 #: data/patterns/Latn.common-error.in:279 msgid "Multiple question- and exclamation marks" msgstr "Múltiplos sinais de interrogação e exclamação" #: data/patterns/Latn.common-error.in:271 #: data/patterns/Latn.common-error.in:280 msgid "" "Replace multiple consequtive question- and exclamation marks with only one" msgstr "" "Substituir sinais de interrogação- e exclamação consecutivos por apenas um" #: data/patterns/Latn.common-error.in:288 #: data/patterns/Latn.common-error.in:298 msgid "Periods around a punctuation mark" msgstr "Pontos ao redor de um sinal de pontuação" #: data/patterns/Latn.common-error.in:289 #: data/patterns/Latn.common-error.in:299 msgid "Remove period before or after various punctuation marks" msgstr "Remover ponto antes ou depois de vários sinais de pontuação" #: data/patterns/Latn.common-error.in:308 msgid "Terminating double-dashes" msgstr "Terminação com traços duplos" #: data/patterns/Latn.common-error.in:309 msgid "Replace a single clause-terminating dash with two dashes" msgstr "Substituir um único hífen de uma cláusula por dois hifens" #: data/patterns/Latn.hearing-impaired.in:5 msgid "Sound in brackets" msgstr "Som entre parênteses" #: data/patterns/Latn.hearing-impaired.in:6 msgid "Remove description of a sound between square brackets" msgstr "Remover descrição de um som entre parênteses rectos" #: data/patterns/Latn.hearing-impaired.in:12 msgid "Sound in parantheses" msgstr "Som entre parênteses" #: data/patterns/Latn.hearing-impaired.in:13 msgid "Remove description of a sound between parantheses" msgstr "Remover descrição de um som entre parênteses" #: data/patterns/Latn.hearing-impaired.in:19 msgid "Song lyrics between number signs" msgstr "Letras de música entre sinais numéricos" #: data/patterns/Latn.hearing-impaired.in:20 msgid "Remove song lyrics starting with or between number signs" msgstr "Remover letras de música a partir de ou entre sinais numéricos" #: data/patterns/Latn.hearing-impaired.in:27 msgid "One-line song lyrics between number signs" msgstr "Letras de música em linha única entre sinais numéricos" #: data/patterns/Latn.hearing-impaired.in:28 msgid "Remove one-line song lyrics starting with or between number signs" msgstr "" "Remover letras de música em linha única a partir de ou entre sinais " "numéricos" #: data/patterns/Latn.hearing-impaired.in:35 msgid "Speaker before a colon" msgstr "Locutor antes de um dois-pontos" #: data/patterns/Latn.hearing-impaired.in:36 msgid "Replace the name of the speaker before a colon with a dialogue dash" msgstr "Substituir o nome do locutor antes de um dois-pontos por um hífen" #: data/patterns/Latn.line-break.in:5 data/patterns/Latn.line-break.in:13 msgid "Dialogue" msgstr "Diálogo" #: data/patterns/Latn.line-break.in:6 data/patterns/Latn.line-break.in:14 msgid "Break according to dialogue separated by dashes" msgstr "Dividir de acordo com o diálogo separado por hifens" #: data/patterns/Latn.line-break.in:21 data/patterns/Latn.line-break.in:30 msgid "Clause" msgstr "Cláusula" #: data/patterns/Latn.line-break.in:22 data/patterns/Latn.line-break.in:31 msgid "Break according to clauses terminated by a punctuation mark" msgstr "" "Quebrar de acordo com as cláusulas terminadas por um sinal de pontuação" #: data/patterns/Latn.line-break.in:38 msgid "Number and unit" msgstr "Número e unidade" #: data/patterns/Latn.line-break.in:39 msgid "Do not break between a number and associated unit" msgstr "Não quebra entre uma unidade associada e um número" #: data/patterns/Zyyy.common-error.in:5 data/patterns/Zyyy.common-error.in:14 msgid "Leading and trailing spaces" msgstr "Espaços em branco do início e do fim" #: data/patterns/Zyyy.common-error.in:6 data/patterns/Zyyy.common-error.in:15 msgid "Remove spaces from the beginning and end of lines" msgstr "Remover espaços do início e do fim das linhas" #: data/patterns/Zyyy.common-error.in:23 msgid "Multiple consecutive spaces" msgstr "Múltiplos espaços consecutivos" #: data/patterns/Zyyy.common-error.in:24 msgid "Replace multiple consecutive spaces with only one" msgstr "Substituir múltiplos espaços consecutivos num único" #: data/patterns/Zyyy.common-error.in:32 data/patterns/Zyyy.common-error.in:45 #: data/patterns/Zyyy.common-error.in:55 data/patterns/Zyyy.common-error.in:65 msgid "Space between digits" msgstr "Espaço entre dígitos" #: data/patterns/Zyyy.common-error.in:33 data/patterns/Zyyy.common-error.in:46 #: data/patterns/Zyyy.common-error.in:56 data/patterns/Zyyy.common-error.in:66 msgid "Remove space between digits of a number" msgstr "Remover espaços entre dígitos de um número" #: data/patterns/Zyyy.common-error.in:79 msgid "Musical notes" msgstr "Notas musicais" #: data/patterns/Zyyy.common-error.in:80 msgid "Replace Unicode musical note characters with number signs" msgstr "Substitui caracteres de nota musical Unicode com sinais de números" #: data/io.otsaloma.gaupol.appdata.xml.in:7 msgid "Editor for text-based subtitles" msgstr "Editor para legendas em texto" #: data/io.otsaloma.gaupol.appdata.xml.in:9 msgid "" "Gaupol is an editor for text-based subtitle files. It supports multiple " "subtitle file formats and provides means of creating subtitles, editing " "texts and timing subtitles to match video." msgstr "" "O Gaupol é um editor de ficheiros de legendas em texto. Possui suporte a " "vários formatos de ficheiro de legenda e fornece meios de criar legendas, " "editar textos e legendas de tempo para corresponder ao vídeo." #: data/io.otsaloma.gaupol.appdata.xml.in:40 msgid "Main window" msgstr "Janela principal" #: data/io.otsaloma.gaupol.desktop.in:5 msgid "Subtitle Editor" msgstr "Editor de legendas" #: data/io.otsaloma.gaupol.desktop.in:6 msgid "Edit subtitle files" msgstr "Editar ficheiros de legenda" #. TRANSLATORS: Search terms to find this application. Do NOT translate or #. localize the semicolons! The list MUST also end with a semicolon! #: data/io.otsaloma.gaupol.desktop.in:12 msgid "video;subtitles;captions;" msgstr "video;subtitles;captions;" gaupol-1.11/po/pt_BR.po000066400000000000000000002233131422217132500147120ustar00rootroot00000000000000# 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. # # Translators: # Osmo Salomaa , 2017 # Rafael Fontenelle , 2021 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-04-03 04:00+0300\n" "PO-Revision-Date: 2016-07-07 00:55+0000\n" "Last-Translator: Rafael Fontenelle , 2021\n" "Language-Team: Portuguese (Brazil) (https://www.transifex.com/otsaloma/teams/64879/pt_BR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pt_BR\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: aeidon/enums.py:40 gaupol/enums.py:38 msgid "Subtitle number" msgstr "Número da legenda" #: aeidon/enums.py:43 msgid "Subtitle position" msgstr "Posição da legenda" #: aeidon/enums.py:59 msgid "23.976 fps" msgstr "23.976 fps" #: aeidon/enums.py:63 msgid "24.000 fps" msgstr "24.000 fps" #: aeidon/enums.py:67 msgid "25.000 fps" msgstr "25.000 fps" #: aeidon/enums.py:71 msgid "29.970 fps" msgstr "29.970 fps" #: aeidon/enums.py:75 data/ui/menubar.ui:248 msgid "30.000 fps" msgstr "30.000 fps" #: aeidon/enums.py:79 data/ui/menubar.ui:253 msgid "50.000 fps" msgstr "50.000 fps" #: aeidon/enums.py:83 data/ui/menubar.ui:258 msgid "59.940 fps" msgstr "59.940 fps" #: aeidon/enums.py:87 data/ui/menubar.ui:263 msgid "60.000 fps" msgstr "60.000 fps" #: aeidon/enums.py:112 msgid "Mac (classic)" msgstr "Mac (clássico)" #. TRANSLATORS: Most of the character encoding descriptions are copied from #. gedit, which is translated to very many languages. Check the gedit .po #. files for a reference: #. . #: aeidon/encodings.py:40 aeidon/encodings.py:43 aeidon/encodings.py:46 msgid "English" msgstr "Inglês" #: aeidon/encodings.py:41 aeidon/encodings.py:42 aeidon/encodings.py:69 msgid "Chinese traditional" msgstr "Chinês tradicional" #: aeidon/encodings.py:44 msgid "German" msgstr "Alemão" #: aeidon/encodings.py:45 aeidon/encodings.py:54 aeidon/encodings.py:59 #: aeidon/encodings.py:79 aeidon/encodings.py:105 msgid "Hebrew" msgstr "Hebraico" #: aeidon/encodings.py:47 aeidon/encodings.py:51 aeidon/encodings.py:56 #: aeidon/encodings.py:73 aeidon/encodings.py:76 aeidon/encodings.py:98 #: aeidon/encodings.py:111 aeidon/encodings.py:122 msgid "Western" msgstr "Ocidental" #: aeidon/encodings.py:48 aeidon/encodings.py:61 aeidon/encodings.py:80 #: aeidon/encodings.py:103 msgid "Arabic" msgstr "Árabe" #: aeidon/encodings.py:49 aeidon/encodings.py:64 aeidon/encodings.py:66 #: aeidon/encodings.py:77 aeidon/encodings.py:104 aeidon/encodings.py:119 msgid "Greek" msgstr "Grego" #: aeidon/encodings.py:50 aeidon/encodings.py:81 aeidon/encodings.py:101 #: aeidon/encodings.py:109 msgid "Baltic" msgstr "Báltico" #: aeidon/encodings.py:52 aeidon/encodings.py:74 aeidon/encodings.py:99 #: aeidon/encodings.py:121 msgid "Central European" msgstr "Europa Central" #: aeidon/encodings.py:53 aeidon/encodings.py:75 aeidon/encodings.py:102 #: aeidon/encodings.py:118 msgid "Cyrillic" msgstr "Cirílico" #: aeidon/encodings.py:55 aeidon/encodings.py:71 aeidon/encodings.py:78 #: aeidon/encodings.py:106 aeidon/encodings.py:123 msgid "Turkish" msgstr "Turco" #: aeidon/encodings.py:57 msgid "Portuguese" msgstr "Português" #: aeidon/encodings.py:58 aeidon/encodings.py:120 msgid "Icelandic" msgstr "Islandês" #: aeidon/encodings.py:60 msgid "Canadian" msgstr "Canadense" #: aeidon/encodings.py:62 aeidon/encodings.py:107 msgid "Nordic" msgstr "Nórdico" #: aeidon/encodings.py:63 aeidon/encodings.py:114 msgid "Russian" msgstr "Russo" #: aeidon/encodings.py:65 aeidon/encodings.py:108 msgid "Thai" msgstr "Tailandês" #: aeidon/encodings.py:67 aeidon/encodings.py:83 aeidon/encodings.py:84 #: aeidon/encodings.py:85 aeidon/encodings.py:91 aeidon/encodings.py:92 #: aeidon/encodings.py:93 aeidon/encodings.py:94 aeidon/encodings.py:95 #: aeidon/encodings.py:96 aeidon/encodings.py:125 aeidon/encodings.py:126 #: aeidon/encodings.py:127 msgid "Japanese" msgstr "Japonês" #: aeidon/encodings.py:68 aeidon/encodings.py:86 aeidon/encodings.py:97 #: aeidon/encodings.py:113 msgid "Korean" msgstr "Coreano" #: aeidon/encodings.py:70 msgid "Urdu" msgstr "Urdo" #: aeidon/encodings.py:72 aeidon/encodings.py:116 msgid "Ukrainian" msgstr "Ucraniano" #: aeidon/encodings.py:82 msgid "Vietnamese" msgstr "Vietnamita" #: aeidon/encodings.py:87 aeidon/encodings.py:90 msgid "Chinese simplified" msgstr "Chinês simplificado" #: aeidon/encodings.py:88 aeidon/encodings.py:89 msgid "Chinese unified" msgstr "Chinês unificado" #: aeidon/encodings.py:100 aeidon/encodings.py:112 msgid "South European" msgstr "Sul da Europa" #: aeidon/encodings.py:110 msgid "Celtic" msgstr "Celta" #: aeidon/encodings.py:115 msgid "Tajik" msgstr "Tajique" #: aeidon/encodings.py:117 msgid "Kazakh" msgstr "Cazaque" #: aeidon/encodings.py:124 msgid "Cyrillic Asian" msgstr "Cirílico Asiático" #: aeidon/encodings.py:128 aeidon/encodings.py:129 aeidon/encodings.py:130 #: aeidon/encodings.py:131 aeidon/encodings.py:132 aeidon/encodings.py:133 #: aeidon/encodings.py:134 aeidon/encodings.py:135 aeidon/encodings.py:136 msgid "Unicode" msgstr "Unicode" #: aeidon/encodings.py:156 #, python-brace-format msgid "{description} ({name})" msgstr "{description} ({name})" #: aeidon/encodings.py:232 msgid "Current locale ({})" msgstr "Idioma atual ({})" #: aeidon/locales.py:46 #, python-brace-format msgid "{language} ({country})" msgstr "{language} ({country})" #: aeidon/agents/search.py:227 msgid "Replacing" msgstr "Substituindo" #: aeidon/agents/search.py:256 aeidon/agents/search.py:258 msgid "Replacing all" msgstr "Substituindo todos" #: aeidon/agents/position.py:74 msgid "Adjusting durations" msgstr "Ajustando durações" #: aeidon/agents/position.py:96 msgid "Converting framerate" msgstr "Convertendo quadros por segundo" #: aeidon/agents/position.py:146 msgid "Setting framerate" msgstr "Definindo quadros por segundo" #: aeidon/agents/position.py:168 msgid "Shifting positions" msgstr "Deslocando posições" #: aeidon/agents/position.py:188 msgid "Transforming positions" msgstr "Transformando posições" #: aeidon/agents/clipboard.py:44 msgid "Cutting texts" msgstr "Recortando textos" #: aeidon/agents/clipboard.py:61 msgid "Pasting texts" msgstr "Colando textos" #: aeidon/agents/text.py:91 msgid "Breaking lines" msgstr "Quebra de linhas" #: aeidon/agents/text.py:128 msgid "Capitalizing texts" msgstr "Capitalizando textos" #: aeidon/agents/text.py:185 msgid "Correcting common errors" msgstr "Corrigindo erros comuns" #: aeidon/agents/text.py:234 msgid "Removing hearing impaired texts" msgstr "Removendo textos para deficientes auditivos" #: aeidon/agents/text.py:315 msgid "Joining words by spell-check suggestions" msgstr "Juntando palavras por sugestão do corretor ortográfico" #: aeidon/agents/text.py:354 msgid "Splitting words by spell-check suggestions" msgstr "Dividindo palavras por sugestão do corretor ortográfico" #: aeidon/agents/set.py:58 aeidon/agents/set.py:80 aeidon/agents/set.py:113 msgid "Editing position" msgstr "Editando posição" #: aeidon/agents/set.py:129 msgid "Editing text" msgstr "Editando texto" #: aeidon/agents/edit.py:35 msgid "Clearing texts" msgstr "Apagando textos" #: aeidon/agents/edit.py:61 aeidon/agents/edit.py:83 msgid "Inserting subtitles" msgstr "Inserindo legendas" #: aeidon/agents/edit.py:103 msgid "Merging subtitles" msgstr "Unindo legendas" #: aeidon/agents/edit.py:114 msgid "Removing subtitles" msgstr "Removendo legendas" #: aeidon/agents/edit.py:131 msgid "Replacing positions" msgstr "Substituindo posições" #: aeidon/agents/edit.py:147 msgid "Replacing texts" msgstr "Substituindo textos" #: aeidon/agents/edit.py:171 msgid "Splitting subtitle" msgstr "Dividindo legenda" #: aeidon/agents/format.py:49 msgid "Adding dialogue dashes" msgstr "Adicionando hifens de diálogo" #: aeidon/agents/format.py:68 msgid "Changing case" msgstr "Mudando maiusculização" #: aeidon/agents/format.py:92 msgid "Italicizing" msgstr "Tornando itálico" #: aeidon/agents/format.py:108 msgid "Removing dialogue dashes" msgstr "Removendo hifens de diálogo" #: aeidon/agents/format.py:174 msgid "Unitalicizing" msgstr "Tornando não-itálico" #: gaupol/application.py:219 gaupol/agents/open.py:203 msgid "Open" msgstr "Abrir" #: gaupol/application.py:223 msgid "Open main files" msgstr "Abre arquivos principais" #: gaupol/application.py:230 msgid "Save" msgstr "Salvar" #: gaupol/application.py:233 msgid "Save the current main document" msgstr "Salva o documento principal atual" #: gaupol/application.py:238 msgid "Undo" msgstr "Desfazer" #: gaupol/application.py:242 msgid "Undo the last action" msgstr "Desfaz a última ação" #: gaupol/application.py:249 msgid "Redo" msgstr "Refazer" #: gaupol/application.py:252 msgid "Redo the last undone action" msgstr "Refaz a última ação desfeita" #: gaupol/application.py:260 msgid "Insert" msgstr "Inserir" #: gaupol/application.py:262 msgid "Insert new subtitles" msgstr "Insere novas legendas" #: gaupol/application.py:266 #: data/extensions/custom-framerates/preferences-dialog.ui:78 msgid "Remove" msgstr "Remover" #: gaupol/application.py:268 msgid "Remove the selected subtitles" msgstr "Remove as legendas selecionadas" #: gaupol/application.py:273 data/ui/search-dialog.ui:283 msgid "Find" msgstr "Localizar" #: gaupol/application.py:275 msgid "Search for and replace text" msgstr "Procurar e substituir texto" #: gaupol/application.py:279 data/ui/preferences-dialog.ui:942 msgid "Video" msgstr "Vídeo" #: gaupol/application.py:281 msgid "Show or hide the video player" msgstr "Mostra ou oculta o reprodutor de vídeo" #: gaupol/application.py:285 data/ui/preferences-dialog.ui:1173 msgid "Preview" msgstr "Pré-visualizar" #: gaupol/application.py:287 msgid "Preview from selected position with a video player" msgstr "Pré-visualiza da posição selecionada com um reprodutor de vídeo" #: gaupol/enums.py:37 msgid "No." msgstr "Num." #: gaupol/enums.py:43 msgid "Start" msgstr "Início" #: gaupol/enums.py:44 msgid "Start position" msgstr "Posição inicial" #: gaupol/enums.py:49 msgid "End" msgstr "Fim" #: gaupol/enums.py:50 msgid "End position" msgstr "Posição final" #. TRANSLATORS: 'Dur.' is short for duration. It is used in the header #. of a column that contains numbers five digits wide. #: gaupol/enums.py:57 msgid "Dur." msgstr "Dur." #: gaupol/enums.py:58 msgid "Duration" msgstr "Duração" #: gaupol/enums.py:63 gaupol/enums.py:64 msgid "Text" msgstr "Texto" #: gaupol/enums.py:69 gaupol/enums.py:70 msgid "Translation" msgstr "Tradução" #: gaupol/enums.py:82 msgid "characters" msgstr "caracteres" #: gaupol/enums.py:85 msgid "ems" msgstr "ems" #: gaupol/page.py:60 msgid "Untitled {:d}" msgstr "Sem-título {:d}" #: gaupol/page.py:133 msgid "Close project" msgstr "Fechar projeto" #: gaupol/page.py:145 msgid "{} translation" msgstr "{} tradução" #: gaupol/page.py:302 msgid "Path:" msgstr "Caminho:" #: gaupol/page.py:303 msgid "Format:" msgstr "Formato:" #: gaupol/page.py:304 msgid "Encoding:" msgstr "Codificação:" #: gaupol/page.py:305 msgid "Newlines:" msgstr "Novas linhas:" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:99 msgid "Tasks and Target" msgstr "Tarefas e alvos" #: gaupol/assistants.py:128 msgid "Correct texts in the text column" msgstr "Corrigir textos na coluna de texto" #: gaupol/assistants.py:129 msgid "Correct texts in the translation column" msgstr "Corrigir textos na coluna de tradução" #: gaupol/assistants.py:138 msgid "Correct texts in selected subtitles" msgstr "Corrigir textos nas legendas selecionadas" #: gaupol/assistants.py:139 msgid "Correct texts in current project" msgstr "Corrigir textos no projeto atual" #: gaupol/assistants.py:140 msgid "Correct texts in all open projects" msgstr "Corrigir textos em todos projetos abertos" #: gaupol/assistants.py:363 msgid "Other" msgstr "Outro(s)" #: gaupol/assistants.py:439 msgid "Capitalize texts written in lower case" msgstr "Capitaliza textos escritos em minúsculo" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:443 msgid "Capitalization Patterns" msgstr "Padrão em caixa alta" #: gaupol/assistants.py:445 msgid "Capitalize texts" msgstr "Capitalizar textos" #: gaupol/assistants.py:468 msgid "Correct common errors made by humans or image recognition software" msgstr "" "Corrige erros comuns feitos por humanos ou programa de reconhecimento de " "imagem" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:472 msgid "Common Error Patterns" msgstr "Padrão de erro comum" #: gaupol/assistants.py:474 msgid "Correct common errors" msgstr "Corrigir erros comuns" #: gaupol/assistants.py:526 msgid "Remove explanatory texts meant for the hearing impaired" msgstr "Remove textos explanatórios destinados a deficientes auditivos" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:530 msgid "Hearing Impaired Patterns" msgstr "Padrão de deficiência auditiva" #: gaupol/assistants.py:532 msgid "Remove hearing impaired texts" msgstr "Remove textos para deficientes auditivos" #: gaupol/assistants.py:544 msgid "" "Use spell-check suggestions to fix whitespace detection errors of image " "recognition software" msgstr "" "Usa as sugestões do corretor ortográfico para corrigir erros de detecção de " "espaços em branco do programa de reconhecimento de imagem" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:548 msgid "Joining and Splitting Words" msgstr "Juntando e dividindo palavras" #: gaupol/assistants.py:550 msgid "Join or Split Words" msgstr "Unir ou dividir palavras" #: gaupol/assistants.py:599 gaupol/agents/tools.py:45 msgid "Failed to load dictionary for language \"{}\"" msgstr "Falha ao carregar dicionário para idioma “{}”" #: gaupol/assistants.py:601 gaupol/player.py:263 gaupol/player.py:381 #: gaupol/dialogs/search.py:560 gaupol/dialogs/search.py:568 #: gaupol/dialogs/text_edit.py:49 gaupol/dialogs/encoding.py:56 #: gaupol/agents/open.py:328 gaupol/agents/open.py:337 #: gaupol/agents/open.py:345 gaupol/agents/open.py:354 #: gaupol/agents/tools.py:48 gaupol/agents/save.py:197 #: gaupol/agents/save.py:205 gaupol/agents/preview.py:108 #: gaupol/agents/preview.py:116 gaupol/agents/preview.py:125 #: gaupol/agents/preview.py:133 msgid "_OK" msgstr "_OK" #: gaupol/assistants.py:635 msgid "Break text into lines of defined length" msgstr "Divide texto em linhas de tamanho definido" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:639 msgid "Line-Break Patterns" msgstr "Padrão de quebra-de-linha" #: gaupol/assistants.py:641 msgid "Break lines" msgstr "Quebra de linhas" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:679 msgid "Line-Break Options" msgstr "Opções de quebra-de-linha" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:763 msgid "Correcting Texts" msgstr "Corrigindo Textos" #: gaupol/assistants.py:769 msgid "Each task is now being run on each project." msgstr "Cada tarefa está sendo executada em cada projeto." #: gaupol/assistants.py:793 #, python-brace-format msgid "{current:d} of {total:d} tasks complete" msgstr "{current:d} de {total:d} tarefas concluídas" #: gaupol/assistants.py:801 msgid "Project: {}" msgstr "Projeto: {}" #: gaupol/assistants.py:807 msgid "Task: {}" msgstr "Tarefas: {}" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:832 msgid "Confirm Changes" msgstr "Confirmar mudanças" #: gaupol/assistants.py:892 msgid "Accept" msgstr "Aceitar" #: gaupol/assistants.py:898 msgid "Original Text" msgstr "Texto original" #: gaupol/assistants.py:899 msgid "Corrected Text" msgstr "Texto corrigido" #: gaupol/assistants.py:1048 msgid "Correct Texts" msgstr "Corrigir textos" #: gaupol/assistants.py:1076 msgid "Correcting texts" msgstr "Corrigindo textos" #: gaupol/assistants.py:1092 #, python-brace-format msgid "Edited {edits:d} and removed {removals:d} subtitles" msgstr "{edits:d} legendas editadas e {removals:d} legendas removidas" #: gaupol/assistants.py:1126 msgid "Confirm {:d} Change" msgid_plural "Confirm {:d} Changes" msgstr[0] "Confirmar {:d} alteração" msgstr[1] "Confirmar {:d} alterações" #: gaupol/renderers/multiline.py:86 msgid "Italic" msgstr "Itálico" #: gaupol/player.py:372 msgid "No video streams found" msgstr "Nenhum fluxo de vídeo encontrado" #: gaupol/player.py:379 msgid "Failed to initialize playback" msgstr "Falha ao inicializar a reprodução" #: gaupol/dialogs/search.py:189 data/ui/menubar.ui:524 msgid "_Help" msgstr "A_juda" #: gaupol/dialogs/search.py:471 msgid "Found and replaced {:d} occurence" msgid_plural "Found and replaced {:d} occurences" msgstr[0] "Encontrada e substituída {:d} ocorrência" msgstr[1] "Encontradas e substituídas {:d} ocorrências" #: gaupol/dialogs/search.py:488 msgid "\"{}\" not found" msgstr "“{}” não encontrado(a)" #: gaupol/dialogs/search.py:558 msgid "Error in regular expression pattern" msgstr "Erro no formato da expressão regular" #: gaupol/dialogs/search.py:566 msgid "Error in regular expression replacement" msgstr "Erro na expressão regular de substituição" #: gaupol/dialogs/text_edit.py:48 gaupol/dialogs/framerate_convert.py:63 #: gaupol/dialogs/insert.py:44 gaupol/dialogs/encoding.py:55 #: gaupol/dialogs/split.py:44 gaupol/dialogs/multi_close.py:54 #: gaupol/dialogs/open.py:63 gaupol/dialogs/position_transform.py:69 #: gaupol/dialogs/position_shift.py:71 gaupol/dialogs/multi_save.py:83 #: gaupol/dialogs/multi_save.py:215 gaupol/dialogs/duration_adjust.py:86 #: gaupol/dialogs/save.py:73 gaupol/dialogs/video.py:41 #: gaupol/agents/open.py:363 gaupol/agents/open.py:375 #: gaupol/agents/open.py:387 gaupol/agents/close.py:71 #: data/extensions/custom-framerates/custom-framerates.py:39 msgid "_Cancel" msgstr "_Cancelar" #: gaupol/dialogs/text_edit.py:53 msgid "Edit Text" msgstr "Editar texto" #: gaupol/dialogs/framerate_convert.py:64 msgid "Co_nvert" msgstr "Co_nverter" #: gaupol/dialogs/insert.py:45 msgid "_Insert" msgstr "_Inserir" #: gaupol/dialogs/insert.py:54 msgid "Above selection" msgstr "Acima da seleção" #: gaupol/dialogs/insert.py:55 msgid "Below selection" msgstr "Abaixo da seleção" #: gaupol/dialogs/encoding.py:60 data/ui/preferences-dialog.ui:70 msgid "Character Encodings" msgstr "Codificação de caracteres" #: gaupol/dialogs/encoding.py:78 gaupol/dialogs/encoding.py:125 msgid "Description" msgstr "Descrição" #: gaupol/dialogs/encoding.py:85 gaupol/dialogs/encoding.py:132 msgid "Encoding" msgstr "Codificação" #: gaupol/dialogs/encoding.py:141 msgid "Show in Menu" msgstr "Mostrar no menu" #: gaupol/dialogs/split.py:45 msgid "_Split" msgstr "_Dividir" #: gaupol/dialogs/split.py:76 msgid "Splitting project" msgstr "Dividindo projeto" #: gaupol/dialogs/split.py:97 #, python-brace-format msgid "Split {amount:d} subtitles to project \"{name}\"" msgstr "Dividir {amount:d} legendas para projeto “{name}”" #: gaupol/dialogs/spell_check.py:269 msgid "Spell-checking" msgstr "Verificar ortografia" #: gaupol/dialogs/preferences.py:217 msgid "{} Extension Website" msgstr "Website da extensão {}" #: gaupol/dialogs/preferences.py:429 msgid "Custom" msgstr "Personalizado" #: gaupol/dialogs/multi_close.py:38 msgid "Save changes to documents before closing?" msgstr "Salvar mudanças no documento antes de fechar?" #: gaupol/dialogs/multi_close.py:39 gaupol/agents/open.py:384 #: gaupol/agents/close.py:68 msgid "If you don't save, changes will be permanently lost." msgstr "Caso você não salve, as mudanças serão perdidas permanentemente." #: gaupol/dialogs/multi_close.py:53 gaupol/agents/close.py:70 msgid "Close _Without Saving" msgstr "Fechar _sem salvar" #: gaupol/dialogs/multi_close.py:55 gaupol/dialogs/multi_save.py:84 #: gaupol/dialogs/save.py:74 gaupol/agents/open.py:388 #: gaupol/agents/close.py:72 data/ui/menubar.ui:34 msgid "_Save" msgstr "_Salvar" #: gaupol/dialogs/multi_close.py:70 msgid "Select the _main documents you want to save:" msgstr "Selecione os docu_mentos principais que deseja salvar:" #: gaupol/dialogs/multi_close.py:95 msgid "Select the _translation documents you want to save:" msgstr "Selecione os documentos de _tradução que deseja salvar:" #: gaupol/dialogs/open.py:64 gaupol/agents/open.py:364 #: gaupol/agents/open.py:376 msgid "_Open" msgstr "_Abrir" #: gaupol/dialogs/position_transform.py:70 msgid "_Transform" msgstr "_Transformar" #: gaupol/dialogs/position_shift.py:72 msgid "_Shift" msgstr "_Deslocar" #: gaupol/dialogs/position_shift.py:150 msgid "frames" msgstr "quadros" #: gaupol/dialogs/position_shift.py:168 data/ui/preferences-dialog.ui:911 msgid "seconds" msgstr "segundos" #: gaupol/dialogs/about.py:36 msgid "About Gaupol" msgstr "Sobre o Gaupol" #: gaupol/dialogs/about.py:40 msgid "Subtitle editor" msgstr "Editor de legendas" #. TRANSLATORS: This is a special message that shouldn't be translated #. literally. It is used in the about dialog to give credits to the #. translators. Thus, you should translate it to your name and email #. address. You can also include other translators who have contributed #. to this translation; in that case, please write them on separate #. lines seperated by newlines (\n). #: gaupol/dialogs/about.py:51 msgid "translator-credits" msgstr "" "Átila Camurça \n" "Darlildo Lima \n" "Felipe Braga \n" "Rafael Fontenelle " #: gaupol/dialogs/about.py:54 msgid "Gaupol Website" msgstr "Site do Gaupol" #: gaupol/dialogs/append.py:35 msgid "Append File" msgstr "Anexar arquivo" #: gaupol/dialogs/debug.py:43 msgid "Something went wrong" msgstr "Alguma coisa deu errado" #: gaupol/dialogs/debug.py:44 msgid "" "You have probably discovered a bug. Please report it by providing the below " "information and a description of what you were doing." msgstr "" "Você provavelmente descobriu um bug. Por favor, relate-o fornecendo as " "informações abaixo e uma descrição do que você estava fazendo." #: gaupol/dialogs/debug.py:52 msgid "_Report Bug" msgstr "_Relatar bug" #: gaupol/dialogs/debug.py:53 data/ui/menubar.ui:56 msgid "_Quit" msgstr "_Sair" #: gaupol/dialogs/debug.py:54 gaupol/dialogs/preview_error.py:45 #: data/ui/menubar.ui:52 data/ui/tab-popup.ui:16 msgid "_Close" msgstr "Fe_char" #: gaupol/dialogs/multi_save.py:98 gaupol/dialogs/save.py:110 msgid "{} (recommended)" msgstr "{} (recomendado)" #: gaupol/dialogs/multi_save.py:212 msgid "" "{:d} of the files to be saved already exist. Do you want to replace them?" msgstr "{:d} dos arquivos a serem salvos já existem. Deseja substituí-los?" #: gaupol/dialogs/multi_save.py:213 msgid "" "The files already exist in \"{}\". Replacing them will overwrite their " "contents." msgstr "" "Os arquivos já existem em “{}”. Substituí-los irá sobrescrever seu conteúdo." #: gaupol/dialogs/multi_save.py:216 data/ui/search-dialog.ui:192 #: data/ui/spell-check-dialog.ui:122 msgid "_Replace" msgstr "_Substituir" #: gaupol/dialogs/duration_adjust.py:70 msgid "Adjusted duration of {:d} subtitle" msgid_plural "Adjusted durations of {:d} subtitles" msgstr[0] "Ajustada duração de {:d} legenda" msgstr[1] "Ajustadas durações de {:d} legendas" #: gaupol/dialogs/duration_adjust.py:87 msgid "_Adjust" msgstr "_Ajustar" #: gaupol/dialogs/preview_error.py:36 msgid "Preview in video player failed" msgstr "Pré-visualização no reprodutor de vídeo falhou" #: gaupol/dialogs/preview_error.py:37 msgid "" "There is probably a problem with either the video file or the video player. " "See the preferences dialog to choose the video player or to customize the " "command." msgstr "" "Provavelmente, há um problema com o arquivo de vídeo ou o reprodutor de " "vídeo. Veja o diálogo de preferências para escolher o reprodutor de vídeo ou" " para personalizar o comando." #: gaupol/dialogs/language.py:97 msgid "Set Language" msgstr "Definir idioma" #: gaupol/dialogs/video.py:52 gaupol/dialogs/file.py:59 msgid "All files" msgstr "Todos os arquivos" #: gaupol/dialogs/video.py:56 msgid "Video files" msgstr "Arquivos de vídeo" #: gaupol/dialogs/file.py:63 msgid "All supported files" msgstr "Todos os arquivos suportados" #: gaupol/dialogs/file.py:77 #, python-brace-format msgid "{format} (*{extension})" msgstr "{format} (*{extension})" #: gaupol/dialogs/file.py:120 msgid "Auto-detected" msgstr "Auto-detecção" #: gaupol/dialogs/file.py:122 msgid "Other…" msgstr "Outro…" #: gaupol/agents/menu.py:94 gaupol/agents/menu.py:103 #: gaupol/agents/menu.py:110 msgid "File not found" msgstr "Arquivo não encontrado" #: gaupol/agents/open.py:85 #, python-brace-format msgid "Appended {amount:d} subtitles from \"{basename}\"" msgstr "Adicionar ao fim {amount:d} legendas de “{basename}”" #: gaupol/agents/open.py:96 msgid "Appending file" msgstr "Anexando arquivo" #: gaupol/agents/open.py:111 msgid "File \"{}\" is already open" msgstr "Arquivo “{}” já está aberto" #: gaupol/agents/open.py:214 msgid "Open Translation" msgstr "Abrir tradução" #: gaupol/agents/open.py:223 msgid "Select Video" msgstr "Selecionar vídeo" #: gaupol/agents/open.py:224 msgid "_Select" msgstr "_Selecionar" #: gaupol/agents/open.py:325 msgid "Failed to decode file \"{}\" with all attempted codecs" msgstr "Falha ao decodificar arquivo “{}” com todos os codecs tentados" #: gaupol/agents/open.py:326 msgid "Please try to open the file with a different character encoding." msgstr "Por favor, tente abrir o arquivo com uma codificação diferente." #: gaupol/agents/open.py:334 msgid "Failed to recognize format of file \"{}\"" msgstr "Falha ao reconhecer formato do arquivo “{}”" #: gaupol/agents/open.py:335 msgid "" "Please check that the file you are trying to open is a subtitle file of a " "format supported by Gaupol." msgstr "" "Por favor, verifique se o arquivo que você está tentando abrir é um arquivo " "de legenda com formato suportado pelo Gaupol." #: gaupol/agents/open.py:343 msgid "Failed to open file \"{}\"" msgstr "Falha ao abrir arquivo “{}”" #: gaupol/agents/open.py:351 msgid "Failed to parse file \"{}\"" msgstr "Falha ao processar arquivo “{}”" #: gaupol/agents/open.py:352 msgid "Please check that the file you are trying to open is a valid {} file." msgstr "" "Por favor, verifique se o arquivo que você está tentando abrir é um arquivo " "{} válido." #: gaupol/agents/open.py:360 msgid "Open abnormally large file \"{}\"?" msgstr "Abrir arquivo absurdamente grande “{}”?" #: gaupol/agents/open.py:361 msgid "" "Size of the file is {:.1f} MB, which is abnormally large for a text-based " "subtitle file. Please, check that you are not trying to open a binary file." msgstr "" "O tamanho do arquivo é {:.1f} MB, o qual é absurdamente grande para um " "arquivo texto de legenda. Por favor, verifique se você não está tentando " "abrir um arquivo binário." #: gaupol/agents/open.py:371 msgid "Open unsorted file \"{}\"?" msgstr "Abrir arquivo não-ordenado “{}”?" #: gaupol/agents/open.py:372 msgid "" "The order of {:d} subtitles needs to be changed. If {:d} sounds like a lot, " "the file may be erroneously composed." msgstr "" "A ordem de {:d} legendas precisa ser mudada. Se {:d} parece muita coisa, o " "arquivo pode estar escrito incorretamente." #: gaupol/agents/open.py:383 msgid "Save changes to translation document \"{}\" before opening a new one?" msgstr "Salvar mudanças para documento de tradução “{}” antes de abrir outro?" #: gaupol/agents/open.py:386 msgid "Open _Without Saving" msgstr "Abrir _sem salvar" #: gaupol/agents/close.py:66 msgid "Save changes to document \"{}\" before closing?" msgstr "Salvar mudanças no documento “{}” antes de fechar?" #: gaupol/agents/edit.py:101 gaupol/agents/edit.py:119 msgid "Stretching end position" msgstr "Posição de início da esticada" #: gaupol/agents/edit.py:208 msgid "Inserted {:d} subtitle to fit clipboard contents" msgid_plural "Inserted {:d} subtitles to fit clipboard contents" msgstr[0] "" "Inseridas {:d} legenda para o conteúdo caber na área de transferência" msgstr[1] "" "Inseridas {:d} legendas para o conteúdo caber na área de transferência" #: gaupol/agents/edit.py:334 gaupol/agents/edit.py:352 msgid "Stretching start position" msgstr "Posição de fim da esticada" #: gaupol/agents/edit.py:411 msgid "Use Shift+Return for line-break" msgstr "Use Shift+Enter para quebra de linha" #: gaupol/agents/save.py:129 msgid "Save As" msgstr "Salvar como" #: gaupol/agents/save.py:135 msgid "Saved main document as \"{}\"" msgstr "Documento principal salvo como “{}”" #: gaupol/agents/save.py:153 msgid "Save Translation As" msgstr "Salvar tradução como" #: gaupol/agents/save.py:159 msgid "Saved translation document as \"{}\"" msgstr "Salvar documento de tradução como “{}”" #: gaupol/agents/save.py:194 #, python-brace-format msgid "Failed to encode file \"{basename}\" with codec \"{codec}\"" msgstr "Falha ao codificar aquivo “{basename}” com codificação “{codec}”" #: gaupol/agents/save.py:195 msgid "Please try to save the file with a different character encoding." msgstr "Por favor, tente salvar o arquivo com uma codificação diferente." #: gaupol/agents/save.py:203 msgid "Failed to save file \"{}\"" msgstr "Falhar ao salvar arquivo “{}”" #: gaupol/agents/video.py:67 data/ui/menubar.ui:380 msgid "_Play/Pause" msgstr "Re_produzir/parar" #: gaupol/agents/video.py:69 msgid "Play or pause video" msgstr "Reproduz ou para o vídeo" #: gaupol/agents/video.py:75 data/ui/menubar.ui:390 msgid "Seek _Previous" msgstr "Ir para legenda _anterior" #: gaupol/agents/video.py:77 msgid "Seek to the start of the previous subtitle" msgstr "Ir para início da legenda anterior" #: gaupol/agents/video.py:81 data/ui/menubar.ui:394 msgid "Seek _Next" msgstr "Ir para _próxima legenda" #: gaupol/agents/video.py:83 msgid "Seek to the start of the next subtitle" msgstr "Ir para início da próxima legenda" #: gaupol/agents/video.py:88 data/ui/menubar.ui:400 msgid "Seek _Backward" msgstr "Ir para _trás" #: gaupol/agents/video.py:90 msgid "Seek backward" msgstr "Ir para trás" #: gaupol/agents/video.py:94 data/ui/menubar.ui:404 msgid "Seek _Forward" msgstr "Ir para _frente" #: gaupol/agents/video.py:96 msgid "Seek forward" msgstr "Ir para frente" #: gaupol/agents/video.py:109 msgid "Volume" msgstr "Volume" #: gaupol/agents/video.py:189 msgid "Load Video" msgstr "Carregar vídeo" #: gaupol/agents/video.py:189 msgid "_Load" msgstr "_Carregar" #: gaupol/agents/video.py:361 msgid "Track {:d}" msgstr "Faixa {:d}" #: gaupol/agents/preview.py:105 msgid "Failed to encode subtitle file to temporary directory \"{}\"" msgstr "Falha ao codificar legenda para o diretório temporário “{}”" #: gaupol/agents/preview.py:106 msgid "" "Subtitle data could not be encoded to a temporary file for preview with the " "current character encoding. Please first save the subtitle file with a " "different character encoding." msgstr "" "A legenda não pode ser codificada para um arquivo temporário para pré-" "visualização com a codificação atual. Por favor, salve antes a legenda com " "uma codificação diferente." #: gaupol/agents/preview.py:114 msgid "Failed to save subtitle file to temporary directory \"{}\"" msgstr "Falha ao salvar arquivo de legenda para o diretório temporário “{}”" #: gaupol/agents/preview.py:122 msgid "Video player not found" msgstr "Reprodutor de vídeo não encontrado" #: gaupol/agents/preview.py:123 msgid "" "Please install one of the supported video players: mpv (recommended), " "MPlayer or VLC. See the preferences dialog to choose the video player or to " "customize the command." msgstr "" "Por favor, instale um dos reprodutores de vídeo compatíveis: mpv " "(recomendado), MPlayer ou VLC. Veja o diálogo de preferências para escolher " "o reprodutor de vídeo ou para personalizar o comando." #: gaupol/agents/preview.py:131 msgid "Failed to launch video player" msgstr "Falha ao lançar reprodutor de vídeo" #: gaupol/applicationman.py:105 msgid "gaupol [OPTION...] [FILE...] [+[NUM]]" msgstr "gaupol [OPÇÃO…] [ARQUIVO…] [+[NÚM]]" #: gaupol/applicationman.py:109 msgid "FILE..." msgstr "ARQUIVO…" #: gaupol/applicationman.py:112 msgid "subtitle files to open" msgstr "arquivo de legendas para abrir" #: gaupol/applicationman.py:122 msgid "ENCODING" msgstr "CODIFICAÇÃO" #: gaupol/applicationman.py:125 msgid "set the character encoding used to open files" msgstr "define a codificação usada para abrir arquivos" #: gaupol/applicationman.py:132 msgid "list all available character encodings" msgstr "lista todas as codificações disponíveis" #: gaupol/applicationman.py:137 gaupol/applicationman.py:154 msgid "FILE" msgstr "ARQUIVO" #: gaupol/applicationman.py:140 msgid "open translation file" msgstr "abre o arquivo de tradução" #: gaupol/applicationman.py:145 msgid "METHOD" msgstr "MÉTODO" #: gaupol/applicationman.py:149 msgid "method used to align translation subtitles: 'number' or 'position'" msgstr "método usado para alinhar legendas traduzidas: “número” ou “posição”" #: gaupol/applicationman.py:157 msgid "select video file" msgstr "seleciona um arquivo de vídeo" #: data/extensions/custom-framerates/custom-framerates.py:40 #: data/ui/spell-check-dialog.ui:152 msgid "_Add" msgstr "_Adicionar" #: data/extensions/custom-framerates/custom-framerates.py:171 msgid "{:.3f} fps" msgstr "{:.3f} fps" #: data/extensions/custom-framerates/add-framerate-dialog.ui:13 msgid "Add Framerate" msgstr "Adicionar taxa de quadros" #: data/extensions/custom-framerates/add-framerate-dialog.ui:44 msgid "_Framerate:" msgstr "_Taxa de quadros:" #: data/extensions/custom-framerates/add-framerate-dialog.ui:73 msgid "fps" msgstr "fps" #: data/extensions/custom-framerates/preferences-dialog.ui:8 msgid "Framerates" msgstr "Taxas de quadros" #: data/extensions/custom-framerates/preferences-dialog.ui:64 msgid "Add" msgstr "Adicionar" #: data/ui/columns-popup.ui:6 data/ui/menubar.ui:275 msgid "_No." msgstr "_Num." #: data/ui/columns-popup.ui:10 data/ui/menubar.ui:279 msgid "_Start" msgstr "_Início" #: data/ui/columns-popup.ui:14 data/ui/menubar.ui:283 msgid "_End" msgstr "_Fim" #: data/ui/columns-popup.ui:18 data/ui/menubar.ui:287 msgid "_Duration" msgstr "_Duração" #: data/ui/columns-popup.ui:22 data/ui/menubar.ui:291 data/ui/menubar.ui:303 msgid "_Text" msgstr "_Texto" #: data/ui/columns-popup.ui:26 data/ui/menubar.ui:295 msgid "T_ranslation" msgstr "T_radução" #: data/ui/split-dialog.ui:15 msgid "Split Project" msgstr "Dividir projeto" #: data/ui/split-dialog.ui:48 msgid "_First subtitle of new project:" msgstr "_Primeira legenda do novo projeto:" #: data/ui/search-dialog.ui:89 msgid "_Search for:" msgstr "_Procurar por:" #: data/ui/search-dialog.ui:103 data/ui/spell-check-dialog.ui:193 msgid "Replace _with:" msgstr "Substituir _por:" #: data/ui/search-dialog.ui:162 data/ui/menubar.ui:328 msgid "Find _Next" msgstr "Localizar _próxima" #: data/ui/search-dialog.ui:177 msgid "Find _Previous" msgstr "Localizar _anterior" #: data/ui/search-dialog.ui:207 msgid "Replace _All" msgstr "Substituir _tudo" #: data/ui/search-dialog.ui:241 msgid "R_egular expression" msgstr "Expressão r_egular" #: data/ui/search-dialog.ui:258 msgid "_Ignore case" msgstr "_Ignorar maiúsculas/minúsculas" #: data/ui/search-dialog.ui:304 data/ui/language-dialog.ui:108 msgid "Columns" msgstr "Colunas" #: data/ui/search-dialog.ui:324 msgid "Find in _text column" msgstr "Localizar na coluna de _texto" #: data/ui/search-dialog.ui:341 msgid "Find in t_ranslation column" msgstr "Localizar na coluna de t_radução" #: data/ui/search-dialog.ui:381 data/ui/framerate-convert-dialog.ui:144 #: data/ui/language-dialog.ui:186 #: data/ui/text-assistant/line-break-options-page.ui:178 #: data/ui/duration-adjust-dialog.ui:388 data/ui/position-shift-dialog.ui:180 #: data/ui/position-transform-dialog.ui:444 msgid "Subtitles" msgstr "Legendas" #: data/ui/search-dialog.ui:401 msgid "Find in c_urrent project" msgstr "Localizar no projeto at_ual" #: data/ui/search-dialog.ui:419 msgid "Find in _all open projects" msgstr "Loc_alizar em todos os projetos abertos" #: data/ui/search-dialog.ui:452 msgid "Target" msgstr "Alvo" #: data/ui/framerate-convert-dialog.ui:8 msgid "Convert Framerate" msgstr "Converter quadros por segundo" #: data/ui/framerate-convert-dialog.ui:48 msgid "Framerate" msgstr "Taxa de quadros" #: data/ui/framerate-convert-dialog.ui:71 msgid "_Input:" msgstr "_Entrada:" #: data/ui/framerate-convert-dialog.ui:86 msgid "_Output:" msgstr "_Saída:" #: data/ui/framerate-convert-dialog.ui:164 msgid "Convert c_urrent project" msgstr "Converter projeto at_ual" #: data/ui/framerate-convert-dialog.ui:181 msgid "Convert _all open projects" msgstr "Converter todos projetos _abertos" #: data/ui/spell-check-dialog.ui:8 msgid "Check Spelling" msgstr "Verificar ortografia" #: data/ui/spell-check-dialog.ui:47 msgid "Join _Back" msgstr "Juntar para _trás" #: data/ui/spell-check-dialog.ui:62 msgid "Join _Forward" msgstr "Juntar para _frente" #: data/ui/spell-check-dialog.ui:77 data/ui/menubar.ui:62 msgid "_Edit" msgstr "_Editar" #: data/ui/spell-check-dialog.ui:92 msgid "_Ignore" msgstr "_Ignorar" #: data/ui/spell-check-dialog.ui:107 msgid "Ig_nore All" msgstr "Ig_norar tudo" #: data/ui/spell-check-dialog.ui:137 msgid "Rep_lace All" msgstr "Sub_stituir tudo" #: data/ui/spell-check-dialog.ui:179 msgid "_Suggestions:" msgstr "_Sugestões:" #: data/ui/multi-save-dialog.ui:8 msgid "Save All As" msgstr "Salvar todos como" #: data/ui/multi-save-dialog.ui:46 msgid "Save in _folder:" msgstr "Salvar no _diretório:" #: data/ui/multi-save-dialog.ui:60 data/ui/save-dialog.ui:25 msgid "For_mat:" msgstr "For_mato:" #: data/ui/multi-save-dialog.ui:74 data/ui/open-dialog.ui:25 #: data/ui/save-dialog.ui:39 msgid "_Encoding:" msgstr "_Codificação:" #: data/ui/multi-save-dialog.ui:88 data/ui/save-dialog.ui:53 msgid "Ne_wlines:" msgstr "No_vas linhas:" #: data/ui/multi-save-dialog.ui:103 msgid "Select A Folder" msgstr "Selecione um diretório" #: data/ui/multi-save-dialog.ui:150 data/ui/save-dialog.ui:102 msgid "F_ramerate:" msgstr "Ta_xa de quadros:" #: data/ui/menubar.ui:5 msgid "_File" msgstr "_Arquivo" #: data/ui/menubar.ui:8 msgid "_New" msgstr "_Novo" #: data/ui/menubar.ui:12 msgid "_Open…" msgstr "_Abrir…" #: data/ui/menubar.ui:16 msgid "Open _Translation…" msgstr "Abrir _tradução…" #: data/ui/menubar.ui:22 msgid "Open _Recent" msgstr "Abrir _recente" #: data/ui/menubar.ui:27 msgid "Open R_ecent Translation" msgstr "Abrir tradução r_ecente" #: data/ui/menubar.ui:38 msgid "Save _As…" msgstr "S_alvar como…" #: data/ui/menubar.ui:42 msgid "Save Trans_lation" msgstr "Sa_lvar tradução" #: data/ui/menubar.ui:46 msgid "Save Translat_ion As…" msgstr "Salvar t_radução como…" #: data/ui/menubar.ui:65 msgid "_Undo" msgstr "_Desfazer" #: data/ui/menubar.ui:69 msgid "_Redo" msgstr "_Refazer" #: data/ui/menubar.ui:75 msgid "_Edit Cell" msgstr "_Editar célula" #: data/ui/menubar.ui:79 msgid "Edit _Next Cell" msgstr "Editar pró_xima célula" #: data/ui/menubar.ui:85 msgid "Stretc_h" msgstr "E_sticar" #: data/ui/menubar.ui:88 msgid "_Start Earlier" msgstr "_Iniciar mais cedo" #: data/ui/menubar.ui:92 msgid "S_tart Later" msgstr "I_niciar mais tarde" #: data/ui/menubar.ui:98 msgid "E_nd Earlier" msgstr "Termi_nar mais cedo" #: data/ui/menubar.ui:102 msgid "En_d Later" msgstr "_Terminar mais tarde" #: data/ui/menubar.ui:108 msgid "Set St_art From Video Position" msgstr "Definir iníci_o da posição vídeo" #: data/ui/menubar.ui:112 msgid "Set En_d From Video Position" msgstr "Definir _fim da posição do vídeo" #: data/ui/menubar.ui:118 data/ui/view-popup.ui:6 msgid "_Split Subtitle" msgstr "_Dividir legenda" #: data/ui/menubar.ui:122 data/ui/view-popup.ui:10 msgid "_Merge Subtitles" msgstr "_Unir legendas" #: data/ui/menubar.ui:128 data/ui/view-popup.ui:16 msgid "_Insert Subtitles…" msgstr "_Inserir legendas…" #: data/ui/menubar.ui:132 msgid "Inser_t Subtitle At Video Position" msgstr "Inseri_r legenda na posição do vídeo" #: data/ui/menubar.ui:136 data/ui/view-popup.ui:20 msgid "Rem_ove Subtitles" msgstr "Rem_over legendas" #: data/ui/menubar.ui:142 msgid "Sele_ction" msgstr "S_eleção" #: data/ui/menubar.ui:145 msgid "Select _All" msgstr "Selecion_ar tudo" #: data/ui/menubar.ui:149 msgid "_Invert Selection" msgstr "I_nverter seleção" #: data/ui/menubar.ui:155 msgid "Extend To _Beginning" msgstr "Prolongar até o _início" #: data/ui/menubar.ui:159 msgid "Extend To _End" msgstr "Prolongar até o _fim" #: data/ui/menubar.ui:165 msgid "_Previous From Video Position" msgstr "_Anterior à posição do vídeo" #: data/ui/menubar.ui:169 msgid "_Next From Video Position" msgstr "_Próximo a partir da posição do vídeo" #: data/ui/menubar.ui:177 msgid "_Preferences" msgstr "_Preferências" #: data/ui/menubar.ui:183 msgid "_View" msgstr "_Ver" #: data/ui/menubar.ui:186 msgid "Tool_bar" msgstr "_Barra de ferramentas" #: data/ui/menubar.ui:190 msgid "_Video Player" msgstr "Reprodutor de _vídeo" #: data/ui/menubar.ui:196 msgid "_Layout" msgstr "_Layout" #: data/ui/menubar.ui:199 msgid "_Horizontal" msgstr "_Horizontal" #: data/ui/menubar.ui:204 msgid "_Vertical" msgstr "_Vertical" #: data/ui/menubar.ui:213 msgid "_Times" msgstr "_Tempos" #: data/ui/menubar.ui:218 msgid "_Frames" msgstr "_Quadros" #: data/ui/menubar.ui:225 msgid "F_ramerate" msgstr "Quad_ros por segundo" #: data/ui/menubar.ui:228 msgid "2_3.976 fps" msgstr "2_3.976 fps" #: data/ui/menubar.ui:233 msgid "2_4.000 fps" msgstr "2_4.000 fps" #: data/ui/menubar.ui:238 msgid "2_5.000 fps" msgstr "2_5.000 fps" #: data/ui/menubar.ui:243 msgid "2_9.970 fps" msgstr "2_9.970 fps" #: data/ui/menubar.ui:272 msgid "_Columns" msgstr "_Colunas" #: data/ui/menubar.ui:306 msgid "Cu_t" msgstr "Recor_tar" #: data/ui/menubar.ui:310 msgid "_Copy" msgstr "_Copiar" #: data/ui/menubar.ui:314 msgid "_Paste" msgstr "C_olar" #: data/ui/menubar.ui:318 msgid "Cl_ear" msgstr "Lim_par" #: data/ui/menubar.ui:324 msgid "_Find And Replace…" msgstr "_Localizar e substituir…" #: data/ui/menubar.ui:332 msgid "Find Pre_vious" msgstr "Localizar _anterior" #: data/ui/menubar.ui:338 msgid "_Italic" msgstr "_Itálico" #: data/ui/menubar.ui:342 msgid "_Dialogue" msgstr "_Diálogo" #: data/ui/menubar.ui:348 msgid "Ca_se" msgstr "Maiú_sculo/Minúsculo" #: data/ui/menubar.ui:351 msgid "_Title" msgstr "_Título" #: data/ui/menubar.ui:355 msgid "_Sentence" msgstr "_Sentença" #: data/ui/menubar.ui:359 msgid "_Upper" msgstr "Ma_iúsculo" #: data/ui/menubar.ui:363 msgid "_Lower" msgstr "Minúscu_lo" #: data/ui/menubar.ui:371 msgid "Vi_deo" msgstr "Ví_deo" #: data/ui/menubar.ui:374 msgid "_Load Video…" msgstr "_Carregar vídeo…" #: data/ui/menubar.ui:384 data/ui/view-popup.ui:26 msgid "Play _Selection" msgstr "Reproduzir _seleção" #: data/ui/menubar.ui:410 data/ui/view-popup.ui:30 msgid "S_eek Selection Start" msgstr "Ir para _início da seleção" #: data/ui/menubar.ui:414 msgid "See_k Selection End" msgstr "Ir para fi_m da seleção" #: data/ui/menubar.ui:420 msgid "_Audio" msgstr "Á_udio" #: data/ui/menubar.ui:423 msgid "_Language" msgstr "_Idioma" #: data/ui/menubar.ui:430 msgid "Volume _Down" msgstr "A_baixar volume" #: data/ui/menubar.ui:434 msgid "Volume _Up" msgstr "A_umentar volume" #: data/ui/menubar.ui:440 msgid "T_ools" msgstr "_Ferramentas" #: data/ui/menubar.ui:443 data/ui/text-assistant/confirmation-page.ui:97 #: data/ui/view-popup.ui:36 msgid "_Preview" msgstr "_Pré-visualizar" #: data/ui/menubar.ui:447 msgid "Select _Video…" msgstr "Selecionar _vídeo…" #: data/ui/menubar.ui:453 msgid "_Check Spelling" msgstr "_Verificação ortográfica" #: data/ui/menubar.ui:457 msgid "Co_nfigure Spell-check…" msgstr "Co_nfigurar corretor ortográfico…" #: data/ui/menubar.ui:461 msgid "C_orrect Texts…" msgstr "C_orrigir textos…" #: data/ui/menubar.ui:467 msgid "_Shift Positions…" msgstr "_Deslocar posições…" #: data/ui/menubar.ui:471 msgid "_Transform Positions…" msgstr "_Transformar posições…" #: data/ui/menubar.ui:475 msgid "Adjust _Durations…" msgstr "Ajustar _durações…" #: data/ui/menubar.ui:479 msgid "Convert _Framerate…" msgstr "Converter taxa de _quadros…" #: data/ui/menubar.ui:485 msgid "_Append File…" msgstr "_Anexar arquivo…" #: data/ui/menubar.ui:489 msgid "Spli_t Project…" msgstr "Dividir proje_to…" #: data/ui/menubar.ui:495 msgid "_Projects" msgstr "_Projetos" #: data/ui/menubar.ui:498 msgid "_Save All" msgstr "_Salvar tudo" #: data/ui/menubar.ui:502 msgid "Save _All As…" msgstr "S_alvar tudo como…" #: data/ui/menubar.ui:506 msgid "_Close All" msgstr "Fe_char todos" #: data/ui/menubar.ui:512 msgid "_Previous" msgstr "A_nterior" #: data/ui/menubar.ui:516 msgid "_Next" msgstr "_Próximo" #: data/ui/menubar.ui:527 msgid "_Documentation" msgstr "_Documentação" #: data/ui/menubar.ui:531 msgid "_Report A Bug" msgstr "_Reportar um problema" #: data/ui/menubar.ui:535 msgid "_About" msgstr "_Sobre" #: data/ui/open-dialog.ui:39 msgid "Align _method:" msgstr "_Método de alinhamento:" #: data/ui/preferences-dialog.ui:18 msgid "Preferences" msgstr "Preferências" #: data/ui/preferences-dialog.ui:93 msgid "When opening files, try encodings in the following order:" msgstr "Quando abrir arquivos, tentar codificações na seguinte ordem:" #: data/ui/preferences-dialog.ui:104 msgid "Curr_ent locale encoding" msgstr "Codificação local at_ual" #: data/ui/preferences-dialog.ui:130 msgid "_Fallback encodings:" msgstr "Codificações _secundárias:" #: data/ui/preferences-dialog.ui:246 msgid "Aut_o-detection" msgstr "Aut_o-detecção" #: data/ui/preferences-dialog.ui:266 msgid "Encoding specified in the open dialog will always be tried first." msgstr "" "Codificação especificada no diálogo Abrir sempre será tentada primeiro." #: data/ui/preferences-dialog.ui:296 msgid "File" msgstr "Arquivo" #: data/ui/preferences-dialog.ui:324 msgid "Font" msgstr "Fonte" #: data/ui/preferences-dialog.ui:344 msgid "Use _default theme fixed width font" msgstr "Usar fonte de largura fixa _padrão do tema" #: data/ui/preferences-dialog.ui:368 msgid "_Editor font:" msgstr "Fonte do _editor:" #: data/ui/preferences-dialog.ui:425 msgid "Line Lengths" msgstr "Tamanho das linhas" #: data/ui/preferences-dialog.ui:445 msgid "_Show line lengths in list cells" msgstr "Mostrar comprimentos das linhas nas _células da lista" #: data/ui/preferences-dialog.ui:462 msgid "S_how line lengths in editable text fields" msgstr "Mostrar comprimentos das linhas em c_ampos texto editáveis" #: data/ui/preferences-dialog.ui:486 msgid "_Length unit:" msgstr "Unidade de _comprimento:" #: data/ui/preferences-dialog.ui:540 msgid "Spell-Check" msgstr "Verificação ortográfica" #: data/ui/preferences-dialog.ui:560 msgid "Chec_k spelling as you type" msgstr "_Verificar a ortográfica ao digitar" #: data/ui/preferences-dialog.ui:598 msgid "Editor" msgstr "Editor" #: data/ui/preferences-dialog.ui:626 msgid "Fonts" msgstr "Fontes" #: data/ui/preferences-dialog.ui:649 msgid "_Subtitles:" msgstr "_Legendas:" #: data/ui/preferences-dialog.ui:679 msgid "_Time:" msgstr "_Tempo:" #: data/ui/preferences-dialog.ui:729 msgid "Colors" msgstr "Cores" #: data/ui/preferences-dialog.ui:752 msgid "Su_btitles:" msgstr "Le_gendas:" #: data/ui/preferences-dialog.ui:777 msgid "_Use a background behind text" msgstr "_Usar um plano de fundo por trás do texto" #: data/ui/preferences-dialog.ui:797 msgid "Ti_me:" msgstr "Te_mpos:" #: data/ui/preferences-dialog.ui:822 msgid "Us_e a background behind text" msgstr "U_sar um plano de fundo por trás do texto" #: data/ui/preferences-dialog.ui:862 msgid "Seek" msgstr "Procurar" #: data/ui/preferences-dialog.ui:883 msgid "_Length:" msgstr "Taman_ho:" #: data/ui/preferences-dialog.ui:971 msgid "Video Player" msgstr "Reprodutor de vídeo" #: data/ui/preferences-dialog.ui:994 msgid "_Application:" msgstr "_Aplicativo:" #: data/ui/preferences-dialog.ui:1008 msgid "Co_mmand:" msgstr "Co_mando:" #. Translators: Only the title is to be translated, field names not. #: data/ui/preferences-dialog.ui:1033 msgid "" "Fields:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" msgstr "" "Campos:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" #: data/ui/preferences-dialog.ui:1048 msgid "Al_ways use UTF-8 character encoding" msgstr "Se_mpre usar codificação UTF-8" #: data/ui/preferences-dialog.ui:1089 msgid "Start Position" msgstr "Posição inicial" #: data/ui/preferences-dialog.ui:1111 msgid "_Offset:" msgstr "Desl_ocar:" #: data/ui/preferences-dialog.ui:1142 msgid "seconds before selection" msgstr "segundos antes da seleção" #: data/ui/preferences-dialog.ui:1281 msgid "Extensions" msgstr "Extensões" #: data/ui/language-dialog.ui:8 msgid "Configure Spell-Check" msgstr "Configurar verificação ortográfica" #: data/ui/language-dialog.ui:50 msgid "Language" msgstr "Idioma" #: data/ui/language-dialog.ui:128 msgid "Check _text column" msgstr "Verificar coluna de _texto" #: data/ui/language-dialog.ui:146 msgid "Check t_ranslation column" msgstr "Verificar coluna de t_radução" #: data/ui/language-dialog.ui:206 msgid "Check c_urrent project" msgstr "Verificar projeto at_ual" #: data/ui/language-dialog.ui:224 msgid "Check _all open projects" msgstr "Verificar todos os projetos _abertos" #: data/ui/text-assistant/confirmation-page.ui:22 msgid "Acc_ept, discard or edit changes:" msgstr "Ac_eitar, descartar ou editar mudanças:" #: data/ui/text-assistant/confirmation-page.ui:67 msgid "_Mark All" msgstr "_Marcar todos" #: data/ui/text-assistant/confirmation-page.ui:82 msgid "_Unmark All" msgstr "_Desmarcar todos" #: data/ui/text-assistant/confirmation-page.ui:119 msgid "_Remove all blank subtitles" msgstr "_Remover todas as legendas em branco" #: data/ui/text-assistant/join-split-page.ui:28 msgid "Spell-Check Dictionary" msgstr "Dicionário do corretor ortográfico" #: data/ui/text-assistant/join-split-page.ui:49 #: data/ui/text-assistant/line-break-page.ui:81 #: data/ui/text-assistant/hearing-impaired-page.ui:81 #: data/ui/text-assistant/common-error-page.ui:80 #: data/ui/text-assistant/capitalization-page.ui:80 msgid "_Language:" msgstr "_Idioma:" #: data/ui/text-assistant/join-split-page.ui:97 msgid "Corrections" msgstr "Correções" #: data/ui/text-assistant/join-split-page.ui:117 msgid "_Join words not found in spell-check dictionary" msgstr "" "_Juntar palavras não encontradas no dicionário do corretor ortográfico" #: data/ui/text-assistant/join-split-page.ui:134 msgid "_Split words not found in spell-check dictionary" msgstr "" "_Dividir palavras não encontradas no dicionário do corretor ortográfico" #: data/ui/text-assistant/line-break-page.ui:22 msgid "S_elect preferred line-break points:" msgstr "S_elecionar pontos de quebra de linha preferidos:" #: data/ui/text-assistant/line-break-page.ui:67 #: data/ui/text-assistant/hearing-impaired-page.ui:67 #: data/ui/text-assistant/common-error-page.ui:66 #: data/ui/text-assistant/capitalization-page.ui:66 msgid "_Script:" msgstr "_Script:" #: data/ui/text-assistant/line-break-page.ui:95 #: data/ui/text-assistant/hearing-impaired-page.ui:95 #: data/ui/text-assistant/common-error-page.ui:94 #: data/ui/text-assistant/capitalization-page.ui:94 msgid "Co_untry:" msgstr "_País:" #: data/ui/text-assistant/introduction-page.ui:28 msgid "_Select corrections to perform on texts:" msgstr "_Selecione as correções a serem aplicadas nos textos:" #: data/ui/text-assistant/introduction-page.ui:79 msgid "Colu_mns:" msgstr "Colu_nas:" #: data/ui/text-assistant/introduction-page.ui:93 msgid "S_ubtitles:" msgstr "L_egendas:" #: data/ui/text-assistant/line-break-options-page.ui:56 #: data/ui/duration-adjust-dialog.ui:207 msgid "Limits" msgstr "Limites" #: data/ui/text-assistant/line-break-options-page.ui:79 msgid "_Maximum line length:" msgstr "Tamanho _máximo da linha:" #: data/ui/text-assistant/line-break-options-page.ui:93 msgid "_Preferred maximum amount of lines:" msgstr "_Preferir quantidade máxima de linhas:" #: data/ui/text-assistant/line-break-options-page.ui:198 msgid "_Skip subtitles with maximum line length of:" msgstr "_Ignorar legendas com linha de tamanho máximo de:" #: data/ui/text-assistant/line-break-options-page.ui:214 msgid "S_kip subtitles with maximum line amount of:" msgstr "_Ignorar legendas com quantidade máxima de linhas:" #: data/ui/text-assistant/hearing-impaired-page.ui:22 msgid "S_elect parts to remove:" msgstr "S_elecionar partes para remover:" #: data/ui/text-assistant/common-error-page.ui:22 msgid "S_elect errors to correct:" msgstr "S_elecionar erros para correção:" #: data/ui/text-assistant/common-error-page.ui:108 msgid "Error types:" msgstr "Tipos de erro:" #: data/ui/text-assistant/common-error-page.ui:158 msgid "_Human errors" msgstr "Erros _humanos" #: data/ui/text-assistant/common-error-page.ui:175 msgid "_Image recognition errors" msgstr "Erros no reconhecimento da _imagem" #: data/ui/text-assistant/capitalization-page.ui:22 msgid "S_elect parts to capitalize:" msgstr "S_elecionar partes para capitalizar:" #: data/ui/duration-adjust-dialog.ui:33 msgid "Adjust Durations" msgstr "Ajustar durações" #: data/ui/duration-adjust-dialog.ui:73 msgid "Theoretic Duration" msgstr "Duração teórica" #: data/ui/duration-adjust-dialog.ui:101 msgid "_Reading speed:" msgstr "Velocidade de leitu_ra:" #: data/ui/duration-adjust-dialog.ui:133 msgid "characters per second" msgstr "caracteres por segundo" #: data/ui/duration-adjust-dialog.ui:150 msgid "_Lengthen duration to match reading speed" msgstr "_Aumentar duração para coincidir com a velocidade de leitura" #: data/ui/duration-adjust-dialog.ui:167 msgid "_Shorten duration to match reading speed" msgstr "_Diminuir duração para coincidir com a velocidade de leitura" #: data/ui/duration-adjust-dialog.ui:227 msgid "_Minimum duration:" msgstr "Duração _mínima:" #: data/ui/duration-adjust-dialog.ui:243 msgid "Ma_ximum duration:" msgstr "Duração má_xima:" #: data/ui/duration-adjust-dialog.ui:259 msgid "_Gap between subtitles:" msgstr "_Intervalo entre legendas:" #: data/ui/duration-adjust-dialog.ui:294 msgid "s_econds" msgstr "s_egundos" #: data/ui/duration-adjust-dialog.ui:324 msgid "seco_nds" msgstr "segu_ndos" #: data/ui/duration-adjust-dialog.ui:354 msgid "secon_ds" msgstr "segun_dos" #: data/ui/duration-adjust-dialog.ui:408 msgid "Adj_ust selected subtitles" msgstr "Aj_ustar legendas selecionadas" #: data/ui/duration-adjust-dialog.ui:425 msgid "Adjus_t current project" msgstr "Ajus_tar projeto atual" #: data/ui/duration-adjust-dialog.ui:442 msgid "Adjust all _open projects" msgstr "Ajustar todos projetos _abertos" #: data/ui/tab-popup.ui:6 msgid "Move Tab _Left" msgstr "Mover aba para _esquerda" #: data/ui/tab-popup.ui:10 msgid "Move Tab _Right" msgstr "Mover aba para _direita" #: data/ui/insert-dialog.ui:15 msgid "Insert Subtitles" msgstr "Inserir legendas" #: data/ui/insert-dialog.ui:48 data/ui/position-shift-dialog.ui:82 msgid "_Amount:" msgstr "Qu_antidade:" #: data/ui/insert-dialog.ui:62 msgid "_Position:" msgstr "_Posição:" #: data/ui/position-shift-dialog.ui:14 msgid "Shift Positions" msgstr "Deslocar posições" #: data/ui/position-shift-dialog.ui:54 msgid "Shift" msgstr "Deslocar" #: data/ui/position-shift-dialog.ui:135 #: data/ui/position-transform-dialog.ui:208 msgid "_Preview Changes" msgstr "_Pré-visualizar mudanças" #: data/ui/position-shift-dialog.ui:200 msgid "Shift s_elected subtitles" msgstr "Deslocar legendas _selecionadas" #: data/ui/position-shift-dialog.ui:217 msgid "Shift su_btitles from selection to end" msgstr "Deslocar legendas da seleção até o _final" #: data/ui/position-shift-dialog.ui:234 msgid "Shift c_urrent project" msgstr "Deslocar projeto at_ual" #: data/ui/position-shift-dialog.ui:251 msgid "Shift all _open projects" msgstr "Deslocar todos projetos _abertos" #: data/ui/position-transform-dialog.ui:22 msgid "Transform Positions" msgstr "Transformar posições" #: data/ui/position-transform-dialog.ui:62 msgid "First Point" msgstr "Primeiro ponto" #: data/ui/position-transform-dialog.ui:91 msgid "_Subtitle:" msgstr "_Legenda:" #: data/ui/position-transform-dialog.ui:105 msgid "C_orrection:" msgstr "C_orreção:" #: data/ui/position-transform-dialog.ui:119 #: data/ui/position-transform-dialog.ui:310 msgid "Text:" msgstr "Texto:" #: data/ui/position-transform-dialog.ui:253 msgid "Second Point" msgstr "Segundo ponto" #: data/ui/position-transform-dialog.ui:282 msgid "Su_btitle:" msgstr "Le_genda:" #: data/ui/position-transform-dialog.ui:296 msgid "Co_rrection:" msgstr "Co_rreção:" #: data/ui/position-transform-dialog.ui:399 msgid "Pre_view Changes" msgstr "_Pré-visualizar mudanças" #: data/ui/position-transform-dialog.ui:464 msgid "Transform se_lected subtitles" msgstr "Transformar legendas se_lecionadas" #: data/ui/position-transform-dialog.ui:482 msgid "Transform c_urrent project" msgstr "Transformar projeto at_ual" #: data/extensions/custom-framerates/custom-framerates.extension.in:7 msgid "Custom Framerates" msgstr "Taxa de quadros personalizada" #: data/extensions/custom-framerates/custom-framerates.extension.in:8 msgid "Allow use of non-standard framerates" msgstr "Permite o uso de taxa de quadros fora do padrão" #: data/patterns/Latn-en-US.common-error.in:5 msgid "Period after title" msgstr "Ponto após título" #: data/patterns/Latn-en-US.common-error.in:6 msgid "Add period after a shortened title, such as \"Mr\" and \"Dr\"" msgstr "Adiciona ponto após uma abreviação, exemplo “Sr” e “Dr”" #: data/patterns/Latn-en.capitalization.in:5 msgid "First person pronoun" msgstr "Pronome de primeira pessoa" #: data/patterns/Latn-en.capitalization.in:6 msgid "Capitalize the first person pronoun \"I\"" msgstr "Capitaliza a primeira letra do pronome pessoal “Eu” (“I” em inglês)" #: data/patterns/Latn-en.common-error.in:5 #: data/patterns/Latn-en.common-error.in:14 #: data/patterns/Latn-en.common-error.in:23 msgid "Letter \"I\" in a lower case word" msgstr "Letra “I” em uma palavra minúscula" #: data/patterns/Latn-en.common-error.in:6 #: data/patterns/Latn-en.common-error.in:15 #: data/patterns/Latn-en.common-error.in:24 msgid "Replace letter \"I\" with letter \"l\" in a lower case word" msgstr "Substitui letra “I” por letra “l” em uma palavra minúscula" #: data/patterns/Latn-en.common-error.in:32 #: data/patterns/Latn-en.common-error.in:41 #: data/patterns/Latn-en.common-error.in:50 #: data/patterns/Latn-en.common-error.in:62 msgid "Letter \"l\" in an upper case word" msgstr "Letra “l” em uma palavra maiúscula" #: data/patterns/Latn-en.common-error.in:33 #: data/patterns/Latn-en.common-error.in:42 #: data/patterns/Latn-en.common-error.in:51 #: data/patterns/Latn-en.common-error.in:63 msgid "Replace letter \"l\" with letter \"I\" in an upper case word" msgstr "Substitui letra “l” por letra “I” em uma palavra maiúscula" #: data/patterns/Latn-en.common-error.in:73 #: data/patterns/Latn-en.common-error.in:82 msgid "Zero in an upper case word" msgstr "Zero em uma palavra maiúscula" #: data/patterns/Latn-en.common-error.in:74 #: data/patterns/Latn-en.common-error.in:83 msgid "Replace zero with letter \"O\" in an upper case word" msgstr "Substitui zero pela letra “O” em uma palavra maiúscula" #: data/patterns/Latn-en.common-error.in:91 #: data/patterns/Latn.common-error.in:108 msgid "Space between number and unit" msgstr "Espaço entre número e unidade" #: data/patterns/Latn-en.common-error.in:92 #: data/patterns/Latn.common-error.in:109 msgid "Add or remove space between a number and the associated unit" msgstr "Adiciona ou remove espaço entre um número e a unidade associada" #: data/patterns/Latn-en.common-error.in:100 msgid "Spaces around an apostrophe" msgstr "Espaços ao redor de uma apóstrofe" #: data/patterns/Latn-en.common-error.in:101 msgid "Remove spaces around an apostrophe" msgstr "Remove espaços ao redor de apóstrofe" #: data/patterns/Latn-en.common-error.in:109 #: data/patterns/Latn-en.common-error.in:118 msgid "Okay" msgstr "Okay" #: data/patterns/Latn-en.common-error.in:110 #: data/patterns/Latn-en.common-error.in:119 msgid "Spell two-letter forms of \"okay\" in all upper case" msgstr "Escreve formas de duas letras de “okay” toda em caixa alta" #: data/patterns/Latn-en.hearing-impaired.in:5 msgid "Uppercase speaker before a colon" msgstr "Locutor em maiúsculo antes de um dois-pontos" #: data/patterns/Latn-en.hearing-impaired.in:6 msgid "" "Replace the uppercase name of the speaker before a colon with a dialogue " "dash" msgstr "" "Substitui o nome do locutor em maiúsculo antes de um dois-pontos por um " "hífen" #: data/patterns/Latn-en.line-break.in:5 msgid "Title" msgstr "Título" #: data/patterns/Latn-en.line-break.in:6 msgid "Do not break after a title, e.g. \" Dr.\"" msgstr "Não quebrar após um título, ex.: “ Dr.”" #: data/patterns/Latn-en.line-break.in:13 msgid "Article" msgstr "Artigo" #: data/patterns/Latn-en.line-break.in:14 msgid "Do not break after an article" msgstr "Não quebra após um artigo" #: data/patterns/Latn-en.line-break.in:21 msgid "Preposition" msgstr "Preposição" #: data/patterns/Latn-en.line-break.in:22 msgid "Do not break after a preposition" msgstr "Não quebra após uma preposição" #: data/patterns/Latn-en.line-break.in:30 msgid "Possessive determiner" msgstr "Determinante possessivo" #: data/patterns/Latn-en.line-break.in:31 msgid "Do not break after a possessive determiner, e.g. \"my\"" msgstr "Não quebra após um determinante possessivo, ex.: “meu”" #: data/patterns/Latn-fi.common-error.in:5 #: data/patterns/Latn.common-error.in:182 msgid "Space after punctuation marks" msgstr "Espaços após sinais de pontuação" #: data/patterns/Latn-fi.common-error.in:6 #: data/patterns/Latn.common-error.in:183 msgid "Add space after various punctuation marks" msgstr "Adiciona espaço em branco após vários sinais de pontuação" #: data/patterns/Latn-fr.common-error.in:5 #: data/patterns/Latn-fr.common-error.in:14 #: data/patterns/Latn-fr.common-error.in:23 #: data/patterns/Latn-fr.common-error.in:32 msgid "Spaces around guillemets" msgstr "Espaços em volta de aspas angulares" #: data/patterns/Latn-fr.common-error.in:6 #: data/patterns/Latn-fr.common-error.in:15 #: data/patterns/Latn-fr.common-error.in:24 #: data/patterns/Latn-fr.common-error.in:33 msgid "Add spaces around guillemets" msgstr "Adiciona espaços em volta de aspas angulares" #: data/patterns/Latn-fr.common-error.in:41 #: data/patterns/Latn-fr.common-error.in:52 #: data/patterns/Latn.common-error.in:171 msgid "Space before punctuation marks" msgstr "Espaços antes de sinais de pontuação" #: data/patterns/Latn-fr.common-error.in:42 #: data/patterns/Latn-fr.common-error.in:53 msgid "Add or remove space before various punctuation marks" msgstr "Adiciona o remover espaço antes de vários sinais de pontuação" #: data/patterns/Latn.capitalization.in:5 msgid "Sentence" msgstr "Sentença" #: data/patterns/Latn.capitalization.in:6 msgid "Capitalize the first word of a sentence" msgstr "Capitaliza a primeira letra de uma frase" #: data/patterns/Latn.capitalization.in:12 msgid "Ellipsis" msgstr "Reticências" #: data/patterns/Latn.capitalization.in:13 msgid "Capitalize after an ellipsis" msgstr "Maiúsculo após reticências" #: data/patterns/Latn.common-error.in:8 data/patterns/Latn.common-error.in:17 #: data/patterns/Latn.common-error.in:26 data/patterns/Latn.common-error.in:35 #: data/patterns/Latn.common-error.in:44 data/patterns/Latn.common-error.in:53 #: data/patterns/Latn.common-error.in:62 msgid "Ligatures" msgstr "Ligaduras" #: data/patterns/Latn.common-error.in:9 data/patterns/Latn.common-error.in:18 #: data/patterns/Latn.common-error.in:27 data/patterns/Latn.common-error.in:36 #: data/patterns/Latn.common-error.in:45 data/patterns/Latn.common-error.in:54 #: data/patterns/Latn.common-error.in:63 msgid "Unpack ligatures to individual characters" msgstr "Desempacota ligaduras para caracteres individuais" #: data/patterns/Latn.common-error.in:71 data/patterns/Latn.common-error.in:80 msgid "Spelling of a.m. and p.m." msgstr "Formato a.m. e p.m." #: data/patterns/Latn.common-error.in:72 data/patterns/Latn.common-error.in:81 msgid "Change the various spellings of 12-hour periods to \"a.m.\" and \"p.m.\"" msgstr "Muda os vários formatos de período de 12 horas para “a.m.” e “p.m.”" #: data/patterns/Latn.common-error.in:89 data/patterns/Latn.common-error.in:98 msgid "Letter \"O\" in a number" msgstr "Letra “O” em um número" #: data/patterns/Latn.common-error.in:90 data/patterns/Latn.common-error.in:99 msgid "Replace letter \"O\" with a zero in a number" msgstr "Substitui letra “O” por zero em um número" #: data/patterns/Latn.common-error.in:117 msgid "Double apostrophe" msgstr "Duplo apóstrofe" #: data/patterns/Latn.common-error.in:118 msgid "Replace a double apostrophe with a quotation mark" msgstr "Substitui duplo apóstrofe por aspas" #: data/patterns/Latn.common-error.in:126 #: data/patterns/Latn.common-error.in:135 #: data/patterns/Latn.common-error.in:144 #: data/patterns/Latn.common-error.in:153 msgid "Spaces around brackets" msgstr "Espaços ao redor de parênteses" #: data/patterns/Latn.common-error.in:127 #: data/patterns/Latn.common-error.in:136 #: data/patterns/Latn.common-error.in:145 #: data/patterns/Latn.common-error.in:154 msgid "Add or remove spaces around parantheses and square brackets" msgstr "Adiciona ou remove espaços ao redor de parênteses e colchetes" #: data/patterns/Latn.common-error.in:162 msgid "Space after a dialogue dash" msgstr "Espaço após um hífen de diálogo" #: data/patterns/Latn.common-error.in:163 msgid "Add space after a dialogue dash" msgstr "Adicionar espaço em branco após um hífen de diálogo" #: data/patterns/Latn.common-error.in:172 msgid "Remove space before various punctuation marks" msgstr "Remover espaço antes de vários sinais de pontuação" #: data/patterns/Latn.common-error.in:192 msgid "Space after an ellipsis" msgstr "Espaço após reticências" #: data/patterns/Latn.common-error.in:193 msgid "Add space after an ellipsis" msgstr "Adicionar espaço em branco após reticências" #: data/patterns/Latn.common-error.in:201 msgid "Space after a starting ellipsis" msgstr "Espaço em branco após a partir de reticências" #: data/patterns/Latn.common-error.in:202 msgid "Remove space after an ellipsis that starts a line" msgstr "Remover espaço após reticências que iniciam uma linha" #: data/patterns/Latn.common-error.in:210 #: data/patterns/Latn.common-error.in:221 #: data/patterns/Latn.common-error.in:232 #: data/patterns/Latn.common-error.in:242 msgid "Spaces around a quotation mark" msgstr "Espaços ao redor das aspas" #: data/patterns/Latn.common-error.in:211 #: data/patterns/Latn.common-error.in:222 #: data/patterns/Latn.common-error.in:233 #: data/patterns/Latn.common-error.in:243 msgid "Remove space after a starting- and before an ending quotation mark" msgstr "Remover espaço após- e depois do fim de aspas" #: data/patterns/Latn.common-error.in:252 #: data/patterns/Latn.common-error.in:261 msgid "Spaces around musical notes" msgstr "Espaços em volta de notas musicais" #: data/patterns/Latn.common-error.in:253 #: data/patterns/Latn.common-error.in:262 msgid "Add spaces between musical note characters and lyrics" msgstr "Adiciona espaços entre letras e caracteres de nota musical" #: data/patterns/Latn.common-error.in:270 #: data/patterns/Latn.common-error.in:279 msgid "Multiple question- and exclamation marks" msgstr "Múltiplos sinais de interrogação e exclamação" #: data/patterns/Latn.common-error.in:271 #: data/patterns/Latn.common-error.in:280 msgid "" "Replace multiple consequtive question- and exclamation marks with only one" msgstr "" "Substituir sinais de interrogação- e exclamação consecutivos por apenas um" #: data/patterns/Latn.common-error.in:288 #: data/patterns/Latn.common-error.in:298 msgid "Periods around a punctuation mark" msgstr "Pontos ao redor de um sinal de pontuação" #: data/patterns/Latn.common-error.in:289 #: data/patterns/Latn.common-error.in:299 msgid "Remove period before or after various punctuation marks" msgstr "Remover ponto antes ou depois de vários sinais de pontuação" #: data/patterns/Latn.common-error.in:308 msgid "Terminating double-dashes" msgstr "Terminação com traços duplos" #: data/patterns/Latn.common-error.in:309 msgid "Replace a single clause-terminating dash with two dashes" msgstr "Substituir um único hífen de uma cláusula por dois hifens" #: data/patterns/Latn.hearing-impaired.in:5 msgid "Sound in brackets" msgstr "Som entre colchetes" #: data/patterns/Latn.hearing-impaired.in:6 msgid "Remove description of a sound between square brackets" msgstr "Remover descrição de um som entre colchetes" #: data/patterns/Latn.hearing-impaired.in:12 msgid "Sound in parantheses" msgstr "Som entre parênteses" #: data/patterns/Latn.hearing-impaired.in:13 msgid "Remove description of a sound between parantheses" msgstr "Remover descrição de um som entre parênteses" #: data/patterns/Latn.hearing-impaired.in:19 msgid "Song lyrics between number signs" msgstr "Letras de música entre sinais numéricos" #: data/patterns/Latn.hearing-impaired.in:20 msgid "Remove song lyrics starting with or between number signs" msgstr "Remover letras de música a partir de ou entre sinais numéricos" #: data/patterns/Latn.hearing-impaired.in:27 msgid "One-line song lyrics between number signs" msgstr "Letras de música em linha única entre sinais numéricos" #: data/patterns/Latn.hearing-impaired.in:28 msgid "Remove one-line song lyrics starting with or between number signs" msgstr "" "Remover letras de música em linha única a partir de ou entre sinais " "numéricos" #: data/patterns/Latn.hearing-impaired.in:35 msgid "Speaker before a colon" msgstr "Locutor antes de um dois-pontos" #: data/patterns/Latn.hearing-impaired.in:36 msgid "Replace the name of the speaker before a colon with a dialogue dash" msgstr "Substituir o nome do locutor antes de um dois-pontos por um hífen" #: data/patterns/Latn.line-break.in:5 data/patterns/Latn.line-break.in:13 msgid "Dialogue" msgstr "Diálogo" #: data/patterns/Latn.line-break.in:6 data/patterns/Latn.line-break.in:14 msgid "Break according to dialogue separated by dashes" msgstr "Dividir de acordo com o diálogo separado por hifens" #: data/patterns/Latn.line-break.in:21 data/patterns/Latn.line-break.in:30 msgid "Clause" msgstr "Cláusula" #: data/patterns/Latn.line-break.in:22 data/patterns/Latn.line-break.in:31 msgid "Break according to clauses terminated by a punctuation mark" msgstr "" "Quebre de acordo com as cláusulas terminadas por um sinal de pontuação" #: data/patterns/Latn.line-break.in:38 msgid "Number and unit" msgstr "Número e unidade" #: data/patterns/Latn.line-break.in:39 msgid "Do not break between a number and associated unit" msgstr "Não quebra entre uma unidade associada e um número" #: data/patterns/Zyyy.common-error.in:5 data/patterns/Zyyy.common-error.in:14 msgid "Leading and trailing spaces" msgstr "Espaços em branco do início e do fim" #: data/patterns/Zyyy.common-error.in:6 data/patterns/Zyyy.common-error.in:15 msgid "Remove spaces from the beginning and end of lines" msgstr "Remover espaços do início e do fim das linhas" #: data/patterns/Zyyy.common-error.in:23 msgid "Multiple consecutive spaces" msgstr "Múltiplos espaços consecutivos" #: data/patterns/Zyyy.common-error.in:24 msgid "Replace multiple consecutive spaces with only one" msgstr "Substituir múltiplos espaços consecutivos em um único" #: data/patterns/Zyyy.common-error.in:32 data/patterns/Zyyy.common-error.in:45 #: data/patterns/Zyyy.common-error.in:55 data/patterns/Zyyy.common-error.in:65 msgid "Space between digits" msgstr "Espaço entre dígitos" #: data/patterns/Zyyy.common-error.in:33 data/patterns/Zyyy.common-error.in:46 #: data/patterns/Zyyy.common-error.in:56 data/patterns/Zyyy.common-error.in:66 msgid "Remove space between digits of a number" msgstr "Remover espaços entre dígitos de um número" #: data/patterns/Zyyy.common-error.in:79 msgid "Musical notes" msgstr "Notas musicais" #: data/patterns/Zyyy.common-error.in:80 msgid "Replace Unicode musical note characters with number signs" msgstr "Substitui caracteres de nota musical Unicode com sinais de números" #: data/io.otsaloma.gaupol.appdata.xml.in:7 msgid "Editor for text-based subtitles" msgstr "Editor para legendas em texto" #: data/io.otsaloma.gaupol.appdata.xml.in:9 msgid "" "Gaupol is an editor for text-based subtitle files. It supports multiple " "subtitle file formats and provides means of creating subtitles, editing " "texts and timing subtitles to match video." msgstr "" "Gaupol é um editor de arquivos de legendas em texto. Ele possui suporte a " "vários formatos de arquivo de legenda e fornece meios de criar legendas, " "editar textos e legendas de tempo para corresponder ao vídeo." #: data/io.otsaloma.gaupol.appdata.xml.in:40 msgid "Main window" msgstr "Janela principal" #: data/io.otsaloma.gaupol.desktop.in:5 msgid "Subtitle Editor" msgstr "Editor de legendas" #: data/io.otsaloma.gaupol.desktop.in:6 msgid "Edit subtitle files" msgstr "Editar arquivos de legenda" #. TRANSLATORS: Search terms to find this application. Do NOT translate or #. localize the semicolons! The list MUST also end with a semicolon! #: data/io.otsaloma.gaupol.desktop.in:12 msgid "video;subtitles;captions;" msgstr "video;vídeo;subtitles;legendas;captions;" gaupol-1.11/po/ru.po000066400000000000000000002445521422217132500143420ustar00rootroot00000000000000# 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. # # Translators: # Osmo Salomaa , 2016 # Ася Л , 2018 # Caarmi, 2021 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-04-03 04:00+0300\n" "PO-Revision-Date: 2016-07-07 00:55+0000\n" "Last-Translator: Caarmi, 2021\n" "Language-Team: Russian (https://www.transifex.com/otsaloma/teams/64879/ru/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ru\n" "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n" #: aeidon/enums.py:40 gaupol/enums.py:38 msgid "Subtitle number" msgstr "По номеру" #: aeidon/enums.py:43 msgid "Subtitle position" msgstr "По позиции" #: aeidon/enums.py:59 msgid "23.976 fps" msgstr "23,976 к/с" #: aeidon/enums.py:63 msgid "24.000 fps" msgstr "24 к/с" #: aeidon/enums.py:67 msgid "25.000 fps" msgstr "25 к/с" #: aeidon/enums.py:71 msgid "29.970 fps" msgstr "29,970 к/с" #: aeidon/enums.py:75 data/ui/menubar.ui:248 msgid "30.000 fps" msgstr "30,000 к/с" #: aeidon/enums.py:79 data/ui/menubar.ui:253 msgid "50.000 fps" msgstr "50,000 к/с" #: aeidon/enums.py:83 data/ui/menubar.ui:258 msgid "59.940 fps" msgstr "59,940 к/с" #: aeidon/enums.py:87 data/ui/menubar.ui:263 msgid "60.000 fps" msgstr "60,000 к/с" #: aeidon/enums.py:112 msgid "Mac (classic)" msgstr "Мак (ранние модели)" #. TRANSLATORS: Most of the character encoding descriptions are copied from #. gedit, which is translated to very many languages. Check the gedit .po #. files for a reference: #. . #: aeidon/encodings.py:40 aeidon/encodings.py:43 aeidon/encodings.py:46 msgid "English" msgstr "Английская" #: aeidon/encodings.py:41 aeidon/encodings.py:42 aeidon/encodings.py:69 msgid "Chinese traditional" msgstr "Китайская традиционная" #: aeidon/encodings.py:44 msgid "German" msgstr "Немецкая" #: aeidon/encodings.py:45 aeidon/encodings.py:54 aeidon/encodings.py:59 #: aeidon/encodings.py:79 aeidon/encodings.py:105 msgid "Hebrew" msgstr "Иврит" #: aeidon/encodings.py:47 aeidon/encodings.py:51 aeidon/encodings.py:56 #: aeidon/encodings.py:73 aeidon/encodings.py:76 aeidon/encodings.py:98 #: aeidon/encodings.py:111 aeidon/encodings.py:122 msgid "Western" msgstr "Западная" #: aeidon/encodings.py:48 aeidon/encodings.py:61 aeidon/encodings.py:80 #: aeidon/encodings.py:103 msgid "Arabic" msgstr "Арабская" #: aeidon/encodings.py:49 aeidon/encodings.py:64 aeidon/encodings.py:66 #: aeidon/encodings.py:77 aeidon/encodings.py:104 aeidon/encodings.py:119 msgid "Greek" msgstr "Греческая" #: aeidon/encodings.py:50 aeidon/encodings.py:81 aeidon/encodings.py:101 #: aeidon/encodings.py:109 msgid "Baltic" msgstr "Прибалтийская" #: aeidon/encodings.py:52 aeidon/encodings.py:74 aeidon/encodings.py:99 #: aeidon/encodings.py:121 msgid "Central European" msgstr "Центральноевропейская" #: aeidon/encodings.py:53 aeidon/encodings.py:75 aeidon/encodings.py:102 #: aeidon/encodings.py:118 msgid "Cyrillic" msgstr "Кириллица" #: aeidon/encodings.py:55 aeidon/encodings.py:71 aeidon/encodings.py:78 #: aeidon/encodings.py:106 aeidon/encodings.py:123 msgid "Turkish" msgstr "Турецкая" #: aeidon/encodings.py:57 msgid "Portuguese" msgstr "Португальская" #: aeidon/encodings.py:58 aeidon/encodings.py:120 msgid "Icelandic" msgstr "Исландская" #: aeidon/encodings.py:60 msgid "Canadian" msgstr "Канадская" #: aeidon/encodings.py:62 aeidon/encodings.py:107 msgid "Nordic" msgstr "Скандинавская" #: aeidon/encodings.py:63 aeidon/encodings.py:114 msgid "Russian" msgstr "Русская" #: aeidon/encodings.py:65 aeidon/encodings.py:108 msgid "Thai" msgstr "Тайская" #: aeidon/encodings.py:67 aeidon/encodings.py:83 aeidon/encodings.py:84 #: aeidon/encodings.py:85 aeidon/encodings.py:91 aeidon/encodings.py:92 #: aeidon/encodings.py:93 aeidon/encodings.py:94 aeidon/encodings.py:95 #: aeidon/encodings.py:96 aeidon/encodings.py:125 aeidon/encodings.py:126 #: aeidon/encodings.py:127 msgid "Japanese" msgstr "Японская" #: aeidon/encodings.py:68 aeidon/encodings.py:86 aeidon/encodings.py:97 #: aeidon/encodings.py:113 msgid "Korean" msgstr "Корейская" #: aeidon/encodings.py:70 msgid "Urdu" msgstr "Урду" #: aeidon/encodings.py:72 aeidon/encodings.py:116 msgid "Ukrainian" msgstr "Украинская" #: aeidon/encodings.py:82 msgid "Vietnamese" msgstr "Вьетнамская" #: aeidon/encodings.py:87 aeidon/encodings.py:90 msgid "Chinese simplified" msgstr "Китайская упрощенная" #: aeidon/encodings.py:88 aeidon/encodings.py:89 msgid "Chinese unified" msgstr "Китайская" #: aeidon/encodings.py:100 aeidon/encodings.py:112 msgid "South European" msgstr "Южноевропейская" #: aeidon/encodings.py:110 msgid "Celtic" msgstr "Кельтская" #: aeidon/encodings.py:115 msgid "Tajik" msgstr "Таджикская" #: aeidon/encodings.py:117 msgid "Kazakh" msgstr "Казахская" #: aeidon/encodings.py:124 msgid "Cyrillic Asian" msgstr "Среднеазиатская (кир.)" #: aeidon/encodings.py:128 aeidon/encodings.py:129 aeidon/encodings.py:130 #: aeidon/encodings.py:131 aeidon/encodings.py:132 aeidon/encodings.py:133 #: aeidon/encodings.py:134 aeidon/encodings.py:135 aeidon/encodings.py:136 msgid "Unicode" msgstr "Юникод" #: aeidon/encodings.py:156 #, python-brace-format msgid "{description} ({name})" msgstr "{description} ({name})" #: aeidon/encodings.py:232 msgid "Current locale ({})" msgstr "Текущая ({})" #: aeidon/locales.py:46 #, python-brace-format msgid "{language} ({country})" msgstr "{language} ({country})" #: aeidon/agents/search.py:227 msgid "Replacing" msgstr "Замена" #: aeidon/agents/search.py:256 aeidon/agents/search.py:258 msgid "Replacing all" msgstr "Глобальная замена" #: aeidon/agents/position.py:74 msgid "Adjusting durations" msgstr "Изменение длительности" #: aeidon/agents/position.py:96 msgid "Converting framerate" msgstr "Изменение частоты кадров" #: aeidon/agents/position.py:146 msgid "Setting framerate" msgstr "Задание частоты кадров" #: aeidon/agents/position.py:168 msgid "Shifting positions" msgstr "Сдвиг положений" #: aeidon/agents/position.py:188 msgid "Transforming positions" msgstr "Преобразование положений" #: aeidon/agents/clipboard.py:44 msgid "Cutting texts" msgstr "Вырезание текста" #: aeidon/agents/clipboard.py:61 msgid "Pasting texts" msgstr "Вставка текста" #: aeidon/agents/text.py:91 msgid "Breaking lines" msgstr "Перенос строк" #: aeidon/agents/text.py:128 msgid "Capitalizing texts" msgstr "Заглавные буквы" #: aeidon/agents/text.py:185 msgid "Correcting common errors" msgstr "Исправление обычных ошибок" #: aeidon/agents/text.py:234 msgid "Removing hearing impaired texts" msgstr "Удаление текста для глухих" #: aeidon/agents/text.py:315 msgid "Joining words by spell-check suggestions" msgstr "Объединение слов" #: aeidon/agents/text.py:354 msgid "Splitting words by spell-check suggestions" msgstr "Разъединение слов" #: aeidon/agents/set.py:58 aeidon/agents/set.py:80 aeidon/agents/set.py:113 msgid "Editing position" msgstr "Изменение положения" #: aeidon/agents/set.py:129 msgid "Editing text" msgstr "Правка текста" #: aeidon/agents/edit.py:35 msgid "Clearing texts" msgstr "Очищение текста" #: aeidon/agents/edit.py:61 aeidon/agents/edit.py:83 msgid "Inserting subtitles" msgstr "Вставка субтитров" #: aeidon/agents/edit.py:103 msgid "Merging subtitles" msgstr "Объединение субтитров" #: aeidon/agents/edit.py:114 msgid "Removing subtitles" msgstr "Удаление субтитров" #: aeidon/agents/edit.py:131 msgid "Replacing positions" msgstr "Замена положений" #: aeidon/agents/edit.py:147 msgid "Replacing texts" msgstr "Замена текста" #: aeidon/agents/edit.py:171 msgid "Splitting subtitle" msgstr "Разделение субтитра" #: aeidon/agents/format.py:49 msgid "Adding dialogue dashes" msgstr "Добавление тире в диалогах" #: aeidon/agents/format.py:68 msgid "Changing case" msgstr "Изменение регистра" #: aeidon/agents/format.py:92 msgid "Italicizing" msgstr "Курсивное начертание" #: aeidon/agents/format.py:108 msgid "Removing dialogue dashes" msgstr "Удаление тире в диалогах" #: aeidon/agents/format.py:174 msgid "Unitalicizing" msgstr "Обычное начертание" #: gaupol/application.py:219 gaupol/agents/open.py:203 msgid "Open" msgstr "Открыть" #: gaupol/application.py:223 msgid "Open main files" msgstr "Открыть основной файл" #: gaupol/application.py:230 msgid "Save" msgstr "Сохранить" #: gaupol/application.py:233 msgid "Save the current main document" msgstr "Сохранить текущий документ" #: gaupol/application.py:238 msgid "Undo" msgstr "Отменить" #: gaupol/application.py:242 msgid "Undo the last action" msgstr "Отмена последнего действия" #: gaupol/application.py:249 msgid "Redo" msgstr "Повторить" #: gaupol/application.py:252 msgid "Redo the last undone action" msgstr "Повторить последнее отмененное действие" #: gaupol/application.py:260 msgid "Insert" msgstr "Вставить" #: gaupol/application.py:262 msgid "Insert new subtitles" msgstr "Вставить новые субтитры" #: gaupol/application.py:266 #: data/extensions/custom-framerates/preferences-dialog.ui:78 msgid "Remove" msgstr "Удалить" #: gaupol/application.py:268 msgid "Remove the selected subtitles" msgstr "Удалить выделенные субтитры" #: gaupol/application.py:273 data/ui/search-dialog.ui:283 msgid "Find" msgstr "Найти" #: gaupol/application.py:275 msgid "Search for and replace text" msgstr "Поиск и замена текста" #: gaupol/application.py:279 data/ui/preferences-dialog.ui:942 msgid "Video" msgstr "Видео" #: gaupol/application.py:281 msgid "Show or hide the video player" msgstr "Показать или скрыть видеоплеер" #: gaupol/application.py:285 data/ui/preferences-dialog.ui:1173 msgid "Preview" msgstr "Просмотр" #: gaupol/application.py:287 msgid "Preview from selected position with a video player" msgstr "Просмотр с выделенной позиции в видеоплеере" #: gaupol/enums.py:37 msgid "No." msgstr "№" #: gaupol/enums.py:43 msgid "Start" msgstr "Начало" #: gaupol/enums.py:44 msgid "Start position" msgstr "Позиция начала" #: gaupol/enums.py:49 msgid "End" msgstr "Конец" #: gaupol/enums.py:50 msgid "End position" msgstr "Позиция конца" #. TRANSLATORS: 'Dur.' is short for duration. It is used in the header #. of a column that contains numbers five digits wide. #: gaupol/enums.py:57 msgid "Dur." msgstr "Длит." #: gaupol/enums.py:58 msgid "Duration" msgstr "Длительность" #: gaupol/enums.py:63 gaupol/enums.py:64 msgid "Text" msgstr "Текст" #: gaupol/enums.py:69 gaupol/enums.py:70 msgid "Translation" msgstr "Перевод" #: gaupol/enums.py:82 msgid "characters" msgstr "символы" #: gaupol/enums.py:85 msgid "ems" msgstr "em" #: gaupol/page.py:60 msgid "Untitled {:d}" msgstr "Без имени {:d}" #: gaupol/page.py:133 msgid "Close project" msgstr "Закрыть проект" #: gaupol/page.py:145 msgid "{} translation" msgstr "Перевод {}" #: gaupol/page.py:302 msgid "Path:" msgstr "Путь:" #: gaupol/page.py:303 msgid "Format:" msgstr "Формат:" #: gaupol/page.py:304 msgid "Encoding:" msgstr "Кодирование:" #: gaupol/page.py:305 msgid "Newlines:" msgstr "Новые строки:" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:99 msgid "Tasks and Target" msgstr "Цели и задачи" #: gaupol/assistants.py:128 msgid "Correct texts in the text column" msgstr "Изменить текст в колонке \"Текст\"" #: gaupol/assistants.py:129 msgid "Correct texts in the translation column" msgstr "Изменить текст в колонке \"Перевод\"" #: gaupol/assistants.py:138 msgid "Correct texts in selected subtitles" msgstr "Изменить текст в выделенных субтитрах" #: gaupol/assistants.py:139 msgid "Correct texts in current project" msgstr "Изменить текст в текущем проекте" #: gaupol/assistants.py:140 msgid "Correct texts in all open projects" msgstr "Изменить тексты во всех открытых проектах" #: gaupol/assistants.py:363 msgid "Other" msgstr "Другое значение" #: gaupol/assistants.py:439 msgid "Capitalize texts written in lower case" msgstr "Расставить в тексте заглавные буквы" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:443 msgid "Capitalization Patterns" msgstr "Заглавные буквы" #: gaupol/assistants.py:445 msgid "Capitalize texts" msgstr "Заглавные буквы" #: gaupol/assistants.py:468 msgid "Correct common errors made by humans or image recognition software" msgstr "" "Исправление распространенных ошибок людей или программ распознавания текста" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:472 msgid "Common Error Patterns" msgstr "Общие шаблоны ошибок" #: gaupol/assistants.py:474 msgid "Correct common errors" msgstr "Исправить обычные ошибки" #: gaupol/assistants.py:526 msgid "Remove explanatory texts meant for the hearing impaired" msgstr "Удалить описательный текст, предназначенный для глухих" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:530 msgid "Hearing Impaired Patterns" msgstr "Текст для глухих" #: gaupol/assistants.py:532 msgid "Remove hearing impaired texts" msgstr "Удалить текст для глухих" #: gaupol/assistants.py:544 msgid "" "Use spell-check suggestions to fix whitespace detection errors of image " "recognition software" msgstr "" "Использовать систему проверки орфографии для исправления неверно " "распознанных пробелов" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:548 msgid "Joining and Splitting Words" msgstr "Объединение и разделение слов" #: gaupol/assistants.py:550 msgid "Join or Split Words" msgstr "Объединить или разделить слова" #: gaupol/assistants.py:599 gaupol/agents/tools.py:45 msgid "Failed to load dictionary for language \"{}\"" msgstr "Не удалось загрузить словарь для языка \"{}\"" #: gaupol/assistants.py:601 gaupol/player.py:263 gaupol/player.py:381 #: gaupol/dialogs/search.py:560 gaupol/dialogs/search.py:568 #: gaupol/dialogs/text_edit.py:49 gaupol/dialogs/encoding.py:56 #: gaupol/agents/open.py:328 gaupol/agents/open.py:337 #: gaupol/agents/open.py:345 gaupol/agents/open.py:354 #: gaupol/agents/tools.py:48 gaupol/agents/save.py:197 #: gaupol/agents/save.py:205 gaupol/agents/preview.py:108 #: gaupol/agents/preview.py:116 gaupol/agents/preview.py:125 #: gaupol/agents/preview.py:133 msgid "_OK" msgstr "ОК" #: gaupol/assistants.py:635 msgid "Break text into lines of defined length" msgstr "Разбить текст на строки определенной длины" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:639 msgid "Line-Break Patterns" msgstr "Разрывы строк" #: gaupol/assistants.py:641 msgid "Break lines" msgstr "Переносы строк" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:679 msgid "Line-Break Options" msgstr "Параметры строк" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:763 msgid "Correcting Texts" msgstr "Исправление текста" #: gaupol/assistants.py:769 msgid "Each task is now being run on each project." msgstr "Выполняются выбранные задачи для каждого из проектов." #: gaupol/assistants.py:793 #, python-brace-format msgid "{current:d} of {total:d} tasks complete" msgstr "Завершено задач: {current:d} из {total:d}" #: gaupol/assistants.py:801 msgid "Project: {}" msgstr "Проект: {}" #: gaupol/assistants.py:807 msgid "Task: {}" msgstr "Задача: {}" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:832 msgid "Confirm Changes" msgstr "Подтверждение изменений" #: gaupol/assistants.py:892 msgid "Accept" msgstr "Принять" #: gaupol/assistants.py:898 msgid "Original Text" msgstr "Исходный текст" #: gaupol/assistants.py:899 msgid "Corrected Text" msgstr "Исправленный текст" #: gaupol/assistants.py:1048 msgid "Correct Texts" msgstr "Исправление текста" #: gaupol/assistants.py:1076 msgid "Correcting texts" msgstr "Исправление текста" #: gaupol/assistants.py:1092 #, python-brace-format msgid "Edited {edits:d} and removed {removals:d} subtitles" msgstr "Изменено субтитров: {edits:d}, удалено: {removals:d}" #: gaupol/assistants.py:1126 msgid "Confirm {:d} Change" msgid_plural "Confirm {:d} Changes" msgstr[0] "Подтвердить {:d} изменение" msgstr[1] "Подтвердить {:d} изменений" msgstr[2] "Подтвердить {:d} изменений" msgstr[3] "Подтвердить {:d} изменений" #: gaupol/renderers/multiline.py:86 msgid "Italic" msgstr "Курсив" #: gaupol/player.py:372 msgid "No video streams found" msgstr "Видеопотоки не найдены" #: gaupol/player.py:379 msgid "Failed to initialize playback" msgstr "Не удалось начать воспроизведение" #: gaupol/dialogs/search.py:189 data/ui/menubar.ui:524 msgid "_Help" msgstr "Спра_вка" #: gaupol/dialogs/search.py:471 msgid "Found and replaced {:d} occurence" msgid_plural "Found and replaced {:d} occurences" msgstr[0] "Найдено и заменено {:d} вхождение" msgstr[1] "Найдено и заменено {:d} вхождения" msgstr[2] "Найдено и заменено {:d} вхождений" msgstr[3] "Найдено и заменено {:d} вхождений" #: gaupol/dialogs/search.py:488 msgid "\"{}\" not found" msgstr "\"{}\" не найден" #: gaupol/dialogs/search.py:558 msgid "Error in regular expression pattern" msgstr "Ошибка в регулярном выражении" #: gaupol/dialogs/search.py:566 msgid "Error in regular expression replacement" msgstr "Ошибка в замещающем тексте" #: gaupol/dialogs/text_edit.py:48 gaupol/dialogs/framerate_convert.py:63 #: gaupol/dialogs/insert.py:44 gaupol/dialogs/encoding.py:55 #: gaupol/dialogs/split.py:44 gaupol/dialogs/multi_close.py:54 #: gaupol/dialogs/open.py:63 gaupol/dialogs/position_transform.py:69 #: gaupol/dialogs/position_shift.py:71 gaupol/dialogs/multi_save.py:83 #: gaupol/dialogs/multi_save.py:215 gaupol/dialogs/duration_adjust.py:86 #: gaupol/dialogs/save.py:73 gaupol/dialogs/video.py:41 #: gaupol/agents/open.py:363 gaupol/agents/open.py:375 #: gaupol/agents/open.py:387 gaupol/agents/close.py:71 #: data/extensions/custom-framerates/custom-framerates.py:39 msgid "_Cancel" msgstr "Отмена" #: gaupol/dialogs/text_edit.py:53 msgid "Edit Text" msgstr "Редактировать текст" #: gaupol/dialogs/framerate_convert.py:64 msgid "Co_nvert" msgstr "_Преобразовать" #: gaupol/dialogs/insert.py:45 msgid "_Insert" msgstr "_Вставить" #: gaupol/dialogs/insert.py:54 msgid "Above selection" msgstr "Перед выделением" #: gaupol/dialogs/insert.py:55 msgid "Below selection" msgstr "После выделения" #: gaupol/dialogs/encoding.py:60 data/ui/preferences-dialog.ui:70 msgid "Character Encodings" msgstr "Кодировки символов" #: gaupol/dialogs/encoding.py:78 gaupol/dialogs/encoding.py:125 msgid "Description" msgstr "Описание" #: gaupol/dialogs/encoding.py:85 gaupol/dialogs/encoding.py:132 msgid "Encoding" msgstr "Кодировка" #: gaupol/dialogs/encoding.py:141 msgid "Show in Menu" msgstr "Включать в меню" #: gaupol/dialogs/split.py:45 msgid "_Split" msgstr "_Разделить" #: gaupol/dialogs/split.py:76 msgid "Splitting project" msgstr "Разделение проекта" #: gaupol/dialogs/split.py:97 #, python-brace-format msgid "Split {amount:d} subtitles to project \"{name}\"" msgstr "Перенесено субтитров в проект \"{name}\": {amount:d}" #: gaupol/dialogs/spell_check.py:269 msgid "Spell-checking" msgstr "Проверка орфографии" #: gaupol/dialogs/preferences.py:217 msgid "{} Extension Website" msgstr "Сайт расширения {}" #: gaupol/dialogs/preferences.py:429 msgid "Custom" msgstr "Другой" #: gaupol/dialogs/multi_close.py:38 msgid "Save changes to documents before closing?" msgstr "Сохранить изменения документов перед закрытием?" #: gaupol/dialogs/multi_close.py:39 gaupol/agents/open.py:384 #: gaupol/agents/close.py:68 msgid "If you don't save, changes will be permanently lost." msgstr "Несохраненные изменения будут навсегда утеряны." #: gaupol/dialogs/multi_close.py:53 gaupol/agents/close.py:70 msgid "Close _Without Saving" msgstr "Закрыть _без сохранения" #: gaupol/dialogs/multi_close.py:55 gaupol/dialogs/multi_save.py:84 #: gaupol/dialogs/save.py:74 gaupol/agents/open.py:388 #: gaupol/agents/close.py:72 data/ui/menubar.ui:34 msgid "_Save" msgstr "_Сохранить" #: gaupol/dialogs/multi_close.py:70 msgid "Select the _main documents you want to save:" msgstr "Выберите _документы, которые вы хотите сохранить:" #: gaupol/dialogs/multi_close.py:95 msgid "Select the _translation documents you want to save:" msgstr "Выберите п_ереводы, которые вы хотите сохранить:" #: gaupol/dialogs/open.py:64 gaupol/agents/open.py:364 #: gaupol/agents/open.py:376 msgid "_Open" msgstr "Открыть" #: gaupol/dialogs/position_transform.py:70 msgid "_Transform" msgstr "_Преобразовать" #: gaupol/dialogs/position_shift.py:72 msgid "_Shift" msgstr "_Сдвиг" #: gaupol/dialogs/position_shift.py:150 msgid "frames" msgstr "кадр." #: gaupol/dialogs/position_shift.py:168 data/ui/preferences-dialog.ui:911 msgid "seconds" msgstr "сек." #: gaupol/dialogs/about.py:36 msgid "About Gaupol" msgstr "О программе Gaupol" #: gaupol/dialogs/about.py:40 msgid "Subtitle editor" msgstr "Редактор субтитров" #. TRANSLATORS: This is a special message that shouldn't be translated #. literally. It is used in the about dialog to give credits to the #. translators. Thus, you should translate it to your name and email #. address. You can also include other translators who have contributed #. to this translation; in that case, please write them on separate #. lines seperated by newlines (\n). #: gaupol/dialogs/about.py:51 msgid "translator-credits" msgstr "Alex, 2010" #: gaupol/dialogs/about.py:54 msgid "Gaupol Website" msgstr "Сайт Gaupol" #: gaupol/dialogs/append.py:35 msgid "Append File" msgstr "Добавить файл" #: gaupol/dialogs/debug.py:43 msgid "Something went wrong" msgstr "Что-то пошло не так..." #: gaupol/dialogs/debug.py:44 msgid "" "You have probably discovered a bug. Please report it by providing the below " "information and a description of what you were doing." msgstr "" "Вероятно вы обнаружили баг. Пожалуйста, сообщите нам об этом, указав " "информацию указанную ниже и описание ваших действий." #: gaupol/dialogs/debug.py:52 msgid "_Report Bug" msgstr "Отчет об ошибке" #: gaupol/dialogs/debug.py:53 data/ui/menubar.ui:56 msgid "_Quit" msgstr "В_ыход" #: gaupol/dialogs/debug.py:54 gaupol/dialogs/preview_error.py:45 #: data/ui/menubar.ui:52 data/ui/tab-popup.ui:16 msgid "_Close" msgstr "_Закрыть" #: gaupol/dialogs/multi_save.py:98 gaupol/dialogs/save.py:110 msgid "{} (recommended)" msgstr "{} (рекомендуется)" #: gaupol/dialogs/multi_save.py:212 msgid "" "{:d} of the files to be saved already exist. Do you want to replace them?" msgstr "{:d} сохраняемых файлов уже существуют. Заменить их?" #: gaupol/dialogs/multi_save.py:213 msgid "" "The files already exist in \"{}\". Replacing them will overwrite their " "contents." msgstr "" "В «{}» уже существуют файлы. Если их заменить, то их содержимое будет " "утеряно." #: gaupol/dialogs/multi_save.py:216 data/ui/search-dialog.ui:192 #: data/ui/spell-check-dialog.ui:122 msgid "_Replace" msgstr "За_менить" #: gaupol/dialogs/duration_adjust.py:70 msgid "Adjusted duration of {:d} subtitle" msgid_plural "Adjusted durations of {:d} subtitles" msgstr[0] "Изменена длительность {:d} субтитра" msgstr[1] "Изменена длительность {:d} субтитров" msgstr[2] "Изменена длительность {:d} субтитров" msgstr[3] "Изменена длительность {:d} субтитров" #: gaupol/dialogs/duration_adjust.py:87 msgid "_Adjust" msgstr "_Настроить" #: gaupol/dialogs/preview_error.py:36 msgid "Preview in video player failed" msgstr "Ошибка просмотра в видеоплеере" #: gaupol/dialogs/preview_error.py:37 msgid "" "There is probably a problem with either the video file or the video player. " "See the preferences dialog to choose the video player or to customize the " "command." msgstr "" "Вероятно, возникла проблема с видеофайлом или плеером. Используйте диалог " "настроек, чтобы выбрать видеоплеер или изменить команду его вызова." #: gaupol/dialogs/language.py:97 msgid "Set Language" msgstr "Задать язык" #: gaupol/dialogs/video.py:52 gaupol/dialogs/file.py:59 msgid "All files" msgstr "Все файлы" #: gaupol/dialogs/video.py:56 msgid "Video files" msgstr "Видеофайлы" #: gaupol/dialogs/file.py:63 msgid "All supported files" msgstr "Все поддерживаемые файлы" #: gaupol/dialogs/file.py:77 #, python-brace-format msgid "{format} (*{extension})" msgstr "{format}(*{extension})" #: gaupol/dialogs/file.py:120 msgid "Auto-detected" msgstr "Автоопределение" #: gaupol/dialogs/file.py:122 msgid "Other…" msgstr "Другая…" #: gaupol/agents/menu.py:94 gaupol/agents/menu.py:103 #: gaupol/agents/menu.py:110 msgid "File not found" msgstr "Файл не найден" #: gaupol/agents/open.py:85 #, python-brace-format msgid "Appended {amount:d} subtitles from \"{basename}\"" msgstr "Добавлены субтитры из файла \"{basename}\": {amount:d}" #: gaupol/agents/open.py:96 msgid "Appending file" msgstr "Добавление файла" #: gaupol/agents/open.py:111 msgid "File \"{}\" is already open" msgstr "Файл \"{}\" уже открыт" #: gaupol/agents/open.py:214 msgid "Open Translation" msgstr "Открыть перевод" #: gaupol/agents/open.py:223 msgid "Select Video" msgstr "Выберите видеофайл" #: gaupol/agents/open.py:224 msgid "_Select" msgstr "_Выбрать" #: gaupol/agents/open.py:325 msgid "Failed to decode file \"{}\" with all attempted codecs" msgstr "Не удалось декодировать файл \"{}\" всеми использованными кодеками" #: gaupol/agents/open.py:326 msgid "Please try to open the file with a different character encoding." msgstr "Попробуйте открыть файл, указав другую кодировку символов." #: gaupol/agents/open.py:334 msgid "Failed to recognize format of file \"{}\"" msgstr "Не удалось определить формат файла \"{}\"" #: gaupol/agents/open.py:335 msgid "" "Please check that the file you are trying to open is a subtitle file of a " "format supported by Gaupol." msgstr "Проверьте, имеет ли открываемый файл формат, поддерживаемый Gaupol." #: gaupol/agents/open.py:343 msgid "Failed to open file \"{}\"" msgstr "Не удалось открыть файл \"{}\"" #: gaupol/agents/open.py:351 msgid "Failed to parse file \"{}\"" msgstr "Не удалось разобрать файл \"{}\"" #: gaupol/agents/open.py:352 msgid "Please check that the file you are trying to open is a valid {} file." msgstr "Проверьте, имеет ли этот файл формат {}." #: gaupol/agents/open.py:360 msgid "Open abnormally large file \"{}\"?" msgstr "Открыть необычно большой файл \"{}\"?" #: gaupol/agents/open.py:361 msgid "" "Size of the file is {:.1f} MB, which is abnormally large for a text-based " "subtitle file. Please, check that you are not trying to open a binary file." msgstr "" "Размер файла составляет {:.1f} МБ, что слишком много для текстового файла " "субтитров. Убедитесь, что это не двоичный файл." #: gaupol/agents/open.py:371 msgid "Open unsorted file \"{}\"?" msgstr "Открыть неотсортированный файл \"{}\"?" #: gaupol/agents/open.py:372 msgid "" "The order of {:d} subtitles needs to be changed. If {:d} sounds like a lot, " "the file may be erroneously composed." msgstr "" "Необходимо изменить порядок {:d} субтитров. Если {:d} это очень много, то " "файл мог быть ошибочно составлен." #: gaupol/agents/open.py:383 msgid "Save changes to translation document \"{}\" before opening a new one?" msgstr "Сохранить изменения в переводе \"{}\" перед открытием нового?" #: gaupol/agents/open.py:386 msgid "Open _Without Saving" msgstr "Открыть _без сохранения" #: gaupol/agents/close.py:66 msgid "Save changes to document \"{}\" before closing?" msgstr "Сохранить изменения в документе «{}» перед закрытием?" #: gaupol/agents/edit.py:101 gaupol/agents/edit.py:119 msgid "Stretching end position" msgstr "Перенести конец" #: gaupol/agents/edit.py:208 msgid "Inserted {:d} subtitle to fit clipboard contents" msgid_plural "Inserted {:d} subtitles to fit clipboard contents" msgstr[0] "Вставлен {:d} субтитр для размещения текста из Буфера обмена" msgstr[1] "Вставлено {:d} субтитра для размещения текста из Буфера обмена" msgstr[2] "Вставлено {:d} субтитров для размещения текста из Буфера обмена" msgstr[3] "Вставлено {:d} субтитров для размещения текста из Буфера обмена" #: gaupol/agents/edit.py:334 gaupol/agents/edit.py:352 msgid "Stretching start position" msgstr "Перенести начало" #: gaupol/agents/edit.py:411 msgid "Use Shift+Return for line-break" msgstr "Для переноса текста используйте Shift+Enter" #: gaupol/agents/save.py:129 msgid "Save As" msgstr "Сохранить как" #: gaupol/agents/save.py:135 msgid "Saved main document as \"{}\"" msgstr "Документ был сохранен под именем \"{}\"" #: gaupol/agents/save.py:153 msgid "Save Translation As" msgstr "Сохранить перевод как" #: gaupol/agents/save.py:159 msgid "Saved translation document as \"{}\"" msgstr "Перевод был сохранен под именем \"{}\"" #: gaupol/agents/save.py:194 #, python-brace-format msgid "Failed to encode file \"{basename}\" with codec \"{codec}\"" msgstr "Не удалось закодировать файл \"{basename}\" с помощью \"{codec}\"" #: gaupol/agents/save.py:195 msgid "Please try to save the file with a different character encoding." msgstr "Попробуйте сохранить файл в другой кодировке символов." #: gaupol/agents/save.py:203 msgid "Failed to save file \"{}\"" msgstr "Не удалось сохранить файл \"{}\"" #: gaupol/agents/video.py:67 data/ui/menubar.ui:380 msgid "_Play/Pause" msgstr "Воспроизвести/Остановить" #: gaupol/agents/video.py:69 msgid "Play or pause video" msgstr "Воспроизвести или остановить видео" #: gaupol/agents/video.py:75 data/ui/menubar.ui:390 msgid "Seek _Previous" msgstr "К _предыдущему" #: gaupol/agents/video.py:77 msgid "Seek to the start of the previous subtitle" msgstr "Перемотать к началу предыдущего субтитра" #: gaupol/agents/video.py:81 data/ui/menubar.ui:394 msgid "Seek _Next" msgstr "К _следующему" #: gaupol/agents/video.py:83 msgid "Seek to the start of the next subtitle" msgstr "Промотать к началу следующего субтитра" #: gaupol/agents/video.py:88 data/ui/menubar.ui:400 msgid "Seek _Backward" msgstr "Перемотать _назад" #: gaupol/agents/video.py:90 msgid "Seek backward" msgstr "Перемотать назад" #: gaupol/agents/video.py:94 data/ui/menubar.ui:404 msgid "Seek _Forward" msgstr "Промотать _вперед" #: gaupol/agents/video.py:96 msgid "Seek forward" msgstr "Промотать вперед" #: gaupol/agents/video.py:109 msgid "Volume" msgstr "Громкость" #: gaupol/agents/video.py:189 msgid "Load Video" msgstr "Загрузить видео" #: gaupol/agents/video.py:189 msgid "_Load" msgstr "Загрузить" #: gaupol/agents/video.py:361 msgid "Track {:d}" msgstr "Дорожка {:d}" #: gaupol/agents/preview.py:105 msgid "Failed to encode subtitle file to temporary directory \"{}\"" msgstr "Не удалось создать перекодированный файл во временном каталоге \"{}\"" #: gaupol/agents/preview.py:106 msgid "" "Subtitle data could not be encoded to a temporary file for preview with the " "current character encoding. Please first save the subtitle file with a " "different character encoding." msgstr "" "Не удалось закодировать в текущей кодировке субтитры во временном файле. " "Сначала сохраните файл в другой кодировке." #: gaupol/agents/preview.py:114 msgid "Failed to save subtitle file to temporary directory \"{}\"" msgstr "Не удалось сохранить файл во временном каталоге \"{}\"" #: gaupol/agents/preview.py:122 msgid "Video player not found" msgstr "Видеоплеер не найден" #: gaupol/agents/preview.py:123 msgid "" "Please install one of the supported video players: mpv (recommended), " "MPlayer or VLC. See the preferences dialog to choose the video player or to " "customize the command." msgstr "" "Установите один из поддерживаемых плееров: mpv (рекомендуется), MPlayer или " "VLC. Используйте диалог настроек для их настройки." #: gaupol/agents/preview.py:131 msgid "Failed to launch video player" msgstr "Не удалось запустить видеоплеер" #: gaupol/applicationman.py:105 msgid "gaupol [OPTION...] [FILE...] [+[NUM]]" msgstr "gaupol [ПАРАМЕТР...] [ФАЙЛ...] [+[ЧИСЛО]]" #: gaupol/applicationman.py:109 msgid "FILE..." msgstr "Файл..." #: gaupol/applicationman.py:112 msgid "subtitle files to open" msgstr "файл с субтитрами" #: gaupol/applicationman.py:122 msgid "ENCODING" msgstr "КОДИРОВКА" #: gaupol/applicationman.py:125 msgid "set the character encoding used to open files" msgstr "задать кодировку открываемых файлов" #: gaupol/applicationman.py:132 msgid "list all available character encodings" msgstr "вывести все доступные кодировки символов" #: gaupol/applicationman.py:137 gaupol/applicationman.py:154 msgid "FILE" msgstr "ФАЙЛ" #: gaupol/applicationman.py:140 msgid "open translation file" msgstr "открыть файл перевода" #: gaupol/applicationman.py:145 msgid "METHOD" msgstr "СПОСОБ" #: gaupol/applicationman.py:149 msgid "method used to align translation subtitles: 'number' or 'position'" msgstr "" "способ сопоставления перевода: 'number' (номер) или 'position' (положение)" #: gaupol/applicationman.py:157 msgid "select video file" msgstr "выбрать видеофайл" #: data/extensions/custom-framerates/custom-framerates.py:40 #: data/ui/spell-check-dialog.ui:152 msgid "_Add" msgstr "_Добавить" #: data/extensions/custom-framerates/custom-framerates.py:171 msgid "{:.3f} fps" msgstr "{:.3f} к/с" #: data/extensions/custom-framerates/add-framerate-dialog.ui:13 msgid "Add Framerate" msgstr "Добавить частоту кадров" #: data/extensions/custom-framerates/add-framerate-dialog.ui:44 msgid "_Framerate:" msgstr "_Частота кадров:" #: data/extensions/custom-framerates/add-framerate-dialog.ui:73 msgid "fps" msgstr "к/с" #: data/extensions/custom-framerates/preferences-dialog.ui:8 msgid "Framerates" msgstr "Частота кадров" #: data/extensions/custom-framerates/preferences-dialog.ui:64 msgid "Add" msgstr "Добавить" #: data/ui/columns-popup.ui:6 data/ui/menubar.ui:275 msgid "_No." msgstr "_Номер" #: data/ui/columns-popup.ui:10 data/ui/menubar.ui:279 msgid "_Start" msgstr "_Конец" #: data/ui/columns-popup.ui:14 data/ui/menubar.ui:283 msgid "_End" msgstr "_Начало" #: data/ui/columns-popup.ui:18 data/ui/menubar.ui:287 msgid "_Duration" msgstr "_Длительность" #: data/ui/columns-popup.ui:22 data/ui/menubar.ui:291 data/ui/menubar.ui:303 msgid "_Text" msgstr "_Текст" #: data/ui/columns-popup.ui:26 data/ui/menubar.ui:295 msgid "T_ranslation" msgstr "Перевод" #: data/ui/split-dialog.ui:15 msgid "Split Project" msgstr "Разделить проект" #: data/ui/split-dialog.ui:48 msgid "_First subtitle of new project:" msgstr "_Первый субтитр нового проекта:" #: data/ui/search-dialog.ui:89 msgid "_Search for:" msgstr "_Искать:" #: data/ui/search-dialog.ui:103 data/ui/spell-check-dialog.ui:193 msgid "Replace _with:" msgstr "_Заменить на:" #: data/ui/search-dialog.ui:162 data/ui/menubar.ui:328 msgid "Find _Next" msgstr "Найти _выше" #: data/ui/search-dialog.ui:177 msgid "Find _Previous" msgstr "Найти _ниже" #: data/ui/search-dialog.ui:207 msgid "Replace _All" msgstr "Заменит_ь все" #: data/ui/search-dialog.ui:241 msgid "R_egular expression" msgstr "_Регулярное выражение" #: data/ui/search-dialog.ui:258 msgid "_Ignore case" msgstr "_Без учета регистра" #: data/ui/search-dialog.ui:304 data/ui/language-dialog.ui:108 msgid "Columns" msgstr "Столбцы" #: data/ui/search-dialog.ui:324 msgid "Find in _text column" msgstr "Найти в колонке \"Текст\"" #: data/ui/search-dialog.ui:341 msgid "Find in t_ranslation column" msgstr "Найти в колонке \"Перевод\"" #: data/ui/search-dialog.ui:381 data/ui/framerate-convert-dialog.ui:144 #: data/ui/language-dialog.ui:186 #: data/ui/text-assistant/line-break-options-page.ui:178 #: data/ui/duration-adjust-dialog.ui:388 data/ui/position-shift-dialog.ui:180 #: data/ui/position-transform-dialog.ui:444 msgid "Subtitles" msgstr "Субтитры" #: data/ui/search-dialog.ui:401 msgid "Find in c_urrent project" msgstr "Искать в _текущем проекте" #: data/ui/search-dialog.ui:419 msgid "Find in _all open projects" msgstr "Искать во _всех проектах" #: data/ui/search-dialog.ui:452 msgid "Target" msgstr "Область" #: data/ui/framerate-convert-dialog.ui:8 msgid "Convert Framerate" msgstr "Частота кадров" #: data/ui/framerate-convert-dialog.ui:48 msgid "Framerate" msgstr "Частота кадров" #: data/ui/framerate-convert-dialog.ui:71 msgid "_Input:" msgstr "На _входе:" #: data/ui/framerate-convert-dialog.ui:86 msgid "_Output:" msgstr "На в_ыходе:" #: data/ui/framerate-convert-dialog.ui:164 msgid "Convert c_urrent project" msgstr "Преобразовать т_екущий проект" #: data/ui/framerate-convert-dialog.ui:181 msgid "Convert _all open projects" msgstr "Преобразовать все _открытые проекты" #: data/ui/spell-check-dialog.ui:8 msgid "Check Spelling" msgstr "Проверка орфографии" #: data/ui/spell-check-dialog.ui:47 msgid "Join _Back" msgstr "Слить с пред_ыдущим" #: data/ui/spell-check-dialog.ui:62 msgid "Join _Forward" msgstr "Слить со с_ледующим" #: data/ui/spell-check-dialog.ui:77 data/ui/menubar.ui:62 msgid "_Edit" msgstr "_Правка" #: data/ui/spell-check-dialog.ui:92 msgid "_Ignore" msgstr "Проп_устить" #: data/ui/spell-check-dialog.ui:107 msgid "Ig_nore All" msgstr "Пропустить _все" #: data/ui/spell-check-dialog.ui:137 msgid "Rep_lace All" msgstr "Заменить в_се" #: data/ui/spell-check-dialog.ui:179 msgid "_Suggestions:" msgstr "В_арианты:" #: data/ui/multi-save-dialog.ui:8 msgid "Save All As" msgstr "Сохранить все как" #: data/ui/multi-save-dialog.ui:46 msgid "Save in _folder:" msgstr "Сохранить в папке:" #: data/ui/multi-save-dialog.ui:60 data/ui/save-dialog.ui:25 msgid "For_mat:" msgstr "Фор_мат:" #: data/ui/multi-save-dialog.ui:74 data/ui/open-dialog.ui:25 #: data/ui/save-dialog.ui:39 msgid "_Encoding:" msgstr "_Кодировка:" #: data/ui/multi-save-dialog.ui:88 data/ui/save-dialog.ui:53 msgid "Ne_wlines:" msgstr "Раз_рывы строк:" #: data/ui/multi-save-dialog.ui:103 msgid "Select A Folder" msgstr "Выбрать папку" #: data/ui/multi-save-dialog.ui:150 data/ui/save-dialog.ui:102 msgid "F_ramerate:" msgstr "Частота кадров" #: data/ui/menubar.ui:5 msgid "_File" msgstr "_Файл" #: data/ui/menubar.ui:8 msgid "_New" msgstr "Со_здать" #: data/ui/menubar.ui:12 msgid "_Open…" msgstr "_Открыть…" #: data/ui/menubar.ui:16 msgid "Open _Translation…" msgstr "Открыть п_еревод…" #: data/ui/menubar.ui:22 msgid "Open _Recent" msgstr "Открыть пос_ледний" #: data/ui/menubar.ui:27 msgid "Open R_ecent Translation" msgstr "Открыть последний пере_вод" #: data/ui/menubar.ui:38 msgid "Save _As…" msgstr "Сохранить _как…" #: data/ui/menubar.ui:42 msgid "Save Trans_lation" msgstr "Сохранить _перевод" #: data/ui/menubar.ui:46 msgid "Save Translat_ion As…" msgstr "Сохранить перево_д как…" #: data/ui/menubar.ui:65 msgid "_Undo" msgstr "От_мена" #: data/ui/menubar.ui:69 msgid "_Redo" msgstr "П_овтор" #: data/ui/menubar.ui:75 msgid "_Edit Cell" msgstr "_Редактировать ячейку" #: data/ui/menubar.ui:79 msgid "Edit _Next Cell" msgstr "Сл_едующая ячейка" #: data/ui/menubar.ui:85 msgid "Stretc_h" msgstr "Раст_януть" #: data/ui/menubar.ui:88 msgid "_Start Earlier" msgstr "_Начать раньше" #: data/ui/menubar.ui:92 msgid "S_tart Later" msgstr "Н_ачать позже" #: data/ui/menubar.ui:98 msgid "E_nd Earlier" msgstr "За_кончить раньше" #: data/ui/menubar.ui:102 msgid "En_d Later" msgstr "_Закончить позже" #: data/ui/menubar.ui:108 msgid "Set St_art From Video Position" msgstr "_Начало в позиции видео" #: data/ui/menubar.ui:112 msgid "Set En_d From Video Position" msgstr "О_кончание в позиции видео" #: data/ui/menubar.ui:118 data/ui/view-popup.ui:6 msgid "_Split Subtitle" msgstr "_Разделить" #: data/ui/menubar.ui:122 data/ui/view-popup.ui:10 msgid "_Merge Subtitles" msgstr "О_бъединить субтитры" #: data/ui/menubar.ui:128 data/ui/view-popup.ui:16 msgid "_Insert Subtitles…" msgstr "В_ставить субтитры…" #: data/ui/menubar.ui:132 msgid "Inser_t Subtitle At Video Position" msgstr "Встав_ить в позицию видео" #: data/ui/menubar.ui:136 data/ui/view-popup.ui:20 msgid "Rem_ove Subtitles" msgstr "_Удалить субтитры" #: data/ui/menubar.ui:142 msgid "Sele_ction" msgstr "Вы_деление" #: data/ui/menubar.ui:145 msgid "Select _All" msgstr "Выделить в_се" #: data/ui/menubar.ui:149 msgid "_Invert Selection" msgstr "О_братить выделение" #: data/ui/menubar.ui:155 msgid "Extend To _Beginning" msgstr "Расширить до _начала" #: data/ui/menubar.ui:159 msgid "Extend To _End" msgstr "Расширить до _конца" #: data/ui/menubar.ui:165 msgid "_Previous From Video Position" msgstr "" #: data/ui/menubar.ui:169 msgid "_Next From Video Position" msgstr "" #: data/ui/menubar.ui:177 msgid "_Preferences" msgstr "_Параметры" #: data/ui/menubar.ui:183 msgid "_View" msgstr "_Вид" #: data/ui/menubar.ui:186 msgid "Tool_bar" msgstr "Панель инструментов" #: data/ui/menubar.ui:190 msgid "_Video Player" msgstr "Видеоплеер" #: data/ui/menubar.ui:196 msgid "_Layout" msgstr "_Расположение" #: data/ui/menubar.ui:199 msgid "_Horizontal" msgstr "_Горизонтально" #: data/ui/menubar.ui:204 msgid "_Vertical" msgstr "_Вертикально" #: data/ui/menubar.ui:213 msgid "_Times" msgstr "_Время" #: data/ui/menubar.ui:218 msgid "_Frames" msgstr "_Кадры" #: data/ui/menubar.ui:225 msgid "F_ramerate" msgstr "_Частота кадров" #: data/ui/menubar.ui:228 msgid "2_3.976 fps" msgstr "2_3,976 к/с" #: data/ui/menubar.ui:233 msgid "2_4.000 fps" msgstr "2_4 к/с" #: data/ui/menubar.ui:238 msgid "2_5.000 fps" msgstr "2_5 к/с" #: data/ui/menubar.ui:243 msgid "2_9.970 fps" msgstr "2_9,970 к/с" #: data/ui/menubar.ui:272 msgid "_Columns" msgstr "Стол_бцы" #: data/ui/menubar.ui:306 msgid "Cu_t" msgstr "В_ырезать" #: data/ui/menubar.ui:310 msgid "_Copy" msgstr "_Копировать" #: data/ui/menubar.ui:314 msgid "_Paste" msgstr "Вс_тавить" #: data/ui/menubar.ui:318 msgid "Cl_ear" msgstr "О_чистить" #: data/ui/menubar.ui:324 msgid "_Find And Replace…" msgstr "По_иск и замена…" #: data/ui/menubar.ui:332 msgid "Find Pre_vious" msgstr "Найти в_ыше" #: data/ui/menubar.ui:338 msgid "_Italic" msgstr "К_урсив" #: data/ui/menubar.ui:342 msgid "_Dialogue" msgstr "_Диалог" #: data/ui/menubar.ui:348 msgid "Ca_se" msgstr "Ре_гистр" #: data/ui/menubar.ui:351 msgid "_Title" msgstr "Начать с _заглавных букв" #: data/ui/menubar.ui:355 msgid "_Sentence" msgstr "Как в _предложении" #: data/ui/menubar.ui:359 msgid "_Upper" msgstr "_Верхний" #: data/ui/menubar.ui:363 msgid "_Lower" msgstr "_Нижний" #: data/ui/menubar.ui:371 msgid "Vi_deo" msgstr "Видео" #: data/ui/menubar.ui:374 msgid "_Load Video…" msgstr "Загрузить видео..." #: data/ui/menubar.ui:384 data/ui/view-popup.ui:26 msgid "Play _Selection" msgstr "Воспроизвести в_ыделенное" #: data/ui/menubar.ui:410 data/ui/view-popup.ui:30 msgid "S_eek Selection Start" msgstr "К н_ачалу выделения" #: data/ui/menubar.ui:414 msgid "See_k Selection End" msgstr "К _концу выделения" #: data/ui/menubar.ui:420 msgid "_Audio" msgstr "Аудио" #: data/ui/menubar.ui:423 msgid "_Language" msgstr "Язык" #: data/ui/menubar.ui:430 msgid "Volume _Down" msgstr "Уменьшить громкость" #: data/ui/menubar.ui:434 msgid "Volume _Up" msgstr "Увеличить громкость" #: data/ui/menubar.ui:440 msgid "T_ools" msgstr "С_ервис" #: data/ui/menubar.ui:443 data/ui/text-assistant/confirmation-page.ui:97 #: data/ui/view-popup.ui:36 msgid "_Preview" msgstr "Прос_мотр" #: data/ui/menubar.ui:447 msgid "Select _Video…" msgstr "Выбрать _видео…" #: data/ui/menubar.ui:453 msgid "_Check Spelling" msgstr "Про_верка орфографии" #: data/ui/menubar.ui:457 msgid "Co_nfigure Spell-check…" msgstr "Настройки проверки ор_фографии…" #: data/ui/menubar.ui:461 msgid "C_orrect Texts…" msgstr "Испра_вить текст…" #: data/ui/menubar.ui:467 msgid "_Shift Positions…" msgstr "_Сдвиг…" #: data/ui/menubar.ui:471 msgid "_Transform Positions…" msgstr "_Преобразовать…" #: data/ui/menubar.ui:475 msgid "Adjust _Durations…" msgstr "Скорректировать _длительность…" #: data/ui/menubar.ui:479 msgid "Convert _Framerate…" msgstr "Изменить _частоту кадров…" #: data/ui/menubar.ui:485 msgid "_Append File…" msgstr "_Добавить файл…" #: data/ui/menubar.ui:489 msgid "Spli_t Project…" msgstr "_Разделить проект…" #: data/ui/menubar.ui:495 msgid "_Projects" msgstr "_Проект" #: data/ui/menubar.ui:498 msgid "_Save All" msgstr "_Сохранить все" #: data/ui/menubar.ui:502 msgid "Save _All As…" msgstr "Сохранить все как..." #: data/ui/menubar.ui:506 msgid "_Close All" msgstr "Зак_рыть все" #: data/ui/menubar.ui:512 msgid "_Previous" msgstr "Пре_дыдущая" #: data/ui/menubar.ui:516 msgid "_Next" msgstr "С_ледующая" #: data/ui/menubar.ui:527 msgid "_Documentation" msgstr "_Документация" #: data/ui/menubar.ui:531 msgid "_Report A Bug" msgstr "_Сообщить об ошибке" #: data/ui/menubar.ui:535 msgid "_About" msgstr "О _программе" #: data/ui/open-dialog.ui:39 msgid "Align _method:" msgstr "С_опоставление:" #: data/ui/preferences-dialog.ui:18 msgid "Preferences" msgstr "Параметры" #: data/ui/preferences-dialog.ui:93 msgid "When opening files, try encodings in the following order:" msgstr "При открытии файла, пробовать кодировки в указанном порядке:" #: data/ui/preferences-dialog.ui:104 msgid "Curr_ent locale encoding" msgstr "Т_екущая системная кодировка" #: data/ui/preferences-dialog.ui:130 msgid "_Fallback encodings:" msgstr "Ре_зервные кодировки:" #: data/ui/preferences-dialog.ui:246 msgid "Aut_o-detection" msgstr "Авто_определение" #: data/ui/preferences-dialog.ui:266 msgid "Encoding specified in the open dialog will always be tried first." msgstr "" "Кодировка, указанная в окне открытия файла, будет использована первой." #: data/ui/preferences-dialog.ui:296 msgid "File" msgstr "Файлы" #: data/ui/preferences-dialog.ui:324 msgid "Font" msgstr "Шрифт" #: data/ui/preferences-dialog.ui:344 msgid "Use _default theme fixed width font" msgstr "Использовать моно_ширинный шрифт из темы" #: data/ui/preferences-dialog.ui:368 msgid "_Editor font:" msgstr "_Шрифт редактора:" #: data/ui/preferences-dialog.ui:425 msgid "Line Lengths" msgstr "Длины строк" #: data/ui/preferences-dialog.ui:445 msgid "_Show line lengths in list cells" msgstr "Показывать дл_ину строк в ячейках списка" #: data/ui/preferences-dialog.ui:462 msgid "S_how line lengths in editable text fields" msgstr "Показывать _длину строк в полях редактирования" #: data/ui/preferences-dialog.ui:486 msgid "_Length unit:" msgstr "_Единицы длины:" #: data/ui/preferences-dialog.ui:540 msgid "Spell-Check" msgstr "Проверка орфографии" #: data/ui/preferences-dialog.ui:560 msgid "Chec_k spelling as you type" msgstr "Про_верять орфографию по мере набора текста" #: data/ui/preferences-dialog.ui:598 msgid "Editor" msgstr "Редактор" #: data/ui/preferences-dialog.ui:626 msgid "Fonts" msgstr "Шрифты" #: data/ui/preferences-dialog.ui:649 msgid "_Subtitles:" msgstr "Субтитры:" #: data/ui/preferences-dialog.ui:679 msgid "_Time:" msgstr "Время:" #: data/ui/preferences-dialog.ui:729 msgid "Colors" msgstr "Цвета" #: data/ui/preferences-dialog.ui:752 msgid "Su_btitles:" msgstr "Субтитры:" #: data/ui/preferences-dialog.ui:777 msgid "_Use a background behind text" msgstr "_Непрозрачный фон" #: data/ui/preferences-dialog.ui:797 msgid "Ti_me:" msgstr "Время:" #: data/ui/preferences-dialog.ui:822 msgid "Us_e a background behind text" msgstr "Н_епрозрачный фон" #: data/ui/preferences-dialog.ui:862 msgid "Seek" msgstr "Искать" #: data/ui/preferences-dialog.ui:883 msgid "_Length:" msgstr "Длина:" #: data/ui/preferences-dialog.ui:971 msgid "Video Player" msgstr "Видеоплеер" #: data/ui/preferences-dialog.ui:994 msgid "_Application:" msgstr "При_ложение:" #: data/ui/preferences-dialog.ui:1008 msgid "Co_mmand:" msgstr "Ко_манда:" #. Translators: Only the title is to be translated, field names not. #: data/ui/preferences-dialog.ui:1033 msgid "" "Fields:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" msgstr "Поля:" #: data/ui/preferences-dialog.ui:1048 msgid "Al_ways use UTF-8 character encoding" msgstr "В_сегда использовать кодировку UTF-8" #: data/ui/preferences-dialog.ui:1089 msgid "Start Position" msgstr "Начальная позиция" #: data/ui/preferences-dialog.ui:1111 msgid "_Offset:" msgstr "_Сдвиг на:" #: data/ui/preferences-dialog.ui:1142 msgid "seconds before selection" msgstr "сек. до начала выделения" #: data/ui/preferences-dialog.ui:1281 msgid "Extensions" msgstr "Расширения" #: data/ui/language-dialog.ui:8 msgid "Configure Spell-Check" msgstr "Настройки проверки орфографии" #: data/ui/language-dialog.ui:50 msgid "Language" msgstr "Язык" #: data/ui/language-dialog.ui:128 msgid "Check _text column" msgstr "Колонку _текста" #: data/ui/language-dialog.ui:146 msgid "Check t_ranslation column" msgstr "Колонку _перевода" #: data/ui/language-dialog.ui:206 msgid "Check c_urrent project" msgstr "Проверить т_екущий проект" #: data/ui/language-dialog.ui:224 msgid "Check _all open projects" msgstr "Проверить _все проекты" #: data/ui/text-assistant/confirmation-page.ui:22 msgid "Acc_ept, discard or edit changes:" msgstr "При_нять, отвергнуть или внести изменения:" #: data/ui/text-assistant/confirmation-page.ui:67 msgid "_Mark All" msgstr "_Все" #: data/ui/text-assistant/confirmation-page.ui:82 msgid "_Unmark All" msgstr "_Ничего" #: data/ui/text-assistant/confirmation-page.ui:119 msgid "_Remove all blank subtitles" msgstr "_Удалить пустые субтитры" #: data/ui/text-assistant/join-split-page.ui:28 msgid "Spell-Check Dictionary" msgstr "Словарь проверки орфографии" #: data/ui/text-assistant/join-split-page.ui:49 #: data/ui/text-assistant/line-break-page.ui:81 #: data/ui/text-assistant/hearing-impaired-page.ui:81 #: data/ui/text-assistant/common-error-page.ui:80 #: data/ui/text-assistant/capitalization-page.ui:80 msgid "_Language:" msgstr "_Язык:" #: data/ui/text-assistant/join-split-page.ui:97 msgid "Corrections" msgstr "Исправления" #: data/ui/text-assistant/join-split-page.ui:117 msgid "_Join words not found in spell-check dictionary" msgstr "_Объединять слова, не найденные в словаре" #: data/ui/text-assistant/join-split-page.ui:134 msgid "_Split words not found in spell-check dictionary" msgstr "_Разделять слова, не найденные в словаре" #: data/ui/text-assistant/line-break-page.ui:22 msgid "S_elect preferred line-break points:" msgstr "В_ыберите места разрыва строк:" #: data/ui/text-assistant/line-break-page.ui:67 #: data/ui/text-assistant/hearing-impaired-page.ui:67 #: data/ui/text-assistant/common-error-page.ui:66 #: data/ui/text-assistant/capitalization-page.ui:66 msgid "_Script:" msgstr "П_исьмо:" #: data/ui/text-assistant/line-break-page.ui:95 #: data/ui/text-assistant/hearing-impaired-page.ui:95 #: data/ui/text-assistant/common-error-page.ui:94 #: data/ui/text-assistant/capitalization-page.ui:94 msgid "Co_untry:" msgstr "Страна:" #: data/ui/text-assistant/introduction-page.ui:28 msgid "_Select corrections to perform on texts:" msgstr "В_ыберите нужные исправления:" #: data/ui/text-assistant/introduction-page.ui:79 msgid "Colu_mns:" msgstr "Колонки:" #: data/ui/text-assistant/introduction-page.ui:93 msgid "S_ubtitles:" msgstr "Субтитры:" #: data/ui/text-assistant/line-break-options-page.ui:56 #: data/ui/duration-adjust-dialog.ui:207 msgid "Limits" msgstr "Пределы" #: data/ui/text-assistant/line-break-options-page.ui:79 msgid "_Maximum line length:" msgstr "_Максимальная длина строки:" #: data/ui/text-assistant/line-break-options-page.ui:93 msgid "_Preferred maximum amount of lines:" msgstr "Предпочтительное макс. _число строк:" #: data/ui/text-assistant/line-break-options-page.ui:198 msgid "_Skip subtitles with maximum line length of:" msgstr "Пропускать субтитры со строками д_линнее:" #: data/ui/text-assistant/line-break-options-page.ui:214 msgid "S_kip subtitles with maximum line amount of:" msgstr "Пропускать субтитры с _количеством строк более:" #: data/ui/text-assistant/hearing-impaired-page.ui:22 msgid "S_elect parts to remove:" msgstr "В_ыберите удаляемые фрагменты:" #: data/ui/text-assistant/common-error-page.ui:22 msgid "S_elect errors to correct:" msgstr "В_ыберите исправляемые ошибки:" #: data/ui/text-assistant/common-error-page.ui:108 msgid "Error types:" msgstr "Виды ошибок:" #: data/ui/text-assistant/common-error-page.ui:158 msgid "_Human errors" msgstr "_Человеческие ошибки" #: data/ui/text-assistant/common-error-page.ui:175 msgid "_Image recognition errors" msgstr "Ошибки _распознавания текста" #: data/ui/text-assistant/capitalization-page.ui:22 msgid "S_elect parts to capitalize:" msgstr "В_ыберите правила написания:" #: data/ui/duration-adjust-dialog.ui:33 msgid "Adjust Durations" msgstr "Скорректировать длительность" #: data/ui/duration-adjust-dialog.ui:73 msgid "Theoretic Duration" msgstr "Теоретическая длительность" #: data/ui/duration-adjust-dialog.ui:101 msgid "_Reading speed:" msgstr "Скорость _чтения:" #: data/ui/duration-adjust-dialog.ui:133 msgid "characters per second" msgstr "символов в секунду" #: data/ui/duration-adjust-dialog.ui:150 msgid "_Lengthen duration to match reading speed" msgstr "_Увеличить до совпадения со скоростью чтения" #: data/ui/duration-adjust-dialog.ui:167 msgid "_Shorten duration to match reading speed" msgstr "У_меньшить до совпадения со скоростью чтения" #: data/ui/duration-adjust-dialog.ui:227 msgid "_Minimum duration:" msgstr "_Минимальная длительность:" #: data/ui/duration-adjust-dialog.ui:243 msgid "Ma_ximum duration:" msgstr "Ма_ксимальная длительность:" #: data/ui/duration-adjust-dialog.ui:259 msgid "_Gap between subtitles:" msgstr "_Задержка между субтитрами:" #: data/ui/duration-adjust-dialog.ui:294 msgid "s_econds" msgstr "_секунд" #: data/ui/duration-adjust-dialog.ui:324 msgid "seco_nds" msgstr "с_екунд" #: data/ui/duration-adjust-dialog.ui:354 msgid "secon_ds" msgstr "се_кунд" #: data/ui/duration-adjust-dialog.ui:408 msgid "Adj_ust selected subtitles" msgstr "В_ыделенные субтитры" #: data/ui/duration-adjust-dialog.ui:425 msgid "Adjus_t current project" msgstr "Тек_ущий проект" #: data/ui/duration-adjust-dialog.ui:442 msgid "Adjust all _open projects" msgstr "_Все открытые проекты" #: data/ui/tab-popup.ui:6 msgid "Move Tab _Left" msgstr "Сдвинуть на_лево" #: data/ui/tab-popup.ui:10 msgid "Move Tab _Right" msgstr "Сдвинуть на_право" #: data/ui/insert-dialog.ui:15 msgid "Insert Subtitles" msgstr "Вставка субтитров" #: data/ui/insert-dialog.ui:48 data/ui/position-shift-dialog.ui:82 msgid "_Amount:" msgstr "_Количество:" #: data/ui/insert-dialog.ui:62 msgid "_Position:" msgstr "_Положение:" #: data/ui/position-shift-dialog.ui:14 msgid "Shift Positions" msgstr "Сдвиг положения" #: data/ui/position-shift-dialog.ui:54 msgid "Shift" msgstr "Сдвиг" #: data/ui/position-shift-dialog.ui:135 #: data/ui/position-transform-dialog.ui:208 msgid "_Preview Changes" msgstr "Прос_мотр изменений" #: data/ui/position-shift-dialog.ui:200 msgid "Shift s_elected subtitles" msgstr "Сдвинуть в_ыделенные субтитры" #: data/ui/position-shift-dialog.ui:217 msgid "Shift su_btitles from selection to end" msgstr "Сдвинуть в_се субтитры" #: data/ui/position-shift-dialog.ui:234 msgid "Shift c_urrent project" msgstr "Сдвинуть т_екущий проект" #: data/ui/position-shift-dialog.ui:251 msgid "Shift all _open projects" msgstr "Сдвинуть все пр_оекты" #: data/ui/position-transform-dialog.ui:22 msgid "Transform Positions" msgstr "Преобразование" #: data/ui/position-transform-dialog.ui:62 msgid "First Point" msgstr "Первая точка" #: data/ui/position-transform-dialog.ui:91 msgid "_Subtitle:" msgstr "_Субтитр:" #: data/ui/position-transform-dialog.ui:105 msgid "C_orrection:" msgstr "_Исправление:" #: data/ui/position-transform-dialog.ui:119 #: data/ui/position-transform-dialog.ui:310 msgid "Text:" msgstr "Текст:" #: data/ui/position-transform-dialog.ui:253 msgid "Second Point" msgstr "Вторая точка" #: data/ui/position-transform-dialog.ui:282 msgid "Su_btitle:" msgstr "Суб_титр:" #: data/ui/position-transform-dialog.ui:296 msgid "Co_rrection:" msgstr "Ис_правление:" #: data/ui/position-transform-dialog.ui:399 msgid "Pre_view Changes" msgstr "Прос_мотр изменений" #: data/ui/position-transform-dialog.ui:464 msgid "Transform se_lected subtitles" msgstr "В_ыделенные субтитры" #: data/ui/position-transform-dialog.ui:482 msgid "Transform c_urrent project" msgstr "Т_екущий проект" #: data/extensions/custom-framerates/custom-framerates.extension.in:7 msgid "Custom Framerates" msgstr "Заказные частоты кадров" #: data/extensions/custom-framerates/custom-framerates.extension.in:8 msgid "Allow use of non-standard framerates" msgstr "Использовать нестандартные частоты кадров" #: data/patterns/Latn-en-US.common-error.in:5 msgid "Period after title" msgstr "Точки после обращений" #: data/patterns/Latn-en-US.common-error.in:6 msgid "Add period after a shortened title, such as \"Mr\" and \"Dr\"" msgstr "Добавить точку после обращений \"Mr\" и \"Dr\"" #: data/patterns/Latn-en.capitalization.in:5 msgid "First person pronoun" msgstr "Местоимение первого лица" #: data/patterns/Latn-en.capitalization.in:6 msgid "Capitalize the first person pronoun \"I\"" msgstr "Писать местоимение \"I\" с заглавной буквы" #: data/patterns/Latn-en.common-error.in:5 #: data/patterns/Latn-en.common-error.in:14 #: data/patterns/Latn-en.common-error.in:23 msgid "Letter \"I\" in a lower case word" msgstr "Буква \"I\" в слове в нижнем регистре" #: data/patterns/Latn-en.common-error.in:6 #: data/patterns/Latn-en.common-error.in:15 #: data/patterns/Latn-en.common-error.in:24 msgid "Replace letter \"I\" with letter \"l\" in a lower case word" msgstr "Заменять \"I\" на \"l\" в словах в нижнем регистре" #: data/patterns/Latn-en.common-error.in:32 #: data/patterns/Latn-en.common-error.in:41 #: data/patterns/Latn-en.common-error.in:50 #: data/patterns/Latn-en.common-error.in:62 msgid "Letter \"l\" in an upper case word" msgstr "Буква \"l\" в слове верхнего регистра" #: data/patterns/Latn-en.common-error.in:33 #: data/patterns/Latn-en.common-error.in:42 #: data/patterns/Latn-en.common-error.in:51 #: data/patterns/Latn-en.common-error.in:63 msgid "Replace letter \"l\" with letter \"I\" in an upper case word" msgstr "Заменить букву \"l\" на \"I\" в словах в верхнем регистре" #: data/patterns/Latn-en.common-error.in:73 #: data/patterns/Latn-en.common-error.in:82 msgid "Zero in an upper case word" msgstr "Ноль в словах в верхнем регистре" #: data/patterns/Latn-en.common-error.in:74 #: data/patterns/Latn-en.common-error.in:83 msgid "Replace zero with letter \"O\" in an upper case word" msgstr "Заменять ноль на букву \"O\" в словах верхнего регистра" #: data/patterns/Latn-en.common-error.in:91 #: data/patterns/Latn.common-error.in:108 msgid "Space between number and unit" msgstr "Пробел между числом и единицей" #: data/patterns/Latn-en.common-error.in:92 #: data/patterns/Latn.common-error.in:109 msgid "Add or remove space between a number and the associated unit" msgstr "Добавить или удалить пробел между числом и единицей измерения" #: data/patterns/Latn-en.common-error.in:100 msgid "Spaces around an apostrophe" msgstr "Пробелы вокруг апострофов" #: data/patterns/Latn-en.common-error.in:101 msgid "Remove spaces around an apostrophe" msgstr "Удалить пробелы вокруг апострофов" #: data/patterns/Latn-en.common-error.in:109 #: data/patterns/Latn-en.common-error.in:118 msgid "Okay" msgstr "Okay" #: data/patterns/Latn-en.common-error.in:110 #: data/patterns/Latn-en.common-error.in:119 msgid "Spell two-letter forms of \"okay\" in all upper case" msgstr "Заменить все формы «okay» на ΟΚ" #: data/patterns/Latn-en.hearing-impaired.in:5 msgid "Uppercase speaker before a colon" msgstr "Имена говорящих" #: data/patterns/Latn-en.hearing-impaired.in:6 msgid "" "Replace the uppercase name of the speaker before a colon with a dialogue " "dash" msgstr "Заменить имя говорящего перед двоеточием на тире" #: data/patterns/Latn-en.line-break.in:5 msgid "Title" msgstr "Заголовок" #: data/patterns/Latn-en.line-break.in:6 msgid "Do not break after a title, e.g. \" Dr.\"" msgstr "Не переносить после титулов, напр. «Dr.»" #: data/patterns/Latn-en.line-break.in:13 msgid "Article" msgstr "Артикль" #: data/patterns/Latn-en.line-break.in:14 msgid "Do not break after an article" msgstr "Не переносить после артикля" #: data/patterns/Latn-en.line-break.in:21 msgid "Preposition" msgstr "Предлог" #: data/patterns/Latn-en.line-break.in:22 msgid "Do not break after a preposition" msgstr "Не переносить после предлогов" #: data/patterns/Latn-en.line-break.in:30 msgid "Possessive determiner" msgstr "Притяжательное местоимение" #: data/patterns/Latn-en.line-break.in:31 msgid "Do not break after a possessive determiner, e.g. \"my\"" msgstr "Не переносить после притяжательных местоимений, напр. «my»" #: data/patterns/Latn-fi.common-error.in:5 #: data/patterns/Latn.common-error.in:182 msgid "Space after punctuation marks" msgstr "Пробел после знаков препинания" #: data/patterns/Latn-fi.common-error.in:6 #: data/patterns/Latn.common-error.in:183 msgid "Add space after various punctuation marks" msgstr "Добавляет пробелы после знаков препинания" #: data/patterns/Latn-fr.common-error.in:5 #: data/patterns/Latn-fr.common-error.in:14 #: data/patterns/Latn-fr.common-error.in:23 #: data/patterns/Latn-fr.common-error.in:32 msgid "Spaces around guillemets" msgstr "Пробелы вокруг «лапок»" #: data/patterns/Latn-fr.common-error.in:6 #: data/patterns/Latn-fr.common-error.in:15 #: data/patterns/Latn-fr.common-error.in:24 #: data/patterns/Latn-fr.common-error.in:33 msgid "Add spaces around guillemets" msgstr "Добавить пробелы вокруг кавычек-лапок" #: data/patterns/Latn-fr.common-error.in:41 #: data/patterns/Latn-fr.common-error.in:52 #: data/patterns/Latn.common-error.in:171 msgid "Space before punctuation marks" msgstr "Пробел перед знаками препинания" #: data/patterns/Latn-fr.common-error.in:42 #: data/patterns/Latn-fr.common-error.in:53 msgid "Add or remove space before various punctuation marks" msgstr "Добавить или удалить пробелы перед знаками пунктуации" #: data/patterns/Latn.capitalization.in:5 msgid "Sentence" msgstr "Предложение" #: data/patterns/Latn.capitalization.in:6 msgid "Capitalize the first word of a sentence" msgstr "Начинать предложения с заглавной буквы" #: data/patterns/Latn.capitalization.in:12 msgid "Ellipsis" msgstr "Многоточие" #: data/patterns/Latn.capitalization.in:13 msgid "Capitalize after an ellipsis" msgstr "Заглавная буква после многоточия" #: data/patterns/Latn.common-error.in:8 data/patterns/Latn.common-error.in:17 #: data/patterns/Latn.common-error.in:26 data/patterns/Latn.common-error.in:35 #: data/patterns/Latn.common-error.in:44 data/patterns/Latn.common-error.in:53 #: data/patterns/Latn.common-error.in:62 msgid "Ligatures" msgstr "Лигатуры" #: data/patterns/Latn.common-error.in:9 data/patterns/Latn.common-error.in:18 #: data/patterns/Latn.common-error.in:27 data/patterns/Latn.common-error.in:36 #: data/patterns/Latn.common-error.in:45 data/patterns/Latn.common-error.in:54 #: data/patterns/Latn.common-error.in:63 msgid "Unpack ligatures to individual characters" msgstr "Разделять лигатуры на составляющие символы" #: data/patterns/Latn.common-error.in:71 data/patterns/Latn.common-error.in:80 msgid "Spelling of a.m. and p.m." msgstr "Написание a.m. и p.m." #: data/patterns/Latn.common-error.in:72 data/patterns/Latn.common-error.in:81 msgid "Change the various spellings of 12-hour periods to \"a.m.\" and \"p.m.\"" msgstr "Заменить различные написания времени суток на «a.m.» и «p.m.»" #: data/patterns/Latn.common-error.in:89 data/patterns/Latn.common-error.in:98 msgid "Letter \"O\" in a number" msgstr "Буква \"O\" в числах" #: data/patterns/Latn.common-error.in:90 data/patterns/Latn.common-error.in:99 msgid "Replace letter \"O\" with a zero in a number" msgstr "Заменить букву \"O\" в числах на ноль" #: data/patterns/Latn.common-error.in:117 msgid "Double apostrophe" msgstr "Двойные апострофы" #: data/patterns/Latn.common-error.in:118 msgid "Replace a double apostrophe with a quotation mark" msgstr "Заменять двойные апострофы на кавычки" #: data/patterns/Latn.common-error.in:126 #: data/patterns/Latn.common-error.in:135 #: data/patterns/Latn.common-error.in:144 #: data/patterns/Latn.common-error.in:153 msgid "Spaces around brackets" msgstr "Пробелы вокруг скобок" #: data/patterns/Latn.common-error.in:127 #: data/patterns/Latn.common-error.in:136 #: data/patterns/Latn.common-error.in:145 #: data/patterns/Latn.common-error.in:154 msgid "Add or remove spaces around parantheses and square brackets" msgstr "Добавление и удаление пробелов вокруг скобок" #: data/patterns/Latn.common-error.in:162 msgid "Space after a dialogue dash" msgstr "Пробел после тире" #: data/patterns/Latn.common-error.in:163 msgid "Add space after a dialogue dash" msgstr "Добавить пробел после тире в диалоге" #: data/patterns/Latn.common-error.in:172 msgid "Remove space before various punctuation marks" msgstr "Удалять пробел перед знаками препинания" #: data/patterns/Latn.common-error.in:192 msgid "Space after an ellipsis" msgstr "Пробел после многоточия" #: data/patterns/Latn.common-error.in:193 msgid "Add space after an ellipsis" msgstr "Добавлять пробел после многоточия" #: data/patterns/Latn.common-error.in:201 msgid "Space after a starting ellipsis" msgstr "Пробел после начального многоточия" #: data/patterns/Latn.common-error.in:202 msgid "Remove space after an ellipsis that starts a line" msgstr "Удалять пробелы перед многоточием в начале строки" #: data/patterns/Latn.common-error.in:210 #: data/patterns/Latn.common-error.in:221 #: data/patterns/Latn.common-error.in:232 #: data/patterns/Latn.common-error.in:242 msgid "Spaces around a quotation mark" msgstr "Пробелы вокруг кавычек" #: data/patterns/Latn.common-error.in:211 #: data/patterns/Latn.common-error.in:222 #: data/patterns/Latn.common-error.in:233 #: data/patterns/Latn.common-error.in:243 msgid "Remove space after a starting- and before an ending quotation mark" msgstr "Удаляет пробелы внутри кавычек" #: data/patterns/Latn.common-error.in:252 #: data/patterns/Latn.common-error.in:261 msgid "Spaces around musical notes" msgstr "Пробелы вокруг нот" #: data/patterns/Latn.common-error.in:253 #: data/patterns/Latn.common-error.in:262 msgid "Add spaces between musical note characters and lyrics" msgstr "Добавить пробелы между значками нот и словами песни" #: data/patterns/Latn.common-error.in:270 #: data/patterns/Latn.common-error.in:279 msgid "Multiple question- and exclamation marks" msgstr "Несколько вопросительных и восклицательных знаков" #: data/patterns/Latn.common-error.in:271 #: data/patterns/Latn.common-error.in:280 msgid "" "Replace multiple consequtive question- and exclamation marks with only one" msgstr "Заменить несколько вопросительных и восклицательных знаков одним" #: data/patterns/Latn.common-error.in:288 #: data/patterns/Latn.common-error.in:298 msgid "Periods around a punctuation mark" msgstr "Пробелы вокруг знаков препинания" #: data/patterns/Latn.common-error.in:289 #: data/patterns/Latn.common-error.in:299 msgid "Remove period before or after various punctuation marks" msgstr "Удалить точку возле других знаков препинания" #: data/patterns/Latn.common-error.in:308 msgid "Terminating double-dashes" msgstr "Два дефиса на конце" #: data/patterns/Latn.common-error.in:309 msgid "Replace a single clause-terminating dash with two dashes" msgstr "Замена завершающего предложение дефиса на два" #: data/patterns/Latn.hearing-impaired.in:5 msgid "Sound in brackets" msgstr "Звуки в квадратных скобках" #: data/patterns/Latn.hearing-impaired.in:6 msgid "Remove description of a sound between square brackets" msgstr "Удалить описания звуков в квадратных скобках" #: data/patterns/Latn.hearing-impaired.in:12 msgid "Sound in parantheses" msgstr "Звуки в скобках" #: data/patterns/Latn.hearing-impaired.in:13 msgid "Remove description of a sound between parantheses" msgstr "Удалить описание звуков в скобках" #: data/patterns/Latn.hearing-impaired.in:19 msgid "Song lyrics between number signs" msgstr "Слова песен между #" #: data/patterns/Latn.hearing-impaired.in:20 msgid "Remove song lyrics starting with or between number signs" msgstr "Удаление слов песен между знаками #" #: data/patterns/Latn.hearing-impaired.in:27 msgid "One-line song lyrics between number signs" msgstr "Одиночные строки песен между знаками #" #: data/patterns/Latn.hearing-impaired.in:28 msgid "Remove one-line song lyrics starting with or between number signs" msgstr "Удалить строки песен между знаками #" #: data/patterns/Latn.hearing-impaired.in:35 msgid "Speaker before a colon" msgstr "Имена говорящих" #: data/patterns/Latn.hearing-impaired.in:36 msgid "Replace the name of the speaker before a colon with a dialogue dash" msgstr "Заменить имя говорящего в начале текста перед двоеточием на тире" #: data/patterns/Latn.line-break.in:5 data/patterns/Latn.line-break.in:13 msgid "Dialogue" msgstr "Диалог" #: data/patterns/Latn.line-break.in:6 data/patterns/Latn.line-break.in:14 msgid "Break according to dialogue separated by dashes" msgstr "Разделение по строкам диалога, начинающимся с тире" #: data/patterns/Latn.line-break.in:21 data/patterns/Latn.line-break.in:30 msgid "Clause" msgstr "Предложение" #: data/patterns/Latn.line-break.in:22 data/patterns/Latn.line-break.in:31 msgid "Break according to clauses terminated by a punctuation mark" msgstr "Переносить по знакам препинания" #: data/patterns/Latn.line-break.in:38 msgid "Number and unit" msgstr "Число и единицы" #: data/patterns/Latn.line-break.in:39 msgid "Do not break between a number and associated unit" msgstr "Не разрывать число и единицы измерения" #: data/patterns/Zyyy.common-error.in:5 data/patterns/Zyyy.common-error.in:14 msgid "Leading and trailing spaces" msgstr "Начальные и конечные пробелы" #: data/patterns/Zyyy.common-error.in:6 data/patterns/Zyyy.common-error.in:15 msgid "Remove spaces from the beginning and end of lines" msgstr "Удалить пробелы в начале и конце строк" #: data/patterns/Zyyy.common-error.in:23 msgid "Multiple consecutive spaces" msgstr "Несколько пробелов подряд" #: data/patterns/Zyyy.common-error.in:24 msgid "Replace multiple consecutive spaces with only one" msgstr "Заменить последовательные пробелы одним" #: data/patterns/Zyyy.common-error.in:32 data/patterns/Zyyy.common-error.in:45 #: data/patterns/Zyyy.common-error.in:55 data/patterns/Zyyy.common-error.in:65 msgid "Space between digits" msgstr "Пробел между цифрами" #: data/patterns/Zyyy.common-error.in:33 data/patterns/Zyyy.common-error.in:46 #: data/patterns/Zyyy.common-error.in:56 data/patterns/Zyyy.common-error.in:66 msgid "Remove space between digits of a number" msgstr "Удаляет пробелы между цифрами числа" #: data/patterns/Zyyy.common-error.in:79 msgid "Musical notes" msgstr "Знаки нот" #: data/patterns/Zyyy.common-error.in:80 msgid "Replace Unicode musical note characters with number signs" msgstr "Заменить значки нот символом #" #: data/io.otsaloma.gaupol.appdata.xml.in:7 msgid "Editor for text-based subtitles" msgstr "Редактор текстовых субтитров" #: data/io.otsaloma.gaupol.appdata.xml.in:9 msgid "" "Gaupol is an editor for text-based subtitle files. It supports multiple " "subtitle file formats and provides means of creating subtitles, editing " "texts and timing subtitles to match video." msgstr "" "Gaupol - редактор для текстовых субтитров. Он поддерживает множество " "форматов файлов субтитров и предоставляет средства для их создания, " "редактирования и синхронизации с видео." #: data/io.otsaloma.gaupol.appdata.xml.in:40 msgid "Main window" msgstr "Главное окно" #: data/io.otsaloma.gaupol.desktop.in:5 msgid "Subtitle Editor" msgstr "Редактор субтитров" #: data/io.otsaloma.gaupol.desktop.in:6 msgid "Edit subtitle files" msgstr "Редактирование файлов субтитров" #. TRANSLATORS: Search terms to find this application. Do NOT translate or #. localize the semicolons! The list MUST also end with a semicolon! #: data/io.otsaloma.gaupol.desktop.in:12 msgid "video;subtitles;captions;" msgstr "видео;фильм;субтитры;" gaupol-1.11/po/sr.po000066400000000000000000002411031422217132500143250ustar00rootroot00000000000000# 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. # # Translators: # Osmo Salomaa , 2016 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-04-03 04:00+0300\n" "PO-Revision-Date: 2016-07-07 00:55+0000\n" "Last-Translator: Osmo Salomaa , 2016\n" "Language-Team: Serbian (https://www.transifex.com/otsaloma/teams/64879/sr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sr\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" #: aeidon/enums.py:40 gaupol/enums.py:38 msgid "Subtitle number" msgstr "Број титла" #: aeidon/enums.py:43 msgid "Subtitle position" msgstr "Положај титла" #: aeidon/enums.py:59 msgid "23.976 fps" msgstr "23.976 к/с" #: aeidon/enums.py:63 msgid "24.000 fps" msgstr "24.000 к/с" #: aeidon/enums.py:67 msgid "25.000 fps" msgstr "25.000 к/с" #: aeidon/enums.py:71 msgid "29.970 fps" msgstr "29.970 к/с" #: aeidon/enums.py:75 data/ui/menubar.ui:248 msgid "30.000 fps" msgstr "" #: aeidon/enums.py:79 data/ui/menubar.ui:253 msgid "50.000 fps" msgstr "" #: aeidon/enums.py:83 data/ui/menubar.ui:258 msgid "59.940 fps" msgstr "" #: aeidon/enums.py:87 data/ui/menubar.ui:263 msgid "60.000 fps" msgstr "" #: aeidon/enums.py:112 msgid "Mac (classic)" msgstr "Мек (класични)" #. TRANSLATORS: Most of the character encoding descriptions are copied from #. gedit, which is translated to very many languages. Check the gedit .po #. files for a reference: #. . #: aeidon/encodings.py:40 aeidon/encodings.py:43 aeidon/encodings.py:46 msgid "English" msgstr "Енглески" #: aeidon/encodings.py:41 aeidon/encodings.py:42 aeidon/encodings.py:69 msgid "Chinese traditional" msgstr "Кинески традиционални" #: aeidon/encodings.py:44 msgid "German" msgstr "" #: aeidon/encodings.py:45 aeidon/encodings.py:54 aeidon/encodings.py:59 #: aeidon/encodings.py:79 aeidon/encodings.py:105 msgid "Hebrew" msgstr "Хебрејски" #: aeidon/encodings.py:47 aeidon/encodings.py:51 aeidon/encodings.py:56 #: aeidon/encodings.py:73 aeidon/encodings.py:76 aeidon/encodings.py:98 #: aeidon/encodings.py:111 aeidon/encodings.py:122 msgid "Western" msgstr "Западни" #: aeidon/encodings.py:48 aeidon/encodings.py:61 aeidon/encodings.py:80 #: aeidon/encodings.py:103 msgid "Arabic" msgstr "Арапски" #: aeidon/encodings.py:49 aeidon/encodings.py:64 aeidon/encodings.py:66 #: aeidon/encodings.py:77 aeidon/encodings.py:104 aeidon/encodings.py:119 msgid "Greek" msgstr "Грчки" #: aeidon/encodings.py:50 aeidon/encodings.py:81 aeidon/encodings.py:101 #: aeidon/encodings.py:109 msgid "Baltic" msgstr "Балтички" #: aeidon/encodings.py:52 aeidon/encodings.py:74 aeidon/encodings.py:99 #: aeidon/encodings.py:121 msgid "Central European" msgstr "Средње-европски" #: aeidon/encodings.py:53 aeidon/encodings.py:75 aeidon/encodings.py:102 #: aeidon/encodings.py:118 msgid "Cyrillic" msgstr "Ћирилични" #: aeidon/encodings.py:55 aeidon/encodings.py:71 aeidon/encodings.py:78 #: aeidon/encodings.py:106 aeidon/encodings.py:123 msgid "Turkish" msgstr "Турски" #: aeidon/encodings.py:57 msgid "Portuguese" msgstr "Португалски" #: aeidon/encodings.py:58 aeidon/encodings.py:120 msgid "Icelandic" msgstr "Исландски" #: aeidon/encodings.py:60 msgid "Canadian" msgstr "Канадски" #: aeidon/encodings.py:62 aeidon/encodings.py:107 msgid "Nordic" msgstr "Нордијски" #: aeidon/encodings.py:63 aeidon/encodings.py:114 msgid "Russian" msgstr "Руски" #: aeidon/encodings.py:65 aeidon/encodings.py:108 msgid "Thai" msgstr "Тајландски" #: aeidon/encodings.py:67 aeidon/encodings.py:83 aeidon/encodings.py:84 #: aeidon/encodings.py:85 aeidon/encodings.py:91 aeidon/encodings.py:92 #: aeidon/encodings.py:93 aeidon/encodings.py:94 aeidon/encodings.py:95 #: aeidon/encodings.py:96 aeidon/encodings.py:125 aeidon/encodings.py:126 #: aeidon/encodings.py:127 msgid "Japanese" msgstr "Јапански" #: aeidon/encodings.py:68 aeidon/encodings.py:86 aeidon/encodings.py:97 #: aeidon/encodings.py:113 msgid "Korean" msgstr "Корејски" #: aeidon/encodings.py:70 msgid "Urdu" msgstr "Урду" #: aeidon/encodings.py:72 aeidon/encodings.py:116 msgid "Ukrainian" msgstr "Украјински" #: aeidon/encodings.py:82 msgid "Vietnamese" msgstr "Вијетнамски" #: aeidon/encodings.py:87 aeidon/encodings.py:90 msgid "Chinese simplified" msgstr "Кинески поједностављени" #: aeidon/encodings.py:88 aeidon/encodings.py:89 msgid "Chinese unified" msgstr "Кинески обједињени" #: aeidon/encodings.py:100 aeidon/encodings.py:112 msgid "South European" msgstr "Јужноевропски" #: aeidon/encodings.py:110 msgid "Celtic" msgstr "Келтски" #: aeidon/encodings.py:115 msgid "Tajik" msgstr "" #: aeidon/encodings.py:117 msgid "Kazakh" msgstr "" #: aeidon/encodings.py:124 msgid "Cyrillic Asian" msgstr "Ћирилични азијски" #: aeidon/encodings.py:128 aeidon/encodings.py:129 aeidon/encodings.py:130 #: aeidon/encodings.py:131 aeidon/encodings.py:132 aeidon/encodings.py:133 #: aeidon/encodings.py:134 aeidon/encodings.py:135 aeidon/encodings.py:136 msgid "Unicode" msgstr "Уникод" #: aeidon/encodings.py:156 #, python-brace-format msgid "{description} ({name})" msgstr "{description} ({name})" #: aeidon/encodings.py:232 msgid "Current locale ({})" msgstr "Текући језик ({})" #: aeidon/locales.py:46 #, python-brace-format msgid "{language} ({country})" msgstr "{language} ({country})" #: aeidon/agents/search.py:227 msgid "Replacing" msgstr "Замењујем" #: aeidon/agents/search.py:256 aeidon/agents/search.py:258 msgid "Replacing all" msgstr "Замењујем све" #: aeidon/agents/position.py:74 msgid "Adjusting durations" msgstr "Подешавам трајања" #: aeidon/agents/position.py:96 msgid "Converting framerate" msgstr "Претварам проток кадрова" #: aeidon/agents/position.py:146 msgid "Setting framerate" msgstr "Подешавам проток кадрова" #: aeidon/agents/position.py:168 msgid "Shifting positions" msgstr "Померам положаје" #: aeidon/agents/position.py:188 msgid "Transforming positions" msgstr "Преображавам положаје" #: aeidon/agents/clipboard.py:44 msgid "Cutting texts" msgstr "Исецам текст" #: aeidon/agents/clipboard.py:61 msgid "Pasting texts" msgstr "Убацујем текст" #: aeidon/agents/text.py:91 msgid "Breaking lines" msgstr "Преламам редове" #: aeidon/agents/text.py:128 msgid "Capitalizing texts" msgstr "Пребацујем текстове у велика слова" #: aeidon/agents/text.py:185 msgid "Correcting common errors" msgstr "Исправљам уобичајене грешке" #: aeidon/agents/text.py:234 msgid "Removing hearing impaired texts" msgstr "Уклањам текстове за особе слабог слуха" #: aeidon/agents/text.py:315 msgid "Joining words by spell-check suggestions" msgstr "Додајем речи према предлозима провере правописа" #: aeidon/agents/text.py:354 msgid "Splitting words by spell-check suggestions" msgstr "Делим речи према предлозима провере правописа" #: aeidon/agents/set.py:58 aeidon/agents/set.py:80 aeidon/agents/set.py:113 msgid "Editing position" msgstr "Уређујем положаје" #: aeidon/agents/set.py:129 msgid "Editing text" msgstr "Уређујем текст" #: aeidon/agents/edit.py:35 msgid "Clearing texts" msgstr "Бришем текст" #: aeidon/agents/edit.py:61 aeidon/agents/edit.py:83 msgid "Inserting subtitles" msgstr "Убацујем титлове" #: aeidon/agents/edit.py:103 msgid "Merging subtitles" msgstr "Стапам титлове" #: aeidon/agents/edit.py:114 msgid "Removing subtitles" msgstr "Уклањам титлове" #: aeidon/agents/edit.py:131 msgid "Replacing positions" msgstr "Замењујем положаје" #: aeidon/agents/edit.py:147 msgid "Replacing texts" msgstr "Замењујем текстове" #: aeidon/agents/edit.py:171 msgid "Splitting subtitle" msgstr "Делим титл" #: aeidon/agents/format.py:49 msgid "Adding dialogue dashes" msgstr "Додавајем цртице разговора" #: aeidon/agents/format.py:68 msgid "Changing case" msgstr "Мењам величину слова" #: aeidon/agents/format.py:92 msgid "Italicizing" msgstr "Искошавам" #: aeidon/agents/format.py:108 msgid "Removing dialogue dashes" msgstr "Уклањам цртице разговора" #: aeidon/agents/format.py:174 msgid "Unitalicizing" msgstr "Поништавам искошавање" #: gaupol/application.py:219 gaupol/agents/open.py:203 msgid "Open" msgstr "Отворите" #: gaupol/application.py:223 msgid "Open main files" msgstr "Отворите изворне датотеке" #: gaupol/application.py:230 msgid "Save" msgstr "" #: gaupol/application.py:233 msgid "Save the current main document" msgstr "Сачувајте текућу изворну датотеку" #: gaupol/application.py:238 msgid "Undo" msgstr "" #: gaupol/application.py:242 msgid "Undo the last action" msgstr "Опозовите последњу радњу" #: gaupol/application.py:249 msgid "Redo" msgstr "" #: gaupol/application.py:252 msgid "Redo the last undone action" msgstr "Поновите последњу поништену радњу" #: gaupol/application.py:260 msgid "Insert" msgstr "Уметни" #: gaupol/application.py:262 msgid "Insert new subtitles" msgstr "Уметните нове титлове" #: gaupol/application.py:266 #: data/extensions/custom-framerates/preferences-dialog.ui:78 msgid "Remove" msgstr "Уклони" #: gaupol/application.py:268 msgid "Remove the selected subtitles" msgstr "Уклоните изабране титлове" #: gaupol/application.py:273 data/ui/search-dialog.ui:283 msgid "Find" msgstr "Нађи" #: gaupol/application.py:275 msgid "Search for and replace text" msgstr "Потражите и замените текст" #: gaupol/application.py:279 data/ui/preferences-dialog.ui:942 msgid "Video" msgstr "Филм" #: gaupol/application.py:281 msgid "Show or hide the video player" msgstr "Прикажите или сакријте програм за пуштање филмова" #: gaupol/application.py:285 data/ui/preferences-dialog.ui:1173 msgid "Preview" msgstr "Преглед" #: gaupol/application.py:287 msgid "Preview from selected position with a video player" msgstr "Пустите преглед од изабраног положаја у програму за филмове" #: gaupol/enums.py:37 msgid "No." msgstr "Бр." #: gaupol/enums.py:43 msgid "Start" msgstr "Почетак" #: gaupol/enums.py:44 msgid "Start position" msgstr "Почетни положај" #: gaupol/enums.py:49 msgid "End" msgstr "Крај" #: gaupol/enums.py:50 msgid "End position" msgstr "Крајњи положај" #. TRANSLATORS: 'Dur.' is short for duration. It is used in the header #. of a column that contains numbers five digits wide. #: gaupol/enums.py:57 msgid "Dur." msgstr "Трајање" #: gaupol/enums.py:58 msgid "Duration" msgstr "Трајање" #: gaupol/enums.py:63 gaupol/enums.py:64 msgid "Text" msgstr "Текст" #: gaupol/enums.py:69 gaupol/enums.py:70 msgid "Translation" msgstr "Превод" #: gaupol/enums.py:82 msgid "characters" msgstr "знакова" #: gaupol/enums.py:85 msgid "ems" msgstr "ems" #: gaupol/page.py:60 msgid "Untitled {:d}" msgstr "Безимени „{:d}“" #: gaupol/page.py:133 msgid "Close project" msgstr "Затворите пројекат" #: gaupol/page.py:145 msgid "{} translation" msgstr "{} превод" #: gaupol/page.py:302 msgid "Path:" msgstr "Путања:" #: gaupol/page.py:303 msgid "Format:" msgstr "Запис:" #: gaupol/page.py:304 msgid "Encoding:" msgstr "Кодирање:" #: gaupol/page.py:305 msgid "Newlines:" msgstr "Нови редови:" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:99 msgid "Tasks and Target" msgstr "Задаци и одредиште" #: gaupol/assistants.py:128 msgid "Correct texts in the text column" msgstr "Исправи текстове у ступцу текста" #: gaupol/assistants.py:129 msgid "Correct texts in the translation column" msgstr "Исправи текстове у ступцу превода" #: gaupol/assistants.py:138 msgid "Correct texts in selected subtitles" msgstr "Исправи текстове у изабраним титловима" #: gaupol/assistants.py:139 msgid "Correct texts in current project" msgstr "Исправи текстове у текућем пројекту" #: gaupol/assistants.py:140 msgid "Correct texts in all open projects" msgstr "Исправи текстове у свим отвореним пројектима" #: gaupol/assistants.py:363 msgid "Other" msgstr "Остало" #: gaupol/assistants.py:439 msgid "Capitalize texts written in lower case" msgstr "Пребаците текстове из малих у велика слова" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:443 msgid "Capitalization Patterns" msgstr "Обрасци великих слова" #: gaupol/assistants.py:445 msgid "Capitalize texts" msgstr "Текстови у велика слова" #: gaupol/assistants.py:468 msgid "Correct common errors made by humans or image recognition software" msgstr "Исправите уобичајене људске или грешке софтвера за препознавања слика" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:472 msgid "Common Error Patterns" msgstr "Обрасци општих грешака" #: gaupol/assistants.py:474 msgid "Correct common errors" msgstr "Исправи уобичајене грешке" #: gaupol/assistants.py:526 msgid "Remove explanatory texts meant for the hearing impaired" msgstr "Уклоните текстове објашњења намењене особама слабог слуха" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:530 msgid "Hearing Impaired Patterns" msgstr "Обрасци за оштећења слуха" #: gaupol/assistants.py:532 msgid "Remove hearing impaired texts" msgstr "Уклони текстове за особе слабог слуха" #: gaupol/assistants.py:544 msgid "" "Use spell-check suggestions to fix whitespace detection errors of image " "recognition software" msgstr "" "Користите предлоге провере писања да исправите грешке откривања празнина " "софтвера за препознавање слика" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:548 msgid "Joining and Splitting Words" msgstr "Спајање и дељење речи" #: gaupol/assistants.py:550 msgid "Join or Split Words" msgstr "Споји или подели речи" #: gaupol/assistants.py:599 gaupol/agents/tools.py:45 msgid "Failed to load dictionary for language \"{}\"" msgstr "Нисам успео да учитам речник за „{}“ језик" #: gaupol/assistants.py:601 gaupol/player.py:263 gaupol/player.py:381 #: gaupol/dialogs/search.py:560 gaupol/dialogs/search.py:568 #: gaupol/dialogs/text_edit.py:49 gaupol/dialogs/encoding.py:56 #: gaupol/agents/open.py:328 gaupol/agents/open.py:337 #: gaupol/agents/open.py:345 gaupol/agents/open.py:354 #: gaupol/agents/tools.py:48 gaupol/agents/save.py:197 #: gaupol/agents/save.py:205 gaupol/agents/preview.py:108 #: gaupol/agents/preview.py:116 gaupol/agents/preview.py:125 #: gaupol/agents/preview.py:133 msgid "_OK" msgstr "У _реду" #: gaupol/assistants.py:635 msgid "Break text into lines of defined length" msgstr "Преломи текст у редове одређене дужине" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:639 msgid "Line-Break Patterns" msgstr "Обрасци прелома реда" #: gaupol/assistants.py:641 msgid "Break lines" msgstr "Преломи редове" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:679 msgid "Line-Break Options" msgstr "Опције прелома реда" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:763 msgid "Correcting Texts" msgstr "Исправка текстова" #: gaupol/assistants.py:769 msgid "Each task is now being run on each project." msgstr "Сваки задатак се сада извршава у сваком пројекту." #: gaupol/assistants.py:793 #, python-brace-format msgid "{current:d} of {total:d} tasks complete" msgstr "Обављен је {current:d}. од {total:d} задатка" #: gaupol/assistants.py:801 msgid "Project: {}" msgstr "Пројекат: {}" #: gaupol/assistants.py:807 msgid "Task: {}" msgstr "Задатак: {}" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:832 msgid "Confirm Changes" msgstr "Потврда измена" #: gaupol/assistants.py:892 msgid "Accept" msgstr "Прихвати" #: gaupol/assistants.py:898 msgid "Original Text" msgstr "Изворни текст" #: gaupol/assistants.py:899 msgid "Corrected Text" msgstr "Исправљени текст" #: gaupol/assistants.py:1048 msgid "Correct Texts" msgstr "Исправи текстове" #: gaupol/assistants.py:1076 msgid "Correcting texts" msgstr "Исправљам текстове" #: gaupol/assistants.py:1092 #, python-brace-format msgid "Edited {edits:d} and removed {removals:d} subtitles" msgstr "Уредих {edits:d} и уклоних {removals:d} титла" #: gaupol/assistants.py:1126 msgid "Confirm {:d} Change" msgid_plural "Confirm {:d} Changes" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: gaupol/renderers/multiline.py:86 msgid "Italic" msgstr "" #: gaupol/player.py:372 msgid "No video streams found" msgstr "" #: gaupol/player.py:379 msgid "Failed to initialize playback" msgstr "" #: gaupol/dialogs/search.py:189 data/ui/menubar.ui:524 msgid "_Help" msgstr "По_моћ" #: gaupol/dialogs/search.py:471 msgid "Found and replaced {:d} occurence" msgid_plural "Found and replaced {:d} occurences" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: gaupol/dialogs/search.py:488 msgid "\"{}\" not found" msgstr "Нисам нашао „{}“" #: gaupol/dialogs/search.py:558 msgid "Error in regular expression pattern" msgstr "Грешка у обрасцу регуларног израза" #: gaupol/dialogs/search.py:566 msgid "Error in regular expression replacement" msgstr "Грешка у замени регуларног израза" #: gaupol/dialogs/text_edit.py:48 gaupol/dialogs/framerate_convert.py:63 #: gaupol/dialogs/insert.py:44 gaupol/dialogs/encoding.py:55 #: gaupol/dialogs/split.py:44 gaupol/dialogs/multi_close.py:54 #: gaupol/dialogs/open.py:63 gaupol/dialogs/position_transform.py:69 #: gaupol/dialogs/position_shift.py:71 gaupol/dialogs/multi_save.py:83 #: gaupol/dialogs/multi_save.py:215 gaupol/dialogs/duration_adjust.py:86 #: gaupol/dialogs/save.py:73 gaupol/dialogs/video.py:41 #: gaupol/agents/open.py:363 gaupol/agents/open.py:375 #: gaupol/agents/open.py:387 gaupol/agents/close.py:71 #: data/extensions/custom-framerates/custom-framerates.py:39 msgid "_Cancel" msgstr "_Откажи" #: gaupol/dialogs/text_edit.py:53 msgid "Edit Text" msgstr "Уредите текст" #: gaupol/dialogs/framerate_convert.py:64 msgid "Co_nvert" msgstr "_Претвори" #: gaupol/dialogs/insert.py:45 msgid "_Insert" msgstr "_Уметни" #: gaupol/dialogs/insert.py:54 msgid "Above selection" msgstr "Изнад изабраног" #: gaupol/dialogs/insert.py:55 msgid "Below selection" msgstr "Испод изабраног" #: gaupol/dialogs/encoding.py:60 data/ui/preferences-dialog.ui:70 msgid "Character Encodings" msgstr "Кодирања знакова" #: gaupol/dialogs/encoding.py:78 gaupol/dialogs/encoding.py:125 msgid "Description" msgstr "Опис" #: gaupol/dialogs/encoding.py:85 gaupol/dialogs/encoding.py:132 msgid "Encoding" msgstr "Кодирање" #: gaupol/dialogs/encoding.py:141 msgid "Show in Menu" msgstr "Прикажи у изборнику" #: gaupol/dialogs/split.py:45 msgid "_Split" msgstr "_Подели" #: gaupol/dialogs/split.py:76 msgid "Splitting project" msgstr "Делим пројекат" #: gaupol/dialogs/split.py:97 #, python-brace-format msgid "Split {amount:d} subtitles to project \"{name}\"" msgstr "Подели {amount:d} титла у пројекат „{name}“" #: gaupol/dialogs/spell_check.py:269 msgid "Spell-checking" msgstr "Провера писања" #: gaupol/dialogs/preferences.py:217 msgid "{} Extension Website" msgstr "Веб страница „{}“ проширења" #: gaupol/dialogs/preferences.py:429 msgid "Custom" msgstr "Произвољно" #: gaupol/dialogs/multi_close.py:38 msgid "Save changes to documents before closing?" msgstr "Да сачувам измене у датотеци пре затварања?" #: gaupol/dialogs/multi_close.py:39 gaupol/agents/open.py:384 #: gaupol/agents/close.py:68 msgid "If you don't save, changes will be permanently lost." msgstr "Ако не сачувате, измене ће бити трајно изгубљене." #: gaupol/dialogs/multi_close.py:53 gaupol/agents/close.py:70 msgid "Close _Without Saving" msgstr "Затвори _без чувања" #: gaupol/dialogs/multi_close.py:55 gaupol/dialogs/multi_save.py:84 #: gaupol/dialogs/save.py:74 gaupol/agents/open.py:388 #: gaupol/agents/close.py:72 data/ui/menubar.ui:34 msgid "_Save" msgstr "_Сачувај" #: gaupol/dialogs/multi_close.py:70 msgid "Select the _main documents you want to save:" msgstr "Изаберите _изворну датотеку коју желите да сачувате:" #: gaupol/dialogs/multi_close.py:95 msgid "Select the _translation documents you want to save:" msgstr "Изаберите _преведену датотеку коју желите да сачувате:" #: gaupol/dialogs/open.py:64 gaupol/agents/open.py:364 #: gaupol/agents/open.py:376 msgid "_Open" msgstr "_Отвори" #: gaupol/dialogs/position_transform.py:70 msgid "_Transform" msgstr "_Преобрати" #: gaupol/dialogs/position_shift.py:72 msgid "_Shift" msgstr "_Премакни" #: gaupol/dialogs/position_shift.py:150 msgid "frames" msgstr "кадрова" #: gaupol/dialogs/position_shift.py:168 data/ui/preferences-dialog.ui:911 msgid "seconds" msgstr "секунде" #: gaupol/dialogs/about.py:36 msgid "About Gaupol" msgstr "О Гауполу" #: gaupol/dialogs/about.py:40 msgid "Subtitle editor" msgstr "Уређивач титлова" #. TRANSLATORS: This is a special message that shouldn't be translated #. literally. It is used in the about dialog to give credits to the #. translators. Thus, you should translate it to your name and email #. address. You can also include other translators who have contributed #. to this translation; in that case, please write them on separate #. lines seperated by newlines (\n). #: gaupol/dialogs/about.py:51 msgid "translator-credits" msgstr "" " Мирослав Николић \n" " http://prevod.org" #: gaupol/dialogs/about.py:54 msgid "Gaupol Website" msgstr "Веб страница Гаупола" #: gaupol/dialogs/append.py:35 msgid "Append File" msgstr "Прикачите датотеку" #: gaupol/dialogs/debug.py:43 msgid "Something went wrong" msgstr "Нешто је пошло наопако" #: gaupol/dialogs/debug.py:44 msgid "" "You have probably discovered a bug. Please report it by providing the below " "information and a description of what you were doing." msgstr "" #: gaupol/dialogs/debug.py:52 msgid "_Report Bug" msgstr "" #: gaupol/dialogs/debug.py:53 data/ui/menubar.ui:56 msgid "_Quit" msgstr "_Изађи" #: gaupol/dialogs/debug.py:54 gaupol/dialogs/preview_error.py:45 #: data/ui/menubar.ui:52 data/ui/tab-popup.ui:16 msgid "_Close" msgstr "_Затвори" #: gaupol/dialogs/multi_save.py:98 gaupol/dialogs/save.py:110 msgid "{} (recommended)" msgstr "" #: gaupol/dialogs/multi_save.py:212 msgid "" "{:d} of the files to be saved already exist. Do you want to replace them?" msgstr "" "Ове датотеке за чување (укупно {:d}) већ постоје. Да ли желите да их " "замените?" #: gaupol/dialogs/multi_save.py:213 msgid "" "The files already exist in \"{}\". Replacing them will overwrite their " "contents." msgstr "" "Већ постоје датотеке у „{}“. Ако их замените преписаћете њихов садржај." #: gaupol/dialogs/multi_save.py:216 data/ui/search-dialog.ui:192 #: data/ui/spell-check-dialog.ui:122 msgid "_Replace" msgstr "_Замени" #: gaupol/dialogs/duration_adjust.py:70 msgid "Adjusted duration of {:d} subtitle" msgid_plural "Adjusted durations of {:d} subtitles" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: gaupol/dialogs/duration_adjust.py:87 msgid "_Adjust" msgstr "_Дотерај" #: gaupol/dialogs/preview_error.py:36 msgid "Preview in video player failed" msgstr "Преглед у програму за филмове није успео" #: gaupol/dialogs/preview_error.py:37 msgid "" "There is probably a problem with either the video file or the video player. " "See the preferences dialog to choose the video player or to customize the " "command." msgstr "" #: gaupol/dialogs/language.py:97 msgid "Set Language" msgstr "Подесите језик" #: gaupol/dialogs/video.py:52 gaupol/dialogs/file.py:59 msgid "All files" msgstr "Све датотеке" #: gaupol/dialogs/video.py:56 msgid "Video files" msgstr "Датотеке филмова" #: gaupol/dialogs/file.py:63 msgid "All supported files" msgstr "Све подржане датотеке" #: gaupol/dialogs/file.py:77 #, python-brace-format msgid "{format} (*{extension})" msgstr "{format} (*{extension})" #: gaupol/dialogs/file.py:120 msgid "Auto-detected" msgstr "Сам одреди" #: gaupol/dialogs/file.py:122 msgid "Other…" msgstr "Друго…" #: gaupol/agents/menu.py:94 gaupol/agents/menu.py:103 #: gaupol/agents/menu.py:110 msgid "File not found" msgstr "" #: gaupol/agents/open.py:85 #, python-brace-format msgid "Appended {amount:d} subtitles from \"{basename}\"" msgstr "Придодао сам {amount:d} титла из „{basename}“" #: gaupol/agents/open.py:96 msgid "Appending file" msgstr "Додајем датотеку" #: gaupol/agents/open.py:111 msgid "File \"{}\" is already open" msgstr "Већ је отворена датотека „{}“" #: gaupol/agents/open.py:214 msgid "Open Translation" msgstr "Отворите превод" #: gaupol/agents/open.py:223 msgid "Select Video" msgstr "Изаберите филм" #: gaupol/agents/open.py:224 msgid "_Select" msgstr "_Изабери" #: gaupol/agents/open.py:325 msgid "Failed to decode file \"{}\" with all attempted codecs" msgstr "" "Нисам успео да декодирам датотеку „{}“ ни са једним од испробаних кодека" #: gaupol/agents/open.py:326 msgid "Please try to open the file with a different character encoding." msgstr "Пробајте да отворите датотеку другим кодирањем знакова." #: gaupol/agents/open.py:334 msgid "Failed to recognize format of file \"{}\"" msgstr "Нисам успео да препознам запис датотеке „{}“" #: gaupol/agents/open.py:335 msgid "" "Please check that the file you are trying to open is a subtitle file of a " "format supported by Gaupol." msgstr "" "Проверите да ли је датотека коју покушавате да отворите у одговарајућем " "запису који Гаупол подржава." #: gaupol/agents/open.py:343 msgid "Failed to open file \"{}\"" msgstr "Нисам успео да отворим датотеку „{}“" #: gaupol/agents/open.py:351 msgid "Failed to parse file \"{}\"" msgstr "Нисам успео да обрадим датотеку „{}“" #: gaupol/agents/open.py:352 msgid "Please check that the file you are trying to open is a valid {} file." msgstr "" "Проверите да ли је датотека коју покушавате да отворите исправна „{}“ " "датотека." #: gaupol/agents/open.py:360 msgid "Open abnormally large file \"{}\"?" msgstr "Да отворим ненормално велику датотеку „{}“?" #: gaupol/agents/open.py:361 msgid "" "Size of the file is {:.1f} MB, which is abnormally large for a text-based " "subtitle file. Please, check that you are not trying to open a binary file." msgstr "" "Величина датотеке је {:.1f} MB, што је ненормална величина за текстуалне " "датотеке титлова. Проверите да не покушавате да отворите извршну датотеку." #: gaupol/agents/open.py:371 msgid "Open unsorted file \"{}\"?" msgstr "Да отворим недотерану датотеку „{}“?" #: gaupol/agents/open.py:372 msgid "" "The order of {:d} subtitles needs to be changed. If {:d} sounds like a lot, " "the file may be erroneously composed." msgstr "" "Редослед {:d} титла треба да се измени. Ако {:d} звучи као много, датотека " "може бити погрешно састављена." #: gaupol/agents/open.py:383 msgid "Save changes to translation document \"{}\" before opening a new one?" msgstr "Да сачувам измене у датотеци превода „{}“ пре отварања још једне?" #: gaupol/agents/open.py:386 msgid "Open _Without Saving" msgstr "Отвори _без чувања" #: gaupol/agents/close.py:66 msgid "Save changes to document \"{}\" before closing?" msgstr "" #: gaupol/agents/edit.py:101 gaupol/agents/edit.py:119 msgid "Stretching end position" msgstr "Развлачим крајњи положај" #: gaupol/agents/edit.py:208 msgid "Inserted {:d} subtitle to fit clipboard contents" msgid_plural "Inserted {:d} subtitles to fit clipboard contents" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: gaupol/agents/edit.py:334 gaupol/agents/edit.py:352 msgid "Stretching start position" msgstr "Развлачим почетни положај" #: gaupol/agents/edit.py:411 msgid "Use Shift+Return for line-break" msgstr "Користите „помак+унеси“ за преламање редова" #: gaupol/agents/save.py:129 msgid "Save As" msgstr "Сачувајте као" #: gaupol/agents/save.py:135 msgid "Saved main document as \"{}\"" msgstr "Сачувах изворну датотеку као „{}“" #: gaupol/agents/save.py:153 msgid "Save Translation As" msgstr "Сачувајте превод као" #: gaupol/agents/save.py:159 msgid "Saved translation document as \"{}\"" msgstr "Сачувах датотеку превода као „{}“" #: gaupol/agents/save.py:194 #, python-brace-format msgid "Failed to encode file \"{basename}\" with codec \"{codec}\"" msgstr "Нисам успео да кодирам датотеку „{basename}“ кодеком „{codec}“" #: gaupol/agents/save.py:195 msgid "Please try to save the file with a different character encoding." msgstr "Пробајте да сачувате датотеку у другом кодирању знакова." #: gaupol/agents/save.py:203 msgid "Failed to save file \"{}\"" msgstr "Нисам успео да сачувам датотеку „{}“" #: gaupol/agents/video.py:67 data/ui/menubar.ui:380 msgid "_Play/Pause" msgstr "_Пусти/застани" #: gaupol/agents/video.py:69 msgid "Play or pause video" msgstr "Пустите или паузирајте филм" #: gaupol/agents/video.py:75 data/ui/menubar.ui:390 msgid "Seek _Previous" msgstr "Пређи на _претходно" #: gaupol/agents/video.py:77 msgid "Seek to the start of the previous subtitle" msgstr "Пређите на почетак претходног титла" #: gaupol/agents/video.py:81 data/ui/menubar.ui:394 msgid "Seek _Next" msgstr "Пређи на _следеће" #: gaupol/agents/video.py:83 msgid "Seek to the start of the next subtitle" msgstr "Пређите на почетак следећег титла" #: gaupol/agents/video.py:88 data/ui/menubar.ui:400 msgid "Seek _Backward" msgstr "Премотај уна_зад" #: gaupol/agents/video.py:90 msgid "Seek backward" msgstr "Премотајте уназад" #: gaupol/agents/video.py:94 data/ui/menubar.ui:404 msgid "Seek _Forward" msgstr "Премотај уна_пред" #: gaupol/agents/video.py:96 msgid "Seek forward" msgstr "Премотајте унапред" #: gaupol/agents/video.py:109 msgid "Volume" msgstr "Јачина звука" #: gaupol/agents/video.py:189 msgid "Load Video" msgstr "Учитајте филм" #: gaupol/agents/video.py:189 msgid "_Load" msgstr "_Учитај" #: gaupol/agents/video.py:361 msgid "Track {:d}" msgstr "" #: gaupol/agents/preview.py:105 msgid "Failed to encode subtitle file to temporary directory \"{}\"" msgstr "Нисам успео да кодирам датотеку титла у привременој датотеци „{}“" #: gaupol/agents/preview.py:106 msgid "" "Subtitle data could not be encoded to a temporary file for preview with the " "current character encoding. Please first save the subtitle file with a " "different character encoding." msgstr "" "Подаци титла не могу бити кодирани у привременој датотеци за преглед са " "текућим кодирањем знакова. Као прво сачувајте датотеку титла у другом " "кодирању знакова." #: gaupol/agents/preview.py:114 msgid "Failed to save subtitle file to temporary directory \"{}\"" msgstr "Нисам успео да сачувам датотеку титла у привременој датотеци „{}“" #: gaupol/agents/preview.py:122 msgid "Video player not found" msgstr "" #: gaupol/agents/preview.py:123 msgid "" "Please install one of the supported video players: mpv (recommended), " "MPlayer or VLC. See the preferences dialog to choose the video player or to " "customize the command." msgstr "" #: gaupol/agents/preview.py:131 msgid "Failed to launch video player" msgstr "Нисам успео да покренем програм за пуштање филмова" #: gaupol/applicationman.py:105 msgid "gaupol [OPTION...] [FILE...] [+[NUM]]" msgstr "gaupol [ОПЦИЈА...] [ДАТОТЕКА...] [+[БРОЈ]]" #: gaupol/applicationman.py:109 msgid "FILE..." msgstr "" #: gaupol/applicationman.py:112 msgid "subtitle files to open" msgstr "" #: gaupol/applicationman.py:122 msgid "ENCODING" msgstr "КОДНИ РАСПОРЕД" #: gaupol/applicationman.py:125 msgid "set the character encoding used to open files" msgstr "поставља кодирање знакова коришћено за отварање датотека" #: gaupol/applicationman.py:132 msgid "list all available character encodings" msgstr "исписује сва доступна кодирања знакова" #: gaupol/applicationman.py:137 gaupol/applicationman.py:154 msgid "FILE" msgstr "ДАТОТЕКА" #: gaupol/applicationman.py:140 msgid "open translation file" msgstr "отвара датотеку превода" #: gaupol/applicationman.py:145 msgid "METHOD" msgstr "НАЧИН" #: gaupol/applicationman.py:149 msgid "method used to align translation subtitles: 'number' or 'position'" msgstr "" "начин коришћен за поравнање титлова превода: „number“ (број) или „position“ " "(положај)" #: gaupol/applicationman.py:157 msgid "select video file" msgstr "бира датотеку филма" #: data/extensions/custom-framerates/custom-framerates.py:40 #: data/ui/spell-check-dialog.ui:152 msgid "_Add" msgstr "_Додај" #: data/extensions/custom-framerates/custom-framerates.py:171 msgid "{:.3f} fps" msgstr "{:.3f} к/с" #: data/extensions/custom-framerates/add-framerate-dialog.ui:13 msgid "Add Framerate" msgstr "Додај проток кадрова" #: data/extensions/custom-framerates/add-framerate-dialog.ui:44 msgid "_Framerate:" msgstr "_Проток кадрова:" #: data/extensions/custom-framerates/add-framerate-dialog.ui:73 msgid "fps" msgstr "к/с" #: data/extensions/custom-framerates/preferences-dialog.ui:8 msgid "Framerates" msgstr "Протоци кадрова" #: data/extensions/custom-framerates/preferences-dialog.ui:64 msgid "Add" msgstr "Додај" #: data/ui/columns-popup.ui:6 data/ui/menubar.ui:275 msgid "_No." msgstr "_Број" #: data/ui/columns-popup.ui:10 data/ui/menubar.ui:279 msgid "_Start" msgstr "_Почетак" #: data/ui/columns-popup.ui:14 data/ui/menubar.ui:283 msgid "_End" msgstr "_Крај" #: data/ui/columns-popup.ui:18 data/ui/menubar.ui:287 msgid "_Duration" msgstr "_Трајање" #: data/ui/columns-popup.ui:22 data/ui/menubar.ui:291 data/ui/menubar.ui:303 msgid "_Text" msgstr "_Текст" #: data/ui/columns-popup.ui:26 data/ui/menubar.ui:295 msgid "T_ranslation" msgstr "_Превод" #: data/ui/split-dialog.ui:15 msgid "Split Project" msgstr "Поделите пројекат" #: data/ui/split-dialog.ui:48 msgid "_First subtitle of new project:" msgstr "_Први титл новог пројекта:" #: data/ui/search-dialog.ui:89 msgid "_Search for:" msgstr "_Потражи:" #: data/ui/search-dialog.ui:103 data/ui/spell-check-dialog.ui:193 msgid "Replace _with:" msgstr "Замени _са:" #: data/ui/search-dialog.ui:162 data/ui/menubar.ui:328 msgid "Find _Next" msgstr "Нађи _следеће" #: data/ui/search-dialog.ui:177 msgid "Find _Previous" msgstr "Нађи _претходно" #: data/ui/search-dialog.ui:207 msgid "Replace _All" msgstr "Замени _све" #: data/ui/search-dialog.ui:241 msgid "R_egular expression" msgstr "Регуларан _израз" #: data/ui/search-dialog.ui:258 msgid "_Ignore case" msgstr "_Занемари величину слова" #: data/ui/search-dialog.ui:304 data/ui/language-dialog.ui:108 msgid "Columns" msgstr "Ступци" #: data/ui/search-dialog.ui:324 msgid "Find in _text column" msgstr "Нађи у ступцу _текста" #: data/ui/search-dialog.ui:341 msgid "Find in t_ranslation column" msgstr "Нађи у ступцу _превода" #: data/ui/search-dialog.ui:381 data/ui/framerate-convert-dialog.ui:144 #: data/ui/language-dialog.ui:186 #: data/ui/text-assistant/line-break-options-page.ui:178 #: data/ui/duration-adjust-dialog.ui:388 data/ui/position-shift-dialog.ui:180 #: data/ui/position-transform-dialog.ui:444 msgid "Subtitles" msgstr "Титлови" #: data/ui/search-dialog.ui:401 msgid "Find in c_urrent project" msgstr "Нађи у _текућем пројекту" #: data/ui/search-dialog.ui:419 msgid "Find in _all open projects" msgstr "Нађи у _свим отвореним пројектима" #: data/ui/search-dialog.ui:452 msgid "Target" msgstr "Одредиште" #: data/ui/framerate-convert-dialog.ui:8 msgid "Convert Framerate" msgstr "Претворите проток кадрова" #: data/ui/framerate-convert-dialog.ui:48 msgid "Framerate" msgstr "Проток кадрова" #: data/ui/framerate-convert-dialog.ui:71 msgid "_Input:" msgstr "_Улаз:" #: data/ui/framerate-convert-dialog.ui:86 msgid "_Output:" msgstr "_Резултат:" #: data/ui/framerate-convert-dialog.ui:164 msgid "Convert c_urrent project" msgstr "Претвори _текући пројекат" #: data/ui/framerate-convert-dialog.ui:181 msgid "Convert _all open projects" msgstr "Претвори _све отворене пројекте" #: data/ui/spell-check-dialog.ui:8 msgid "Check Spelling" msgstr "Провера писања" #: data/ui/spell-check-dialog.ui:47 msgid "Join _Back" msgstr "Придружи _позади" #: data/ui/spell-check-dialog.ui:62 msgid "Join _Forward" msgstr "Придружи _напред" #: data/ui/spell-check-dialog.ui:77 data/ui/menubar.ui:62 msgid "_Edit" msgstr "_Уређивање" #: data/ui/spell-check-dialog.ui:92 msgid "_Ignore" msgstr "_Занемари" #: data/ui/spell-check-dialog.ui:107 msgid "Ig_nore All" msgstr "Занемари _све" #: data/ui/spell-check-dialog.ui:137 msgid "Rep_lace All" msgstr "За_мени све" #: data/ui/spell-check-dialog.ui:179 msgid "_Suggestions:" msgstr "_Предлози:" #: data/ui/multi-save-dialog.ui:8 msgid "Save All As" msgstr "Сачувајте све као" #: data/ui/multi-save-dialog.ui:46 msgid "Save in _folder:" msgstr "Сачувај у _фасцикли:" #: data/ui/multi-save-dialog.ui:60 data/ui/save-dialog.ui:25 msgid "For_mat:" msgstr "_Запис:" #: data/ui/multi-save-dialog.ui:74 data/ui/open-dialog.ui:25 #: data/ui/save-dialog.ui:39 msgid "_Encoding:" msgstr "_Кодирање:" #: data/ui/multi-save-dialog.ui:88 data/ui/save-dialog.ui:53 msgid "Ne_wlines:" msgstr "Нови _редови:" #: data/ui/multi-save-dialog.ui:103 msgid "Select A Folder" msgstr "Изаберите фасциклу" #: data/ui/multi-save-dialog.ui:150 data/ui/save-dialog.ui:102 msgid "F_ramerate:" msgstr "Проток _кадрова:" #: data/ui/menubar.ui:5 msgid "_File" msgstr "_Датотека" #: data/ui/menubar.ui:8 msgid "_New" msgstr "_Ново" #: data/ui/menubar.ui:12 msgid "_Open…" msgstr "_Отвори…" #: data/ui/menubar.ui:16 msgid "Open _Translation…" msgstr "Отвори _превод…" #: data/ui/menubar.ui:22 msgid "Open _Recent" msgstr "Отвори _скорашње" #: data/ui/menubar.ui:27 msgid "Open R_ecent Translation" msgstr "Отвори скорашњи _превод" #: data/ui/menubar.ui:38 msgid "Save _As…" msgstr "Сачувај _као…" #: data/ui/menubar.ui:42 msgid "Save Trans_lation" msgstr "Сачувај _превод" #: data/ui/menubar.ui:46 msgid "Save Translat_ion As…" msgstr "Сачувај превод _као…" #: data/ui/menubar.ui:65 msgid "_Undo" msgstr "_Опозови" #: data/ui/menubar.ui:69 msgid "_Redo" msgstr "_Понови" #: data/ui/menubar.ui:75 msgid "_Edit Cell" msgstr "Уреди _поље" #: data/ui/menubar.ui:79 msgid "Edit _Next Cell" msgstr "Уреди _следеће поље" #: data/ui/menubar.ui:85 msgid "Stretc_h" msgstr "" #: data/ui/menubar.ui:88 msgid "_Start Earlier" msgstr "Почни _раније" #: data/ui/menubar.ui:92 msgid "S_tart Later" msgstr "Почни _касније" #: data/ui/menubar.ui:98 msgid "E_nd Earlier" msgstr "Заврши _раније" #: data/ui/menubar.ui:102 msgid "En_d Later" msgstr "Заврши _касније" #: data/ui/menubar.ui:108 msgid "Set St_art From Video Position" msgstr "" #: data/ui/menubar.ui:112 msgid "Set En_d From Video Position" msgstr "Подеси _крај са положаја у филму" #: data/ui/menubar.ui:118 data/ui/view-popup.ui:6 msgid "_Split Subtitle" msgstr "_Подели титл" #: data/ui/menubar.ui:122 data/ui/view-popup.ui:10 msgid "_Merge Subtitles" msgstr "_Стопи титлове" #: data/ui/menubar.ui:128 data/ui/view-popup.ui:16 msgid "_Insert Subtitles…" msgstr "_Уметни титлове…" #: data/ui/menubar.ui:132 msgid "Inser_t Subtitle At Video Position" msgstr "Уметни титл на положају у _филму" #: data/ui/menubar.ui:136 data/ui/view-popup.ui:20 msgid "Rem_ove Subtitles" msgstr "Уклони _титлове" #: data/ui/menubar.ui:142 msgid "Sele_ction" msgstr "_Избор" #: data/ui/menubar.ui:145 msgid "Select _All" msgstr "Изабери _све" #: data/ui/menubar.ui:149 msgid "_Invert Selection" msgstr "_Преокрени избор" #: data/ui/menubar.ui:155 msgid "Extend To _Beginning" msgstr "Прошири на _почетак" #: data/ui/menubar.ui:159 msgid "Extend To _End" msgstr "Прошири на _крај" #: data/ui/menubar.ui:165 msgid "_Previous From Video Position" msgstr "" #: data/ui/menubar.ui:169 msgid "_Next From Video Position" msgstr "" #: data/ui/menubar.ui:177 msgid "_Preferences" msgstr "_Поставке" #: data/ui/menubar.ui:183 msgid "_View" msgstr "_Преглед" #: data/ui/menubar.ui:186 msgid "Tool_bar" msgstr "Трака _алата" #: data/ui/menubar.ui:190 msgid "_Video Player" msgstr "_Програм за пуштање" #: data/ui/menubar.ui:196 msgid "_Layout" msgstr "_Распоред" #: data/ui/menubar.ui:199 msgid "_Horizontal" msgstr "_Водоравно" #: data/ui/menubar.ui:204 msgid "_Vertical" msgstr "_Усправно" #: data/ui/menubar.ui:213 msgid "_Times" msgstr "_Времена" #: data/ui/menubar.ui:218 msgid "_Frames" msgstr "_Кадрови" #: data/ui/menubar.ui:225 msgid "F_ramerate" msgstr "Проток _кадрова" #: data/ui/menubar.ui:228 msgid "2_3.976 fps" msgstr "2_3.976 к/с" #: data/ui/menubar.ui:233 msgid "2_4.000 fps" msgstr "2_4.000 к/с" #: data/ui/menubar.ui:238 msgid "2_5.000 fps" msgstr "2_5.000 к/с" #: data/ui/menubar.ui:243 msgid "2_9.970 fps" msgstr "2_9.970 к/с" #: data/ui/menubar.ui:272 msgid "_Columns" msgstr "_Ступци" #: data/ui/menubar.ui:306 msgid "Cu_t" msgstr "_Исеци" #: data/ui/menubar.ui:310 msgid "_Copy" msgstr "_Умножи" #: data/ui/menubar.ui:314 msgid "_Paste" msgstr "_Убаци" #: data/ui/menubar.ui:318 msgid "Cl_ear" msgstr "_Очисти" #: data/ui/menubar.ui:324 msgid "_Find And Replace…" msgstr "Нађи и _замени…" #: data/ui/menubar.ui:332 msgid "Find Pre_vious" msgstr "Нађи _претходно" #: data/ui/menubar.ui:338 msgid "_Italic" msgstr "_Искошено" #: data/ui/menubar.ui:342 msgid "_Dialogue" msgstr "_Разговор" #: data/ui/menubar.ui:348 msgid "Ca_se" msgstr "_Величина слова" #: data/ui/menubar.ui:351 msgid "_Title" msgstr "_Наслов" #: data/ui/menubar.ui:355 msgid "_Sentence" msgstr "_Реченица" #: data/ui/menubar.ui:359 msgid "_Upper" msgstr "_Велика" #: data/ui/menubar.ui:363 msgid "_Lower" msgstr "_Мала" #: data/ui/menubar.ui:371 msgid "Vi_deo" msgstr "_Филм" #: data/ui/menubar.ui:374 msgid "_Load Video…" msgstr "_Учитај филм…" #: data/ui/menubar.ui:384 data/ui/view-popup.ui:26 msgid "Play _Selection" msgstr "Пусти _изабрано" #: data/ui/menubar.ui:410 data/ui/view-popup.ui:30 msgid "S_eek Selection Start" msgstr "Пређи на _почетак избора" #: data/ui/menubar.ui:414 msgid "See_k Selection End" msgstr "Пређи на _крај избора" #: data/ui/menubar.ui:420 msgid "_Audio" msgstr "_Звук" #: data/ui/menubar.ui:423 msgid "_Language" msgstr "_Језик" #: data/ui/menubar.ui:430 msgid "Volume _Down" msgstr "_Утишај" #: data/ui/menubar.ui:434 msgid "Volume _Up" msgstr "_Појачај" #: data/ui/menubar.ui:440 msgid "T_ools" msgstr "_Алати" #: data/ui/menubar.ui:443 data/ui/text-assistant/confirmation-page.ui:97 #: data/ui/view-popup.ui:36 msgid "_Preview" msgstr "_Преглед" #: data/ui/menubar.ui:447 msgid "Select _Video…" msgstr "Изабери _филм…" #: data/ui/menubar.ui:453 msgid "_Check Spelling" msgstr "_Провери писање" #: data/ui/menubar.ui:457 msgid "Co_nfigure Spell-check…" msgstr "_Подеси проверу писања…" #: data/ui/menubar.ui:461 msgid "C_orrect Texts…" msgstr "_Исправи текстове…" #: data/ui/menubar.ui:467 msgid "_Shift Positions…" msgstr "_Премакни положаје…" #: data/ui/menubar.ui:471 msgid "_Transform Positions…" msgstr "_Преобрати положаје…" #: data/ui/menubar.ui:475 msgid "Adjust _Durations…" msgstr "Дотерај _трајања…" #: data/ui/menubar.ui:479 msgid "Convert _Framerate…" msgstr "Претвори проток _кадрова…" #: data/ui/menubar.ui:485 msgid "_Append File…" msgstr "_Прикачи датотеку…" #: data/ui/menubar.ui:489 msgid "Spli_t Project…" msgstr "Подели _пројекат…" #: data/ui/menubar.ui:495 msgid "_Projects" msgstr "_Пројекти" #: data/ui/menubar.ui:498 msgid "_Save All" msgstr "_Сачувај све" #: data/ui/menubar.ui:502 msgid "Save _All As…" msgstr "Сачувај све _као…" #: data/ui/menubar.ui:506 msgid "_Close All" msgstr "Затвори _све" #: data/ui/menubar.ui:512 msgid "_Previous" msgstr "_Претходни" #: data/ui/menubar.ui:516 msgid "_Next" msgstr "_Следећи" #: data/ui/menubar.ui:527 msgid "_Documentation" msgstr "" #: data/ui/menubar.ui:531 msgid "_Report A Bug" msgstr "Пријави _грешку" #: data/ui/menubar.ui:535 msgid "_About" msgstr "_О програму" #: data/ui/open-dialog.ui:39 msgid "Align _method:" msgstr "Начин _поравнања:" #: data/ui/preferences-dialog.ui:18 msgid "Preferences" msgstr "Поставке" #: data/ui/preferences-dialog.ui:93 msgid "When opening files, try encodings in the following order:" msgstr "Приликом отварања датотека, пробај кодирања по следећем редоследу:" #: data/ui/preferences-dialog.ui:104 msgid "Curr_ent locale encoding" msgstr "Текуће _кодирање језика" #: data/ui/preferences-dialog.ui:130 msgid "_Fallback encodings:" msgstr "_Резервно кодирање:" #: data/ui/preferences-dialog.ui:246 msgid "Aut_o-detection" msgstr "_Сам одреди" #: data/ui/preferences-dialog.ui:266 msgid "Encoding specified in the open dialog will always be tried first." msgstr "Кодирање наведено у прозорчету отварања увек ће бити пробано прво." #: data/ui/preferences-dialog.ui:296 msgid "File" msgstr "Датотека" #: data/ui/preferences-dialog.ui:324 msgid "Font" msgstr "Словни лик" #: data/ui/preferences-dialog.ui:344 msgid "Use _default theme fixed width font" msgstr "" #: data/ui/preferences-dialog.ui:368 msgid "_Editor font:" msgstr "_Словни лик уређивача:" #: data/ui/preferences-dialog.ui:425 msgid "Line Lengths" msgstr "Дужина реда" #: data/ui/preferences-dialog.ui:445 msgid "_Show line lengths in list cells" msgstr "_Прикажи дужине редова у списку окца" #: data/ui/preferences-dialog.ui:462 msgid "S_how line lengths in editable text fields" msgstr "Прикажи дужине редова у пољима за уређивање _текста" #: data/ui/preferences-dialog.ui:486 msgid "_Length unit:" msgstr "_Јединица дужине:" #: data/ui/preferences-dialog.ui:540 msgid "Spell-Check" msgstr "Провера писања" #: data/ui/preferences-dialog.ui:560 msgid "Chec_k spelling as you type" msgstr "_Проверавај писање док куцам" #: data/ui/preferences-dialog.ui:598 msgid "Editor" msgstr "Уређивач" #: data/ui/preferences-dialog.ui:626 msgid "Fonts" msgstr "Словни ликови" #: data/ui/preferences-dialog.ui:649 msgid "_Subtitles:" msgstr "_Титлови:" #: data/ui/preferences-dialog.ui:679 msgid "_Time:" msgstr "_Време:" #: data/ui/preferences-dialog.ui:729 msgid "Colors" msgstr "Боје" #: data/ui/preferences-dialog.ui:752 msgid "Su_btitles:" msgstr "_Титлови:" #: data/ui/preferences-dialog.ui:777 msgid "_Use a background behind text" msgstr "_Користи позадину иза текста" #: data/ui/preferences-dialog.ui:797 msgid "Ti_me:" msgstr "_Време:" #: data/ui/preferences-dialog.ui:822 msgid "Us_e a background behind text" msgstr "Користи позадину _иза текста" #: data/ui/preferences-dialog.ui:862 msgid "Seek" msgstr "" #: data/ui/preferences-dialog.ui:883 msgid "_Length:" msgstr "" #: data/ui/preferences-dialog.ui:971 msgid "Video Player" msgstr "Програм за пуштање филма" #: data/ui/preferences-dialog.ui:994 msgid "_Application:" msgstr "_Програм:" #: data/ui/preferences-dialog.ui:1008 msgid "Co_mmand:" msgstr "_Наредба:" #. Translators: Only the title is to be translated, field names not. #: data/ui/preferences-dialog.ui:1033 msgid "" "Fields:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" msgstr "" #: data/ui/preferences-dialog.ui:1048 msgid "Al_ways use UTF-8 character encoding" msgstr "_Увек користи УТФ-8 кодирање знакова" #: data/ui/preferences-dialog.ui:1089 msgid "Start Position" msgstr "Почетни положај" #: data/ui/preferences-dialog.ui:1111 msgid "_Offset:" msgstr "_Померај:" #: data/ui/preferences-dialog.ui:1142 msgid "seconds before selection" msgstr "секунде након избора" #: data/ui/preferences-dialog.ui:1281 msgid "Extensions" msgstr "Проширења" #: data/ui/language-dialog.ui:8 msgid "Configure Spell-Check" msgstr "Подесите проверу писања" #: data/ui/language-dialog.ui:50 msgid "Language" msgstr "Језик" #: data/ui/language-dialog.ui:128 msgid "Check _text column" msgstr "Провери стубац _текста" #: data/ui/language-dialog.ui:146 msgid "Check t_ranslation column" msgstr "Провери стубац _превода" #: data/ui/language-dialog.ui:206 msgid "Check c_urrent project" msgstr "Провери _текући пројекат" #: data/ui/language-dialog.ui:224 msgid "Check _all open projects" msgstr "Провери _све отворене пројекте" #: data/ui/text-assistant/confirmation-page.ui:22 msgid "Acc_ept, discard or edit changes:" msgstr "Прихвати, _одбаци или уреди измене:" #: data/ui/text-assistant/confirmation-page.ui:67 msgid "_Mark All" msgstr "_Обележи све" #: data/ui/text-assistant/confirmation-page.ui:82 msgid "_Unmark All" msgstr "_Разбележи све" #: data/ui/text-assistant/confirmation-page.ui:119 msgid "_Remove all blank subtitles" msgstr "_Уклони све празне преводе" #: data/ui/text-assistant/join-split-page.ui:28 msgid "Spell-Check Dictionary" msgstr "Речник за проверу правописа" #: data/ui/text-assistant/join-split-page.ui:49 #: data/ui/text-assistant/line-break-page.ui:81 #: data/ui/text-assistant/hearing-impaired-page.ui:81 #: data/ui/text-assistant/common-error-page.ui:80 #: data/ui/text-assistant/capitalization-page.ui:80 msgid "_Language:" msgstr "_Језик:" #: data/ui/text-assistant/join-split-page.ui:97 msgid "Corrections" msgstr "Исправке" #: data/ui/text-assistant/join-split-page.ui:117 msgid "_Join words not found in spell-check dictionary" msgstr "Додај _речи којих нема у речнику правописара" #: data/ui/text-assistant/join-split-page.ui:134 msgid "_Split words not found in spell-check dictionary" msgstr "Подели речи којих _нема у речнику правописара" #: data/ui/text-assistant/line-break-page.ui:22 msgid "S_elect preferred line-break points:" msgstr "Изабери жељене _тачке прелома реда:" #: data/ui/text-assistant/line-break-page.ui:67 #: data/ui/text-assistant/hearing-impaired-page.ui:67 #: data/ui/text-assistant/common-error-page.ui:66 #: data/ui/text-assistant/capitalization-page.ui:66 msgid "_Script:" msgstr "_Скрипта:" #: data/ui/text-assistant/line-break-page.ui:95 #: data/ui/text-assistant/hearing-impaired-page.ui:95 #: data/ui/text-assistant/common-error-page.ui:94 #: data/ui/text-assistant/capitalization-page.ui:94 msgid "Co_untry:" msgstr "_Држава:" #: data/ui/text-assistant/introduction-page.ui:28 msgid "_Select corrections to perform on texts:" msgstr "_Изабери исправке за текстове:" #: data/ui/text-assistant/introduction-page.ui:79 msgid "Colu_mns:" msgstr "_Ступци:" #: data/ui/text-assistant/introduction-page.ui:93 msgid "S_ubtitles:" msgstr "_Титлови:" #: data/ui/text-assistant/line-break-options-page.ui:56 #: data/ui/duration-adjust-dialog.ui:207 msgid "Limits" msgstr "Ограничења" #: data/ui/text-assistant/line-break-options-page.ui:79 msgid "_Maximum line length:" msgstr "Нај_већа дужина реда:" #: data/ui/text-assistant/line-break-options-page.ui:93 msgid "_Preferred maximum amount of lines:" msgstr "Жељени _највећи број редова:" #: data/ui/text-assistant/line-break-options-page.ui:198 msgid "_Skip subtitles with maximum line length of:" msgstr "Прескочи титлове са _дужином реда већом од:" #: data/ui/text-assistant/line-break-options-page.ui:214 msgid "S_kip subtitles with maximum line amount of:" msgstr "Прескочи титлове са _бројем реда већим од:" #: data/ui/text-assistant/hearing-impaired-page.ui:22 msgid "S_elect parts to remove:" msgstr "Изаберите делове за _уклањање:" #: data/ui/text-assistant/common-error-page.ui:22 msgid "S_elect errors to correct:" msgstr "Изаберите _грешке за исправљање:" #: data/ui/text-assistant/common-error-page.ui:108 msgid "Error types:" msgstr "Врсте грешака:" #: data/ui/text-assistant/common-error-page.ui:158 msgid "_Human errors" msgstr "Људске _грешке" #: data/ui/text-assistant/common-error-page.ui:175 msgid "_Image recognition errors" msgstr "Грешке препознавања _слике" #: data/ui/text-assistant/capitalization-page.ui:22 msgid "S_elect parts to capitalize:" msgstr "Изабери _делове за велика слова:" #: data/ui/duration-adjust-dialog.ui:33 msgid "Adjust Durations" msgstr "Дотерајте трајања" #: data/ui/duration-adjust-dialog.ui:73 msgid "Theoretic Duration" msgstr "Теоретско трајање" #: data/ui/duration-adjust-dialog.ui:101 msgid "_Reading speed:" msgstr "Брзина _читања:" #: data/ui/duration-adjust-dialog.ui:133 msgid "characters per second" msgstr "знакова у секунди" #: data/ui/duration-adjust-dialog.ui:150 msgid "_Lengthen duration to match reading speed" msgstr "_Продужи трајање да одговара брзини читања" #: data/ui/duration-adjust-dialog.ui:167 msgid "_Shorten duration to match reading speed" msgstr "_Смањи трајање да одговара брзини читања" #: data/ui/duration-adjust-dialog.ui:227 msgid "_Minimum duration:" msgstr "Нај_мање трајање:" #: data/ui/duration-adjust-dialog.ui:243 msgid "Ma_ximum duration:" msgstr "Нај_веће трајање:" #: data/ui/duration-adjust-dialog.ui:259 msgid "_Gap between subtitles:" msgstr "_Размак између титлова:" #: data/ui/duration-adjust-dialog.ui:294 msgid "s_econds" msgstr "с_екунде" #: data/ui/duration-adjust-dialog.ui:324 msgid "seco_nds" msgstr "секу_нде" #: data/ui/duration-adjust-dialog.ui:354 msgid "secon_ds" msgstr "секун_де" #: data/ui/duration-adjust-dialog.ui:408 msgid "Adj_ust selected subtitles" msgstr "Подеси _изабране титлове" #: data/ui/duration-adjust-dialog.ui:425 msgid "Adjus_t current project" msgstr "Подеси _текући пројекат" #: data/ui/duration-adjust-dialog.ui:442 msgid "Adjust all _open projects" msgstr "Подеси све _отворене пројекте" #: data/ui/tab-popup.ui:6 msgid "Move Tab _Left" msgstr "Премести језичак _лево" #: data/ui/tab-popup.ui:10 msgid "Move Tab _Right" msgstr "Премести језичак _десно" #: data/ui/insert-dialog.ui:15 msgid "Insert Subtitles" msgstr "Уметните титлове" #: data/ui/insert-dialog.ui:48 data/ui/position-shift-dialog.ui:82 msgid "_Amount:" msgstr "_Количина:" #: data/ui/insert-dialog.ui:62 msgid "_Position:" msgstr "_Положај:" #: data/ui/position-shift-dialog.ui:14 msgid "Shift Positions" msgstr "Премакните положаје" #: data/ui/position-shift-dialog.ui:54 msgid "Shift" msgstr "Премакни" #: data/ui/position-shift-dialog.ui:135 #: data/ui/position-transform-dialog.ui:208 msgid "_Preview Changes" msgstr "_Претходна измена" #: data/ui/position-shift-dialog.ui:200 msgid "Shift s_elected subtitles" msgstr "Премакни _изабране титлове" #: data/ui/position-shift-dialog.ui:217 msgid "Shift su_btitles from selection to end" msgstr "Премакни _титлове са избора на крај" #: data/ui/position-shift-dialog.ui:234 msgid "Shift c_urrent project" msgstr "Премакни _текући пројекат" #: data/ui/position-shift-dialog.ui:251 msgid "Shift all _open projects" msgstr "" #: data/ui/position-transform-dialog.ui:22 msgid "Transform Positions" msgstr "Преобратите положаје" #: data/ui/position-transform-dialog.ui:62 msgid "First Point" msgstr "Прва тачка" #: data/ui/position-transform-dialog.ui:91 msgid "_Subtitle:" msgstr "_Титл:" #: data/ui/position-transform-dialog.ui:105 msgid "C_orrection:" msgstr "_Исправка:" #: data/ui/position-transform-dialog.ui:119 #: data/ui/position-transform-dialog.ui:310 msgid "Text:" msgstr "Текст:" #: data/ui/position-transform-dialog.ui:253 msgid "Second Point" msgstr "Друга тачка" #: data/ui/position-transform-dialog.ui:282 msgid "Su_btitle:" msgstr "_Титл:" #: data/ui/position-transform-dialog.ui:296 msgid "Co_rrection:" msgstr "_Исправка:" #: data/ui/position-transform-dialog.ui:399 msgid "Pre_view Changes" msgstr "_Прегледај измене" #: data/ui/position-transform-dialog.ui:464 msgid "Transform se_lected subtitles" msgstr "Преобрати _изабране титлове" #: data/ui/position-transform-dialog.ui:482 msgid "Transform c_urrent project" msgstr "Преобрати _текући пројекат" #: data/extensions/custom-framerates/custom-framerates.extension.in:7 msgid "Custom Framerates" msgstr "Произвољни протоци кадрова" #: data/extensions/custom-framerates/custom-framerates.extension.in:8 msgid "Allow use of non-standard framerates" msgstr "Дозволи коришћење неуобичајених кадрова протока" #: data/patterns/Latn-en-US.common-error.in:5 msgid "Period after title" msgstr "Тачка након титла" #: data/patterns/Latn-en-US.common-error.in:6 msgid "Add period after a shortened title, such as \"Mr\" and \"Dr\"" msgstr "Додајте тачку након скраћеног титла, нпр. „Мр“ и „Др“" #: data/patterns/Latn-en.capitalization.in:5 msgid "First person pronoun" msgstr "Заменица првог лица" #: data/patterns/Latn-en.capitalization.in:6 msgid "Capitalize the first person pronoun \"I\"" msgstr "Испишите великим словом заменицу првог лица једнине „I“" #: data/patterns/Latn-en.common-error.in:5 #: data/patterns/Latn-en.common-error.in:14 #: data/patterns/Latn-en.common-error.in:23 msgid "Letter \"I\" in a lower case word" msgstr "Слово „I“ у речима малим словима" #: data/patterns/Latn-en.common-error.in:6 #: data/patterns/Latn-en.common-error.in:15 #: data/patterns/Latn-en.common-error.in:24 msgid "Replace letter \"I\" with letter \"l\" in a lower case word" msgstr "Замените слово „I“ словом „l“ у речима написаним малим словима" #: data/patterns/Latn-en.common-error.in:32 #: data/patterns/Latn-en.common-error.in:41 #: data/patterns/Latn-en.common-error.in:50 #: data/patterns/Latn-en.common-error.in:62 msgid "Letter \"l\" in an upper case word" msgstr "Слово „l“ у речима великим словима" #: data/patterns/Latn-en.common-error.in:33 #: data/patterns/Latn-en.common-error.in:42 #: data/patterns/Latn-en.common-error.in:51 #: data/patterns/Latn-en.common-error.in:63 msgid "Replace letter \"l\" with letter \"I\" in an upper case word" msgstr "Замените слово „l“ словом „I“ у речима написаним великим словима" #: data/patterns/Latn-en.common-error.in:73 #: data/patterns/Latn-en.common-error.in:82 msgid "Zero in an upper case word" msgstr "Нула у речима великим словима" #: data/patterns/Latn-en.common-error.in:74 #: data/patterns/Latn-en.common-error.in:83 msgid "Replace zero with letter \"O\" in an upper case word" msgstr "Замените нулу словом „O“ у речима написаним великим словима" #: data/patterns/Latn-en.common-error.in:91 #: data/patterns/Latn.common-error.in:108 msgid "Space between number and unit" msgstr "Размак између броја и јединице" #: data/patterns/Latn-en.common-error.in:92 #: data/patterns/Latn.common-error.in:109 msgid "Add or remove space between a number and the associated unit" msgstr "Додајте или замените размаке између броја и придружене јединице" #: data/patterns/Latn-en.common-error.in:100 msgid "Spaces around an apostrophe" msgstr "Размаци око апострофа" #: data/patterns/Latn-en.common-error.in:101 msgid "Remove spaces around an apostrophe" msgstr "Уклоните размаке око апострофа" #: data/patterns/Latn-en.common-error.in:109 #: data/patterns/Latn-en.common-error.in:118 msgid "Okay" msgstr "Okay" #: data/patterns/Latn-en.common-error.in:110 #: data/patterns/Latn-en.common-error.in:119 msgid "Spell two-letter forms of \"okay\" in all upper case" msgstr "Испиши двословни облик за „okay“ великим словима" #: data/patterns/Latn-en.hearing-impaired.in:5 msgid "Uppercase speaker before a colon" msgstr "Говорник великим словом пре двотачке" #: data/patterns/Latn-en.hearing-impaired.in:6 msgid "" "Replace the uppercase name of the speaker before a colon with a dialogue " "dash" msgstr "" "Замените име говорника исписано великим словима пре двотачке цртицом " "дијалога" #: data/patterns/Latn-en.line-break.in:5 msgid "Title" msgstr "Наслов" #: data/patterns/Latn-en.line-break.in:6 msgid "Do not break after a title, e.g. \" Dr.\"" msgstr "Не прекидајте након наслова, нпр. „ Др.“" #: data/patterns/Latn-en.line-break.in:13 msgid "Article" msgstr "Чланак" #: data/patterns/Latn-en.line-break.in:14 msgid "Do not break after an article" msgstr "Не прекидајте након чланка" #: data/patterns/Latn-en.line-break.in:21 msgid "Preposition" msgstr "Предлог" #: data/patterns/Latn-en.line-break.in:22 msgid "Do not break after a preposition" msgstr "Не преламајте након предлога" #: data/patterns/Latn-en.line-break.in:30 msgid "Possessive determiner" msgstr "Присвојни придев" #: data/patterns/Latn-en.line-break.in:31 msgid "Do not break after a possessive determiner, e.g. \"my\"" msgstr "Не преламајте након присвојног придева, нпр. „my“" #: data/patterns/Latn-fi.common-error.in:5 #: data/patterns/Latn.common-error.in:182 msgid "Space after punctuation marks" msgstr "Размак након интерпункцијских знакова" #: data/patterns/Latn-fi.common-error.in:6 #: data/patterns/Latn.common-error.in:183 msgid "Add space after various punctuation marks" msgstr "Додајте размак након разних интерпункцијских знакова" #: data/patterns/Latn-fr.common-error.in:5 #: data/patterns/Latn-fr.common-error.in:14 #: data/patterns/Latn-fr.common-error.in:23 #: data/patterns/Latn-fr.common-error.in:32 msgid "Spaces around guillemets" msgstr "Размаци око наводника" #: data/patterns/Latn-fr.common-error.in:6 #: data/patterns/Latn-fr.common-error.in:15 #: data/patterns/Latn-fr.common-error.in:24 #: data/patterns/Latn-fr.common-error.in:33 msgid "Add spaces around guillemets" msgstr "Додајте размаке око наводника" #: data/patterns/Latn-fr.common-error.in:41 #: data/patterns/Latn-fr.common-error.in:52 #: data/patterns/Latn.common-error.in:171 msgid "Space before punctuation marks" msgstr "Размак пре интерпункцијских знакова" #: data/patterns/Latn-fr.common-error.in:42 #: data/patterns/Latn-fr.common-error.in:53 msgid "Add or remove space before various punctuation marks" msgstr "Додајте или уклоните размак након разних интерпункцијских знакова" #: data/patterns/Latn.capitalization.in:5 msgid "Sentence" msgstr "Реченица" #: data/patterns/Latn.capitalization.in:6 msgid "Capitalize the first word of a sentence" msgstr "Испиши великим словом прво слово реченице" #: data/patterns/Latn.capitalization.in:12 msgid "Ellipsis" msgstr "Скраћивање" #: data/patterns/Latn.capitalization.in:13 msgid "Capitalize after an ellipsis" msgstr "Велико слово након скраћивања" #: data/patterns/Latn.common-error.in:8 data/patterns/Latn.common-error.in:17 #: data/patterns/Latn.common-error.in:26 data/patterns/Latn.common-error.in:35 #: data/patterns/Latn.common-error.in:44 data/patterns/Latn.common-error.in:53 #: data/patterns/Latn.common-error.in:62 msgid "Ligatures" msgstr "" #: data/patterns/Latn.common-error.in:9 data/patterns/Latn.common-error.in:18 #: data/patterns/Latn.common-error.in:27 data/patterns/Latn.common-error.in:36 #: data/patterns/Latn.common-error.in:45 data/patterns/Latn.common-error.in:54 #: data/patterns/Latn.common-error.in:63 msgid "Unpack ligatures to individual characters" msgstr "" #: data/patterns/Latn.common-error.in:71 data/patterns/Latn.common-error.in:80 msgid "Spelling of a.m. and p.m." msgstr "Исписивање „a.m.“ и „p.m.“" #: data/patterns/Latn.common-error.in:72 data/patterns/Latn.common-error.in:81 msgid "Change the various spellings of 12-hour periods to \"a.m.\" and \"p.m.\"" msgstr "Измените разна исписивања 12-часовних раздобља у „a.m.“ и „p.m.“" #: data/patterns/Latn.common-error.in:89 data/patterns/Latn.common-error.in:98 msgid "Letter \"O\" in a number" msgstr "Слово „O“ у броју" #: data/patterns/Latn.common-error.in:90 data/patterns/Latn.common-error.in:99 msgid "Replace letter \"O\" with a zero in a number" msgstr "Замените слово „O“ нулом у бројевима" #: data/patterns/Latn.common-error.in:117 msgid "Double apostrophe" msgstr "Двоструки апостроф" #: data/patterns/Latn.common-error.in:118 msgid "Replace a double apostrophe with a quotation mark" msgstr "Замените двоструки апостроф знаком наводника" #: data/patterns/Latn.common-error.in:126 #: data/patterns/Latn.common-error.in:135 #: data/patterns/Latn.common-error.in:144 #: data/patterns/Latn.common-error.in:153 msgid "Spaces around brackets" msgstr "Размаци око заграда" #: data/patterns/Latn.common-error.in:127 #: data/patterns/Latn.common-error.in:136 #: data/patterns/Latn.common-error.in:145 #: data/patterns/Latn.common-error.in:154 msgid "Add or remove spaces around parantheses and square brackets" msgstr "Додајте или замените размаке око заграда и угластих заграда" #: data/patterns/Latn.common-error.in:162 msgid "Space after a dialogue dash" msgstr "Размак након цртице дијалога" #: data/patterns/Latn.common-error.in:163 msgid "Add space after a dialogue dash" msgstr "Додајте размак након цртице дијалога" #: data/patterns/Latn.common-error.in:172 msgid "Remove space before various punctuation marks" msgstr "Уклоните размак након разних интерпункцијских знакова" #: data/patterns/Latn.common-error.in:192 msgid "Space after an ellipsis" msgstr "Размак након скраћивања" #: data/patterns/Latn.common-error.in:193 msgid "Add space after an ellipsis" msgstr "Додај размак након скраћивања" #: data/patterns/Latn.common-error.in:201 msgid "Space after a starting ellipsis" msgstr "Размак након почетног скраћивања" #: data/patterns/Latn.common-error.in:202 msgid "Remove space after an ellipsis that starts a line" msgstr "Уклоните размак након скраћивања којим почиње ред" #: data/patterns/Latn.common-error.in:210 #: data/patterns/Latn.common-error.in:221 #: data/patterns/Latn.common-error.in:232 #: data/patterns/Latn.common-error.in:242 msgid "Spaces around a quotation mark" msgstr "Размаци око знака наводника" #: data/patterns/Latn.common-error.in:211 #: data/patterns/Latn.common-error.in:222 #: data/patterns/Latn.common-error.in:233 #: data/patterns/Latn.common-error.in:243 msgid "Remove space after a starting- and before an ending quotation mark" msgstr "" "Уклоните размак након знака отварање и пре знака за затварање наводника" #: data/patterns/Latn.common-error.in:252 #: data/patterns/Latn.common-error.in:261 msgid "Spaces around musical notes" msgstr "Размаци око музичких нота" #: data/patterns/Latn.common-error.in:253 #: data/patterns/Latn.common-error.in:262 msgid "Add spaces between musical note characters and lyrics" msgstr "Додајте размаке између знакова музичких нота и текствова" #: data/patterns/Latn.common-error.in:270 #: data/patterns/Latn.common-error.in:279 msgid "Multiple question- and exclamation marks" msgstr "Вишеструки знакови питања и узвичника" #: data/patterns/Latn.common-error.in:271 #: data/patterns/Latn.common-error.in:280 msgid "" "Replace multiple consequtive question- and exclamation marks with only one" msgstr "Замените више узастопних знакова питања и узвичника само једним" #: data/patterns/Latn.common-error.in:288 #: data/patterns/Latn.common-error.in:298 msgid "Periods around a punctuation mark" msgstr "Тачке око интерпункцијског знака" #: data/patterns/Latn.common-error.in:289 #: data/patterns/Latn.common-error.in:299 msgid "Remove period before or after various punctuation marks" msgstr "Уклоните тачку пре или након разних интерпункцијских знакова" #: data/patterns/Latn.common-error.in:308 msgid "Terminating double-dashes" msgstr "Двоструке цртице окончавања" #: data/patterns/Latn.common-error.in:309 msgid "Replace a single clause-terminating dash with two dashes" msgstr "Замените једну цртицу окончавања двема" #: data/patterns/Latn.hearing-impaired.in:5 msgid "Sound in brackets" msgstr "Звук у заградама" #: data/patterns/Latn.hearing-impaired.in:6 msgid "Remove description of a sound between square brackets" msgstr "Уклоните опис звука између угластих заграда" #: data/patterns/Latn.hearing-impaired.in:12 msgid "Sound in parantheses" msgstr "Звук у малим заградама" #: data/patterns/Latn.hearing-impaired.in:13 msgid "Remove description of a sound between parantheses" msgstr "Уклоните опис звука између малих заграда" #: data/patterns/Latn.hearing-impaired.in:19 msgid "Song lyrics between number signs" msgstr "Текстови песама између знакова бројева" #: data/patterns/Latn.hearing-impaired.in:20 msgid "Remove song lyrics starting with or between number signs" msgstr "Уклоните текстове песама који почињу или су између знакова бројева" #: data/patterns/Latn.hearing-impaired.in:27 msgid "One-line song lyrics between number signs" msgstr "Једноредни текстови песама између знакова бројева" #: data/patterns/Latn.hearing-impaired.in:28 msgid "Remove one-line song lyrics starting with or between number signs" msgstr "" "Уклоните једноредне текстове песама који почињу или су између знакова " "бројева" #: data/patterns/Latn.hearing-impaired.in:35 msgid "Speaker before a colon" msgstr "Говорник пре двотачке" #: data/patterns/Latn.hearing-impaired.in:36 msgid "Replace the name of the speaker before a colon with a dialogue dash" msgstr "Замените име говорника пре двотачке цртицом дијалога" #: data/patterns/Latn.line-break.in:5 data/patterns/Latn.line-break.in:13 msgid "Dialogue" msgstr "Разговор" #: data/patterns/Latn.line-break.in:6 data/patterns/Latn.line-break.in:14 msgid "Break according to dialogue separated by dashes" msgstr "Преломи у складу са разговором одвојеним цртицама" #: data/patterns/Latn.line-break.in:21 data/patterns/Latn.line-break.in:30 msgid "Clause" msgstr "Полуреченица" #: data/patterns/Latn.line-break.in:22 data/patterns/Latn.line-break.in:31 msgid "Break according to clauses terminated by a punctuation mark" msgstr "Преломи у складу са полуреченицама окончаним интерпункцијским знаком" #: data/patterns/Latn.line-break.in:38 msgid "Number and unit" msgstr "Број и јединица" #: data/patterns/Latn.line-break.in:39 msgid "Do not break between a number and associated unit" msgstr "Не преламај између броја и придружене јединице" #: data/patterns/Zyyy.common-error.in:5 data/patterns/Zyyy.common-error.in:14 msgid "Leading and trailing spaces" msgstr "Водећи и пратећи размаци" #: data/patterns/Zyyy.common-error.in:6 data/patterns/Zyyy.common-error.in:15 msgid "Remove spaces from the beginning and end of lines" msgstr "Уклоните размаке са почетка и краја редова" #: data/patterns/Zyyy.common-error.in:23 msgid "Multiple consecutive spaces" msgstr "Више узастопних размака" #: data/patterns/Zyyy.common-error.in:24 msgid "Replace multiple consecutive spaces with only one" msgstr "Замените више узастопних размака само једним" #: data/patterns/Zyyy.common-error.in:32 data/patterns/Zyyy.common-error.in:45 #: data/patterns/Zyyy.common-error.in:55 data/patterns/Zyyy.common-error.in:65 msgid "Space between digits" msgstr "Размак између цифара" #: data/patterns/Zyyy.common-error.in:33 data/patterns/Zyyy.common-error.in:46 #: data/patterns/Zyyy.common-error.in:56 data/patterns/Zyyy.common-error.in:66 msgid "Remove space between digits of a number" msgstr "Уклоните размак између цифара бојева" #: data/patterns/Zyyy.common-error.in:79 msgid "Musical notes" msgstr "Музичке ноте" #: data/patterns/Zyyy.common-error.in:80 msgid "Replace Unicode musical note characters with number signs" msgstr "Замените Уникод знакове музичких нота знаковима бројева" #: data/io.otsaloma.gaupol.appdata.xml.in:7 msgid "Editor for text-based subtitles" msgstr "" #: data/io.otsaloma.gaupol.appdata.xml.in:9 msgid "" "Gaupol is an editor for text-based subtitle files. It supports multiple " "subtitle file formats and provides means of creating subtitles, editing " "texts and timing subtitles to match video." msgstr "" #: data/io.otsaloma.gaupol.appdata.xml.in:40 msgid "Main window" msgstr "" #: data/io.otsaloma.gaupol.desktop.in:5 msgid "Subtitle Editor" msgstr "Уређивач титлова" #: data/io.otsaloma.gaupol.desktop.in:6 msgid "Edit subtitle files" msgstr "Уређујте датотеке титлова" #. TRANSLATORS: Search terms to find this application. Do NOT translate or #. localize the semicolons! The list MUST also end with a semicolon! #: data/io.otsaloma.gaupol.desktop.in:12 msgid "video;subtitles;captions;" msgstr "превод;титл;филм;снимање;" gaupol-1.11/po/tr.po000066400000000000000000002143321422217132500143320ustar00rootroot00000000000000# 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. # # Translators: # Osmo Salomaa , 2016 # Yasin ÇUKUR , 2020 # CJ9 , 2020 # Hasan Kalaman , 2021 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-04-03 04:00+0300\n" "PO-Revision-Date: 2016-07-07 00:55+0000\n" "Last-Translator: Hasan Kalaman , 2021\n" "Language-Team: Turkish (https://www.transifex.com/otsaloma/teams/64879/tr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: tr\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: aeidon/enums.py:40 gaupol/enums.py:38 msgid "Subtitle number" msgstr "Altyazı numarası" #: aeidon/enums.py:43 msgid "Subtitle position" msgstr "Altyazı durumu" #: aeidon/enums.py:59 msgid "23.976 fps" msgstr "23.976 fps" #: aeidon/enums.py:63 msgid "24.000 fps" msgstr "24.000 fps" #: aeidon/enums.py:67 msgid "25.000 fps" msgstr "25.000 fps" #: aeidon/enums.py:71 msgid "29.970 fps" msgstr "29.970 fps" #: aeidon/enums.py:75 data/ui/menubar.ui:248 msgid "30.000 fps" msgstr "" #: aeidon/enums.py:79 data/ui/menubar.ui:253 msgid "50.000 fps" msgstr "" #: aeidon/enums.py:83 data/ui/menubar.ui:258 msgid "59.940 fps" msgstr "" #: aeidon/enums.py:87 data/ui/menubar.ui:263 msgid "60.000 fps" msgstr "" #: aeidon/enums.py:112 msgid "Mac (classic)" msgstr "Mac (klasik)" #. TRANSLATORS: Most of the character encoding descriptions are copied from #. gedit, which is translated to very many languages. Check the gedit .po #. files for a reference: #. . #: aeidon/encodings.py:40 aeidon/encodings.py:43 aeidon/encodings.py:46 msgid "English" msgstr "İngilizce" #: aeidon/encodings.py:41 aeidon/encodings.py:42 aeidon/encodings.py:69 msgid "Chinese traditional" msgstr "Çince (Geleneksel)" #: aeidon/encodings.py:44 msgid "German" msgstr "Almanca" #: aeidon/encodings.py:45 aeidon/encodings.py:54 aeidon/encodings.py:59 #: aeidon/encodings.py:79 aeidon/encodings.py:105 msgid "Hebrew" msgstr "İbranice" #: aeidon/encodings.py:47 aeidon/encodings.py:51 aeidon/encodings.py:56 #: aeidon/encodings.py:73 aeidon/encodings.py:76 aeidon/encodings.py:98 #: aeidon/encodings.py:111 aeidon/encodings.py:122 msgid "Western" msgstr "Batı Dili" #: aeidon/encodings.py:48 aeidon/encodings.py:61 aeidon/encodings.py:80 #: aeidon/encodings.py:103 msgid "Arabic" msgstr "Arapça" #: aeidon/encodings.py:49 aeidon/encodings.py:64 aeidon/encodings.py:66 #: aeidon/encodings.py:77 aeidon/encodings.py:104 aeidon/encodings.py:119 msgid "Greek" msgstr "Yunanca" #: aeidon/encodings.py:50 aeidon/encodings.py:81 aeidon/encodings.py:101 #: aeidon/encodings.py:109 msgid "Baltic" msgstr "Baltık" #: aeidon/encodings.py:52 aeidon/encodings.py:74 aeidon/encodings.py:99 #: aeidon/encodings.py:121 msgid "Central European" msgstr "Orta Avrupa" #: aeidon/encodings.py:53 aeidon/encodings.py:75 aeidon/encodings.py:102 #: aeidon/encodings.py:118 msgid "Cyrillic" msgstr "Kiril Dili" #: aeidon/encodings.py:55 aeidon/encodings.py:71 aeidon/encodings.py:78 #: aeidon/encodings.py:106 aeidon/encodings.py:123 msgid "Turkish" msgstr "Türkçe" #: aeidon/encodings.py:57 msgid "Portuguese" msgstr "Portekizce" #: aeidon/encodings.py:58 aeidon/encodings.py:120 msgid "Icelandic" msgstr "İzlandaca" #: aeidon/encodings.py:60 msgid "Canadian" msgstr "Kanadaca" #: aeidon/encodings.py:62 aeidon/encodings.py:107 msgid "Nordic" msgstr "Nordik" #: aeidon/encodings.py:63 aeidon/encodings.py:114 msgid "Russian" msgstr "Rusça" #: aeidon/encodings.py:65 aeidon/encodings.py:108 msgid "Thai" msgstr "Tayca" #: aeidon/encodings.py:67 aeidon/encodings.py:83 aeidon/encodings.py:84 #: aeidon/encodings.py:85 aeidon/encodings.py:91 aeidon/encodings.py:92 #: aeidon/encodings.py:93 aeidon/encodings.py:94 aeidon/encodings.py:95 #: aeidon/encodings.py:96 aeidon/encodings.py:125 aeidon/encodings.py:126 #: aeidon/encodings.py:127 msgid "Japanese" msgstr "Japonca" #: aeidon/encodings.py:68 aeidon/encodings.py:86 aeidon/encodings.py:97 #: aeidon/encodings.py:113 msgid "Korean" msgstr "Korece" #: aeidon/encodings.py:70 msgid "Urdu" msgstr "Urduca" #: aeidon/encodings.py:72 aeidon/encodings.py:116 msgid "Ukrainian" msgstr "Ukraynaca" #: aeidon/encodings.py:82 msgid "Vietnamese" msgstr "Vietnamca" #: aeidon/encodings.py:87 aeidon/encodings.py:90 msgid "Chinese simplified" msgstr "Çince (Basitleştirilmiş)" #: aeidon/encodings.py:88 aeidon/encodings.py:89 msgid "Chinese unified" msgstr "Çince (Birleştirilmiş)" #: aeidon/encodings.py:100 aeidon/encodings.py:112 msgid "South European" msgstr "Güney Avrupa" #: aeidon/encodings.py:110 msgid "Celtic" msgstr "Keltce" #: aeidon/encodings.py:115 msgid "Tajik" msgstr "Tacikce" #: aeidon/encodings.py:117 msgid "Kazakh" msgstr "Kazakça" #: aeidon/encodings.py:124 msgid "Cyrillic Asian" msgstr "Kirilce (Asya)" #: aeidon/encodings.py:128 aeidon/encodings.py:129 aeidon/encodings.py:130 #: aeidon/encodings.py:131 aeidon/encodings.py:132 aeidon/encodings.py:133 #: aeidon/encodings.py:134 aeidon/encodings.py:135 aeidon/encodings.py:136 msgid "Unicode" msgstr "Unicode" #: aeidon/encodings.py:156 #, python-brace-format msgid "{description} ({name})" msgstr "{description} ({name})" #: aeidon/encodings.py:232 msgid "Current locale ({})" msgstr "Şimdiki lokal: \"{}\"" #: aeidon/locales.py:46 #, python-brace-format msgid "{language} ({country})" msgstr "{language} ({country})" #: aeidon/agents/search.py:227 msgid "Replacing" msgstr "Değiştiriliyor" #: aeidon/agents/search.py:256 aeidon/agents/search.py:258 msgid "Replacing all" msgstr "Hepsini değiştir" #: aeidon/agents/position.py:74 msgid "Adjusting durations" msgstr "Süreç ayarlanıyor" #: aeidon/agents/position.py:96 msgid "Converting framerate" msgstr "Kare hızı dönüştürülüyor" #: aeidon/agents/position.py:146 msgid "Setting framerate" msgstr "Kare hızı ayarlanıyor" #: aeidon/agents/position.py:168 msgid "Shifting positions" msgstr "Durum öteleniyor" #: aeidon/agents/position.py:188 msgid "Transforming positions" msgstr "Durumlar dönüştürülüyor" #: aeidon/agents/clipboard.py:44 msgid "Cutting texts" msgstr "Yazılar kesiliyor" #: aeidon/agents/clipboard.py:61 msgid "Pasting texts" msgstr "Yazılar yapıştırılıyor" #: aeidon/agents/text.py:91 msgid "Breaking lines" msgstr "Satırlar bölünüyor" #: aeidon/agents/text.py:128 msgid "Capitalizing texts" msgstr "Yazılar büyütülüyor" #: aeidon/agents/text.py:185 msgid "Correcting common errors" msgstr "Genel hatalar düzeltiliyor" #: aeidon/agents/text.py:234 msgid "Removing hearing impaired texts" msgstr "İşitme Engeli desteği yazılar siliniyor" #: aeidon/agents/text.py:315 msgid "Joining words by spell-check suggestions" msgstr "Yazım kontrolü önerilerine göre kelimeler birleştiriliyor" #: aeidon/agents/text.py:354 msgid "Splitting words by spell-check suggestions" msgstr "Yazım kontrolü önerilerine göre kelimeler ayrılıyor" #: aeidon/agents/set.py:58 aeidon/agents/set.py:80 aeidon/agents/set.py:113 msgid "Editing position" msgstr "Durumu düzenle" #: aeidon/agents/set.py:129 msgid "Editing text" msgstr "Yazı düzenleniyor" #: aeidon/agents/edit.py:35 msgid "Clearing texts" msgstr "Yazılar temizleniyor" #: aeidon/agents/edit.py:61 aeidon/agents/edit.py:83 msgid "Inserting subtitles" msgstr "Altyazılar ekleniyor" #: aeidon/agents/edit.py:103 msgid "Merging subtitles" msgstr "Altyazılar birleştiriliyor" #: aeidon/agents/edit.py:114 msgid "Removing subtitles" msgstr "Altyazılar siliniyor" #: aeidon/agents/edit.py:131 msgid "Replacing positions" msgstr "Durumlar değiştiriliyor" #: aeidon/agents/edit.py:147 msgid "Replacing texts" msgstr "Yazılar değiştiriliyor" #: aeidon/agents/edit.py:171 msgid "Splitting subtitle" msgstr "Altyazı bölünüyor" #: aeidon/agents/format.py:49 msgid "Adding dialogue dashes" msgstr "Konuşma çizgisi ekleniyor" #: aeidon/agents/format.py:68 msgid "Changing case" msgstr "Büyük/küçük harf değiştiriliyor" #: aeidon/agents/format.py:92 msgid "Italicizing" msgstr "İtalikleştiriliyor" #: aeidon/agents/format.py:108 msgid "Removing dialogue dashes" msgstr "Konuşma çizgileri siliniyor" #: aeidon/agents/format.py:174 msgid "Unitalicizing" msgstr "İtaliklik geri alınıyor" #: gaupol/application.py:219 gaupol/agents/open.py:203 msgid "Open" msgstr "Aç" #: gaupol/application.py:223 msgid "Open main files" msgstr "Ana dosya aç" #: gaupol/application.py:230 msgid "Save" msgstr "Kaydet" #: gaupol/application.py:233 msgid "Save the current main document" msgstr "Şimdiki ana dökümanı kaydet" #: gaupol/application.py:238 msgid "Undo" msgstr "Geri al" #: gaupol/application.py:242 msgid "Undo the last action" msgstr "Son yapılanı geri al" #: gaupol/application.py:249 msgid "Redo" msgstr "Tekrarla" #: gaupol/application.py:252 msgid "Redo the last undone action" msgstr "Son geri almayı iptal et" #: gaupol/application.py:260 msgid "Insert" msgstr "Ekle" #: gaupol/application.py:262 msgid "Insert new subtitles" msgstr "Yeni altyazı ekle" #: gaupol/application.py:266 #: data/extensions/custom-framerates/preferences-dialog.ui:78 msgid "Remove" msgstr "Sil" #: gaupol/application.py:268 msgid "Remove the selected subtitles" msgstr "Seçili altyazıları sil" #: gaupol/application.py:273 data/ui/search-dialog.ui:283 msgid "Find" msgstr "Ara" #: gaupol/application.py:275 msgid "Search for and replace text" msgstr "Bul ve değiştir" #: gaupol/application.py:279 data/ui/preferences-dialog.ui:942 msgid "Video" msgstr "Video" #: gaupol/application.py:281 msgid "Show or hide the video player" msgstr "Video oynatıcıyı göster/gizle" #: gaupol/application.py:285 data/ui/preferences-dialog.ui:1173 msgid "Preview" msgstr "İzleyerek dene" #: gaupol/application.py:287 msgid "Preview from selected position with a video player" msgstr "Seçili durumdan itibaren video oynayıcısında önizle" #: gaupol/enums.py:37 msgid "No." msgstr "No." #: gaupol/enums.py:43 msgid "Start" msgstr "Başlangıç" #: gaupol/enums.py:44 msgid "Start position" msgstr "Başlangıç durumu" #: gaupol/enums.py:49 msgid "End" msgstr "Bitiş" #: gaupol/enums.py:50 msgid "End position" msgstr "Bitiş durumu" #. TRANSLATORS: 'Dur.' is short for duration. It is used in the header #. of a column that contains numbers five digits wide. #: gaupol/enums.py:57 msgid "Dur." msgstr "Süre" #: gaupol/enums.py:58 msgid "Duration" msgstr "Süre" #: gaupol/enums.py:63 gaupol/enums.py:64 msgid "Text" msgstr "Metin" #: gaupol/enums.py:69 gaupol/enums.py:70 msgid "Translation" msgstr "Çeviri" #: gaupol/enums.py:82 msgid "characters" msgstr "karakterler" #: gaupol/enums.py:85 msgid "ems" msgstr "ems" #: gaupol/page.py:60 msgid "Untitled {:d}" msgstr "İsimsiz {:d}" #: gaupol/page.py:133 msgid "Close project" msgstr "Projeyi kapat" #: gaupol/page.py:145 msgid "{} translation" msgstr "{} çevirisi" #: gaupol/page.py:302 msgid "Path:" msgstr "Yol:" #: gaupol/page.py:303 msgid "Format:" msgstr "Tip:" #: gaupol/page.py:304 msgid "Encoding:" msgstr "Kodlama:" #: gaupol/page.py:305 msgid "Newlines:" msgstr "Yeni satırlar:" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:99 msgid "Tasks and Target" msgstr "Görevler ve Hedef" #: gaupol/assistants.py:128 msgid "Correct texts in the text column" msgstr "Metin sütunundaki metinleri düzeltin" #: gaupol/assistants.py:129 msgid "Correct texts in the translation column" msgstr "Çeviri sütunundaki metinleri düzeltin" #: gaupol/assistants.py:138 msgid "Correct texts in selected subtitles" msgstr "Seçili altyazıdaki metinleri düzeltin" #: gaupol/assistants.py:139 msgid "Correct texts in current project" msgstr "Güncel projedeki metinleri düzeltin" #: gaupol/assistants.py:140 msgid "Correct texts in all open projects" msgstr "Tüm açılmamış projedeki metinleri düzeltin" #: gaupol/assistants.py:363 msgid "Other" msgstr "Diğer" #: gaupol/assistants.py:439 msgid "Capitalize texts written in lower case" msgstr "Küçük harfle yazılanları büyült" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:443 msgid "Capitalization Patterns" msgstr "" #: gaupol/assistants.py:445 msgid "Capitalize texts" msgstr "Büyük harf kuralını uygula" #: gaupol/assistants.py:468 msgid "Correct common errors made by humans or image recognition software" msgstr "" "Kullanıcı yada resim tanıma yazılımı tarafından oluşan genel hataları düzelt" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:472 msgid "Common Error Patterns" msgstr "" #: gaupol/assistants.py:474 msgid "Correct common errors" msgstr "Genel hataları düzelt" #: gaupol/assistants.py:526 msgid "Remove explanatory texts meant for the hearing impaired" msgstr "Bozulmuş oturum için açıklayıcı yazıyı sil" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:530 msgid "Hearing Impaired Patterns" msgstr "" #: gaupol/assistants.py:532 msgid "Remove hearing impaired texts" msgstr "Bozulmuş durum yazılarını sil" #: gaupol/assistants.py:544 msgid "" "Use spell-check suggestions to fix whitespace detection errors of image " "recognition software" msgstr "" "Resim tanıma yazılımının boşluk algılama hatalarını düzeltmek için yazım " "kontrolünü kullan" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:548 msgid "Joining and Splitting Words" msgstr "" #: gaupol/assistants.py:550 msgid "Join or Split Words" msgstr "Kelimeleri Birleştir/Ayır" #: gaupol/assistants.py:599 gaupol/agents/tools.py:45 msgid "Failed to load dictionary for language \"{}\"" msgstr "\"{}\" için sözlük yüklenemedi." #: gaupol/assistants.py:601 gaupol/player.py:263 gaupol/player.py:381 #: gaupol/dialogs/search.py:560 gaupol/dialogs/search.py:568 #: gaupol/dialogs/text_edit.py:49 gaupol/dialogs/encoding.py:56 #: gaupol/agents/open.py:328 gaupol/agents/open.py:337 #: gaupol/agents/open.py:345 gaupol/agents/open.py:354 #: gaupol/agents/tools.py:48 gaupol/agents/save.py:197 #: gaupol/agents/save.py:205 gaupol/agents/preview.py:108 #: gaupol/agents/preview.py:116 gaupol/agents/preview.py:125 #: gaupol/agents/preview.py:133 msgid "_OK" msgstr "_TAMAM" #: gaupol/assistants.py:635 msgid "Break text into lines of defined length" msgstr "Yazııları belirtilen uzunlukta satırlara böl" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:639 msgid "Line-Break Patterns" msgstr "" #: gaupol/assistants.py:641 msgid "Break lines" msgstr "Satırları durdur" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:679 msgid "Line-Break Options" msgstr "" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:763 msgid "Correcting Texts" msgstr "Yazılar düzeltiliyor" #: gaupol/assistants.py:769 msgid "Each task is now being run on each project." msgstr "Her görev, kendi projesinde çalışıyor." #: gaupol/assistants.py:793 #, python-brace-format msgid "{current:d} of {total:d} tasks complete" msgstr "Toplam {total:d} olaydan {current:d} 'i tamamlandı." #: gaupol/assistants.py:801 msgid "Project: {}" msgstr "Proje: {}" #: gaupol/assistants.py:807 msgid "Task: {}" msgstr "Görev: {}" #. TRANSLATORS: Keep these page titles short, since they #. affect the width of the text correction assistant sidebar. #: gaupol/assistants.py:832 msgid "Confirm Changes" msgstr "Değişimleri onayla" #: gaupol/assistants.py:892 msgid "Accept" msgstr "Kabul" #: gaupol/assistants.py:898 msgid "Original Text" msgstr "Orjinal Yazı" #: gaupol/assistants.py:899 msgid "Corrected Text" msgstr "Yazı Düzeltildi" #: gaupol/assistants.py:1048 msgid "Correct Texts" msgstr "Yazıları Düzelt" #: gaupol/assistants.py:1076 msgid "Correcting texts" msgstr "Yazılar düzeltiliyor" #: gaupol/assistants.py:1092 #, python-brace-format msgid "Edited {edits:d} and removed {removals:d} subtitles" msgstr "Düzenlenen: {edits:d}, Silinen: {removals:d} alt yazı." #: gaupol/assistants.py:1126 msgid "Confirm {:d} Change" msgid_plural "Confirm {:d} Changes" msgstr[0] "{:d} Değişikliği Doğrula" msgstr[1] "{:d} Değişikliği Doğrula" #: gaupol/renderers/multiline.py:86 msgid "Italic" msgstr "Eğik" #: gaupol/player.py:372 msgid "No video streams found" msgstr "" #: gaupol/player.py:379 msgid "Failed to initialize playback" msgstr "" #: gaupol/dialogs/search.py:189 data/ui/menubar.ui:524 msgid "_Help" msgstr "_Yardım" #: gaupol/dialogs/search.py:471 msgid "Found and replaced {:d} occurence" msgid_plural "Found and replaced {:d} occurences" msgstr[0] "" msgstr[1] "" #: gaupol/dialogs/search.py:488 msgid "\"{}\" not found" msgstr "\"{}\" bulunamadı" #: gaupol/dialogs/search.py:558 msgid "Error in regular expression pattern" msgstr "Düzenli ifade modellemesinde hata var" #: gaupol/dialogs/search.py:566 msgid "Error in regular expression replacement" msgstr "Düzenli ifade değiştirilmesinde hata var" #: gaupol/dialogs/text_edit.py:48 gaupol/dialogs/framerate_convert.py:63 #: gaupol/dialogs/insert.py:44 gaupol/dialogs/encoding.py:55 #: gaupol/dialogs/split.py:44 gaupol/dialogs/multi_close.py:54 #: gaupol/dialogs/open.py:63 gaupol/dialogs/position_transform.py:69 #: gaupol/dialogs/position_shift.py:71 gaupol/dialogs/multi_save.py:83 #: gaupol/dialogs/multi_save.py:215 gaupol/dialogs/duration_adjust.py:86 #: gaupol/dialogs/save.py:73 gaupol/dialogs/video.py:41 #: gaupol/agents/open.py:363 gaupol/agents/open.py:375 #: gaupol/agents/open.py:387 gaupol/agents/close.py:71 #: data/extensions/custom-framerates/custom-framerates.py:39 msgid "_Cancel" msgstr "_İptal" #: gaupol/dialogs/text_edit.py:53 msgid "Edit Text" msgstr "Yazıyı Düzenle" #: gaupol/dialogs/framerate_convert.py:64 msgid "Co_nvert" msgstr "_Dönüştür" #: gaupol/dialogs/insert.py:45 msgid "_Insert" msgstr "Ekle" #: gaupol/dialogs/insert.py:54 msgid "Above selection" msgstr "Seçilenin üstü" #: gaupol/dialogs/insert.py:55 msgid "Below selection" msgstr "Seçilenin altı" #: gaupol/dialogs/encoding.py:60 data/ui/preferences-dialog.ui:70 msgid "Character Encodings" msgstr "Karakter Kodlaması" #: gaupol/dialogs/encoding.py:78 gaupol/dialogs/encoding.py:125 msgid "Description" msgstr "Açıklama" #: gaupol/dialogs/encoding.py:85 gaupol/dialogs/encoding.py:132 msgid "Encoding" msgstr "Kodlama" #: gaupol/dialogs/encoding.py:141 msgid "Show in Menu" msgstr "Menüde göster" #: gaupol/dialogs/split.py:45 msgid "_Split" msgstr "B_öl" #: gaupol/dialogs/split.py:76 msgid "Splitting project" msgstr "Projeyi böl" #: gaupol/dialogs/split.py:97 #, python-brace-format msgid "Split {amount:d} subtitles to project \"{name}\"" msgstr "Alt yazıların {amount:d} 'i, \"{name}\" olarak bölündü." #: gaupol/dialogs/spell_check.py:269 msgid "Spell-checking" msgstr "Yazım kontrolü" #: gaupol/dialogs/preferences.py:217 msgid "{} Extension Website" msgstr "{} uzantılı web sitesi" #: gaupol/dialogs/preferences.py:429 msgid "Custom" msgstr "Kişisel" #: gaupol/dialogs/multi_close.py:38 msgid "Save changes to documents before closing?" msgstr "Kapatmadan önce dosyaları kaydetmek ister misiniz?" #: gaupol/dialogs/multi_close.py:39 gaupol/agents/open.py:384 #: gaupol/agents/close.py:68 msgid "If you don't save, changes will be permanently lost." msgstr "Kaydetmezseniz, değişiklikler silinecek." #: gaupol/dialogs/multi_close.py:53 gaupol/agents/close.py:70 msgid "Close _Without Saving" msgstr "Kaydetmeden kapat" #: gaupol/dialogs/multi_close.py:55 gaupol/dialogs/multi_save.py:84 #: gaupol/dialogs/save.py:74 gaupol/agents/open.py:388 #: gaupol/agents/close.py:72 data/ui/menubar.ui:34 msgid "_Save" msgstr "_Kaydet" #: gaupol/dialogs/multi_close.py:70 msgid "Select the _main documents you want to save:" msgstr "Kaydet_mek istediğiniz kaynak metni seçin:" #: gaupol/dialogs/multi_close.py:95 msgid "Select the _translation documents you want to save:" msgstr "Kaydetmek istediğini_z çeviri metnini seçin:" #: gaupol/dialogs/open.py:64 gaupol/agents/open.py:364 #: gaupol/agents/open.py:376 msgid "_Open" msgstr "_Aç" #: gaupol/dialogs/position_transform.py:70 msgid "_Transform" msgstr "Dönüştür" #: gaupol/dialogs/position_shift.py:72 msgid "_Shift" msgstr "_Kaydır" #: gaupol/dialogs/position_shift.py:150 msgid "frames" msgstr "kare (frame)" #: gaupol/dialogs/position_shift.py:168 data/ui/preferences-dialog.ui:911 msgid "seconds" msgstr "saniye" #: gaupol/dialogs/about.py:36 msgid "About Gaupol" msgstr "Gaupol Hakkında" #: gaupol/dialogs/about.py:40 msgid "Subtitle editor" msgstr "Alt Yazı Düzenleyicisi" #. TRANSLATORS: This is a special message that shouldn't be translated #. literally. It is used in the about dialog to give credits to the #. translators. Thus, you should translate it to your name and email #. address. You can also include other translators who have contributed #. to this translation; in that case, please write them on separate #. lines seperated by newlines (\n). #: gaupol/dialogs/about.py:51 msgid "translator-credits" msgstr "" "Koray Löker \n" "Çağlar Kilimci " #: gaupol/dialogs/about.py:54 msgid "Gaupol Website" msgstr "Gaupol web sitesi" #: gaupol/dialogs/append.py:35 msgid "Append File" msgstr "Dosyaya ilave et" #: gaupol/dialogs/debug.py:43 msgid "Something went wrong" msgstr "Birşeyler ters gitti" #: gaupol/dialogs/debug.py:44 msgid "" "You have probably discovered a bug. Please report it by providing the below " "information and a description of what you were doing." msgstr "" "Muhtemelen bir yazılım hatası ile karşılaştınız. Lütfen aşağıdaki alana " "gerekli bilgileri ve yaptığınız işlemin detaylı açıklamasını giriniz." #: gaupol/dialogs/debug.py:52 msgid "_Report Bug" msgstr "_Hatayı Raporla" #: gaupol/dialogs/debug.py:53 data/ui/menubar.ui:56 msgid "_Quit" msgstr "_Çık" #: gaupol/dialogs/debug.py:54 gaupol/dialogs/preview_error.py:45 #: data/ui/menubar.ui:52 data/ui/tab-popup.ui:16 msgid "_Close" msgstr "_Kapat" #: gaupol/dialogs/multi_save.py:98 gaupol/dialogs/save.py:110 msgid "{} (recommended)" msgstr "{} (Önerilir)" #: gaupol/dialogs/multi_save.py:212 msgid "" "{:d} of the files to be saved already exist. Do you want to replace them?" msgstr "" "Kaydedilecek olan {:d} dosya zaten var. Üzerine yazmak istiyor musunuz?" #: gaupol/dialogs/multi_save.py:213 msgid "" "The files already exist in \"{}\". Replacing them will overwrite their " "contents." msgstr "" "\"{}\" isimli zaten bir dosya var. Bu dosyanın üzerine yazmak istermisiniz?" #: gaupol/dialogs/multi_save.py:216 data/ui/search-dialog.ui:192 #: data/ui/spell-check-dialog.ui:122 msgid "_Replace" msgstr "_Değiştir" #: gaupol/dialogs/duration_adjust.py:70 msgid "Adjusted duration of {:d} subtitle" msgid_plural "Adjusted durations of {:d} subtitles" msgstr[0] "{:d} satırın süresi ayarlandı." msgstr[1] "{:d} satırın süresi ayarlandı." #: gaupol/dialogs/duration_adjust.py:87 msgid "_Adjust" msgstr "A_yarla" #: gaupol/dialogs/preview_error.py:36 msgid "Preview in video player failed" msgstr "Deneme filmi oynatılamadı" #: gaupol/dialogs/preview_error.py:37 msgid "" "There is probably a problem with either the video file or the video player. " "See the preferences dialog to choose the video player or to customize the " "command." msgstr "" "Muhtemelen video ya da video oynatıcıyla alakalı bir sorun oluştu. Video " "oynatıcı seçimi yapmak ya da komutu özelleştirmek için Tercihler sekmesine " "bakınız." #: gaupol/dialogs/language.py:97 msgid "Set Language" msgstr "Dili ayarla" #: gaupol/dialogs/video.py:52 gaupol/dialogs/file.py:59 msgid "All files" msgstr "Bütün dosyalar" #: gaupol/dialogs/video.py:56 msgid "Video files" msgstr "Video dosyası" #: gaupol/dialogs/file.py:63 msgid "All supported files" msgstr "Bütün desteklenen dosyalar" #: gaupol/dialogs/file.py:77 #, python-brace-format msgid "{format} (*{extension})" msgstr "" #: gaupol/dialogs/file.py:120 msgid "Auto-detected" msgstr "Otomatik algıla" #: gaupol/dialogs/file.py:122 msgid "Other…" msgstr "Diğer…" #: gaupol/agents/menu.py:94 gaupol/agents/menu.py:103 #: gaupol/agents/menu.py:110 msgid "File not found" msgstr "" #: gaupol/agents/open.py:85 #, python-brace-format msgid "Appended {amount:d} subtitles from \"{basename}\"" msgstr "\"{basename}\" den {amount:d} alt yazı eklendi" #: gaupol/agents/open.py:96 msgid "Appending file" msgstr "Dosya ekleniyor" #: gaupol/agents/open.py:111 msgid "File \"{}\" is already open" msgstr "\"{}\" dosyası zaten açık" #: gaupol/agents/open.py:214 msgid "Open Translation" msgstr "Çeviri aç" #: gaupol/agents/open.py:223 msgid "Select Video" msgstr "Video Seç" #: gaupol/agents/open.py:224 msgid "_Select" msgstr "_Seç" #: gaupol/agents/open.py:325 msgid "Failed to decode file \"{}\" with all attempted codecs" msgstr "\"{}\" dosyası denenen bütün kodeklerle oynatılamadı" #: gaupol/agents/open.py:326 msgid "Please try to open the file with a different character encoding." msgstr "Dosyayı başka karakter kodlamasıyla açmayı deneyin" #: gaupol/agents/open.py:334 msgid "Failed to recognize format of file \"{}\"" msgstr "\"{}\" dosyasının tipi tanınamadı" #: gaupol/agents/open.py:335 msgid "" "Please check that the file you are trying to open is a subtitle file of a " "format supported by Gaupol." msgstr "" "Lüften Gaupol tarafından desteklenen alt yazı dosyalarını açmaya çalışın." #: gaupol/agents/open.py:343 msgid "Failed to open file \"{}\"" msgstr "\"{}\" dosyası açılamadı" #: gaupol/agents/open.py:351 msgid "Failed to parse file \"{}\"" msgstr "\"{}\" dosyasının dizilimi hatalı" #: gaupol/agents/open.py:352 msgid "Please check that the file you are trying to open is a valid {} file." msgstr "" "Açtığınız dosyanın geçerli bir {} dosyası olup olmadığını kontrol edin." #: gaupol/agents/open.py:360 msgid "Open abnormally large file \"{}\"?" msgstr "\"{}\" dosyası çok büyük. Açmak istiyor musunuz?" #: gaupol/agents/open.py:361 msgid "" "Size of the file is {:.1f} MB, which is abnormally large for a text-based " "subtitle file. Please, check that you are not trying to open a binary file." msgstr "" "Dosyanın boyutu {:.1f} MB ki bu normal bir alt yazı dosyası için çok büyük. " "Lüften ikili dosya açmadığınızdan emin olun." #: gaupol/agents/open.py:371 msgid "Open unsorted file \"{}\"?" msgstr "\"{}\" dosyası sıralanmamış. Açmak istiyor musunuz?" #: gaupol/agents/open.py:372 msgid "" "The order of {:d} subtitles needs to be changed. If {:d} sounds like a lot, " "the file may be erroneously composed." msgstr "" "{:d} tane alt yazının sırası değişmesi gerekiyor. {:d} sayısı fazla gibi " "geldiyse dosya yanlışlıkla oluşmuş olabilir." #: gaupol/agents/open.py:383 msgid "Save changes to translation document \"{}\" before opening a new one?" msgstr "" "Yeni çeviri dosyası açmadan önce değişiklikleri \"{}\" 'e kaydetmek istiyor " "musunuz?" #: gaupol/agents/open.py:386 msgid "Open _Without Saving" msgstr "Kaydet_meden Aç" #: gaupol/agents/close.py:66 msgid "Save changes to document \"{}\" before closing?" msgstr "Kapatmadan önce değişiklikler \"{}\" dosyasına kaydedilsin mi?" #: gaupol/agents/edit.py:101 gaupol/agents/edit.py:119 msgid "Stretching end position" msgstr "" #: gaupol/agents/edit.py:208 msgid "Inserted {:d} subtitle to fit clipboard contents" msgid_plural "Inserted {:d} subtitles to fit clipboard contents" msgstr[0] "" msgstr[1] "" #: gaupol/agents/edit.py:334 gaupol/agents/edit.py:352 msgid "Stretching start position" msgstr "" #: gaupol/agents/edit.py:411 msgid "Use Shift+Return for line-break" msgstr "Satır arası bırakmak için Shift+Enter kullanın" #: gaupol/agents/save.py:129 msgid "Save As" msgstr "Farklı Kaydet" #: gaupol/agents/save.py:135 msgid "Saved main document as \"{}\"" msgstr "Ana döküman \"{}\" olarak kaydedildi" #: gaupol/agents/save.py:153 msgid "Save Translation As" msgstr "Çeviriyi farklı kaydet" #: gaupol/agents/save.py:159 msgid "Saved translation document as \"{}\"" msgstr "Çeviri dosyası \"{}\" olarak kaydedildi" #: gaupol/agents/save.py:194 #, python-brace-format msgid "Failed to encode file \"{basename}\" with codec \"{codec}\"" msgstr "\"{codec}\" kodeğini kullanarak \"{basename}\" dosyası kodlanamadı" #: gaupol/agents/save.py:195 msgid "Please try to save the file with a different character encoding." msgstr "Lütfen farklı karakter kodlama ile kaydetmeyi deneyin." #: gaupol/agents/save.py:203 msgid "Failed to save file \"{}\"" msgstr "\"{}\" kaydedilemedi" #: gaupol/agents/video.py:67 data/ui/menubar.ui:380 msgid "_Play/Pause" msgstr "_Oynat/Duraklat" #: gaupol/agents/video.py:69 msgid "Play or pause video" msgstr "" #: gaupol/agents/video.py:75 data/ui/menubar.ui:390 msgid "Seek _Previous" msgstr "" #: gaupol/agents/video.py:77 msgid "Seek to the start of the previous subtitle" msgstr "" #: gaupol/agents/video.py:81 data/ui/menubar.ui:394 msgid "Seek _Next" msgstr "" #: gaupol/agents/video.py:83 msgid "Seek to the start of the next subtitle" msgstr "" #: gaupol/agents/video.py:88 data/ui/menubar.ui:400 msgid "Seek _Backward" msgstr "" #: gaupol/agents/video.py:90 msgid "Seek backward" msgstr "" #: gaupol/agents/video.py:94 data/ui/menubar.ui:404 msgid "Seek _Forward" msgstr "" #: gaupol/agents/video.py:96 msgid "Seek forward" msgstr "" #: gaupol/agents/video.py:109 msgid "Volume" msgstr "" #: gaupol/agents/video.py:189 msgid "Load Video" msgstr "Video Yükle" #: gaupol/agents/video.py:189 msgid "_Load" msgstr "_Yükle" #: gaupol/agents/video.py:361 msgid "Track {:d}" msgstr "" #: gaupol/agents/preview.py:105 msgid "Failed to encode subtitle file to temporary directory \"{}\"" msgstr "Geçici yer olarak \"{}\" 'e kodlanamadı." #: gaupol/agents/preview.py:106 msgid "" "Subtitle data could not be encoded to a temporary file for preview with the " "current character encoding. Please first save the subtitle file with a " "different character encoding." msgstr "" "Alt yazı ön izleme için kullanılan karakter kodlama ile geçici dosyaya " "kodlanamadı. Lütfen farklı bir karakter kodlama ile kaydedin." #: gaupol/agents/preview.py:114 msgid "Failed to save subtitle file to temporary directory \"{}\"" msgstr "Alt yazı dosyası geçici klasör olan \"{}\" 'e kaydedilemedi" #: gaupol/agents/preview.py:122 msgid "Video player not found" msgstr "Video oynatıcı bulunamadı" #: gaupol/agents/preview.py:123 msgid "" "Please install one of the supported video players: mpv (recommended), " "MPlayer or VLC. See the preferences dialog to choose the video player or to " "customize the command." msgstr "" #: gaupol/agents/preview.py:131 msgid "Failed to launch video player" msgstr "Video oynatıcısı oynatılamadı" #: gaupol/applicationman.py:105 msgid "gaupol [OPTION...] [FILE...] [+[NUM]]" msgstr "gaupol [SEÇENEK...] [DOSYA...] [+[NUM]]" #: gaupol/applicationman.py:109 msgid "FILE..." msgstr "" #: gaupol/applicationman.py:112 msgid "subtitle files to open" msgstr "" #: gaupol/applicationman.py:122 msgid "ENCODING" msgstr "KARAKTER KODLAMA" #: gaupol/applicationman.py:125 msgid "set the character encoding used to open files" msgstr "Açık olan dosya için karakter kodlamayı uygula" #: gaupol/applicationman.py:132 msgid "list all available character encodings" msgstr "Ulaşılabilir bütün karakter kodlamalarını listele" #: gaupol/applicationman.py:137 gaupol/applicationman.py:154 msgid "FILE" msgstr "DOSYA" #: gaupol/applicationman.py:140 msgid "open translation file" msgstr "Açık çeviri dosyası" #: gaupol/applicationman.py:145 msgid "METHOD" msgstr "YÖNTEM" #: gaupol/applicationman.py:149 msgid "method used to align translation subtitles: 'number' or 'position'" msgstr "" "Çeviri alt yazılarını hizaya sokmak için 'numara' ya da 'durum' yöntemini " "kullanın." #: gaupol/applicationman.py:157 msgid "select video file" msgstr "Video dosyası seçiniz" #: data/extensions/custom-framerates/custom-framerates.py:40 #: data/ui/spell-check-dialog.ui:152 msgid "_Add" msgstr "_Ekle" #: data/extensions/custom-framerates/custom-framerates.py:171 msgid "{:.3f} fps" msgstr "{:.3f} fps" #: data/extensions/custom-framerates/add-framerate-dialog.ui:13 msgid "Add Framerate" msgstr "" #: data/extensions/custom-framerates/add-framerate-dialog.ui:44 msgid "_Framerate:" msgstr "" #: data/extensions/custom-framerates/add-framerate-dialog.ui:73 msgid "fps" msgstr "fps" #: data/extensions/custom-framerates/preferences-dialog.ui:8 msgid "Framerates" msgstr "" #: data/extensions/custom-framerates/preferences-dialog.ui:64 msgid "Add" msgstr "" #: data/ui/columns-popup.ui:6 data/ui/menubar.ui:275 msgid "_No." msgstr "_No." #: data/ui/columns-popup.ui:10 data/ui/menubar.ui:279 msgid "_Start" msgstr "_Başlangıç" #: data/ui/columns-popup.ui:14 data/ui/menubar.ui:283 msgid "_End" msgstr "Bi_tiş" #: data/ui/columns-popup.ui:18 data/ui/menubar.ui:287 msgid "_Duration" msgstr "_Süreç" #: data/ui/columns-popup.ui:22 data/ui/menubar.ui:291 data/ui/menubar.ui:303 msgid "_Text" msgstr "_Yazı" #: data/ui/columns-popup.ui:26 data/ui/menubar.ui:295 msgid "T_ranslation" msgstr "" #: data/ui/split-dialog.ui:15 msgid "Split Project" msgstr "Projeyi Böl" #: data/ui/split-dialog.ui:48 msgid "_First subtitle of new project:" msgstr "Yeni projenin _ilk altyazısı" #: data/ui/search-dialog.ui:89 msgid "_Search for:" msgstr "Aranan ifade:" #: data/ui/search-dialog.ui:103 data/ui/spell-check-dialog.ui:193 msgid "Replace _with:" msgstr "Bununla değişsin:" #: data/ui/search-dialog.ui:162 data/ui/menubar.ui:328 msgid "Find _Next" msgstr "S_onrakini bul" #: data/ui/search-dialog.ui:177 msgid "Find _Previous" msgstr "Ö_ncekini bul" #: data/ui/search-dialog.ui:207 msgid "Replace _All" msgstr "_Hepsini değiştir" #: data/ui/search-dialog.ui:241 msgid "R_egular expression" msgstr "_Düzenli ifade" #: data/ui/search-dialog.ui:258 msgid "_Ignore case" msgstr "Küçük/büyük harf _fark etmez" #: data/ui/search-dialog.ui:304 data/ui/language-dialog.ui:108 msgid "Columns" msgstr "Sütunlar" #: data/ui/search-dialog.ui:324 msgid "Find in _text column" msgstr "" #: data/ui/search-dialog.ui:341 msgid "Find in t_ranslation column" msgstr "" #: data/ui/search-dialog.ui:381 data/ui/framerate-convert-dialog.ui:144 #: data/ui/language-dialog.ui:186 #: data/ui/text-assistant/line-break-options-page.ui:178 #: data/ui/duration-adjust-dialog.ui:388 data/ui/position-shift-dialog.ui:180 #: data/ui/position-transform-dialog.ui:444 msgid "Subtitles" msgstr "Altyazılar" #: data/ui/search-dialog.ui:401 msgid "Find in c_urrent project" msgstr "B_u projede ara" #: data/ui/search-dialog.ui:419 msgid "Find in _all open projects" msgstr "Açık _tüm projelerde ara" #: data/ui/search-dialog.ui:452 msgid "Target" msgstr "Hedef" #: data/ui/framerate-convert-dialog.ui:8 msgid "Convert Framerate" msgstr "Kare hızını (framerate) dönüştür" #: data/ui/framerate-convert-dialog.ui:48 msgid "Framerate" msgstr "Kare hızı (framerate)" #: data/ui/framerate-convert-dialog.ui:71 msgid "_Input:" msgstr "Girdi:" #: data/ui/framerate-convert-dialog.ui:86 msgid "_Output:" msgstr "Çıktı:" #: data/ui/framerate-convert-dialog.ui:164 msgid "Convert c_urrent project" msgstr "Sade_ce bu projeyi dönüştür" #: data/ui/framerate-convert-dialog.ui:181 msgid "Convert _all open projects" msgstr "_Tüm açık projeleri dönüştür" #: data/ui/spell-check-dialog.ui:8 msgid "Check Spelling" msgstr "İmla denetimi" #: data/ui/spell-check-dialog.ui:47 msgid "Join _Back" msgstr "Ön_cekiyle birleştir" #: data/ui/spell-check-dialog.ui:62 msgid "Join _Forward" msgstr "S_onrakiyle birleştir" #: data/ui/spell-check-dialog.ui:77 data/ui/menubar.ui:62 msgid "_Edit" msgstr "_Düzenle" #: data/ui/spell-check-dialog.ui:92 msgid "_Ignore" msgstr "A_tla" #: data/ui/spell-check-dialog.ui:107 msgid "Ig_nore All" msgstr "He_psini atla" #: data/ui/spell-check-dialog.ui:137 msgid "Rep_lace All" msgstr "_Hepsini Değiştir" #: data/ui/spell-check-dialog.ui:179 msgid "_Suggestions:" msgstr "Öner_i" #: data/ui/multi-save-dialog.ui:8 msgid "Save All As" msgstr "Tümünü farklı kaydet" #: data/ui/multi-save-dialog.ui:46 msgid "Save in _folder:" msgstr "Tümünü _klasöre kaydet:" #: data/ui/multi-save-dialog.ui:60 data/ui/save-dialog.ui:25 msgid "For_mat:" msgstr "B_içim:" #: data/ui/multi-save-dialog.ui:74 data/ui/open-dialog.ui:25 #: data/ui/save-dialog.ui:39 msgid "_Encoding:" msgstr "" #: data/ui/multi-save-dialog.ui:88 data/ui/save-dialog.ui:53 msgid "Ne_wlines:" msgstr "Y_eni satır:" #: data/ui/multi-save-dialog.ui:103 msgid "Select A Folder" msgstr "Bir klasör seçin" #: data/ui/multi-save-dialog.ui:150 data/ui/save-dialog.ui:102 msgid "F_ramerate:" msgstr "" #: data/ui/menubar.ui:5 msgid "_File" msgstr "_Dosya" #: data/ui/menubar.ui:8 msgid "_New" msgstr "_Yeni" #: data/ui/menubar.ui:12 msgid "_Open…" msgstr "_Aç…" #: data/ui/menubar.ui:16 msgid "Open _Translation…" msgstr "Çeviri Aç…" #: data/ui/menubar.ui:22 msgid "Open _Recent" msgstr "_Geçmişi Aç" #: data/ui/menubar.ui:27 msgid "Open R_ecent Translation" msgstr "Geç_miş Çevirleri Aç" #: data/ui/menubar.ui:38 msgid "Save _As…" msgstr "_Farklı Kaydet" #: data/ui/menubar.ui:42 msgid "Save Trans_lation" msgstr "Çeviriyi Kayde_t" #: data/ui/menubar.ui:46 msgid "Save Translat_ion As…" msgstr "Çev_iriyi farklı kaydet…" #: data/ui/menubar.ui:65 msgid "_Undo" msgstr "_Geri Al" #: data/ui/menubar.ui:69 msgid "_Redo" msgstr "_İleri al" #: data/ui/menubar.ui:75 msgid "_Edit Cell" msgstr "Hücreyi _Düzenle" #: data/ui/menubar.ui:79 msgid "Edit _Next Cell" msgstr "_Sonraki Hücreyi Düzenle" #: data/ui/menubar.ui:85 msgid "Stretc_h" msgstr "" #: data/ui/menubar.ui:88 msgid "_Start Earlier" msgstr "" #: data/ui/menubar.ui:92 msgid "S_tart Later" msgstr "" #: data/ui/menubar.ui:98 msgid "E_nd Earlier" msgstr "" #: data/ui/menubar.ui:102 msgid "En_d Later" msgstr "" #: data/ui/menubar.ui:108 msgid "Set St_art From Video Position" msgstr "" #: data/ui/menubar.ui:112 msgid "Set En_d From Video Position" msgstr "" #: data/ui/menubar.ui:118 data/ui/view-popup.ui:6 msgid "_Split Subtitle" msgstr "Alt Yazıyı B_öl" #: data/ui/menubar.ui:122 data/ui/view-popup.ui:10 msgid "_Merge Subtitles" msgstr "Alt Yazıları _Birleştir" #: data/ui/menubar.ui:128 data/ui/view-popup.ui:16 msgid "_Insert Subtitles…" msgstr "Yeni atl yazı _Ekle" #: data/ui/menubar.ui:132 msgid "Inser_t Subtitle At Video Position" msgstr "" #: data/ui/menubar.ui:136 data/ui/view-popup.ui:20 msgid "Rem_ove Subtitles" msgstr "Alt yazıları _Sil" #: data/ui/menubar.ui:142 msgid "Sele_ction" msgstr "Seçi_m" #: data/ui/menubar.ui:145 msgid "Select _All" msgstr "_Hepsini Seç" #: data/ui/menubar.ui:149 msgid "_Invert Selection" msgstr "_Ters Çevir" #: data/ui/menubar.ui:155 msgid "Extend To _Beginning" msgstr "_Başlangıca Uzat" #: data/ui/menubar.ui:159 msgid "Extend To _End" msgstr "_Sona Uzat" #: data/ui/menubar.ui:165 msgid "_Previous From Video Position" msgstr "" #: data/ui/menubar.ui:169 msgid "_Next From Video Position" msgstr "" #: data/ui/menubar.ui:177 msgid "_Preferences" msgstr "_Tercihler" #: data/ui/menubar.ui:183 msgid "_View" msgstr "_Görünüş" #: data/ui/menubar.ui:186 msgid "Tool_bar" msgstr "" #: data/ui/menubar.ui:190 msgid "_Video Player" msgstr "_Video Oynatıcı" #: data/ui/menubar.ui:196 msgid "_Layout" msgstr "_Yerleşim" #: data/ui/menubar.ui:199 msgid "_Horizontal" msgstr "_Yatay" #: data/ui/menubar.ui:204 msgid "_Vertical" msgstr "_Dikey" #: data/ui/menubar.ui:213 msgid "_Times" msgstr "_Tekrar" #: data/ui/menubar.ui:218 msgid "_Frames" msgstr "_Kare" #: data/ui/menubar.ui:225 msgid "F_ramerate" msgstr "Kare _Hızı" #: data/ui/menubar.ui:228 msgid "2_3.976 fps" msgstr "2_3.976 fps" #: data/ui/menubar.ui:233 msgid "2_4.000 fps" msgstr "2_4.000 fps" #: data/ui/menubar.ui:238 msgid "2_5.000 fps" msgstr "2_5.000 fps" #: data/ui/menubar.ui:243 msgid "2_9.970 fps" msgstr "2_9.970 fps" #: data/ui/menubar.ui:272 msgid "_Columns" msgstr "_Sütunlar" #: data/ui/menubar.ui:306 msgid "Cu_t" msgstr "Ke_s" #: data/ui/menubar.ui:310 msgid "_Copy" msgstr "K_opyala" #: data/ui/menubar.ui:314 msgid "_Paste" msgstr "_Yapıştır" #: data/ui/menubar.ui:318 msgid "Cl_ear" msgstr "T_emizle" #: data/ui/menubar.ui:324 msgid "_Find And Replace…" msgstr "Bul ve Değiştir…" #: data/ui/menubar.ui:332 msgid "Find Pre_vious" msgstr "Sonrakini _Bul" #: data/ui/menubar.ui:338 msgid "_Italic" msgstr "_Italik" #: data/ui/menubar.ui:342 msgid "_Dialogue" msgstr "_Diyalog" #: data/ui/menubar.ui:348 msgid "Ca_se" msgstr "Büyük/Küçük Harf" #: data/ui/menubar.ui:351 msgid "_Title" msgstr "_Başlık" #: data/ui/menubar.ui:355 msgid "_Sentence" msgstr "_Cümle" #: data/ui/menubar.ui:359 msgid "_Upper" msgstr "Harfleri _Büyüt" #: data/ui/menubar.ui:363 msgid "_Lower" msgstr "Harfleri _Küçült" #: data/ui/menubar.ui:371 msgid "Vi_deo" msgstr "Vi_deo" #: data/ui/menubar.ui:374 msgid "_Load Video…" msgstr "_Video Yükle…" #: data/ui/menubar.ui:384 data/ui/view-popup.ui:26 msgid "Play _Selection" msgstr "" #: data/ui/menubar.ui:410 data/ui/view-popup.ui:30 msgid "S_eek Selection Start" msgstr "" #: data/ui/menubar.ui:414 msgid "See_k Selection End" msgstr "" #: data/ui/menubar.ui:420 msgid "_Audio" msgstr "_Ses" #: data/ui/menubar.ui:423 msgid "_Language" msgstr "_Dil" #: data/ui/menubar.ui:430 msgid "Volume _Down" msgstr "Sesi _Azalt" #: data/ui/menubar.ui:434 msgid "Volume _Up" msgstr "Sesi _Arttır" #: data/ui/menubar.ui:440 msgid "T_ools" msgstr "_Araçlar" #: data/ui/menubar.ui:443 data/ui/text-assistant/confirmation-page.ui:97 #: data/ui/view-popup.ui:36 msgid "_Preview" msgstr "İ_zleyerek dene" #: data/ui/menubar.ui:447 msgid "Select _Video…" msgstr "_Video Seç…" #: data/ui/menubar.ui:453 msgid "_Check Spelling" msgstr "Yazım _Kontrolu Yap" #: data/ui/menubar.ui:457 msgid "Co_nfigure Spell-check…" msgstr "Yazım ko_ntrolü ayarla" #: data/ui/menubar.ui:461 msgid "C_orrect Texts…" msgstr "Yazıyı Düzelt…" #: data/ui/menubar.ui:467 msgid "_Shift Positions…" msgstr "Durumu Ka_ydır" #: data/ui/menubar.ui:471 msgid "_Transform Positions…" msgstr "Durumları Dönüş_tür…" #: data/ui/menubar.ui:475 msgid "Adjust _Durations…" msgstr "Süreçleri Ayarla…" #: data/ui/menubar.ui:479 msgid "Convert _Framerate…" msgstr "_Kare Hızını Çevir…" #: data/ui/menubar.ui:485 msgid "_Append File…" msgstr "Dosya _Ekle..." #: data/ui/menubar.ui:489 msgid "Spli_t Project…" msgstr "Projeyi B_öl…" #: data/ui/menubar.ui:495 msgid "_Projects" msgstr "_Proje" #: data/ui/menubar.ui:498 msgid "_Save All" msgstr "_Hepsini Kaydet" #: data/ui/menubar.ui:502 msgid "Save _All As…" msgstr "Hepsini F_arklı Kaydet..." #: data/ui/menubar.ui:506 msgid "_Close All" msgstr "Hepsini Kapa_t" #: data/ui/menubar.ui:512 msgid "_Previous" msgstr "_Önceki" #: data/ui/menubar.ui:516 msgid "_Next" msgstr "_Sonraki" #: data/ui/menubar.ui:527 msgid "_Documentation" msgstr "_Belgelendirme" #: data/ui/menubar.ui:531 msgid "_Report A Bug" msgstr "Ha_ta Bildir" #: data/ui/menubar.ui:535 msgid "_About" msgstr "Ha_kkında" #: data/ui/open-dialog.ui:39 msgid "Align _method:" msgstr "Hi_zalama:" #: data/ui/preferences-dialog.ui:18 msgid "Preferences" msgstr "Tercihler" #: data/ui/preferences-dialog.ui:93 msgid "When opening files, try encodings in the following order:" msgstr "Dosya açarken kodlamaları aşağıdaki sırayla dene:" #: data/ui/preferences-dialog.ui:104 msgid "Curr_ent locale encoding" msgstr "S_eçili yerel kodlama" #: data/ui/preferences-dialog.ui:130 msgid "_Fallback encodings:" msgstr "Kodlamayı _Geri al:" #: data/ui/preferences-dialog.ui:246 msgid "Aut_o-detection" msgstr "O_tomatik bul" #: data/ui/preferences-dialog.ui:266 msgid "Encoding specified in the open dialog will always be tried first." msgstr "Önce dosyayı açarken seçilen karakter kodlaması denensin" #: data/ui/preferences-dialog.ui:296 msgid "File" msgstr "Dosya" #: data/ui/preferences-dialog.ui:324 msgid "Font" msgstr "Yazı tipi" #: data/ui/preferences-dialog.ui:344 msgid "Use _default theme fixed width font" msgstr "" #: data/ui/preferences-dialog.ui:368 msgid "_Editor font:" msgstr "Editör yazı tipi:" #: data/ui/preferences-dialog.ui:425 msgid "Line Lengths" msgstr "Satır uzunluğu" #: data/ui/preferences-dialog.ui:445 msgid "_Show line lengths in list cells" msgstr "Liste _görünümünde satır uzunluğu göster" #: data/ui/preferences-dialog.ui:462 msgid "S_how line lengths in editable text fields" msgstr "Metin alanlarında satır uzunluğunu göster" #: data/ui/preferences-dialog.ui:486 msgid "_Length unit:" msgstr "Uzunluk _birimi:" #: data/ui/preferences-dialog.ui:540 msgid "Spell-Check" msgstr "İmla denetimi" #: data/ui/preferences-dialog.ui:560 msgid "Chec_k spelling as you type" msgstr "Yazarken imla denet_le" #: data/ui/preferences-dialog.ui:598 msgid "Editor" msgstr "Editör" #: data/ui/preferences-dialog.ui:626 msgid "Fonts" msgstr "Yazıtipleri" #: data/ui/preferences-dialog.ui:649 msgid "_Subtitles:" msgstr "_Altyazılar:" #: data/ui/preferences-dialog.ui:679 msgid "_Time:" msgstr "_Zaman:" #: data/ui/preferences-dialog.ui:729 msgid "Colors" msgstr "Renkler" #: data/ui/preferences-dialog.ui:752 msgid "Su_btitles:" msgstr "" #: data/ui/preferences-dialog.ui:777 msgid "_Use a background behind text" msgstr "" #: data/ui/preferences-dialog.ui:797 msgid "Ti_me:" msgstr "" #: data/ui/preferences-dialog.ui:822 msgid "Us_e a background behind text" msgstr "" #: data/ui/preferences-dialog.ui:862 msgid "Seek" msgstr "" #: data/ui/preferences-dialog.ui:883 msgid "_Length:" msgstr "" #: data/ui/preferences-dialog.ui:971 msgid "Video Player" msgstr "Video oynatıcı" #: data/ui/preferences-dialog.ui:994 msgid "_Application:" msgstr "_Uygulama:" #: data/ui/preferences-dialog.ui:1008 msgid "Co_mmand:" msgstr "Ko_mut:" #. Translators: Only the title is to be translated, field names not. #: data/ui/preferences-dialog.ui:1033 msgid "" "Fields:\n" " $MILLISECONDS\n" " $SECONDS\n" " $SUBFILE\n" " $VIDEOFILE" msgstr "" #: data/ui/preferences-dialog.ui:1048 msgid "Al_ways use UTF-8 character encoding" msgstr "Mutlaka UTF-8 karakter kodlaması kullan" #: data/ui/preferences-dialog.ui:1089 msgid "Start Position" msgstr "Başlangıç pozisyonu" #: data/ui/preferences-dialog.ui:1111 msgid "_Offset:" msgstr "_Ofset:" #: data/ui/preferences-dialog.ui:1142 msgid "seconds before selection" msgstr "seçimden kaç saniye önce" #: data/ui/preferences-dialog.ui:1281 msgid "Extensions" msgstr "Eklentiler" #: data/ui/language-dialog.ui:8 msgid "Configure Spell-Check" msgstr "İmla denetimini yapılandır" #: data/ui/language-dialog.ui:50 msgid "Language" msgstr "Dil" #: data/ui/language-dialog.ui:128 msgid "Check _text column" msgstr "" #: data/ui/language-dialog.ui:146 msgid "Check t_ranslation column" msgstr "" #: data/ui/language-dialog.ui:206 msgid "Check c_urrent project" msgstr "Bu pro_jeyi kontrol et" #: data/ui/language-dialog.ui:224 msgid "Check _all open projects" msgstr "Tüm açık projeleri ko_ntrol et" #: data/ui/text-assistant/confirmation-page.ui:22 msgid "Acc_ept, discard or edit changes:" msgstr "Değişi_klikleri kabul et, reddet ya da düzenle:" #: data/ui/text-assistant/confirmation-page.ui:67 msgid "_Mark All" msgstr "Hepsini _seç" #: data/ui/text-assistant/confirmation-page.ui:82 msgid "_Unmark All" msgstr "Tüm seçimleri _kaldır" #: data/ui/text-assistant/confirmation-page.ui:119 msgid "_Remove all blank subtitles" msgstr "Boş altyazıların tümünü _sil" #: data/ui/text-assistant/join-split-page.ui:28 msgid "Spell-Check Dictionary" msgstr "İmla Denetimi Sözlüğü" #: data/ui/text-assistant/join-split-page.ui:49 #: data/ui/text-assistant/line-break-page.ui:81 #: data/ui/text-assistant/hearing-impaired-page.ui:81 #: data/ui/text-assistant/common-error-page.ui:80 #: data/ui/text-assistant/capitalization-page.ui:80 msgid "_Language:" msgstr "_Dil:" #: data/ui/text-assistant/join-split-page.ui:97 msgid "Corrections" msgstr "Düzeltmeler" #: data/ui/text-assistant/join-split-page.ui:117 msgid "_Join words not found in spell-check dictionary" msgstr "İmla denetimi sözlüğünde olmayan sözcükleri _birleştir" #: data/ui/text-assistant/join-split-page.ui:134 msgid "_Split words not found in spell-check dictionary" msgstr "İmla denetimi sözlüğünde bulunamayan sözcükleri _ayır" #: data/ui/text-assistant/line-break-page.ui:22 msgid "S_elect preferred line-break points:" msgstr "Tercih edilen _satır başı noktası seçimi:" #: data/ui/text-assistant/line-break-page.ui:67 #: data/ui/text-assistant/hearing-impaired-page.ui:67 #: data/ui/text-assistant/common-error-page.ui:66 #: data/ui/text-assistant/capitalization-page.ui:66 msgid "_Script:" msgstr "_Alfabe" #: data/ui/text-assistant/line-break-page.ui:95 #: data/ui/text-assistant/hearing-impaired-page.ui:95 #: data/ui/text-assistant/common-error-page.ui:94 #: data/ui/text-assistant/capitalization-page.ui:94 msgid "Co_untry:" msgstr "" #: data/ui/text-assistant/introduction-page.ui:28 msgid "_Select corrections to perform on texts:" msgstr "Metinler için düzelt_meleri seç:" #: data/ui/text-assistant/introduction-page.ui:79 msgid "Colu_mns:" msgstr "" #: data/ui/text-assistant/introduction-page.ui:93 msgid "S_ubtitles:" msgstr "" #: data/ui/text-assistant/line-break-options-page.ui:56 #: data/ui/duration-adjust-dialog.ui:207 msgid "Limits" msgstr "Sınır" #: data/ui/text-assistant/line-break-options-page.ui:79 msgid "_Maximum line length:" msgstr "Ma_ksimum satır sayısı:" #: data/ui/text-assistant/line-break-options-page.ui:93 msgid "_Preferred maximum amount of lines:" msgstr "_Tercih edilen maksimum satır sayısı:" #: data/ui/text-assistant/line-break-options-page.ui:198 msgid "_Skip subtitles with maximum line length of:" msgstr "Bu _değerin üzerinde satır sayısı olan altyazıları atla:" #: data/ui/text-assistant/line-break-options-page.ui:214 msgid "S_kip subtitles with maximum line amount of:" msgstr "Bu _değerin üzerinde satır sayısı olan altyazıları atla:" #: data/ui/text-assistant/hearing-impaired-page.ui:22 msgid "S_elect parts to remove:" msgstr "Silinecek bölümleri s_eç:" #: data/ui/text-assistant/common-error-page.ui:22 msgid "S_elect errors to correct:" msgstr "Dü_zeltilecek hatalar:" #: data/ui/text-assistant/common-error-page.ui:108 msgid "Error types:" msgstr "Hata tipi:" #: data/ui/text-assistant/common-error-page.ui:158 msgid "_Human errors" msgstr "İ_nsan hatası" #: data/ui/text-assistant/common-error-page.ui:175 msgid "_Image recognition errors" msgstr "_Resim tanıma hataları" #: data/ui/text-assistant/capitalization-page.ui:22 msgid "S_elect parts to capitalize:" msgstr "Büyük har_f yapılacaklar:" #: data/ui/duration-adjust-dialog.ui:33 msgid "Adjust Durations" msgstr "Süreyi ayarla" #: data/ui/duration-adjust-dialog.ui:73 msgid "Theoretic Duration" msgstr "Varsayılan Süre" #: data/ui/duration-adjust-dialog.ui:101 msgid "_Reading speed:" msgstr "Ok_uma hızı:" #: data/ui/duration-adjust-dialog.ui:133 msgid "characters per second" msgstr "karakter/saniye" #: data/ui/duration-adjust-dialog.ui:150 msgid "_Lengthen duration to match reading speed" msgstr "Süre_yi okuma hızına uydurmak için uzat" #: data/ui/duration-adjust-dialog.ui:167 msgid "_Shorten duration to match reading speed" msgstr "Süre_yi okuma hızına uydurmak için kısalt" #: data/ui/duration-adjust-dialog.ui:227 msgid "_Minimum duration:" msgstr "Mi_nimum süre:" #: data/ui/duration-adjust-dialog.ui:243 msgid "Ma_ximum duration:" msgstr "Mak_simum süre:" #: data/ui/duration-adjust-dialog.ui:259 msgid "_Gap between subtitles:" msgstr "Altyazılar arasındaki b_oşluk" #: data/ui/duration-adjust-dialog.ui:294 msgid "s_econds" msgstr "s_aniye" #: data/ui/duration-adjust-dialog.ui:324 msgid "seco_nds" msgstr "san_iye" #: data/ui/duration-adjust-dialog.ui:354 msgid "secon_ds" msgstr "saniy_e" #: data/ui/duration-adjust-dialog.ui:408 msgid "Adj_ust selected subtitles" msgstr "Seçili altyazıyı a_yarla" #: data/ui/duration-adjust-dialog.ui:425 msgid "Adjus_t current project" msgstr "Bu projeyi _ayarla" #: data/ui/duration-adjust-dialog.ui:442 msgid "Adjust all _open projects" msgstr "Açık tü_m projeleri ayarla" #: data/ui/tab-popup.ui:6 msgid "Move Tab _Left" msgstr "Sekmeyi So_la Taşı" #: data/ui/tab-popup.ui:10 msgid "Move Tab _Right" msgstr "Sekmeyi Sa_ğa Taşı" #: data/ui/insert-dialog.ui:15 msgid "Insert Subtitles" msgstr "Altyazı ekle" #: data/ui/insert-dialog.ui:48 data/ui/position-shift-dialog.ui:82 msgid "_Amount:" msgstr "Kaydırılacak süre:" #: data/ui/insert-dialog.ui:62 msgid "_Position:" msgstr "Pozisyon:" #: data/ui/position-shift-dialog.ui:14 msgid "Shift Positions" msgstr "Pozisyonları kaydır" #: data/ui/position-shift-dialog.ui:54 msgid "Shift" msgstr "Kaydır" #: data/ui/position-shift-dialog.ui:135 #: data/ui/position-transform-dialog.ui:208 msgid "_Preview Changes" msgstr "İ_zleyerek dene" #: data/ui/position-shift-dialog.ui:200 msgid "Shift s_elected subtitles" msgstr "S_eçili altyazıyı kaydır" #: data/ui/position-shift-dialog.ui:217 msgid "Shift su_btitles from selection to end" msgstr "" #: data/ui/position-shift-dialog.ui:234 msgid "Shift c_urrent project" msgstr "B_u projeyi kaydır" #: data/ui/position-shift-dialog.ui:251 msgid "Shift all _open projects" msgstr "" #: data/ui/position-transform-dialog.ui:22 msgid "Transform Positions" msgstr "Pozisyonları dönüştür" #: data/ui/position-transform-dialog.ui:62 msgid "First Point" msgstr "Başlangıç Noktası" #: data/ui/position-transform-dialog.ui:91 msgid "_Subtitle:" msgstr "Al_tyazı" #: data/ui/position-transform-dialog.ui:105 msgid "C_orrection:" msgstr "_Düzeltme:" #: data/ui/position-transform-dialog.ui:119 #: data/ui/position-transform-dialog.ui:310 msgid "Text:" msgstr "Metin:" #: data/ui/position-transform-dialog.ui:253 msgid "Second Point" msgstr "İkinci Nokta" #: data/ui/position-transform-dialog.ui:282 msgid "Su_btitle:" msgstr "A_ltyazı:" #: data/ui/position-transform-dialog.ui:296 msgid "Co_rrection:" msgstr "Dü_zeltme:" #: data/ui/position-transform-dialog.ui:399 msgid "Pre_view Changes" msgstr "İ_zleyerek dene" #: data/ui/position-transform-dialog.ui:464 msgid "Transform se_lected subtitles" msgstr "S_eçili altyazıları dönüştür" #: data/ui/position-transform-dialog.ui:482 msgid "Transform c_urrent project" msgstr "Bu proje _için pozisyonları dönüştür" #: data/extensions/custom-framerates/custom-framerates.extension.in:7 msgid "Custom Framerates" msgstr "" #: data/extensions/custom-framerates/custom-framerates.extension.in:8 msgid "Allow use of non-standard framerates" msgstr "" #: data/patterns/Latn-en-US.common-error.in:5 msgid "Period after title" msgstr "Hitap sonu süresi" #: data/patterns/Latn-en-US.common-error.in:6 msgid "Add period after a shortened title, such as \"Mr\" and \"Dr\"" msgstr "\"Dr\" ya da \"Bay\" gibi kısa bir hitaptan sonra süre ekle" #: data/patterns/Latn-en.capitalization.in:5 msgid "First person pronoun" msgstr "İngilizce birinci tekil şahıs zamiri" #: data/patterns/Latn-en.capitalization.in:6 msgid "Capitalize the first person pronoun \"I\"" msgstr "I şeklindeki İngilizce birinci tekil zamirini büyük harf yap" #: data/patterns/Latn-en.common-error.in:5 #: data/patterns/Latn-en.common-error.in:14 #: data/patterns/Latn-en.common-error.in:23 msgid "Letter \"I\" in a lower case word" msgstr "\"I\" harfi küçük harfle yazılan sözcük içinde" #: data/patterns/Latn-en.common-error.in:6 #: data/patterns/Latn-en.common-error.in:15 #: data/patterns/Latn-en.common-error.in:24 msgid "Replace letter \"I\" with letter \"l\" in a lower case word" msgstr "\"I\" harfini küçük harfli sözcüklerde \"l\" ile değiştir" #: data/patterns/Latn-en.common-error.in:32 #: data/patterns/Latn-en.common-error.in:41 #: data/patterns/Latn-en.common-error.in:50 #: data/patterns/Latn-en.common-error.in:62 msgid "Letter \"l\" in an upper case word" msgstr "\"I\" harfi büyük harfle yazılan sözcük içinde" #: data/patterns/Latn-en.common-error.in:33 #: data/patterns/Latn-en.common-error.in:42 #: data/patterns/Latn-en.common-error.in:51 #: data/patterns/Latn-en.common-error.in:63 msgid "Replace letter \"l\" with letter \"I\" in an upper case word" msgstr "\"l\" harfini büyük harfli sözcüklerde \"I\" ile değiştir" #: data/patterns/Latn-en.common-error.in:73 #: data/patterns/Latn-en.common-error.in:82 msgid "Zero in an upper case word" msgstr "Büyük harfle yazımda sıfır" #: data/patterns/Latn-en.common-error.in:74 #: data/patterns/Latn-en.common-error.in:83 msgid "Replace zero with letter \"O\" in an upper case word" msgstr "Büyük harfli yazımda sıfır yerine \"O\" kullan" #: data/patterns/Latn-en.common-error.in:91 #: data/patterns/Latn.common-error.in:108 msgid "Space between number and unit" msgstr "Rakam ve birim arasındaki boşluk" #: data/patterns/Latn-en.common-error.in:92 #: data/patterns/Latn.common-error.in:109 msgid "Add or remove space between a number and the associated unit" msgstr "Rakamla ilgili karakter arasındaki boşluğu ekle ya da kaldır" #: data/patterns/Latn-en.common-error.in:100 msgid "Spaces around an apostrophe" msgstr "Kesme işareti çevresinde boşluk" #: data/patterns/Latn-en.common-error.in:101 msgid "Remove spaces around an apostrophe" msgstr "Kesme işaretinin önünde sonunda boşluk kalmasın" #: data/patterns/Latn-en.common-error.in:109 #: data/patterns/Latn-en.common-error.in:118 msgid "Okay" msgstr "Okay" #: data/patterns/Latn-en.common-error.in:110 #: data/patterns/Latn-en.common-error.in:119 msgid "Spell two-letter forms of \"okay\" in all upper case" msgstr "" #: data/patterns/Latn-en.hearing-impaired.in:5 msgid "Uppercase speaker before a colon" msgstr "İki nokta öncesinde büyük harfli isim" #: data/patterns/Latn-en.hearing-impaired.in:6 msgid "" "Replace the uppercase name of the speaker before a colon with a dialogue " "dash" msgstr "" "Diyalog işaretli cümlede iki nokta varsa konuşmacı ismindeki büyük harfi " "düzelt" #: data/patterns/Latn-en.line-break.in:5 msgid "Title" msgstr "Başlık" #: data/patterns/Latn-en.line-break.in:6 msgid "Do not break after a title, e.g. \" Dr.\"" msgstr "" #: data/patterns/Latn-en.line-break.in:13 msgid "Article" msgstr "" #: data/patterns/Latn-en.line-break.in:14 msgid "Do not break after an article" msgstr "" #: data/patterns/Latn-en.line-break.in:21 msgid "Preposition" msgstr "" #: data/patterns/Latn-en.line-break.in:22 msgid "Do not break after a preposition" msgstr "" #: data/patterns/Latn-en.line-break.in:30 msgid "Possessive determiner" msgstr "" #: data/patterns/Latn-en.line-break.in:31 msgid "Do not break after a possessive determiner, e.g. \"my\"" msgstr "" #: data/patterns/Latn-fi.common-error.in:5 #: data/patterns/Latn.common-error.in:182 msgid "Space after punctuation marks" msgstr "Noktalama işraretlerinden sonraki boşluk" #: data/patterns/Latn-fi.common-error.in:6 #: data/patterns/Latn.common-error.in:183 msgid "Add space after various punctuation marks" msgstr "Noktalama işaretlerinden sonra boşluk koy" #: data/patterns/Latn-fr.common-error.in:5 #: data/patterns/Latn-fr.common-error.in:14 #: data/patterns/Latn-fr.common-error.in:23 #: data/patterns/Latn-fr.common-error.in:32 msgid "Spaces around guillemets" msgstr "" #: data/patterns/Latn-fr.common-error.in:6 #: data/patterns/Latn-fr.common-error.in:15 #: data/patterns/Latn-fr.common-error.in:24 #: data/patterns/Latn-fr.common-error.in:33 msgid "Add spaces around guillemets" msgstr "" #: data/patterns/Latn-fr.common-error.in:41 #: data/patterns/Latn-fr.common-error.in:52 #: data/patterns/Latn.common-error.in:171 msgid "Space before punctuation marks" msgstr "Noktalama işraretlerinden önceki boşluk" #: data/patterns/Latn-fr.common-error.in:42 #: data/patterns/Latn-fr.common-error.in:53 msgid "Add or remove space before various punctuation marks" msgstr "" #: data/patterns/Latn.capitalization.in:5 msgid "Sentence" msgstr "Cümle" #: data/patterns/Latn.capitalization.in:6 msgid "Capitalize the first word of a sentence" msgstr "Cümlenin ilk harfini büyüt" #: data/patterns/Latn.capitalization.in:12 msgid "Ellipsis" msgstr "" #: data/patterns/Latn.capitalization.in:13 msgid "Capitalize after an ellipsis" msgstr "" #: data/patterns/Latn.common-error.in:8 data/patterns/Latn.common-error.in:17 #: data/patterns/Latn.common-error.in:26 data/patterns/Latn.common-error.in:35 #: data/patterns/Latn.common-error.in:44 data/patterns/Latn.common-error.in:53 #: data/patterns/Latn.common-error.in:62 msgid "Ligatures" msgstr "" #: data/patterns/Latn.common-error.in:9 data/patterns/Latn.common-error.in:18 #: data/patterns/Latn.common-error.in:27 data/patterns/Latn.common-error.in:36 #: data/patterns/Latn.common-error.in:45 data/patterns/Latn.common-error.in:54 #: data/patterns/Latn.common-error.in:63 msgid "Unpack ligatures to individual characters" msgstr "" #: data/patterns/Latn.common-error.in:71 data/patterns/Latn.common-error.in:80 msgid "Spelling of a.m. and p.m." msgstr "\"ö.ö.\" ve \"ö.s.\" yazılımı" #: data/patterns/Latn.common-error.in:72 data/patterns/Latn.common-error.in:81 msgid "Change the various spellings of 12-hour periods to \"a.m.\" and \"p.m.\"" msgstr "12 saat esasına göre yazıları \"a.m.\" ve \"p.m.\" formatında düzenle" #: data/patterns/Latn.common-error.in:89 data/patterns/Latn.common-error.in:98 msgid "Letter \"O\" in a number" msgstr "Rakam için \"O\" karakteri" #: data/patterns/Latn.common-error.in:90 data/patterns/Latn.common-error.in:99 msgid "Replace letter \"O\" with a zero in a number" msgstr "\"O\" harfini, sıfır sayısı ile değiştir" #: data/patterns/Latn.common-error.in:117 msgid "Double apostrophe" msgstr "Çift tırnak" #: data/patterns/Latn.common-error.in:118 msgid "Replace a double apostrophe with a quotation mark" msgstr "İki tırnak yerine çift tırnak karakterini kullan" #: data/patterns/Latn.common-error.in:126 #: data/patterns/Latn.common-error.in:135 #: data/patterns/Latn.common-error.in:144 #: data/patterns/Latn.common-error.in:153 msgid "Spaces around brackets" msgstr "Parantez etrafındaki boşluklar" #: data/patterns/Latn.common-error.in:127 #: data/patterns/Latn.common-error.in:136 #: data/patterns/Latn.common-error.in:145 #: data/patterns/Latn.common-error.in:154 msgid "Add or remove spaces around parantheses and square brackets" msgstr "Parantez ve köşeli parantez çevresindeki boşluğu ekle ya da kaldır" #: data/patterns/Latn.common-error.in:162 msgid "Space after a dialogue dash" msgstr "Konuşma çizgisinden sonra boşluk bırak" #: data/patterns/Latn.common-error.in:163 msgid "Add space after a dialogue dash" msgstr "Diyalog kesmesinden önce boşluk ekle" #: data/patterns/Latn.common-error.in:172 msgid "Remove space before various punctuation marks" msgstr "Noktalama işaretlerinden önceki boşluğu kaldır" #: data/patterns/Latn.common-error.in:192 msgid "Space after an ellipsis" msgstr "Üç noktadan sonra boşluk" #: data/patterns/Latn.common-error.in:193 msgid "Add space after an ellipsis" msgstr "Üç noktadan sonra boşluk ekle" #: data/patterns/Latn.common-error.in:201 msgid "Space after a starting ellipsis" msgstr "Üç noktayla başlangıçtan sonra boşluk bırak" #: data/patterns/Latn.common-error.in:202 msgid "Remove space after an ellipsis that starts a line" msgstr "Cümle başındaki üç noktadan sonra boşluk koyma" #: data/patterns/Latn.common-error.in:210 #: data/patterns/Latn.common-error.in:221 #: data/patterns/Latn.common-error.in:232 #: data/patterns/Latn.common-error.in:242 msgid "Spaces around a quotation mark" msgstr "Tırnak işrareti etrafındaki boşluklar" #: data/patterns/Latn.common-error.in:211 #: data/patterns/Latn.common-error.in:222 #: data/patterns/Latn.common-error.in:233 #: data/patterns/Latn.common-error.in:243 msgid "Remove space after a starting- and before an ending quotation mark" msgstr "Tırnaktan sonra ve kapanıştan önce boşlukları kaldır" #: data/patterns/Latn.common-error.in:252 #: data/patterns/Latn.common-error.in:261 msgid "Spaces around musical notes" msgstr "" #: data/patterns/Latn.common-error.in:253 #: data/patterns/Latn.common-error.in:262 msgid "Add spaces between musical note characters and lyrics" msgstr "" #: data/patterns/Latn.common-error.in:270 #: data/patterns/Latn.common-error.in:279 msgid "Multiple question- and exclamation marks" msgstr "Birden fazla soru işareti ve ünlem" #: data/patterns/Latn.common-error.in:271 #: data/patterns/Latn.common-error.in:280 msgid "" "Replace multiple consequtive question- and exclamation marks with only one" msgstr "Arka arkaya olan çoklu soru ve ünlem işaretini teke indir" #: data/patterns/Latn.common-error.in:288 #: data/patterns/Latn.common-error.in:298 msgid "Periods around a punctuation mark" msgstr "Noktalama işaretiyle birlikte nokta kullanımı" #: data/patterns/Latn.common-error.in:289 #: data/patterns/Latn.common-error.in:299 msgid "Remove period before or after various punctuation marks" msgstr "Noktalama işaretlerinin önünde sonunda nokta koyma" #: data/patterns/Latn.common-error.in:308 msgid "Terminating double-dashes" msgstr "İkili konuşma çizgileri sonlandırılıyor" #: data/patterns/Latn.common-error.in:309 msgid "Replace a single clause-terminating dash with two dashes" msgstr "Kesik cümle bitirmesindeki tek tireyi, çift tire yap" #: data/patterns/Latn.hearing-impaired.in:5 msgid "Sound in brackets" msgstr "Parantez içinde sesler" #: data/patterns/Latn.hearing-impaired.in:6 msgid "Remove description of a sound between square brackets" msgstr "Köşeli parantez arasındaki ses açıklamalarını sil" #: data/patterns/Latn.hearing-impaired.in:12 msgid "Sound in parantheses" msgstr "Parantez içinde sesler" #: data/patterns/Latn.hearing-impaired.in:13 msgid "Remove description of a sound between parantheses" msgstr "Parantez arasındaki ses açıklamalarını sil" #: data/patterns/Latn.hearing-impaired.in:19 msgid "Song lyrics between number signs" msgstr "Numara işaretleri arası şarkı sözleri" #: data/patterns/Latn.hearing-impaired.in:20 msgid "Remove song lyrics starting with or between number signs" msgstr "Numara işaterleri arasınaki şarkı sözlerini sil" #: data/patterns/Latn.hearing-impaired.in:27 msgid "One-line song lyrics between number signs" msgstr "Numara işaterleri arasınaki tek satırlık şarkı sözleri" #: data/patterns/Latn.hearing-impaired.in:28 msgid "Remove one-line song lyrics starting with or between number signs" msgstr "Numara işaterleri arasınaki tek satırlı şarkı sözlerini sil" #: data/patterns/Latn.hearing-impaired.in:35 msgid "Speaker before a colon" msgstr "Konuşandan sonra iki nokta üst üste" #: data/patterns/Latn.hearing-impaired.in:36 msgid "Replace the name of the speaker before a colon with a dialogue dash" msgstr "Konuşmacı adını ve iki nokta üst üsteyi konuşma çizgisiyle değiştir" #: data/patterns/Latn.line-break.in:5 data/patterns/Latn.line-break.in:13 msgid "Dialogue" msgstr "Konuşma" #: data/patterns/Latn.line-break.in:6 data/patterns/Latn.line-break.in:14 msgid "Break according to dialogue separated by dashes" msgstr "Konuşmayı konuşma çizgisiyle böl" #: data/patterns/Latn.line-break.in:21 data/patterns/Latn.line-break.in:30 msgid "Clause" msgstr "Kural" #: data/patterns/Latn.line-break.in:22 data/patterns/Latn.line-break.in:31 msgid "Break according to clauses terminated by a punctuation mark" msgstr "Noktalama işareti kurala göre satır başına engel olunca" #: data/patterns/Latn.line-break.in:38 msgid "Number and unit" msgstr "" #: data/patterns/Latn.line-break.in:39 msgid "Do not break between a number and associated unit" msgstr "" #: data/patterns/Zyyy.common-error.in:5 data/patterns/Zyyy.common-error.in:14 msgid "Leading and trailing spaces" msgstr "Baş ve son boşluklar" #: data/patterns/Zyyy.common-error.in:6 data/patterns/Zyyy.common-error.in:15 msgid "Remove spaces from the beginning and end of lines" msgstr "Satır başındaki ve sonundaki boşlukları sil" #: data/patterns/Zyyy.common-error.in:23 msgid "Multiple consecutive spaces" msgstr "Çoklu ardışık boşluklar" #: data/patterns/Zyyy.common-error.in:24 msgid "Replace multiple consecutive spaces with only one" msgstr "Birden çok boşluğu teke indir" #: data/patterns/Zyyy.common-error.in:32 data/patterns/Zyyy.common-error.in:45 #: data/patterns/Zyyy.common-error.in:55 data/patterns/Zyyy.common-error.in:65 msgid "Space between digits" msgstr "Rakamlar arasında boşluk" #: data/patterns/Zyyy.common-error.in:33 data/patterns/Zyyy.common-error.in:46 #: data/patterns/Zyyy.common-error.in:56 data/patterns/Zyyy.common-error.in:66 msgid "Remove space between digits of a number" msgstr "Rakamlar arasındaki boşlukları sil" #: data/patterns/Zyyy.common-error.in:79 msgid "Musical notes" msgstr "Müzikal notalar" #: data/patterns/Zyyy.common-error.in:80 msgid "Replace Unicode musical note characters with number signs" msgstr "Unicode müzikal nota karakterlerini rakamlarla değiştir" #: data/io.otsaloma.gaupol.appdata.xml.in:7 msgid "Editor for text-based subtitles" msgstr "Metin tabanlı altyazılar için düzenleyici." #: data/io.otsaloma.gaupol.appdata.xml.in:9 msgid "" "Gaupol is an editor for text-based subtitle files. It supports multiple " "subtitle file formats and provides means of creating subtitles, editing " "texts and timing subtitles to match video." msgstr "" "Gaupol, metin tabanlı altyazı dosyaları için bir düzenleyicidir. Birçok " "altyazı dosya biçimini destekler ve video eşleştirmek için altyazı " "oluşturma, metinleri düzenleme ve altyazıları zamanlama araçları sağlar." #: data/io.otsaloma.gaupol.appdata.xml.in:40 msgid "Main window" msgstr "Ana pencere" #: data/io.otsaloma.gaupol.desktop.in:5 msgid "Subtitle Editor" msgstr "Alt Yazı Düzenleyicisi" #: data/io.otsaloma.gaupol.desktop.in:6 msgid "Edit subtitle files" msgstr "Alt yazı dosyasını düzenle" #. TRANSLATORS: Search terms to find this application. Do NOT translate or #. localize the semicolons! The list MUST also end with a semicolon! #: data/io.otsaloma.gaupol.desktop.in:12 msgid "video;subtitles;captions;" msgstr "video;altyazılar;captions;" gaupol-1.11/setup-aeidon.py000077500000000000000000000017051422217132500156770ustar00rootroot00000000000000#!/usr/bin/env python3 """setuptools/wheel/PyPI version of the aeidon package.""" import shutil from setup import get_aeidon_version from setuptools import find_packages from setuptools import setup # Copy data files to the aeidon package, so they can be included. shutil.copytree("data/headers", "aeidon/data/headers") shutil.copytree("data/patterns", "aeidon/data/patterns") setup( name="aeidon", version=get_aeidon_version(), author="Osmo Salomaa", author_email="otsaloma@iki.fi", description="Reading, writing and manipulating text-based subtitle files", long_description=open("README.aeidon.md", "r").read(), long_description_content_type="text/markdown", url="https://github.com/otsaloma/gaupol", license="GPL", packages=find_packages(exclude=["gaupol*", "*.test"]), package_data={"aeidon": ["data/*/*"]}, python_requires=">=3.2.0", install_requires=["chardet>=2.2.1"], ) shutil.rmtree("aeidon/data") gaupol-1.11/setup.py000077500000000000000000000351031422217132500144410ustar00rootroot00000000000000#!/usr/bin/env python3 """ There are four relevant customizations to the standard distutils installation process: (1) allowing separate installations of aeidon and gaupol, (2) writing the aeidon.paths module, (3) handling translations and (4) extensions. (1) Allowing separate installations of aeidon and gaupol are handled through global options --with-aeidon, --without-aeidon, --with-gaupol and --without-gaupol. See 'python3 setup.py --help' and the file 'README.aeidon.md' for documentation and the Distribution class defined in this file for the implementation and logic of how that is handled. (2) Gaupol finds non-Python files based on the paths written in module aeidon.paths. In aeidon/paths.py the paths default to the ones in the source directory. During the 'install_lib' command the file gets rewritten to build/aeidon/paths.py with the installation paths and that file will be installed. The paths are based on variable 'install_data' with the 'root' variable stripped if it is given. If doing distro-packaging, make sure this file gets correctly written. (3) During installation, the .po files are compiled into .mo files and the appdata, desktop, pattern and extension metadata files are translated. This requires gettext. (4) Extensions are installed under the data directory. All python code included in the extensions are compiled during the 'install_data' command, using the same arguments for 'byte_compile' as used by the 'install_lib' command. If the 'install_lib' command was given the '--no-compile' option, then extensions are not compiled either. """ import distutils import glob import os import re import shutil import sys from distutils import log from distutils.command.clean import clean from distutils.command.install import install from distutils.command.install_data import install_data from distutils.command.install_lib import install_lib from distutils.dist import Distribution as distribution distribution.global_options.extend([ ("mandir=", None, "relative installation directory for man pages (defaults to 'share/man')"), ("with-aeidon", None, "install the aeidon package"), ("without-aeidon", None, "don't install the aeidon package"), ("with-gaupol", None, "install the gaupol package"), ("without-gaupol", None, "don't install the gaupol package"), ("with-iso-codes", None, "install iso-codes JSON files"), ("without-iso-codes", None, "don't install iso-codes JSON files"), ]) distribution.negative_opt.update({ "without-aeidon": "with-aeidon", "without-gaupol": "with-gaupol", "without-iso-codes": "with-iso-codes", }) def get_aeidon_version(): path = os.path.join("aeidon", "__init__.py") text = open(path, "r", encoding="utf_8").read() return re.search(r"__version__ *= *['\"](.*?)['\"]", text).group(1) def get_gaupol_version(): path = os.path.join("gaupol", "__init__.py") text = open(path, "r", encoding="utf_8").read() return re.search(r"__version__ *= *['\"](.*?)['\"]", text).group(1) def run_or_exit(cmd): if os.system(cmd) == 0: return log.error("command {!r} failed".format(cmd)) raise SystemExit(1) def run_or_warn(cmd): if os.system(cmd) == 0: return log.warn("command {!r} failed".format(cmd)) class Clean(clean): def run(self): clean.run(self) f = open(os.path.join("manifests", "clean.manifest"), "r") for targets in [glob.glob(x.strip()) for x in f]: for target in filter(os.path.isdir, targets): log.info("removing {}".format(target)) if not self.dry_run: shutil.rmtree(target) for target in filter(os.path.isfile, targets): log.info("removing {}".format(target)) if not self.dry_run: os.remove(target) f.close() class Distribution(distribution): def __init__(self, attrs=None): if sys.platform == "win32": self.executables = [] self.mandir = "share/man" self.with_aeidon = True self.with_gaupol = True self.with_iso_codes = True distribution.__init__(self, attrs) self.data_files = [] self.packages = [] self.scripts = [] def __find_data_files(self, name): fok = lambda x: not x.endswith((".in", ".pyc")) basename = "{}.manifest".format(name) f = open(os.path.join("manifests", basename), "r") for line in [x.strip() for x in f]: if not line: continue if line.startswith("["): dest = line[1:-1] continue files = list(filter(fok, glob.glob(line))) files = list(filter(os.path.isfile, files)) assert files self.data_files.append((dest, files)) f.close() def __find_man_pages(self): mandir = self.mandir while mandir.endswith("/"): mandir = mandir[:-1] dest = "{}/man1".format(mandir) self.data_files.append((dest, ["data/gaupol.1"])) def __find_packages(self, name): for root, dirs, files in os.walk(name): init_path = os.path.join(root, "__init__.py") if not os.path.isfile(init_path): continue path = root.replace(os.sep, ".") if path.endswith(".test"): continue self.packages.append(path[path.find(name):]) def __find_scripts(self, name): if name == "gaupol": self.scripts.append("bin/gaupol") def parse_command_line(self): value = distribution.parse_command_line(self) # Configuration files are parsed before the command line, so once the # command line is parsed, all options have their final values and thus # files corresponding to the packages to install can finally be set. if self.with_aeidon: self.__find_data_files("aeidon") self.__find_packages("aeidon") if self.with_aeidon and self.with_iso_codes: self.__find_data_files("iso-codes") if self.with_gaupol: self.__find_data_files("gaupol") self.__find_man_pages() self.__find_packages("gaupol") self.__find_scripts("gaupol") # Redefine name, version and requires metadata attributes. These are # used in the egg-info file written by distutils. While egg-info files # appear completely useless, it needs to be ensured that if aeidon and # gaupol are installed separately, they install differently named # egg-info files in order to avoid overwriting each other. if self.with_gaupol: self.metadata.name = "gaupol" self.metadata.version = get_gaupol_version() else: # without gaupol self.metadata.name = "aeidon" self.metadata.version = get_aeidon_version() return value def parse_config_files(self, filenames=None): value = distribution.parse_config_files(self, filenames) strtobool = distutils.util.strtobool for option in ["with_aeidon", "with_gaupol", "with_iso_codes"]: value = getattr(self, option) if isinstance(value, str): setattr(self, option, strtobool(value)) return value class Install(install): def run(self): install.run(self) if not self.distribution.with_gaupol: return get_command_obj = self.distribution.get_command_obj root = get_command_obj("install").root data_dir = get_command_obj("install_data").install_dir # Assume we're actually installing if --root was not given. if (root is not None) or (data_dir is None): return directory = os.path.join(data_dir, "share", "applications") log.info("updating desktop database in {}".format(directory)) run_or_warn('update-desktop-database "{}"'.format(directory)) class InstallData(install_data): def __build_extensions(self): get_command_obj = self.distribution.get_command_obj if not get_command_obj("install_lib").compile: return optimize = get_command_obj("install_lib").optimize data_dir = get_command_obj("install_data").install_dir data_dir = os.path.join(data_dir, "share", "gaupol") files = glob.glob("{}/extensions/*/*.py".format(data_dir)) distutils.util.byte_compile(files, optimize, self.force, self.dry_run) # Figure out paths of the compiled files and add them to # self.outfiles so that 'setup.py --record' works correctly. def get_cache_pattern(path): dir, file = os.path.split(path) file = os.path.splitext(file)[0] + ".*" return os.path.join(dir, "__pycache__", file) for pattern in map(get_cache_pattern, files): for file in glob.glob(pattern): if not file in self.outfiles: self.outfiles.append(file) def __generate_linguas(self): linguas = sorted(glob.glob("po/*.po")) linguas = [os.path.basename(x)[:-3] for x in linguas] with open("po/LINGUAS", "w") as f: f.write("\n".join(linguas) + "\n") def __get_appdata_file(self): path = os.path.join("data", "io.otsaloma.gaupol.appdata.xml") command = "msgfmt --xml -d po --template {}.in -o {}" run_or_warn(command.format(path, path)) if not os.path.isfile(path): # The above can fail with an old version of gettext, # fall back on copying the file without translations. shutil.copy("{}.in".format(path), path) return ("share/metainfo", [path]) def __get_desktop_file(self): path = os.path.join("data", "io.otsaloma.gaupol.desktop") command = "msgfmt --desktop -d po --template {}.in -o {}" run_or_warn(command.format(path, path)) if not os.path.isfile(path): # The above can fail with an old version of gettext, # fall back on copying the file without translations. shutil.copy("{}.in".format(path), path) return ("share/applications", [path]) def __get_extension_file(self, extension_file): assert extension_file.endswith(".in") path = extension_file[:-3] command = " ".join(( "msgfmt --desktop -d po --template {}.in -o {}", "--keyword=", "--keyword=Name", "--keyword=Description", )) run_or_warn(command.format(path, path)) if not os.path.isfile(path): # The above can fail with an old version of gettext, # fall back on copying the file without translations. shutil.copy("{}.in".format(path), path) extension = os.path.basename(os.path.dirname(extension_file)) return ("share/gaupol/extensions/{}".format(extension), [path]) def __get_extension_files(self): files = sorted(glob.glob("data/extensions/*/*.extension.in")) return [self.__get_extension_file(x) for x in files] def __get_mo_file(self, po_file): locale = os.path.basename(po_file[:-3]) mo_dir = os.path.join("locale", locale, "LC_MESSAGES") mo_file = os.path.join(mo_dir, "gaupol.mo") log.info("compiling {}".format(mo_file)) os.makedirs(mo_dir, exist_ok=True) run_or_exit("msgfmt {} -o {}".format(po_file, mo_file)) dest_dir = os.path.join("share", mo_dir) return (dest_dir, [mo_file]) def __get_mo_files(self): if sys.platform == "win32": return [] files = sorted(glob.glob("po/*.po")) return [self.__get_mo_file(x) for x in files] def __get_pattern_file(self, pattern_file): assert pattern_file.endswith(".in") path = pattern_file[:-3] command = " ".join(( "msgfmt --desktop -d po --template {}.in -o {}", "--keyword=", "--keyword=Name", "--keyword=Description", )) run_or_warn(command.format(path, path)) if not os.path.isfile(path): # The above can fail with an old version of gettext, # fall back on copying the file without translations. shutil.copy("{}.in".format(path), path) return ("share/gaupol/patterns", [path]) def __get_pattern_files(self): files = sorted(glob.glob("data/patterns/*.in")) return [self.__get_pattern_file(x) for x in files] def run(self): self.__generate_linguas() if self.distribution.with_aeidon: self.data_files.extend(self.__get_mo_files()) self.data_files.extend(self.__get_pattern_files()) if self.distribution.with_gaupol: self.data_files.extend(self.__get_extension_files()) self.data_files.append(self.__get_appdata_file()) self.data_files.append(self.__get_desktop_file()) install_data.run(self) if self.distribution.with_gaupol: self.__build_extensions() class InstallLib(install_lib): def install(self): if not self.distribution.with_aeidon: return install_lib.install(self) get_command_obj = self.distribution.get_command_obj root = get_command_obj("install").root prefix = get_command_obj("install").install_data # Allow --root to be used like DESTDIR. if root is not None: prefix = os.path.abspath(prefix) prefix = prefix.replace(os.path.abspath(root), "") data_dir = os.path.join(prefix, "share", "gaupol") locale_dir = os.path.join(prefix, "share", "locale") # Write changes to the aeidon.paths module. path = os.path.join(self.build_dir, "aeidon", "paths.py") text = open(path, "r", encoding="utf_8").read() patt = r"^DATA_DIR = .*$" repl = "DATA_DIR = {!r}".format(data_dir) text = re.sub(patt, repl, text, flags=re.MULTILINE) assert text.count(repl) == 1 patt = r"^LOCALE_DIR = .*$" repl = "LOCALE_DIR = {!r}".format(locale_dir) text = re.sub(patt, repl, text, flags=re.MULTILINE) assert text.count(repl) == 1 open(path, "w", encoding="utf_8").write(text) return install_lib.install(self) setup_kwargs = { "name": "gaupol", "version": get_gaupol_version(), "author": "Osmo Salomaa", "author_email": "otsaloma@iki.fi", "url": "https://otsaloma.io/gaupol/", "description": "Editor for text-based subtitle files", "license": "GPL", "distclass": Distribution, "cmdclass": { "clean": Clean, "install": Install, "install_data": InstallData, "install_lib": InstallLib, }, } if __name__ == "__main__": os.chdir(os.path.dirname(__file__) or ".") distutils.core.setup(**setup_kwargs) gaupol-1.11/tools/000077500000000000000000000000001422217132500140625ustar00rootroot00000000000000gaupol-1.11/tools/check-translations000077500000000000000000000034221422217132500176050ustar00rootroot00000000000000#!/usr/bin/env python3 """ Check translation files for common errors. Usage: check-translations [XX[_YY[@ZZ]]...] """ import glob, polib, re, sys def print_error(title, entry): print("\n{}:".format(title), entry, sep="\n") args = ["po/{}.po".format(x) for x in sys.argv[1:]] for name in args or sorted(glob.glob("po/*.po")): po = polib.pofile(name) print("{}: {}% translated".format(name, po.percent_translated())) for entry in po.translated_entries(): translations = ( list(entry.msgstr_plural.values()) if entry.msgid_plural else [entry.msgstr]) for translation in translations: # Check that Python string formatting fields exists as-is # in the translation (order can vary, but not the field). for field in re.findall(r"\{.*?\}", entry.msgid, flags=re.M): if not field in translation: print_error("Python string formatting mismatch", entry) raise SystemExit("FATAL ERROR") # Check that the translation of a label includes # a keyboard accelerator defined by an underscore. if "_" in entry.msgid: if not "_" in translation: print_error("Missing accelerator", entry) # Check that the translation of a label includes # a terminating colon. if entry.msgid.endswith(":"): if not translation.endswith(":"): print_error("Missing terminating colon", entry) # Check that the translation of a menu item includes # an ellipsis defined by the Unicode character. if "…" in entry.msgid: if not "…" in translation: print_error("Missing ellipsis", entry) gaupol-1.11/tools/extract-translations000077500000000000000000000034201422217132500202000ustar00rootroot00000000000000#!/bin/sh cd "$(dirname "$0")/.." || exit 1 truncate -s0 po/gaupol.pot # Python code xgettext \ --output=po/gaupol.pot \ --join-existing \ --from-code=UTF-8 \ --language=Python \ --keyword=_:1 \ --keyword=d_:2 \ --keyword=n_:1,2 \ --add-comments=TRANSLATORS: \ $(find . -name "*.py" -not -path "*/test/*") # GtkBuilder XML files xgettext \ --output=po/gaupol.pot \ --join-existing \ --from-code=UTF-8 \ $(find data -name "*.ui") # Extension metadata files xgettext \ --output=po/gaupol.pot \ --join-existing \ --from-code=UTF-8 \ --language=Desktop \ --keyword= \ --keyword=Name \ --keyword=Description \ --add-comments=TRANSLATORS: \ data/extensions/*/*.extension.in # Pattern files xgettext \ --output=po/gaupol.pot \ --join-existing \ --from-code=UTF-8 \ --language=Desktop \ --keyword= \ --keyword=Name \ --keyword=Description \ --add-comments=TRANSLATORS: \ data/patterns/*.in # AppData XML file xgettext \ --output=po/gaupol.pot \ --join-existing \ --from-code=UTF-8 \ data/io.otsaloma.gaupol.appdata.xml.in # Desktop file xgettext \ --output=po/gaupol.pot \ --join-existing \ --from-code=UTF-8 \ --language=Desktop \ --keyword= \ --keyword=GenericName \ --keyword=Comment \ --keyword=Keywords \ --add-comments=TRANSLATORS: \ data/io.otsaloma.gaupol.desktop.in # XXX: Fix charset=CHARSET which causes msggrep to fail. sed -i s/charset=CHARSET/charset=UTF-8/ po/gaupol.pot # Remove AppData entries that shouldn't be translated. msggrep \ --invert-match \ --msgid \ --regexp="^Gaupol$" \ --regexp="^Osmo Salomaa$" \ --output-file=po/tmp.pot \ po/gaupol.pot && mv -f po/tmp.pot po/gaupol.pot gaupol-1.11/tools/play000077500000000000000000000007221422217132500147560ustar00rootroot00000000000000#!/usr/bin/env python3 """Play video file using gaupol.VideoPlayer.""" import os, sys directory = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, os.path.join(directory, "..")) import gaupol from gi.repository import Gtk player = gaupol.VideoPlayer() window = Gtk.Window() window.set_default_size(1280, 720) window.connect("delete-event", Gtk.main_quit) window.add(player.widget) window.show_all() player.set_path(sys.argv[1]) player.play() Gtk.main() gaupol-1.11/tools/release000077500000000000000000000011361422217132500154310ustar00rootroot00000000000000#!/bin/bash # Commit changes, tag and push release to GitHub. cd "$(dirname "$0")/.." || exit 1 VERSION="$(python3 -c "import gaupol; print(gaupol.__version__)")" echo "Git status:" git status --porcelain printf "\nRelease version: $VERSION\n" read -p "Press Enter to continue or Ctrl+C to abort: " git commit -a -m "RELEASE $VERSION" git tag -s -m "RELEASE $VERSION" $VERSION git push git push --tags egrep -B 999 -m2 "^===+" NEWS.md \ | head -n-3 \ | tail -n+4 \ | sed ':a;N;$!ba;s/\n / /g' \ | gh release create \ --notes-file - \ --title $VERSION \ $VERSION gaupol-1.11/tools/update-iso-codes000077500000000000000000000004521422217132500171560ustar00rootroot00000000000000#!/bin/sh # Update iso-codes JSON files from /usr/share/iso-codes/json. cd "$(dirname "$0")/.." || exit 1 cp -fv /usr/share/iso-codes/json/iso_639-2.json data/iso-codes cp -fv /usr/share/iso-codes/json/iso_3166-1.json data/iso-codes cp -fv /usr/share/iso-codes/json/iso_15924.json data/iso-codes gaupol-1.11/tools/update-translations000077500000000000000000000006331422217132500200130ustar00rootroot00000000000000#!/bin/bash set -e cd "$(dirname "$0")/.." || exit 1 tools/extract-translations tx push -s tx pull -af --minimum-perc=50 emacs1 po/fi.po tx push -tf --no-interactive -l fi for PO in po/*.po; do LANG=$(basename $PO .po) tools/check-translations $LANG read -p "Keep? [Y/n] " [ "$REPLY" = "n" ] && rm -fv $PO done # rm -f po/LINGUAS # ls po/*.po | cut -d/ -f2 | cut -d. -f1 > po/LINGUAS git status